优化
This commit is contained in:
@@ -0,0 +1,165 @@
|
||||
function valueAt(record, path) {
|
||||
return path.split('.').reduce((value, key) => value?.[key], record)
|
||||
}
|
||||
|
||||
export function isPositiveId(value) {
|
||||
return /^\d+$/.test(String(value ?? '')) && BigInt(String(value)) > 0n
|
||||
}
|
||||
|
||||
export function isNonBlank(value) {
|
||||
return typeof value === 'string' && value.trim().length > 0
|
||||
}
|
||||
|
||||
export function isIsoDateTime(value) {
|
||||
return isNonBlank(value) && Number.isFinite(Date.parse(value))
|
||||
}
|
||||
|
||||
export function isNonNegativeNumber(value) {
|
||||
return value !== null && value !== '' && Number.isFinite(Number(value)) && Number(value) >= 0
|
||||
}
|
||||
|
||||
function gaps(record, rules) {
|
||||
return Object.entries(rules)
|
||||
.filter(([path, predicate]) => !predicate(valueAt(record, path), record))
|
||||
.map(([path]) => path)
|
||||
}
|
||||
|
||||
export function containerFieldGaps(record, { requireContainerNo = false } = {}) {
|
||||
return gaps(record, {
|
||||
id: isPositiveId,
|
||||
cabinetNo: isNonBlank,
|
||||
warehouseId: isPositiveId,
|
||||
warehouseName: isNonBlank,
|
||||
channelCode: isNonBlank,
|
||||
containerType: isNonBlank,
|
||||
capacityCbm: (value) => Number(value) > 0,
|
||||
maxWeightKg: (value) => Number(value) > 0,
|
||||
planStatus: isNonBlank,
|
||||
...(requireContainerNo ? { containerNo: isNonBlank } : {}),
|
||||
})
|
||||
}
|
||||
|
||||
export function preloadFieldGaps(record) {
|
||||
return gaps(record, {
|
||||
planId: isPositiveId,
|
||||
containerBookingId: isPositiveId,
|
||||
preloadNo: isNonBlank,
|
||||
cabinetNo: isNonBlank,
|
||||
customers: (value) => Array.isArray(value) && value.length > 0
|
||||
&& value.every((customer) => isPositiveId(customer?.accountId) && isNonBlank(customer?.customerName)),
|
||||
warehouseName: isNonBlank,
|
||||
containerType: isNonBlank,
|
||||
status: isNonBlank,
|
||||
skuCount: isNonNegativeNumber,
|
||||
totalPackageCount: isNonNegativeNumber,
|
||||
totalVolumeCbm: isNonNegativeNumber,
|
||||
totalGrossWeightKg: isNonNegativeNumber,
|
||||
createdAt: isIsoDateTime,
|
||||
})
|
||||
}
|
||||
|
||||
export function loadingListFieldGaps(record) {
|
||||
return gaps(record, {
|
||||
planId: isPositiveId,
|
||||
containerBookingId: isPositiveId,
|
||||
loadingListNo: isNonBlank,
|
||||
containerNo: isNonBlank,
|
||||
cabinetNo: isNonBlank,
|
||||
warehouseName: isNonBlank,
|
||||
status: (value) => value === 'COMPLETED',
|
||||
totalPackageCount: isNonNegativeNumber,
|
||||
totalGrossWeightKg: isNonNegativeNumber,
|
||||
totalNetWeightKg: isNonNegativeNumber,
|
||||
totalVolumeCbm: isNonNegativeNumber,
|
||||
totalQuantity: isNonNegativeNumber,
|
||||
createdAt: isIsoDateTime,
|
||||
})
|
||||
}
|
||||
|
||||
export function oceanBookingFieldGaps(record) {
|
||||
return gaps(record, {
|
||||
id: isPositiveId,
|
||||
bookingNo: isNonBlank,
|
||||
status: (value) => ['CONFIRMED', 'CHANGE_PENDING', 'RELEASED', 'CANCELLED'].includes(value),
|
||||
vesselName: isNonBlank,
|
||||
voyageNo: isNonBlank,
|
||||
estimatedSailingAt: isIsoDateTime,
|
||||
estimatedArrivalAt: isIsoDateTime,
|
||||
customerName: (value, item) => item.customerId == null ? value == null : isNonBlank(value),
|
||||
shippingCompanyName: (value, item) => item.shippingCompanyId == null ? value == null : isNonBlank(value),
|
||||
bookingAgentName: (value, item) => item.bookingAgentId == null ? value == null : isNonBlank(value),
|
||||
})
|
||||
}
|
||||
|
||||
export function portScheduleFieldGaps(record) {
|
||||
const view = record?.portSchedule ?? record
|
||||
const schedule = view?.schedule ?? view
|
||||
return gaps(schedule, {
|
||||
id: isPositiveId,
|
||||
scheduleNo: isNonBlank,
|
||||
sourceName: isNonBlank,
|
||||
vesselName: isNonBlank,
|
||||
voyageNo: isNonBlank,
|
||||
departurePortCode: isNonBlank,
|
||||
destinationPortCode: isNonBlank,
|
||||
etdAt: isIsoDateTime,
|
||||
etaAt: isIsoDateTime,
|
||||
observedAt: isIsoDateTime,
|
||||
updatedAt: isIsoDateTime,
|
||||
expiresAt: isIsoDateTime,
|
||||
}).concat(typeof view?.expired === 'boolean' ? [] : ['expired'])
|
||||
}
|
||||
|
||||
export function truckAppointmentFieldGaps(record) {
|
||||
return gaps(record, {
|
||||
id: isPositiveId,
|
||||
appointmentNo: isNonBlank,
|
||||
oceanBookingId: isPositiveId,
|
||||
containerBookingId: isPositiveId,
|
||||
loadingPlanId: isPositiveId,
|
||||
warehouseId: isPositiveId,
|
||||
warehouseName: isNonBlank,
|
||||
plannedLoadingAt: isIsoDateTime,
|
||||
status: isNonBlank,
|
||||
customerName: (value, item) => item.customerId == null ? value == null : isNonBlank(value),
|
||||
carrierName: (value, item) => item.carrierId == null ? value == null : isNonBlank(value),
|
||||
})
|
||||
}
|
||||
|
||||
export function customsCaseFieldGaps(record) {
|
||||
const customsCase = record?.customsCase ?? record?.case ?? record
|
||||
return gaps(customsCase, {
|
||||
id: isPositiveId,
|
||||
customsNo: isNonBlank,
|
||||
orderId: isPositiveId,
|
||||
inboundId: isPositiveId,
|
||||
containerBookingId: isPositiveId,
|
||||
checklistVersionId: isPositiveId,
|
||||
checklistCode: isNonBlank,
|
||||
checklistVersionNo: isNonBlank,
|
||||
status: isNonBlank,
|
||||
updatedAt: isIsoDateTime,
|
||||
})
|
||||
}
|
||||
|
||||
export function outboundAggregateFieldGaps(record) {
|
||||
const aggregate = record?.aggregate ?? record
|
||||
return gaps(aggregate, {
|
||||
orderId: isPositiveId,
|
||||
inboundId: isPositiveId,
|
||||
inboundCode: isNonBlank,
|
||||
customerId: isPositiveId,
|
||||
customerName: isNonBlank,
|
||||
containerBookingId: isPositiveId,
|
||||
containerNo: isNonBlank,
|
||||
loadingPlanId: isPositiveId,
|
||||
loadingPlanStatus: isNonBlank,
|
||||
pickTaskId: isPositiveId,
|
||||
pickTaskStatus: isNonBlank,
|
||||
oceanBookingId: isPositiveId,
|
||||
oceanBookingStatus: isNonBlank,
|
||||
dispatchStatus: isNonBlank,
|
||||
version: isNonNegativeNumber,
|
||||
'gate.items': (value) => Array.isArray(value),
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user