340 lines
9.6 KiB
TypeScript
340 lines
9.6 KiB
TypeScript
import { apiBlobRequest, apiRequest } from '@/api/http'
|
|
|
|
export type ApiFirstLegStatus = 'DRAFT' | 'SUBMITTED' | 'APPROVED' | 'ACCEPTED' | 'REJECTED' | 'CANCELLED' | 'PROCESSING' | 'COMPLETED'
|
|
export type ApiTransportMode = 'SEA' | 'AIR' | 'RAIL' | 'TRUCK'
|
|
export type ApiPickupMethod = 'SELF_EXPRESS' | 'PICKUP' | 'SELF_TRUCK'
|
|
export type ApiTaxMode = 'BUY_DECLARATION' | 'TAX_REFUND'
|
|
export type ApiContainerMode = 'FULL_CONTAINER' | 'LCL'
|
|
export type ApiDestinationType = 'FBA' | 'OVERSEAS' | 'PRIVATE'
|
|
export type ApiPricingTaxMode = 'TAX_INCLUDED' | 'TAX_EXCLUDED'
|
|
export type ApiPriceModel = 'FBA_WAREHOUSE_RATE' | 'REGION_WEIGHT_TIER'
|
|
|
|
export interface PageResult<T> {
|
|
records: T[]
|
|
page: number
|
|
size: number
|
|
total: number
|
|
pages: number
|
|
}
|
|
|
|
export type MerchantWarehouseType = 'DOMESTIC' | 'FBA' | 'OVERSEAS'
|
|
|
|
export interface MerchantWarehouseQuery {
|
|
page?: number
|
|
size?: number
|
|
status?: 'ACTIVE' | 'INACTIVE'
|
|
warehouseType?: MerchantWarehouseType
|
|
}
|
|
|
|
export interface MerchantWarehouse {
|
|
id: number | string
|
|
warehouseCode: string
|
|
warehouseName: string
|
|
warehouseType: string
|
|
countryCode: string
|
|
timezone: string | null
|
|
contactName: string | null
|
|
contactPhone: string | null
|
|
contactEmail: string | null
|
|
status: 'ACTIVE' | 'INACTIVE'
|
|
remark: string | null
|
|
updatedAt: string | null
|
|
}
|
|
|
|
export interface MerchantWarehouseAddress {
|
|
countryCode: string
|
|
stateProvince: string | null
|
|
city: string | null
|
|
district: string | null
|
|
postalCode: string | null
|
|
addressLine1: string
|
|
addressLine2: string | null
|
|
}
|
|
|
|
export interface MerchantWarehouseCapability {
|
|
capabilityCode: string
|
|
capabilityName: string
|
|
enabled: boolean
|
|
cutoffTime: string | null
|
|
description: string | null
|
|
}
|
|
|
|
export interface MerchantWarehouseDetail {
|
|
warehouse: MerchantWarehouse
|
|
addresses: MerchantWarehouseAddress[]
|
|
capabilities: MerchantWarehouseCapability[]
|
|
}
|
|
|
|
export interface FirstLegOrderPartyPayload {
|
|
companyName: string
|
|
contactName: string
|
|
phone: string
|
|
email?: string
|
|
countryCode: string
|
|
province?: string
|
|
city: string
|
|
district?: string
|
|
addressLine: string
|
|
postalCode?: string
|
|
}
|
|
|
|
export interface FirstLegOrderCargoPayload {
|
|
cargoName: string
|
|
hsCode?: string
|
|
packageType: string
|
|
packageCount: number
|
|
grossWeightKg: number
|
|
volumeCbm: number
|
|
lengthCm?: number
|
|
widthCm?: number
|
|
heightCm?: number
|
|
declaredValue?: number
|
|
currency?: string
|
|
dangerousGoods?: boolean
|
|
cargoRemark?: string
|
|
skuNo?: string
|
|
upcNo?: string
|
|
cargoNameEn?: string
|
|
customsHsCode?: string
|
|
unitsPerPackage?: number
|
|
totalQuantity?: number
|
|
netWeightKg?: number
|
|
unitDeclaredValue?: number
|
|
material?: string
|
|
usage?: string
|
|
model?: string
|
|
brand?: string
|
|
productLengthCm?: number
|
|
productWidthCm?: number
|
|
productHeightCm?: number
|
|
shipmentId?: string
|
|
referenceId?: string
|
|
productImageFileId?: number | string
|
|
}
|
|
|
|
export interface ProductImageUploadResult {
|
|
fileId: number | string
|
|
fileName: string
|
|
contentType: string
|
|
sizeBytes: number
|
|
}
|
|
|
|
export interface FirstLegOrderSaveRequest {
|
|
customerId?: number | string
|
|
customerName: string
|
|
transportMode: ApiTransportMode
|
|
tradeTerm?: string
|
|
destinationCountryCode: string
|
|
destinationWarehouseId?: number | string
|
|
destinationWarehouseName: string
|
|
expectedShipDate?: string
|
|
customerRemark?: string
|
|
sender?: FirstLegOrderPartyPayload
|
|
receiver?: FirstLegOrderPartyPayload
|
|
cargoes: FirstLegOrderCargoPayload[]
|
|
pickupMethod: ApiPickupMethod
|
|
receivingWarehouseId: number | string
|
|
receivingWarehouseName: string
|
|
receivingWarehouseAddress?: string | null
|
|
receivingTime?: string | null
|
|
channelCode: string
|
|
channelName: string
|
|
pricingTaxMode: ApiPricingTaxMode
|
|
taxMode: ApiTaxMode
|
|
containerMode?: ApiContainerMode
|
|
customsInspection: boolean
|
|
destinationType: ApiDestinationType
|
|
amazonWarehouseCode?: string
|
|
shipmentId?: string
|
|
referenceId?: string
|
|
}
|
|
|
|
export interface MerchantFirstLegOrder {
|
|
id: number | string
|
|
orderNo: string | null
|
|
customerId: number | string | null
|
|
customerName: string
|
|
status: ApiFirstLegStatus
|
|
transportMode: ApiTransportMode
|
|
tradeTerm: string | null
|
|
destinationCountryCode: string
|
|
destinationWarehouseId: number | string | null
|
|
destinationWarehouseName: string
|
|
expectedShipDate: string | null
|
|
customerRemark: string | null
|
|
pickupMethod: ApiPickupMethod
|
|
receivingWarehouseId: number | string
|
|
receivingWarehouseName: string
|
|
receivingWarehouseAddress?: string | null
|
|
receivingTime?: string | null
|
|
channelCode: string
|
|
channelName: string
|
|
pricingTaxMode?: ApiPricingTaxMode | null
|
|
carrierId?: number | string | null
|
|
carrierName?: string | null
|
|
taxMode: ApiTaxMode
|
|
containerMode: ApiContainerMode | null
|
|
customsInspection: boolean
|
|
destinationType: ApiDestinationType
|
|
amazonWarehouseCode: string | null
|
|
shipmentId: string | null
|
|
referenceId: string | null
|
|
expressCompany?: string | null
|
|
expressTrackingNo?: string | null
|
|
submittedAt?: string | null
|
|
completedAt?: string | null
|
|
version: number
|
|
createdAt: string
|
|
updatedAt: string
|
|
}
|
|
|
|
export interface MerchantFirstLegOrderCargo extends FirstLegOrderCargoPayload {
|
|
id: number | string
|
|
itemNo: number
|
|
}
|
|
|
|
export interface MerchantFirstLegOrderParty extends FirstLegOrderPartyPayload {
|
|
id: number | string
|
|
partyType: 'SENDER' | 'RECEIVER' | string
|
|
}
|
|
|
|
export interface MerchantOrderStatusHistory {
|
|
id: number | string
|
|
fromStatus: ApiFirstLegStatus | null
|
|
toStatus: ApiFirstLegStatus
|
|
action: string
|
|
reason: string | null
|
|
operatorName: string | null
|
|
occurredAt: string
|
|
}
|
|
|
|
export interface MerchantFirstLegOrderDetail {
|
|
order: MerchantFirstLegOrder
|
|
cargoes: MerchantFirstLegOrderCargo[]
|
|
parties: MerchantFirstLegOrderParty[]
|
|
internalNotes: []
|
|
statusHistory: MerchantOrderStatusHistory[]
|
|
}
|
|
|
|
export function uploadMerchantProductImage(file: File) {
|
|
const data = new FormData()
|
|
data.append('file', file)
|
|
return apiRequest<ProductImageUploadResult>({ method: 'POST', url: '/merchant/v1/files/product-images', data })
|
|
}
|
|
|
|
export function downloadMerchantProductImage(fileId: number | string) {
|
|
return apiBlobRequest({ method: 'GET', url: `/merchant/v1/files/product-images/${fileId}` })
|
|
}
|
|
|
|
export interface FirstLegOrderQuery {
|
|
keyword?: string
|
|
status?: ApiFirstLegStatus
|
|
customerId?: number | string
|
|
destinationWarehouseId?: number | string
|
|
createdFrom?: string
|
|
createdTo?: string
|
|
page?: number
|
|
size?: number
|
|
}
|
|
|
|
export interface MerchantPricingChannel {
|
|
priceBookVersionId: number | string
|
|
channelCode: string
|
|
channelName: string
|
|
priceModel: ApiPriceModel
|
|
pricingTaxModes: ApiPricingTaxMode[]
|
|
estimatedDepartureDate: string | null
|
|
estimatedDepartureText: string | null
|
|
latestWarehouseEntry: string | null
|
|
referenceTransit: string | null
|
|
surchargeDescription: string | null
|
|
remark: string | null
|
|
}
|
|
|
|
export interface MerchantPriceEstimateRequest {
|
|
originWarehouseId: number | string
|
|
channelCode: string
|
|
destinationCode?: string
|
|
destinationType: Exclude<ApiDestinationType, 'PRIVATE'>
|
|
destinationWarehouseId?: number | string
|
|
destinationName?: string
|
|
pricingTaxMode: ApiPricingTaxMode
|
|
actualWeightKg: number
|
|
actualVolumeCbm: number
|
|
}
|
|
|
|
export interface MerchantPriceEstimate {
|
|
priceBookVersionId: number | string
|
|
channelCode: string
|
|
priceModel: ApiPriceModel
|
|
pricingTaxMode: ApiPricingTaxMode
|
|
chargeableQuantity: number
|
|
chargeUnit: string
|
|
unitPrice: number
|
|
estimatedAmount: number
|
|
currency: string
|
|
disclaimer: string
|
|
}
|
|
|
|
export function getMerchantWarehouses(params: MerchantWarehouseQuery = {}) {
|
|
return apiRequest<PageResult<MerchantWarehouse>>({
|
|
method: 'GET',
|
|
url: '/merchant/v1/warehouses',
|
|
params: { page: 1, size: 200, status: 'ACTIVE', ...params },
|
|
})
|
|
}
|
|
|
|
export function getMerchantWarehouseDetail(id: number | string) {
|
|
return apiRequest<MerchantWarehouseDetail>({ method: 'GET', url: `/merchant/v1/warehouses/${id}` })
|
|
}
|
|
|
|
export function getMerchantPricingChannels(originWarehouseId: number | string) {
|
|
return apiRequest<MerchantPricingChannel[]>({
|
|
method: 'GET',
|
|
url: '/merchant/v1/first-leg/pricing/channels',
|
|
params: { originWarehouseId },
|
|
})
|
|
}
|
|
|
|
export function estimateMerchantFirstLegPrice(payload: MerchantPriceEstimateRequest) {
|
|
return apiRequest<MerchantPriceEstimate>({
|
|
method: 'POST',
|
|
url: '/merchant/v1/first-leg/pricing/estimate',
|
|
data: payload,
|
|
})
|
|
}
|
|
|
|
export function getMerchantFirstLegOrders(params: FirstLegOrderQuery = {}) {
|
|
return apiRequest<PageResult<MerchantFirstLegOrder>>({ method: 'GET', url: '/merchant/v1/orders/first-leg', params: { page: 1, size: 200, ...params } })
|
|
}
|
|
|
|
export function getMerchantFirstLegOrder(id: number | string) {
|
|
return apiRequest<MerchantFirstLegOrderDetail>({ method: 'GET', url: `/merchant/v1/orders/first-leg/${id}` })
|
|
}
|
|
|
|
export function createMerchantFirstLegOrder(payload: FirstLegOrderSaveRequest) {
|
|
return apiRequest<number | string>({
|
|
method: 'POST',
|
|
url: '/merchant/v1/orders/first-leg',
|
|
data: payload,
|
|
headers: { 'Idempotency-Key': createIdempotencyKey('first-leg-create') },
|
|
})
|
|
}
|
|
|
|
export function updateMerchantFirstLegOrder(id: number | string, payload: FirstLegOrderSaveRequest) {
|
|
return apiRequest<void>({ method: 'PUT', url: `/merchant/v1/orders/first-leg/${id}`, data: payload })
|
|
}
|
|
|
|
export function submitMerchantFirstLegOrder(id: number | string) {
|
|
return apiRequest<void>({
|
|
method: 'POST',
|
|
url: `/merchant/v1/orders/first-leg/${id}/submit`,
|
|
headers: { 'Idempotency-Key': createIdempotencyKey(`first-leg-submit-${id}`) },
|
|
})
|
|
}
|
|
|
|
function createIdempotencyKey(scope: string) {
|
|
const randomPart = globalThis.crypto?.randomUUID?.() ?? `${Date.now()}-${Math.random().toString(36).slice(2)}`
|
|
return `${scope}-${randomPart}`
|
|
}
|