feat(pl): 实现合同产品用证与额度结转以支持购买证和运输证全流程管理。
This commit is contained in:
1 parent
cb0344498a
commit
fb866c7fa7
104 files changed
+10187
-3833
No files matched your search
@@ -1,3 +1,4 @@
|
||||
import type { QuotaConfiguration, ManualQuotaQuantity } from './quota-cert'
|
||||
/**
|
||||
* 运输计划管理 API
|
||||
*/
|
||||
@@ -858,6 +859,13 @@ export interface PlanArchiveFeedbacksBlock {
|
||||
}
|
||||
|
||||
export interface PlanArchiveBody {
|
||||
operationId?: string
|
||||
quotaAllowSupplement?: boolean
|
||||
quotaConfiguration?: QuotaConfiguration
|
||||
quotaManualActuals?: ManualQuotaQuantity[]
|
||||
quotaReason?: string
|
||||
quotaEvidenceUrls?: string
|
||||
quotaSourceNote?: string
|
||||
products?: PlanArchiveProductItem[]
|
||||
load?: PlanArchiveLoadBlock
|
||||
deliveries?: PlanArchiveDeliveryBlock[]
|
||||
@@ -1165,6 +1173,9 @@ export interface TransportStopDibangOption {
|
||||
}
|
||||
|
||||
export interface TransportArrange {
|
||||
operationId?: string
|
||||
quotaConfiguration?: QuotaConfiguration
|
||||
quotaManualActuals?: ManualQuotaQuantity[]
|
||||
vehicleId: string
|
||||
driverId?: string
|
||||
escortId?: string
|
||||
|
||||
@@ -0,0 +1,270 @@
|
||||
import request, { pickBxData } from '@/utils/http/bx'
|
||||
|
||||
export type CertType = 'purchase' | 'transport'
|
||||
export interface PurchaseReference {
|
||||
id?: string
|
||||
referenceType: 'purchase_permit' | 'purchase_filing' | 'export_permit' | 'unknown'
|
||||
referenceNo: string
|
||||
purchaseCertId?: string | null
|
||||
remark?: string | null
|
||||
orderNum?: number | null
|
||||
}
|
||||
export interface CertBody {
|
||||
certNo: string
|
||||
issueDate?: string | null
|
||||
productNameOnCert: string
|
||||
totalQty: string | number
|
||||
quantityUnit: string
|
||||
validFrom?: string | null
|
||||
validTo?: string | null
|
||||
validUseText: string
|
||||
entryMode: 'manual' | 'image_parse'
|
||||
attachmentUrls?: string | null
|
||||
status?: 'draft' | 'suspended' | 'void'
|
||||
remark?: string | null
|
||||
orderNum?: number | null
|
||||
buyerName?: string | null
|
||||
buyerAddress?: string | null
|
||||
buyerLegalRepresentative?: string | null
|
||||
buyerPhone?: string | null
|
||||
sellerName?: string | null
|
||||
sellerAddress?: string | null
|
||||
sellerLegalRepresentative?: string | null
|
||||
sellerPhone?: string | null
|
||||
purchasePurpose?: string | null
|
||||
shipperName?: string | null
|
||||
shipperAddress?: string | null
|
||||
shipperLegalRepresentative?: string | null
|
||||
shipperPhone?: string | null
|
||||
packagingText?: string | null
|
||||
carrierName?: string | null
|
||||
carrierAddressPhone?: string | null
|
||||
transportMode?: string | null
|
||||
vehicleNumbersJson?: string[]
|
||||
routeText?: string | null
|
||||
consigneeName?: string | null
|
||||
applicantName?: string | null
|
||||
purchaseRefs?: PurchaseReference[]
|
||||
}
|
||||
export interface QuotaCert extends Omit<CertBody, 'status'> {
|
||||
id: string
|
||||
status: 'draft' | 'active' | 'suspended' | 'void'
|
||||
revision: number
|
||||
reservedQty: string | number
|
||||
usedQty: string | number
|
||||
availableQty: string | number
|
||||
verifiedTime?: string | null
|
||||
openingConfirmed: boolean
|
||||
usagePolicy: 'once' | 'multiple' | 'needs_confirmation'
|
||||
createTime?: string
|
||||
}
|
||||
export interface ScopeProduct {
|
||||
id?: string
|
||||
contractProductId: string
|
||||
scopeStatus?: 'active' | 'inactive'
|
||||
remark?: string | null
|
||||
orderNum?: number | null
|
||||
}
|
||||
export interface CertBinding {
|
||||
id?: string
|
||||
certType: CertType
|
||||
certId: string
|
||||
linkStatus?: 'active' | 'inactive'
|
||||
products: ScopeProduct[]
|
||||
scopeRevision?: number
|
||||
remark?: string | null
|
||||
orderNum?: number | null
|
||||
}
|
||||
export interface ContractOption {
|
||||
id: string
|
||||
contractNo: string
|
||||
contractName: string
|
||||
contractType?: string
|
||||
}
|
||||
export interface ContractProduct {
|
||||
id: string
|
||||
productId: string
|
||||
productName: string
|
||||
model?: string
|
||||
unit?: string
|
||||
quantity?: string | number
|
||||
}
|
||||
export interface LegalDocument {
|
||||
id: string
|
||||
planNo: string
|
||||
archiveStatus: string
|
||||
transportStatus: string
|
||||
products: {
|
||||
id: string
|
||||
productId: string
|
||||
productName: string
|
||||
model?: string
|
||||
legalUseCertUrl: string | null
|
||||
documentStatus: 'uploaded' | 'pending'
|
||||
contexts?: {
|
||||
stopType: string
|
||||
stopProductId: string
|
||||
partyName?: string
|
||||
address?: string
|
||||
contractId?: string
|
||||
contractNo?: string
|
||||
contractProductId?: string
|
||||
}[]
|
||||
}[]
|
||||
}
|
||||
const base = '/transport/quota-certs'
|
||||
export const quotaCertApi = {
|
||||
list: (kind: CertType, params: { keyword?: string; status?: string } = {}) =>
|
||||
request.get(`${base}/${kind}`, { params }).then(pickBxData<QuotaCert[]>),
|
||||
get: (kind: CertType, id: string) =>
|
||||
request.get(`${base}/${kind}/${id}`).then(pickBxData<QuotaCert>),
|
||||
save: (kind: CertType, body: CertBody, id?: string) =>
|
||||
(id ? request.put(`${base}/${kind}/${id}`, body) : request.post(`${base}/${kind}`, body)).then(
|
||||
pickBxData<QuotaCert>
|
||||
),
|
||||
remove: (kind: CertType, id: string) => request.delete(`${base}/${kind}/${id}`),
|
||||
confirm: (
|
||||
kind: CertType,
|
||||
id: string,
|
||||
body: {
|
||||
operationId: string
|
||||
usedQty: string
|
||||
singleUseConsumed: boolean
|
||||
reason: string
|
||||
sourceNote?: string
|
||||
evidenceUrls?: string
|
||||
}
|
||||
) => request.post(`${base}/${kind}/${id}/confirm`, body).then(pickBxData<QuotaCert>),
|
||||
verify: (kind: CertType, id: string, body: { operationId: string; reason: string }) =>
|
||||
request.post(`${base}/${kind}/${id}/verify`, body).then(pickBxData<QuotaCert>),
|
||||
recognize: (kind: CertType, attachmentUrl: string) =>
|
||||
request.post(`${base}/${kind}/recognize`, { attachmentUrl }, { timeout: 90000 }).then(
|
||||
pickBxData<{
|
||||
candidates: Partial<CertBody>
|
||||
invalidFields: Record<string, string>
|
||||
requiresConfirmation: boolean
|
||||
}>
|
||||
),
|
||||
contracts: (keyword = '') =>
|
||||
request.get(`${base}/contracts`, { params: { keyword } }).then(pickBxData<ContractOption[]>),
|
||||
products: (id: string) =>
|
||||
request.get(`${base}/contracts/${id}/products`).then(pickBxData<ContractProduct[]>),
|
||||
bindings: (id: string) =>
|
||||
request.get(`${base}/contracts/${id}/bindings`).then(pickBxData<CertBinding[]>),
|
||||
saveBindings: (id: string, bindings: CertBinding[]) =>
|
||||
request.put(`${base}/contracts/${id}/bindings`, { bindings }).then(pickBxData<CertBinding[]>),
|
||||
certificateContracts: (kind: CertType, id: string) =>
|
||||
request.get(`${base}/${kind}/${id}/contracts`).then(pickBxData<ContractOption[]>)
|
||||
}
|
||||
const legalBase = '/transport/legal-use-documents'
|
||||
export const legalDocumentApi = {
|
||||
list: (params: { keyword?: string; status?: string }) =>
|
||||
request.get(legalBase, { params }).then(pickBxData<LegalDocument[]>),
|
||||
get: (id: string) => request.get(`${legalBase}/${id}`).then(pickBxData<LegalDocument>),
|
||||
save: (id: string, products: { id: string; legalUseCertUrl?: string | null }[]) =>
|
||||
request.patch(`${legalBase}/${id}`, { products }).then(pickBxData<LegalDocument>)
|
||||
}
|
||||
|
||||
export interface QuotaSourceOption {
|
||||
sourceStopType: 'load' | 'delivery'
|
||||
sourceStopProductId: string
|
||||
planProductId: string
|
||||
productName: string
|
||||
model?: string
|
||||
quantity: string | number
|
||||
unit: string
|
||||
contractId: string
|
||||
contractProductId: string
|
||||
partyName?: string
|
||||
}
|
||||
export interface QuotaSourcePair {
|
||||
sourceStopType: 'load' | 'delivery'
|
||||
sourceStopProductId: string
|
||||
relatedStopProductIds: string[]
|
||||
}
|
||||
export interface ManualQuotaQuantity {
|
||||
permitKind: CertType
|
||||
sourceId: string
|
||||
permitId: string
|
||||
sourceQuantity: string | number
|
||||
permitQuantity: string | number
|
||||
note: string
|
||||
}
|
||||
export interface QuotaCondition {
|
||||
certType: CertType
|
||||
certId: string
|
||||
certRevision: number
|
||||
sourceFingerprint: string
|
||||
partiesConfirmed: boolean
|
||||
routeConfirmed: boolean
|
||||
note: string
|
||||
}
|
||||
export interface QuotaConfiguration {
|
||||
sourceMapping?: QuotaSourcePair[] | null
|
||||
purchaseCertIds: string[]
|
||||
transportCertIds: string[]
|
||||
manualAllocations: ManualQuotaQuantity[]
|
||||
conditions: QuotaCondition[]
|
||||
}
|
||||
export interface PlanQuota {
|
||||
planId: string
|
||||
planNo: string
|
||||
licensePlate?: string
|
||||
canSaveConfiguration?: boolean
|
||||
configuration: Partial<QuotaConfiguration>
|
||||
sourceOptions: QuotaSourceOption[]
|
||||
usages: Record<string, any>[]
|
||||
}
|
||||
export interface QuotaContext {
|
||||
sourceFingerprint: string
|
||||
sources: {
|
||||
source_stop_type: string
|
||||
source_stop_product_id: string
|
||||
quantity: string
|
||||
unit: string
|
||||
snapshot: { stops: Record<string, any>[]; vehicle?: string; trailer?: string }
|
||||
}[]
|
||||
}
|
||||
export interface QuotaPreview extends Partial<QuotaContext> {
|
||||
status: string
|
||||
reasons?: string[]
|
||||
diagnostics?: {
|
||||
certType: CertType
|
||||
sourceIds: string[]
|
||||
unit: string
|
||||
demand: string
|
||||
availableUpperBound: string | null
|
||||
gapLowerBound: string | null
|
||||
reason: string
|
||||
}[]
|
||||
purchaseAllocations?: Record<string, any>[]
|
||||
transportAllocations?: Record<string, any>[]
|
||||
}
|
||||
export const planQuotaApi = {
|
||||
get: (id: string) => request.get(`${base}/plans/${id}/usage`).then(pickBxData<PlanQuota>),
|
||||
context: (id: string, body: QuotaConfiguration & QuotaPreviewVehicle) =>
|
||||
request.post(`${base}/plans/${id}/context`, body).then(pickBxData<QuotaContext>),
|
||||
preview: (id: string, body: QuotaConfiguration & QuotaPreviewVehicle) =>
|
||||
request.post(`${base}/plans/${id}/preview`, body).then(pickBxData<QuotaPreview>),
|
||||
save: (id: string, body: QuotaConfiguration) =>
|
||||
request.put(`${base}/plans/${id}/configuration`, body).then(pickBxData<QuotaConfiguration>)
|
||||
}
|
||||
|
||||
export interface QuotaPreviewVehicle {
|
||||
targetLicensePlate?: string
|
||||
targetTrailerNo?: string | null
|
||||
}
|
||||
|
||||
export interface CertTotalAdjustment {
|
||||
operationId: string
|
||||
totalQty: string
|
||||
reason: string
|
||||
sourceNote: string
|
||||
evidenceUrls: string
|
||||
}
|
||||
export const quotaAdjustmentApi = {
|
||||
logs: (kind: CertType, id: string) =>
|
||||
request.get(`${base}/${kind}/${id}/logs`).then(pickBxData<Record<string, any>[]>),
|
||||
total: (kind: CertType, id: string, body: CertTotalAdjustment) =>
|
||||
request.post(`${base}/${kind}/${id}/total-adjust`, body)
|
||||
}
|
||||
Reference in new issue
Block a user