fix(procurement): render file download actions
This commit is contained in:
@@ -10,6 +10,7 @@ import { useAccessPreviewStore } from '@/core/access/accessPreview'
|
|||||||
import { useAuthStore } from '@/core/auth/auth'
|
import { useAuthStore } from '@/core/auth/auth'
|
||||||
import { listPlatformTenants } from '@/modules/iam'
|
import { listPlatformTenants } from '@/modules/iam'
|
||||||
import type { PlatformProcurement } from '../procurementTypes'
|
import type { PlatformProcurement } from '../procurementTypes'
|
||||||
|
import { downloadProcurementFile } from '../api/procurementCommands'
|
||||||
import type { FleetArrangement } from '../fleetArrangement'
|
import type { FleetArrangement } from '../fleetArrangement'
|
||||||
import type { LocalLooseboardDetail, LocalLooseboardOrder, LocalTransportDetail, LocalTransportOrder } from '../types'
|
import type { LocalLooseboardDetail, LocalLooseboardOrder, LocalTransportDetail, LocalTransportOrder } from '../types'
|
||||||
import {
|
import {
|
||||||
@@ -29,6 +30,10 @@ const purchaseDetailSource = readFileSync(resolve(process.cwd(), 'src/modules/ov
|
|||||||
const routing = vi.hoisted(() => ({ push: vi.fn(), route: { params: {} as Record<string, string>, query: {} as Record<string, string> } }))
|
const routing = vi.hoisted(() => ({ push: vi.fn(), route: { params: {} as Record<string, string>, query: {} as Record<string, string> } }))
|
||||||
vi.mock('vue-router', () => ({ useRoute: () => routing.route, useRouter: () => ({ push: routing.push }) }))
|
vi.mock('vue-router', () => ({ useRoute: () => routing.route, useRouter: () => ({ push: routing.push }) }))
|
||||||
vi.mock('@/modules/iam', () => ({ listPlatformTenants: vi.fn() }))
|
vi.mock('@/modules/iam', () => ({ listPlatformTenants: vi.fn() }))
|
||||||
|
vi.mock('../api/procurementCommands', async importOriginal => ({
|
||||||
|
...await importOriginal<typeof import('../api/procurementCommands')>(),
|
||||||
|
downloadProcurementFile: vi.fn(),
|
||||||
|
}))
|
||||||
vi.mock('../api/platformOverseasBusiness', () => ({
|
vi.mock('../api/platformOverseasBusiness', () => ({
|
||||||
listOverseasPurchases: vi.fn(), getOverseasPurchase: vi.fn(), getOverseasPurchaseEditor: vi.fn(), updateOverseasPurchase: vi.fn(), listOverseasPurchaseCustomerOptions: vi.fn(), listOverseasPurchaseWarehouseOptions: vi.fn(),
|
listOverseasPurchases: vi.fn(), getOverseasPurchase: vi.fn(), getOverseasPurchaseEditor: vi.fn(), updateOverseasPurchase: vi.fn(), listOverseasPurchaseCustomerOptions: vi.fn(), listOverseasPurchaseWarehouseOptions: vi.fn(),
|
||||||
listUsTruckOrders: vi.fn(), getUsTruckOrder: vi.fn(), createUsTruckOrder: vi.fn(), updateUsTruckOrder: vi.fn(),
|
listUsTruckOrders: vi.fn(), getUsTruckOrder: vi.fn(), createUsTruckOrder: vi.fn(), updateUsTruckOrder: vi.fn(),
|
||||||
@@ -64,6 +69,7 @@ describe('overseas business mounted pages', () => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
vi.stubGlobal('ResizeObserver', ResizeObserverStub); vi.stubGlobal('localStorage', memoryStorage()); vi.stubGlobal('sessionStorage', memoryStorage()); document.body.innerHTML = ''
|
vi.stubGlobal('ResizeObserver', ResizeObserverStub); vi.stubGlobal('localStorage', memoryStorage()); vi.stubGlobal('sessionStorage', memoryStorage()); document.body.innerHTML = ''
|
||||||
routing.push.mockReset(); routing.route.params = {}; routing.route.query = {}
|
routing.push.mockReset(); routing.route.params = {}; routing.route.query = {}
|
||||||
|
vi.mocked(downloadProcurementFile).mockReset()
|
||||||
vi.mocked(listOverseasPurchases).mockReset().mockResolvedValue({ records: [purchase], page: 1, size: 20, total: 1, pages: 1 }); vi.mocked(getOverseasPurchase).mockReset().mockResolvedValue(procurementDetail()); vi.mocked(updateOverseasPurchase).mockReset().mockResolvedValue({ ...purchase, version: 4 })
|
vi.mocked(listOverseasPurchases).mockReset().mockResolvedValue({ records: [purchase], page: 1, size: 20, total: 1, pages: 1 }); vi.mocked(getOverseasPurchase).mockReset().mockResolvedValue(procurementDetail()); vi.mocked(updateOverseasPurchase).mockReset().mockResolvedValue({ ...purchase, version: 4 })
|
||||||
vi.mocked(getOverseasPurchaseEditor).mockReset().mockResolvedValue({ customerView: { order: { orderNo: purchase.orderNo, customerId: purchase.customerId, productName: purchase.productName, purchaseQuantity: purchase.purchaseQuantity, version: purchase.version } }, internalRemark: purchase.remark })
|
vi.mocked(getOverseasPurchaseEditor).mockReset().mockResolvedValue({ customerView: { order: { orderNo: purchase.orderNo, customerId: purchase.customerId, productName: purchase.productName, purchaseQuantity: purchase.purchaseQuantity, version: purchase.version } }, internalRemark: purchase.remark })
|
||||||
vi.mocked(listOverseasPurchaseCustomerOptions).mockReset().mockResolvedValue([{ customerId: '10001', customerName: '客户甲' }]); vi.mocked(listOverseasPurchaseWarehouseOptions).mockReset().mockResolvedValue([{ warehouseId: '20001', warehouseCode: 'LAX', warehouseName: '洛杉矶采购仓', countryCode: 'US' }])
|
vi.mocked(listOverseasPurchaseCustomerOptions).mockReset().mockResolvedValue([{ customerId: '10001', customerName: '客户甲' }]); vi.mocked(listOverseasPurchaseWarehouseOptions).mockReset().mockResolvedValue([{ warehouseId: '20001', warehouseCode: 'LAX', warehouseName: '洛杉矶采购仓', countryCode: 'US' }])
|
||||||
@@ -166,6 +172,28 @@ describe('overseas business mounted pages', () => {
|
|||||||
expect(routing.push).toHaveBeenCalledWith({ name: 'overseas-business-purchases' })
|
expect(routing.push).toHaveBeenCalledWith({ name: 'overseas-business-purchases' })
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('downloads procurement files with list access and prevents duplicate pending downloads', async () => {
|
||||||
|
routing.route.params = { purchaseId: 'OP-100' }; routing.route.query = { customerId: '10001' }
|
||||||
|
const result = procurementDetail()
|
||||||
|
result.files = [{ id: '9007199254741000', fileId: '9007199254741001', category: 'LABEL', fileName: 'label.pdf', contentType: 'application/pdf', sizeBytes: 123, createdAt: '2026-10-10T10:00:00' }]
|
||||||
|
vi.mocked(getOverseasPurchase).mockResolvedValue(result)
|
||||||
|
let rejectDownload!: (error: Error) => void
|
||||||
|
vi.mocked(downloadProcurementFile).mockImplementation(() => new Promise((_resolve, reject) => { rejectDownload = reject }))
|
||||||
|
const wrapper = mountPage(PurchaseOrderDetailView)
|
||||||
|
useAuthStore().permissions = ['platform:overseas-business:purchase:list']
|
||||||
|
await flushPromises()
|
||||||
|
const button = wrapper.findAll('.el-table__body-wrapper button').find(item => item.text() === '下载')
|
||||||
|
expect(button).toBeDefined()
|
||||||
|
await button!.trigger('click'); await flushPromises()
|
||||||
|
expect(downloadProcurementFile).toHaveBeenCalledWith('OP-100', '10001', '9007199254741001')
|
||||||
|
expect(button!.attributes('disabled')).toBeDefined()
|
||||||
|
await button!.trigger('click')
|
||||||
|
expect(downloadProcurementFile).toHaveBeenCalledTimes(1)
|
||||||
|
rejectDownload(new Error('TEST download unavailable')); await flushPromises()
|
||||||
|
expect(button!.attributes('disabled')).toBeUndefined()
|
||||||
|
expect(document.body.textContent).toContain('文件下载失败')
|
||||||
|
})
|
||||||
|
|
||||||
it('renders estimate holds separately from actual payment without claiming inbound settlement', async () => {
|
it('renders estimate holds separately from actual payment without claiming inbound settlement', async () => {
|
||||||
routing.route.params = { purchaseId: 'OP-100' }; routing.route.query = { customerId: '10001' }
|
routing.route.params = { purchaseId: 'OP-100' }; routing.route.query = { customerId: '10001' }
|
||||||
const result = procurementDetail()
|
const result = procurementDetail()
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ const correctionColumns: DataTableColumn[] = [
|
|||||||
{ key: 'feeNos', label: '关联实际费用或调整', minWidth: 240, formatter: (row: PlatformProcurement['feeCorrections'][number]) => row.feeNos.join(';') || '无资金差额' },
|
{ key: 'feeNos', label: '关联实际费用或调整', minWidth: 240, formatter: (row: PlatformProcurement['feeCorrections'][number]) => row.feeNos.join(';') || '无资金差额' },
|
||||||
]
|
]
|
||||||
const fileColumns: DataTableColumn[] = [
|
const fileColumns: DataTableColumn[] = [
|
||||||
{ key: 'actions', label: '操作', width: 90, fixed: 'left' }, { key: 'fileName', prop: 'fileName', label: '文件名', minWidth: 250 },
|
{ key: 'actions', slotName: 'actions', label: '操作', width: 90, fixed: 'left' }, { key: 'fileName', prop: 'fileName', label: '文件名', minWidth: 250 },
|
||||||
{ key: 'category', label: '用途', width: 120, formatter: (row: ProcurementFile) => fileLabels[row.category] || '待核对' },
|
{ key: 'category', label: '用途', width: 120, formatter: (row: ProcurementFile) => fileLabels[row.category] || '待核对' },
|
||||||
{ key: 'createdAt', label: '上传时间', minWidth: 160, formatter: (row: ProcurementFile) => dateTime(row.createdAt) },
|
{ key: 'createdAt', label: '上传时间', minWidth: 160, formatter: (row: ProcurementFile) => dateTime(row.createdAt) },
|
||||||
]
|
]
|
||||||
|
|||||||
Reference in New Issue
Block a user