Feat(fulfillment): service provider registration + fulfillment management (#6524)

**What**
- Create the fulfillment manual package with a first iteration API 
- Create a new `AbstractFulfillmentProviderService` and `IFulfillmentProvider`
- Modify the module service interface to add new methods to manipulate the fulfillment and the communication with the external provider
  - create (no bulk)
  - cancel (no bulk)
  - update (no bulk)
  - list
  - listAndCount
  - retrieve
- Add new methods to the service provider service to include communication with the third party provider
  - get options
  - create
  - cancel
  - validate data
  - validate option
- Update/create interfaces and DTO's
- fix repository serializer to allow non entity to be passed without throwing
- split module tests into multiple files to simplify navigation
- Add integration tests to validate fulfillments manipulation and external provider loading + communication

FIXES CORE-1729
FIXES CORE-1785
FIXES CORE-1784
FIXES CORE-1766
This commit is contained in:
Adrien de Peretti
2024-03-05 11:11:14 +00:00
committed by GitHub
parent f9ef37a2f2
commit 62a7bcc30c
55 changed files with 4066 additions and 2749 deletions
@@ -0,0 +1,46 @@
import { CreateFulfillmentDTO } from "@medusajs/types"
export function generateCreateFulfillmentData(
data: Partial<CreateFulfillmentDTO> & {
provider_id: string
shipping_option_id: string
}
) {
return {
location_id: "test-location",
packed_at: null,
shipped_at: null,
delivered_at: null,
canceled_at: null,
data: null,
provider_id: data.provider_id,
shipping_option_id: data.shipping_option_id,
metadata: data.metadata ?? null,
delivery_address: data.delivery_address ?? {
address_1: "test-address",
address_2: "test-address",
city: "test-city",
postal_code: "test-postal-code",
country_code: "test-country-code",
province: "test-province",
phone: "test-phone",
full_name: "test-full-name",
},
items: data.items ?? [
{
title: "test-title",
sku: "test-sku",
quantity: 1,
barcode: "test-barcode",
},
],
labels: data.labels ?? [
{
tracking_number: "test-tracking-number",
tracking_url: "test-tracking-url",
label_url: "test-label-url",
},
],
order: data.order ?? {},
}
}
@@ -1,39 +1,2 @@
import { CreateShippingOptionDTO } from "@medusajs/types"
export function generateCreateShippingOptionsData({
name,
service_zone_id,
shipping_profile_id,
service_provider_id,
price_type,
rules,
type,
data,
}: Omit<CreateShippingOptionDTO, "name" | "price_type" | "type"> & {
price_type?: CreateShippingOptionDTO["price_type"]
name?: string
type?: CreateShippingOptionDTO["type"]
}): Required<CreateShippingOptionDTO> {
return {
service_zone_id: service_zone_id,
shipping_profile_id: shipping_profile_id,
service_provider_id: service_provider_id,
type: type ?? {
code: "test-type",
description: "test-description",
label: "test-label",
},
data: data ?? {
amount: 1000,
},
name: name ?? Math.random().toString(36).substring(7),
price_type: price_type ?? "flat",
rules: rules ?? [
{
attribute: "weight",
operator: "eq",
value: "test",
},
],
}
}
export * from "./shipping-options"
export * from "./fulfillment"
@@ -0,0 +1,19 @@
import { AbstractFulfillmentProviderService } from "@medusajs/utils/src"
export class FulfillmentProviderServiceFixtures extends AbstractFulfillmentProviderService {
static identifier = "fixtures-fulfillment-provider"
async createFulfillment(data, items, order, fulfillment): Promise<any> {
return {}
}
async cancelFulfillment(fulfillment): Promise<any> {
return {}
}
async getFulfillmentOptions(): Promise<any> {
return {}
}
}
export const services = [FulfillmentProviderServiceFixtures]
@@ -0,0 +1 @@
export * from "./default-provider"
@@ -0,0 +1,39 @@
import { CreateShippingOptionDTO } from "@medusajs/types"
export function generateCreateShippingOptionsData({
name,
service_zone_id,
shipping_profile_id,
fulfillment_provider_id,
price_type,
rules,
type,
data,
}: Omit<CreateShippingOptionDTO, "name" | "price_type" | "type"> & {
price_type?: CreateShippingOptionDTO["price_type"]
name?: string
type?: CreateShippingOptionDTO["type"]
}): Required<CreateShippingOptionDTO> {
return {
service_zone_id: service_zone_id,
shipping_profile_id: shipping_profile_id,
fulfillment_provider_id: fulfillment_provider_id,
type: type ?? {
code: "test-type",
description: "test-description",
label: "test-label",
},
data: data ?? {
amount: 1000,
},
name: name ?? Math.random().toString(36).substring(7),
price_type: price_type ?? "flat",
rules: rules ?? [
{
attribute: "weight",
operator: "eq",
value: "test",
},
],
}
}