fix(admin): compact container departure gates
This commit is contained in:
@@ -29,7 +29,7 @@ const overview = {
|
||||
const outboundDetail = {
|
||||
aggregate: {
|
||||
containerBookingId: '2092438843630391297', cabinetNo: 'CAB-1', containerNo: 'C11111111',
|
||||
loadingPlanId: '2092438843630391401', loadingPlanStatus: 'COMPLETED', dispatchStatus: 'READY_FOR_DISPATCH', version: 4,
|
||||
loadingPlanId: '2092438843630391401', loadingPlanStatus: 'COMPLETED', truckAppointmentStatus: 'ARRIVED', dispatchStatus: 'READY_FOR_DISPATCH', version: 4,
|
||||
inbounds: [{ orderId: '11', orderNo: 'O-1', inboundId: '2092438843630391501', inboundCode: 'IN-1', tenantId: '22', inboundStatus: 'LOADED' }],
|
||||
gate: { passed: true, checkedAt: '2026-08-26T12:00:00', inbounds: [{ inboundId: '2092438843630391501', inboundCode: 'IN-1', gate: { passed: true, checkedAt: '2026-08-26T12:00:00', items: [{ code: 'CUSTOMS_CLEARANCE', name: '报关协同完成', passed: true, actual: 'COMPLETED', requirement: 'COMPLETED' }] } }] },
|
||||
},
|
||||
@@ -100,8 +100,14 @@ describe('ContainerDetailView', () => {
|
||||
expect(getContainerOutboundDispatch).toHaveBeenCalledOnce()
|
||||
expect(getContainerOutboundDispatch).toHaveBeenCalledWith('2092438843630391297')
|
||||
expect(wrapper.text()).toContain('国内出仓门禁')
|
||||
expect(wrapper.text()).toContain('报关协同完成')
|
||||
expect(wrapper.text()).toContain('IN-1')
|
||||
expect(wrapper.find('.gate-summary').text()).toContain('总门禁 1')
|
||||
expect(wrapper.find('.gate-summary').text()).toContain('已通过 1')
|
||||
expect(wrapper.find('.gate-summary').text()).toContain('阻断 0')
|
||||
expect(wrapper.find('.gate-list').text()).not.toContain('报关协同完成')
|
||||
await wrapper.find('.gate-summary button').trigger('click')
|
||||
expect(wrapper.find('.gate-list').text()).toContain('报关协同完成')
|
||||
expect(wrapper.find('.gate-list').text()).toContain('覆盖 1 个入库码')
|
||||
expect(wrapper.find('.gate-list').text()).toContain('IN-1')
|
||||
expect(wrapper.text()).toContain('确认离仓')
|
||||
wrapper.unmount()
|
||||
})
|
||||
@@ -142,14 +148,98 @@ describe('ContainerDetailView', () => {
|
||||
...outboundDetail,
|
||||
aggregate: {
|
||||
...outboundDetail.aggregate,
|
||||
gate: { passed: false, checkedAt: '2026-08-26T12:00:00', inbounds: [{ inboundId: '2092438843630391501', inboundCode: 'IN-1', gate: { passed: false, checkedAt: '2026-08-26T12:00:00', items: [{ code: 'TRUCK_DEPARTED', name: '关联拖车已离仓', passed: false, actual: 'ARRIVED', requirement: 'DEPARTED或COMPLETED' }] } }] },
|
||||
gate: { passed: false, checkedAt: '2026-08-26T12:00:00', inbounds: [{ inboundId: '2092438843630391501', inboundCode: 'IN-1', gate: { passed: false, checkedAt: '2026-08-26T12:00:00', items: [{ code: 'SAILING_SCHEDULE', name: '船期有效且未过期', passed: false, actual: 'EXPIRED', requirement: 'VALID' }] } }] },
|
||||
},
|
||||
} as never)
|
||||
const wrapper = mountView(); await flushPromises()
|
||||
expect(wrapper.text()).toContain('关联拖车已离仓')
|
||||
expect(wrapper.text()).toContain('ARRIVED')
|
||||
expect(wrapper.text()).toContain('DEPARTED或COMPLETED')
|
||||
expect(wrapper.text()).toContain('船期有效且未过期')
|
||||
expect(wrapper.text()).toContain('EXPIRED')
|
||||
expect(wrapper.text()).toContain('VALID')
|
||||
expect(wrapper.find('.outbound-panel__actions button').exists()).toBe(false)
|
||||
wrapper.unmount()
|
||||
})
|
||||
|
||||
it('deduplicates identical gates across inbounds and shows compact coverage counts', async () => {
|
||||
const blocked = { code: 'CUSTOMS_CLEARANCE', name: '报关协同完成', passed: false, actual: 'MISSING', requirement: 'COMPLETED' }
|
||||
const passed = { code: 'SAILING_SCHEDULE', name: '船期有效且未过期', passed: true, actual: 'VALID', requirement: 'VALID' }
|
||||
vi.mocked(getContainerOutboundDispatch).mockResolvedValueOnce({
|
||||
...outboundDetail,
|
||||
aggregate: {
|
||||
...outboundDetail.aggregate,
|
||||
gate: {
|
||||
passed: false,
|
||||
checkedAt: '2026-08-26T12:00:00',
|
||||
inbounds: [
|
||||
{ inboundId: '101', inboundCode: 'IN-101', gate: { passed: false, checkedAt: '2026-08-26T12:00:00', items: [blocked, passed] } },
|
||||
{ inboundId: '102', inboundCode: 'IN-102', gate: { passed: false, checkedAt: '2026-08-26T12:00:00', items: [blocked, passed] } },
|
||||
],
|
||||
},
|
||||
},
|
||||
} as never)
|
||||
const wrapper = mountView(); await flushPromises()
|
||||
expect(wrapper.find('.gate-summary').text()).toContain('总门禁 2')
|
||||
expect(wrapper.find('.gate-summary').text()).toContain('已通过 1')
|
||||
expect(wrapper.find('.gate-summary').text()).toContain('阻断 1')
|
||||
expect(wrapper.findAll('.gate-row')).toHaveLength(1)
|
||||
expect(wrapper.find('.gate-row').text()).toContain('影响 2 个入库码')
|
||||
expect(wrapper.find('.gate-row').text()).toContain('IN-101')
|
||||
expect(wrapper.find('.gate-row').text()).toContain('IN-102')
|
||||
await wrapper.find('.gate-summary button').trigger('click')
|
||||
expect(wrapper.findAll('.gate-row')).toHaveLength(2)
|
||||
expect(wrapper.findAll('.gate-row')[1]?.text()).toContain('覆盖 2 个入库码')
|
||||
wrapper.unmount()
|
||||
})
|
||||
|
||||
it('keeps different facts for the same gate code separate and labels the affected inbound', async () => {
|
||||
vi.mocked(getContainerOutboundDispatch).mockResolvedValueOnce({
|
||||
...outboundDetail,
|
||||
aggregate: {
|
||||
...outboundDetail.aggregate,
|
||||
gate: {
|
||||
passed: false,
|
||||
checkedAt: '2026-08-26T12:00:00',
|
||||
inbounds: [
|
||||
{ inboundId: '201', inboundCode: 'IN-MISSING', gate: { passed: false, checkedAt: '2026-08-26T12:00:00', items: [{ code: 'CUSTOMS_CLEARANCE', name: '报关协同完成', passed: false, actual: 'MISSING', requirement: 'COMPLETED' }] } },
|
||||
{ inboundId: '202', inboundCode: 'IN-PENDING', gate: { passed: false, checkedAt: '2026-08-26T12:00:00', items: [{ code: 'CUSTOMS_CLEARANCE', name: '报关协同完成', passed: false, actual: 'PENDING', requirement: 'COMPLETED' }] } },
|
||||
{ inboundId: '203', inboundCode: 'IN-DONE', gate: { passed: true, checkedAt: '2026-08-26T12:00:00', items: [{ code: 'CUSTOMS_CLEARANCE', name: '报关协同完成', passed: true, actual: 'COMPLETED', requirement: 'COMPLETED' }] } },
|
||||
],
|
||||
},
|
||||
},
|
||||
} as never)
|
||||
const wrapper = mountView(); await flushPromises()
|
||||
expect(wrapper.findAll('.gate-row')).toHaveLength(2)
|
||||
expect(wrapper.find('.gate-list').text()).toContain('MISSING')
|
||||
expect(wrapper.find('.gate-list').text()).toContain('IN-MISSING')
|
||||
expect(wrapper.find('.gate-list').text()).toContain('PENDING')
|
||||
expect(wrapper.find('.gate-list').text()).toContain('IN-PENDING')
|
||||
await wrapper.find('.gate-summary button').trigger('click')
|
||||
expect(wrapper.findAll('.gate-row')).toHaveLength(3)
|
||||
expect(wrapper.find('.gate-list').text()).toContain('IN-DONE')
|
||||
wrapper.unmount()
|
||||
})
|
||||
|
||||
it('keeps truck status as reference only and never counts the legacy truck gate as blocking', async () => {
|
||||
vi.mocked(getContainerOutboundDispatch).mockResolvedValueOnce({
|
||||
...outboundDetail,
|
||||
aggregate: {
|
||||
...outboundDetail.aggregate,
|
||||
truckAppointmentStatus: 'ARRIVED',
|
||||
gate: {
|
||||
passed: false,
|
||||
checkedAt: '2026-08-26T12:00:00',
|
||||
inbounds: [{ inboundId: '301', inboundCode: 'IN-301', gate: { passed: false, checkedAt: '2026-08-26T12:00:00', items: [
|
||||
{ code: 'TRUCK_DEPARTED', name: '关联拖车已离仓', passed: false, actual: 'ARRIVED', requirement: 'DEPARTED或COMPLETED' },
|
||||
{ code: 'CUSTOMS_CLEARANCE', name: '报关协同完成', passed: true, actual: 'COMPLETED', requirement: 'COMPLETED' },
|
||||
] } }],
|
||||
},
|
||||
},
|
||||
} as never)
|
||||
const wrapper = mountView(); await flushPromises()
|
||||
expect(wrapper.find('.gate-summary').text()).toContain('总门禁 1')
|
||||
expect(wrapper.find('.gate-summary').text()).toContain('阻断 0')
|
||||
expect(wrapper.find('.gate-summary').text()).toContain('拖车状态(参考):已到仓')
|
||||
expect(wrapper.text()).not.toContain('关联拖车已离仓')
|
||||
expect(wrapper.find('.outbound-panel__actions button').text()).toContain('确认离仓')
|
||||
wrapper.unmount()
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user