提交
This commit is contained in:
1 parent
67d37a1f0e
commit
54a1ba0c5c
21 files changed
+8646
-7577
No files matched your search
@@ -0,0 +1,59 @@
|
||||
import assert from 'node:assert/strict'
|
||||
import { describe, it } from 'node:test'
|
||||
import {
|
||||
canManualToggleStopDibang,
|
||||
resolveStopDibangDefaults
|
||||
} from './pl-plan-stop-form'
|
||||
import { isPlDibangOptionalVehiclePlate } from './pl-internal-customer'
|
||||
|
||||
const INTERNAL = '安庆市山峡化工有限公司'
|
||||
const YUNDONG = '安徽云栋化工有限公司'
|
||||
const EXTERNAL = '某某贸易有限公司'
|
||||
const OPTIONAL_PLATE = '皖H21522'
|
||||
|
||||
describe('isPlDibangOptionalVehiclePlate', () => {
|
||||
it('matches exact main plate', () => {
|
||||
assert.equal(isPlDibangOptionalVehiclePlate(OPTIONAL_PLATE), true)
|
||||
assert.equal(isPlDibangOptionalVehiclePlate(` ${OPTIONAL_PLATE} `), true)
|
||||
})
|
||||
|
||||
it('rejects other plates', () => {
|
||||
assert.equal(isPlDibangOptionalVehiclePlate('皖A12345'), false)
|
||||
assert.equal(isPlDibangOptionalVehiclePlate(''), false)
|
||||
})
|
||||
})
|
||||
|
||||
describe('resolveStopDibangDefaults + canManualToggleStopDibang', () => {
|
||||
it('internal + normal vehicle: auto-check, not manual', () => {
|
||||
assert.deepEqual(resolveStopDibangDefaults(INTERNAL, 'load', '皖A11111'), {
|
||||
generateDibang: 1,
|
||||
dibangDirection: 'outbound'
|
||||
})
|
||||
assert.deepEqual(resolveStopDibangDefaults(YUNDONG, 'delivery', '皖A11111'), {
|
||||
generateDibang: 1,
|
||||
dibangDirection: 'inbound'
|
||||
})
|
||||
assert.equal(canManualToggleStopDibang(INTERNAL, '皖A11111'), false)
|
||||
})
|
||||
|
||||
it('internal + optional vehicle: unchecked, manual allowed', () => {
|
||||
assert.deepEqual(resolveStopDibangDefaults(INTERNAL, 'load', OPTIONAL_PLATE), {
|
||||
generateDibang: 0,
|
||||
dibangDirection: 'none'
|
||||
})
|
||||
assert.deepEqual(resolveStopDibangDefaults(YUNDONG, 'delivery', OPTIONAL_PLATE), {
|
||||
generateDibang: 0,
|
||||
dibangDirection: 'none'
|
||||
})
|
||||
assert.equal(canManualToggleStopDibang(INTERNAL, OPTIONAL_PLATE), true)
|
||||
assert.equal(canManualToggleStopDibang(YUNDONG, OPTIONAL_PLATE), true)
|
||||
})
|
||||
|
||||
it('external + optional vehicle: still locked off', () => {
|
||||
assert.deepEqual(resolveStopDibangDefaults(EXTERNAL, 'load', OPTIONAL_PLATE), {
|
||||
generateDibang: 0,
|
||||
dibangDirection: 'none'
|
||||
})
|
||||
assert.equal(canManualToggleStopDibang(EXTERNAL, OPTIONAL_PLATE), false)
|
||||
})
|
||||
})
|
||||
@@ -4,11 +4,22 @@ export const PL_INTERNAL_CUSTOMER_NAMES = [
|
||||
'安徽云栋化工有限公司'
|
||||
] as const
|
||||
|
||||
/**
|
||||
* 地磅单「可选」车辆主牌:内部客户时默认不勾且允许手动勾选。
|
||||
* 匹配主牌精确值(不含挂车拼接)。
|
||||
*/
|
||||
export const PL_DIBANG_OPTIONAL_VEHICLE_PLATES = ['皖H21522'] as const
|
||||
|
||||
export function isPlInternalCustomerName(name?: string | null): boolean {
|
||||
const n = (name || '').trim()
|
||||
return (PL_INTERNAL_CUSTOMER_NAMES as readonly string[]).includes(n)
|
||||
}
|
||||
|
||||
export function isPlDibangOptionalVehiclePlate(plate?: string | null): boolean {
|
||||
const p = (plate || '').trim()
|
||||
return (PL_DIBANG_OPTIONAL_VEHICLE_PLATES as readonly string[]).includes(p)
|
||||
}
|
||||
|
||||
/** 装货或送货段任一段客户为山峡/云栋时,需要现场链接。 */
|
||||
export function planRequiresSiteLink(
|
||||
plan?: {
|
||||
|
||||
@@ -2,7 +2,10 @@ import type { Plan, PlanContractLink, PlanDelivery, PlanLoad, PlanStopProduct }
|
||||
import type { PlanFormProductRow } from '@/composables/usePlContractToPlan'
|
||||
import type { BrandOption } from '@/utils/crm-product-brand'
|
||||
import { formatBrandConstraintLabel } from '@/utils/crm-product-brand'
|
||||
import { isPlInternalCustomerName } from '@/utils/pl-internal-customer'
|
||||
import {
|
||||
isPlDibangOptionalVehiclePlate,
|
||||
isPlInternalCustomerName
|
||||
} from '@/utils/pl-internal-customer'
|
||||
|
||||
export interface PlanStopProductFormRow {
|
||||
id?: string
|
||||
@@ -111,27 +114,45 @@ export interface PlanDeliveryForm {
|
||||
products: PlanStopProductFormRow[]
|
||||
}
|
||||
|
||||
/** 地磅勾选仅对内部客户(山峡/云栋)生效:默认勾选且不可改;其他客户默认不勾且不可勾。 */
|
||||
/**
|
||||
* 地磅勾选规则:
|
||||
* - 内部客户(山峡/云栋):默认勾选且不可改
|
||||
* - 地磅可选车(如皖H21522)+ 内部客户:默认不勾,可手动勾选
|
||||
* - 其他客户:默认不勾且不可勾
|
||||
*/
|
||||
export function resolveStopDibangDefaults(
|
||||
customerName?: string | null,
|
||||
stopType: 'load' | 'delivery' = 'load'
|
||||
stopType: 'load' | 'delivery' = 'load',
|
||||
vehiclePlate?: string | null
|
||||
): { generateDibang: number; dibangDirection: string } {
|
||||
if (!isPlInternalCustomerName(customerName)) {
|
||||
return { generateDibang: 0, dibangDirection: 'none' }
|
||||
}
|
||||
if (isPlDibangOptionalVehiclePlate(vehiclePlate)) {
|
||||
return { generateDibang: 0, dibangDirection: 'none' }
|
||||
}
|
||||
if (stopType === 'load') {
|
||||
return { generateDibang: 1, dibangDirection: 'outbound' }
|
||||
}
|
||||
return { generateDibang: 1, dibangDirection: 'inbound' }
|
||||
}
|
||||
|
||||
/** 仅「内部客户 + 地磅可选车」允许用户手动勾选地磅单 */
|
||||
export function canManualToggleStopDibang(
|
||||
customerName?: string | null,
|
||||
vehiclePlate?: string | null
|
||||
): boolean {
|
||||
return isPlInternalCustomerName(customerName) && isPlDibangOptionalVehiclePlate(vehiclePlate)
|
||||
}
|
||||
|
||||
function normalizeStopDibangFieldsFromApi(
|
||||
customerName: string | null | undefined,
|
||||
stopType: 'load' | 'delivery',
|
||||
generateDibang?: number | null,
|
||||
dibangDirection?: string | null
|
||||
dibangDirection?: string | null,
|
||||
vehiclePlate?: string | null
|
||||
): { generateDibang: number; dibangDirection: string } {
|
||||
const defaults = resolveStopDibangDefaults(customerName, stopType)
|
||||
const defaults = resolveStopDibangDefaults(customerName, stopType, vehiclePlate)
|
||||
// 非山峡/云栋:禁止生成地磅单(编辑回填也强制清掉历史勾选)
|
||||
if (!isPlInternalCustomerName(customerName)) {
|
||||
return { generateDibang: 0, dibangDirection: 'none' }
|
||||
@@ -140,7 +161,8 @@ function normalizeStopDibangFieldsFromApi(
|
||||
let direction = (dibangDirection || '').trim()
|
||||
if (gen) {
|
||||
if (direction !== 'outbound' && direction !== 'inbound') {
|
||||
direction = defaults.dibangDirection
|
||||
// 可选车默认 direction 为 none,勾选回填时按段类型补方向
|
||||
direction = stopType === 'load' ? 'outbound' : 'inbound'
|
||||
}
|
||||
} else {
|
||||
direction = 'none'
|
||||
@@ -409,13 +431,17 @@ export function resolveDeliveryViewAddress(
|
||||
return ''
|
||||
}
|
||||
|
||||
export function mapLoadFromApi(load?: PlanLoad | null): PlanLoadForm {
|
||||
export function mapLoadFromApi(
|
||||
load?: PlanLoad | null,
|
||||
vehiclePlate?: string | null
|
||||
): PlanLoadForm {
|
||||
if (!load) return createEmptyLoadForm()
|
||||
const dibang = normalizeStopDibangFieldsFromApi(
|
||||
load.customerName,
|
||||
'load',
|
||||
load.generateDibang,
|
||||
load.dibangDirection
|
||||
load.dibangDirection,
|
||||
vehiclePlate
|
||||
)
|
||||
return {
|
||||
customerId: load.customerId || '',
|
||||
@@ -436,14 +462,18 @@ export function mapLoadFromApi(load?: PlanLoad | null): PlanLoadForm {
|
||||
}
|
||||
}
|
||||
|
||||
export function mapDeliveriesFromApi(deliveries?: PlanDelivery[]): PlanDeliveryForm[] {
|
||||
export function mapDeliveriesFromApi(
|
||||
deliveries?: PlanDelivery[],
|
||||
vehiclePlate?: string | null
|
||||
): PlanDeliveryForm[] {
|
||||
if (!deliveries?.length) return [createEmptyDeliveryForm(1)]
|
||||
return deliveries.map((row, index) => {
|
||||
const dibang = normalizeStopDibangFieldsFromApi(
|
||||
row.customerName,
|
||||
'delivery',
|
||||
row.generateDibang,
|
||||
row.dibangDirection
|
||||
row.dibangDirection,
|
||||
vehiclePlate
|
||||
)
|
||||
return {
|
||||
seq: row.seq ?? index + 1,
|
||||
@@ -471,8 +501,9 @@ export function mapLegacyPlanToStops(plan: Plan): {
|
||||
load: PlanLoadForm
|
||||
deliveries: PlanDeliveryForm[]
|
||||
} {
|
||||
const loadDefaults = resolveStopDibangDefaults(plan.supplierName, 'load')
|
||||
const deliveryDefaults = resolveStopDibangDefaults(plan.customerName, 'delivery')
|
||||
const plate = plan.licensePlate
|
||||
const loadDefaults = resolveStopDibangDefaults(plan.supplierName, 'load', plate)
|
||||
const deliveryDefaults = resolveStopDibangDefaults(plan.customerName, 'delivery', plate)
|
||||
const stopProducts = createStopProductsFromPlanProducts(
|
||||
(plan.products || []).map((item, index) => ({
|
||||
id: item.id,
|
||||
|
||||
Reference in new issue
Block a user