Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d413398b3d | ||
|
|
6be55186b0 | ||
|
|
348c5c1d3c | ||
|
|
411a4cb57c |
No files matched your search
@@ -879,6 +879,20 @@ def list_donations(
|
|||||||
if t.express_company_id
|
if t.express_company_id
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
from app.crud import sample_freight as sample_freight_svc
|
||||||
|
|
||||||
|
all_list_sample_ids = [
|
||||||
|
s.id
|
||||||
|
for samples in sample_map.values()
|
||||||
|
for s in samples
|
||||||
|
if getattr(s, "id", None)
|
||||||
|
]
|
||||||
|
freight_by_sample = sample_freight_svc.freight_map_for_samples(
|
||||||
|
db,
|
||||||
|
tenant_no=tenant_no,
|
||||||
|
sample_source=sample_freight_svc.SAMPLE_SOURCE_DONATION,
|
||||||
|
sample_ids=all_list_sample_ids,
|
||||||
|
)
|
||||||
|
|
||||||
result = []
|
result = []
|
||||||
for r in rows:
|
for r in rows:
|
||||||
@@ -957,11 +971,13 @@ def list_donations(
|
|||||||
}
|
}
|
||||||
sample_items.append(
|
sample_items.append(
|
||||||
{
|
{
|
||||||
|
"id": s.id,
|
||||||
"sampleTypeName": type_name,
|
"sampleTypeName": type_name,
|
||||||
"sampleCode": code,
|
"sampleCode": code,
|
||||||
"sampleStatus": (s.sample_status or "").strip(),
|
"sampleStatus": (s.sample_status or "").strip(),
|
||||||
"labStorageCode": lab_code_map.get(code, "") if code else "",
|
"labStorageCode": lab_code_map.get(code, "") if code else "",
|
||||||
"transport": transport_dict,
|
"transport": transport_dict,
|
||||||
|
"freight": freight_by_sample.get(s.id),
|
||||||
**sample_special_to_dict(s),
|
**sample_special_to_dict(s),
|
||||||
**build_sample_item_reception_qc_fields(
|
**build_sample_item_reception_qc_fields(
|
||||||
reception_summary_map.get(code) if code else None,
|
reception_summary_map.get(code) if code else None,
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import {
|
|||||||
RESEARCH_HEADERS,
|
RESEARCH_HEADERS,
|
||||||
buildCellStorageLedgerRows,
|
buildCellStorageLedgerRows,
|
||||||
buildCustomerServiceLedgerRows,
|
buildCustomerServiceLedgerRows,
|
||||||
|
buildFreightMergeRanges,
|
||||||
buildPresignLedgerRows,
|
buildPresignLedgerRows,
|
||||||
buildResearchLedgerRows,
|
buildResearchLedgerRows,
|
||||||
formatLedgerDateTime
|
formatLedgerDateTime
|
||||||
@@ -141,19 +142,99 @@ describe('buildResearchLedgerRows', () => {
|
|||||||
birthOrder: 1,
|
birthOrder: 1,
|
||||||
maternalBloodCollectTime: '2025-08-29 13:30:00',
|
maternalBloodCollectTime: '2025-08-29 13:30:00',
|
||||||
consentFormUrls: 'http://example/consent',
|
consentFormUrls: 'http://example/consent',
|
||||||
remark: ''
|
remark: '',
|
||||||
|
freightId: 'fr1',
|
||||||
|
freightTransportLabel: '专线车',
|
||||||
|
freightAmountLabel: '100'
|
||||||
} as unknown as ProtocolAuditFlatRow
|
} as unknown as ProtocolAuditFlatRow
|
||||||
const [row] = buildResearchLedgerRows([flat])
|
const { rows } = buildResearchLedgerRows([flat])
|
||||||
|
const row = rows[0]
|
||||||
assert.equal(row.length, RESEARCH_HEADERS.length)
|
assert.equal(row.length, RESEARCH_HEADERS.length)
|
||||||
assert.equal(row[1], '2025年')
|
assert.equal(row[1], '2025年')
|
||||||
assert.equal(row[4], '202508001')
|
assert.equal(row[4], '202508001')
|
||||||
assert.equal(row[6], '已作废(实验室废弃)')
|
assert.equal(row[6], '实验室废弃')
|
||||||
assert.equal(row[7], '母血乙肝阳性')
|
assert.equal(row[7], '母血乙肝阳性')
|
||||||
|
assert.equal(row[16], '专线车')
|
||||||
|
assert.equal(row[17], '100')
|
||||||
assert.equal(row[18], '女')
|
assert.equal(row[18], '女')
|
||||||
assert.equal(row[19], '3000g')
|
assert.equal(row[19], '3000g')
|
||||||
assert.equal(row[20], '顺产')
|
assert.equal(row[20], '顺产')
|
||||||
assert.equal(row[23], '1')
|
assert.equal(row[23], '1')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('maps sdfq void type code to 属地废弃 labels', () => {
|
||||||
|
const flat = {
|
||||||
|
protocol: {
|
||||||
|
donationStatus: 'yzf',
|
||||||
|
voidType: 'sdfq',
|
||||||
|
voidDesc: '',
|
||||||
|
monthlyVerifyNo: ''
|
||||||
|
},
|
||||||
|
sampleIndex: 0,
|
||||||
|
sampleCollectTime: '2025-08-29 12:27:00',
|
||||||
|
motherName: '测试',
|
||||||
|
sampleTypeName: '围产期造血干细胞',
|
||||||
|
regionName: '亳州',
|
||||||
|
hospitalName: '涡阳县人民医院',
|
||||||
|
labStorageCode: 'A0000002',
|
||||||
|
salesUserName: '',
|
||||||
|
regionManagerUserName: '',
|
||||||
|
transportType: '',
|
||||||
|
newbornDeliveryTime: '',
|
||||||
|
newbornSex: '',
|
||||||
|
newbornWeightGram: '',
|
||||||
|
deliveryMode: 'pgc',
|
||||||
|
birthOrder: '',
|
||||||
|
maternalBloodCollectTime: '',
|
||||||
|
consentFormUrls: '',
|
||||||
|
remark: '',
|
||||||
|
freightId: '',
|
||||||
|
freightTransportLabel: '',
|
||||||
|
freightAmountLabel: ''
|
||||||
|
} as unknown as ProtocolAuditFlatRow
|
||||||
|
const { rows } = buildResearchLedgerRows([flat])
|
||||||
|
const row = rows[0]
|
||||||
|
assert.equal(row[6], '属地废弃')
|
||||||
|
assert.equal(row[7], '属地废弃')
|
||||||
|
assert.equal(row[20], '剖腹产')
|
||||||
|
assert.equal(row[22], '无母血')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('merges transport and freight columns for the same freight batch', () => {
|
||||||
|
const base = {
|
||||||
|
protocol: { donationStatus: 'sxz', voidType: '', voidDesc: '', monthlyVerifyNo: '' },
|
||||||
|
sampleCollectTime: '2025-09-11 18:13:00',
|
||||||
|
motherName: '甲',
|
||||||
|
sampleTypeName: 'NK',
|
||||||
|
regionName: '常州',
|
||||||
|
hospitalName: '溧阳市人民医院',
|
||||||
|
labStorageCode: 'UBMC1',
|
||||||
|
freightId: 'batch-a',
|
||||||
|
freightTransportLabel: '专线车',
|
||||||
|
freightAmountLabel: '100'
|
||||||
|
}
|
||||||
|
const { rows, merges } = buildResearchLedgerRows([
|
||||||
|
{ ...base, sampleIndex: 0 } as unknown as ProtocolAuditFlatRow,
|
||||||
|
{
|
||||||
|
...base,
|
||||||
|
sampleIndex: 1,
|
||||||
|
motherName: '乙',
|
||||||
|
labStorageCode: 'UBMC2'
|
||||||
|
} as unknown as ProtocolAuditFlatRow
|
||||||
|
])
|
||||||
|
assert.equal(rows[0][16], '专线车')
|
||||||
|
assert.equal(rows[0][17], '100')
|
||||||
|
assert.equal(rows[1][16], '')
|
||||||
|
assert.equal(rows[1][17], '')
|
||||||
|
assert.deepEqual(merges, [
|
||||||
|
{ startRow: 2, endRow: 3, startCol: 17, endCol: 17 },
|
||||||
|
{ startRow: 2, endRow: 3, startCol: 18, endCol: 18 }
|
||||||
|
])
|
||||||
|
assert.deepEqual(buildFreightMergeRanges(['', 'x', 'x', 'y']), [
|
||||||
|
{ startRow: 3, endRow: 4, startCol: 17, endCol: 17 },
|
||||||
|
{ startRow: 3, endRow: 4, startCol: 18, endCol: 18 }
|
||||||
|
])
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('buildCustomerServiceLedgerRows', () => {
|
describe('buildCustomerServiceLedgerRows', () => {
|
||||||
|
|||||||
@@ -166,12 +166,16 @@ const PROTOCOL_STATUS: Record<string, string> = {
|
|||||||
zckc: '转细胞存储'
|
zckc: '转细胞存储'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 作废类型兜底;与 void-type-dict 默认项一致,并覆盖误写入作废类型的状态码。 */
|
||||||
const VOID_TYPE: Record<string, string> = {
|
const VOID_TYPE: Record<string, string> = {
|
||||||
khhc: '客户毁存',
|
khhc: '客户毁存',
|
||||||
jcbhg: '检测不合格',
|
jcbhg: '检测不合格',
|
||||||
sysfq: '实验室废弃'
|
sysfq: '实验室废弃'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 导出前由字典填充;单元测试环境可为空。 */
|
||||||
|
let runtimeVoidLabels: Record<string, string> = {}
|
||||||
|
|
||||||
const PAY_MODE: Record<string, string> = {
|
const PAY_MODE: Record<string, string> = {
|
||||||
dj: '趸交',
|
dj: '趸交',
|
||||||
fq: '分期',
|
fq: '分期',
|
||||||
@@ -194,6 +198,19 @@ const DELIVERY: Record<string, string> = {
|
|||||||
pgc: '剖宫产'
|
pgc: '剖宫产'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 科研表模板多用「剖腹产」。 */
|
||||||
|
const RESEARCH_DELIVERY: Record<string, string> = {
|
||||||
|
sc: '顺产',
|
||||||
|
pgc: '剖腹产'
|
||||||
|
}
|
||||||
|
|
||||||
|
export type LedgerMergeRange = {
|
||||||
|
startRow: number
|
||||||
|
endRow: number
|
||||||
|
startCol: number
|
||||||
|
endCol: number
|
||||||
|
}
|
||||||
|
|
||||||
function text(value: unknown): string {
|
function text(value: unknown): string {
|
||||||
return value == null ? '' : String(value).trim()
|
return value == null ? '' : String(value).trim()
|
||||||
}
|
}
|
||||||
@@ -275,16 +292,82 @@ function dayText(value: unknown): string {
|
|||||||
return parts ? String(parts.day) : ''
|
return parts ? String(parts.day) : ''
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 作废类型:字典 → 本地兜底 → 协议状态码文案(如 sdfq→属地废弃)。 */
|
||||||
|
function voidTypeText(value: unknown): string {
|
||||||
|
const code = text(value)
|
||||||
|
if (!code) return ''
|
||||||
|
return (
|
||||||
|
runtimeVoidLabels[code] ||
|
||||||
|
VOID_TYPE[code] ||
|
||||||
|
PROTOCOL_STATUS[code] ||
|
||||||
|
code
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
function statusText(status: unknown, voidType: unknown): string {
|
function statusText(status: unknown, voidType: unknown): string {
|
||||||
const code = text(status)
|
const code = text(status)
|
||||||
const base = PROTOCOL_STATUS[code] || code
|
const base = PROTOCOL_STATUS[code] || code
|
||||||
if (code !== 'yzf') return base
|
if (code !== 'yzf') return base
|
||||||
const reason = label(VOID_TYPE, voidType)
|
const reason = voidTypeText(voidType)
|
||||||
return reason ? `${base}(${reason})` : base
|
return reason ? `${base}(${reason})` : base
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 科研表储存状态:废弃写类别文案,正常样本留空,对齐线下大表。 */
|
||||||
|
function researchStorageStatus(status: unknown, voidType: unknown): string {
|
||||||
|
const code = text(status)
|
||||||
|
if (code === 'yzf') return voidTypeText(voidType)
|
||||||
|
if (code === 'sdfq') return PROTOCOL_STATUS.sdfq
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
|
||||||
function voidReason(row: Row): string {
|
function voidReason(row: Row): string {
|
||||||
return text(row.voidDesc) || label(VOID_TYPE, row.voidType)
|
return text(row.voidDesc) || voidTypeText(row.voidType)
|
||||||
|
}
|
||||||
|
|
||||||
|
function researchTransportText(row: ProtocolAuditFlatRow): string {
|
||||||
|
return text(row.freightTransportLabel) || transportText(row)
|
||||||
|
}
|
||||||
|
|
||||||
|
function researchFreightText(row: ProtocolAuditFlatRow): string {
|
||||||
|
return text(row.freightAmountLabel)
|
||||||
|
}
|
||||||
|
|
||||||
|
function researchMaternalBloodText(value: unknown): string {
|
||||||
|
const formatted = formatLedgerDateTime(value)
|
||||||
|
if (formatted) return formatted
|
||||||
|
return text(value) ? text(value) : '无母血'
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 相邻且 freightId 相同的导出行,合并运输方式/运费列(Excel 行号含表头)。 */
|
||||||
|
export function buildFreightMergeRanges(freightIds: string[]): LedgerMergeRange[] {
|
||||||
|
const merges: LedgerMergeRange[] = []
|
||||||
|
let index = 0
|
||||||
|
while (index < freightIds.length) {
|
||||||
|
const freightId = text(freightIds[index])
|
||||||
|
if (!freightId) {
|
||||||
|
index += 1
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
let end = index + 1
|
||||||
|
while (end < freightIds.length && text(freightIds[end]) === freightId) end += 1
|
||||||
|
if (end - index >= 2) {
|
||||||
|
const startRow = index + 2
|
||||||
|
const endRow = end + 1
|
||||||
|
merges.push({ startRow, endRow, startCol: 17, endCol: 17 })
|
||||||
|
merges.push({ startRow, endRow, startCol: 18, endCol: 18 })
|
||||||
|
}
|
||||||
|
index = end
|
||||||
|
}
|
||||||
|
return merges
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 导出前加载作废类型字典,避免列表外的编码原样写入 Excel。 */
|
||||||
|
export async function prepareCollectionLedgerExport(): Promise<void> {
|
||||||
|
const { loadVoidTypeDict, getVoidTypeOptions } = await import('./void-type-dict')
|
||||||
|
await loadVoidTypeDict()
|
||||||
|
runtimeVoidLabels = Object.fromEntries(
|
||||||
|
getVoidTypeOptions().map((item) => [String(item.value), String(item.label)])
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function payModeText(value: unknown, fallback = ''): string {
|
function payModeText(value: unknown, fallback = ''): string {
|
||||||
@@ -414,7 +497,7 @@ function storageLedgerRow(row: ProtocolAuditFlatRow, index: number, research: bo
|
|||||||
cells[3] = dayText(collectTime)
|
cells[3] = dayText(collectTime)
|
||||||
cells[4] = text(protocol.monthlyVerifyNo)
|
cells[4] = text(protocol.monthlyVerifyNo)
|
||||||
cells[5] = text(row.labStorageCode)
|
cells[5] = text(row.labStorageCode)
|
||||||
cells[6] = statusText(status, protocol.voidType)
|
cells[6] = researchStorageStatus(status, protocol.voidType)
|
||||||
cells[7] = voidReason(protocol)
|
cells[7] = voidReason(protocol)
|
||||||
cells[8] = text(row.motherName)
|
cells[8] = text(row.motherName)
|
||||||
cells[9] = text(row.sampleTypeName)
|
cells[9] = text(row.sampleTypeName)
|
||||||
@@ -424,12 +507,13 @@ function storageLedgerRow(row: ProtocolAuditFlatRow, index: number, research: bo
|
|||||||
cells[13] = formatLedgerDateTime(collectTime)
|
cells[13] = formatLedgerDateTime(collectTime)
|
||||||
cells[14] = text(row.salesUserName)
|
cells[14] = text(row.salesUserName)
|
||||||
cells[15] = text(row.regionManagerUserName)
|
cells[15] = text(row.regionManagerUserName)
|
||||||
cells[16] = transportText(row)
|
cells[16] = researchTransportText(row)
|
||||||
|
cells[17] = researchFreightText(row)
|
||||||
cells[18] = label(SEX, row.newbornSex)
|
cells[18] = label(SEX, row.newbornSex)
|
||||||
cells[19] = weightText(row.newbornWeightGram)
|
cells[19] = weightText(row.newbornWeightGram)
|
||||||
cells[20] = label(DELIVERY, row.deliveryMode)
|
cells[20] = label(RESEARCH_DELIVERY, row.deliveryMode) || label(DELIVERY, row.deliveryMode)
|
||||||
cells[21] = text(row.birthOrder)
|
cells[21] = text(row.birthOrder)
|
||||||
cells[22] = formatLedgerDateTime(row.maternalBloodCollectTime)
|
cells[22] = researchMaternalBloodText(row.maternalBloodCollectTime)
|
||||||
cells[23] = text(row.consentFormUrls) ? '1' : ''
|
cells[23] = text(row.consentFormUrls) ? '1' : ''
|
||||||
cells[24] = text(row.remark)
|
cells[24] = text(row.remark)
|
||||||
return cells
|
return cells
|
||||||
@@ -481,8 +565,23 @@ export function buildCellStorageLedgerRows(rows: ProtocolAuditFlatRow[]): string
|
|||||||
return rows.map((row, index) => storageLedgerRow(row, index, false))
|
return rows.map((row, index) => storageLedgerRow(row, index, false))
|
||||||
}
|
}
|
||||||
|
|
||||||
export function buildResearchLedgerRows(rows: ProtocolAuditFlatRow[]): string[][] {
|
export function buildResearchLedgerRows(rows: ProtocolAuditFlatRow[]): {
|
||||||
return rows.map((row, index) => storageLedgerRow(row, index, true))
|
rows: string[][]
|
||||||
|
merges: LedgerMergeRange[]
|
||||||
|
} {
|
||||||
|
const freightIds = rows.map((row) => text(row.freightId))
|
||||||
|
const built = rows.map((row, index) => storageLedgerRow(row, index, true))
|
||||||
|
const merges = buildFreightMergeRanges(freightIds)
|
||||||
|
// 合并区域内仅保留首行运输/运费,其余清空,避免合并后重复显示
|
||||||
|
for (const merge of merges) {
|
||||||
|
if (merge.startCol !== 17 && merge.startCol !== 18) continue
|
||||||
|
const colIndex = merge.startCol - 1
|
||||||
|
for (let excelRow = merge.startRow + 1; excelRow <= merge.endRow; excelRow += 1) {
|
||||||
|
const dataIndex = excelRow - 2
|
||||||
|
if (dataIndex >= 0 && dataIndex < built.length) built[dataIndex][colIndex] = ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return { rows: built, merges }
|
||||||
}
|
}
|
||||||
|
|
||||||
export function buildCustomerServiceLedgerRows(rows: Row[]): string[][] {
|
export function buildCustomerServiceLedgerRows(rows: Row[]): string[][] {
|
||||||
@@ -551,7 +650,8 @@ export async function saveCollectionLedgerWorkbook(
|
|||||||
sheetName: string,
|
sheetName: string,
|
||||||
headers: string[],
|
headers: string[],
|
||||||
rows: string[][],
|
rows: string[][],
|
||||||
filenamePrefix: string
|
filenamePrefix: string,
|
||||||
|
merges: LedgerMergeRange[] = []
|
||||||
) {
|
) {
|
||||||
const ExcelJS = (await import('exceljs')).default
|
const ExcelJS = (await import('exceljs')).default
|
||||||
const FileSaver = (await import('file-saver')).default
|
const FileSaver = (await import('file-saver')).default
|
||||||
@@ -568,8 +668,15 @@ export async function saveCollectionLedgerWorkbook(
|
|||||||
const cell = added.getCell(index + 1)
|
const cell = added.getCell(index + 1)
|
||||||
cell.value = value
|
cell.value = value
|
||||||
cell.numFmt = '@'
|
cell.numFmt = '@'
|
||||||
|
cell.alignment = { vertical: 'middle', horizontal: 'center', wrapText: true }
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
merges.forEach((merge) => {
|
||||||
|
if (merge.endRow <= merge.startRow) return
|
||||||
|
sheet.mergeCells(merge.startRow, merge.startCol, merge.endRow, merge.endCol)
|
||||||
|
const cell = sheet.getCell(merge.startRow, merge.startCol)
|
||||||
|
cell.alignment = { vertical: 'middle', horizontal: 'center', wrapText: true }
|
||||||
|
})
|
||||||
headers.forEach((header, index) => {
|
headers.forEach((header, index) => {
|
||||||
sheet.getColumn(index + 1).width = Math.min(28, Math.max(12, header.replace(/\n/g, '').length + 2))
|
sheet.getColumn(index + 1).width = Math.min(28, Math.max(12, header.replace(/\n/g, '').length + 2))
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -110,7 +110,18 @@ describe('flattenProtocolAuditRows', () => {
|
|||||||
infectiousDiseaseReportUrls: '',
|
infectiousDiseaseReportUrls: '',
|
||||||
attachmentUrls: 'https://x/b.pdf',
|
attachmentUrls: 'https://x/b.pdf',
|
||||||
remark: '备注一',
|
remark: '备注一',
|
||||||
sampleItems: [{ sampleTypeName: 'NK', sampleCode: 'D2', labStorageCode: 'A1' }]
|
sampleItems: [
|
||||||
|
{
|
||||||
|
sampleTypeName: 'NK',
|
||||||
|
sampleCode: 'D2',
|
||||||
|
labStorageCode: 'A1',
|
||||||
|
freight: {
|
||||||
|
id: 'fr-1',
|
||||||
|
transportModeLabel: '专线车',
|
||||||
|
freightAmountLabel: '100'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
assert.equal(rows[0].monthlyVerifyNo, '202508001')
|
assert.equal(rows[0].monthlyVerifyNo, '202508001')
|
||||||
@@ -122,6 +133,9 @@ describe('flattenProtocolAuditRows', () => {
|
|||||||
assert.equal(rows[0].infectiousDiseaseReportUrls, '')
|
assert.equal(rows[0].infectiousDiseaseReportUrls, '')
|
||||||
assert.equal(rows[0].attachmentUrls, 'https://x/b.pdf')
|
assert.equal(rows[0].attachmentUrls, 'https://x/b.pdf')
|
||||||
assert.equal(rows[0].remark, '备注一')
|
assert.equal(rows[0].remark, '备注一')
|
||||||
|
assert.equal(rows[0].freightId, 'fr-1')
|
||||||
|
assert.equal(rows[0].freightTransportLabel, '专线车')
|
||||||
|
assert.equal(rows[0].freightAmountLabel, '100')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -37,6 +37,10 @@ export type ProtocolAuditFlatRow = {
|
|||||||
labStorageCode: string
|
labStorageCode: string
|
||||||
transportType: string
|
transportType: string
|
||||||
transportLabel: string
|
transportLabel: string
|
||||||
|
/** 样本运费批次;多样本共用时 id 相同 */
|
||||||
|
freightId: string
|
||||||
|
freightTransportLabel: string
|
||||||
|
freightAmountLabel: string
|
||||||
paymentSummary: QcProtocolPaymentSummary | null
|
paymentSummary: QcProtocolPaymentSummary | null
|
||||||
monthlyVerifyNo: string
|
monthlyVerifyNo: string
|
||||||
donationStatus: string
|
donationStatus: string
|
||||||
@@ -90,7 +94,13 @@ export function flattenProtocolAuditRows(
|
|||||||
slots.forEach((item, sampleIndex) => {
|
slots.forEach((item, sampleIndex) => {
|
||||||
const rec = item || {}
|
const rec = item || {}
|
||||||
const transport = asRecord(rec.transport)
|
const transport = asRecord(rec.transport)
|
||||||
|
const freight = asRecord(rec.freight)
|
||||||
const transportType = str(transport?.transportType)
|
const transportType = str(transport?.transportType)
|
||||||
|
const freightAmountLabel = str(freight?.freightAmountLabel)
|
||||||
|
const freightAmount =
|
||||||
|
freight?.freightAmount == null || freight?.freightAmount === ''
|
||||||
|
? ''
|
||||||
|
: String(freight.freightAmount)
|
||||||
out.push({
|
out.push({
|
||||||
rowKey: `${protocolId}|${str(rec.sampleCode) || sampleIndex}`,
|
rowKey: `${protocolId}|${str(rec.sampleCode) || sampleIndex}`,
|
||||||
protocolId,
|
protocolId,
|
||||||
@@ -113,6 +123,9 @@ export function flattenProtocolAuditRows(
|
|||||||
labStorageCode: str(rec.labStorageCode),
|
labStorageCode: str(rec.labStorageCode),
|
||||||
transportType,
|
transportType,
|
||||||
transportLabel: '',
|
transportLabel: '',
|
||||||
|
freightId: str(freight?.id),
|
||||||
|
freightTransportLabel: str(freight?.transportModeLabel) || str(freight?.transportMode),
|
||||||
|
freightAmountLabel: freightAmountLabel || freightAmount,
|
||||||
paymentSummary:
|
paymentSummary:
|
||||||
protocol.paymentSummary && typeof protocol.paymentSummary === 'object'
|
protocol.paymentSummary && typeof protocol.paymentSummary === 'object'
|
||||||
? (protocol.paymentSummary as QcProtocolPaymentSummary)
|
? (protocol.paymentSummary as QcProtocolPaymentSummary)
|
||||||
|
|||||||
@@ -206,7 +206,8 @@
|
|||||||
buildPresignLedgerRows,
|
buildPresignLedgerRows,
|
||||||
fetchAllPages,
|
fetchAllPages,
|
||||||
PRESIGN_HEADERS,
|
PRESIGN_HEADERS,
|
||||||
saveCollectionLedgerWorkbook
|
saveCollectionLedgerWorkbook,
|
||||||
|
prepareCollectionLedgerExport
|
||||||
} from '@/utils/collection-ledger-export'
|
} from '@/utils/collection-ledger-export'
|
||||||
import { formatDisplayOrDash } from '@/utils/datetime-display'
|
import { formatDisplayOrDash } from '@/utils/datetime-display'
|
||||||
import { formatMoneyDisplay } from '@/utils/money-format'
|
import { formatMoneyDisplay } from '@/utils/money-format'
|
||||||
@@ -262,6 +263,7 @@
|
|||||||
if (exporting.value) return
|
if (exporting.value) return
|
||||||
exporting.value = true
|
exporting.value = true
|
||||||
try {
|
try {
|
||||||
|
await prepareCollectionLedgerExport()
|
||||||
const rows = selectedRows.value.length
|
const rows = selectedRows.value.length
|
||||||
? selectedRows.value
|
? selectedRows.value
|
||||||
: await fetchAllPages((page, pageSize) =>
|
: await fetchAllPages((page, pageSize) =>
|
||||||
|
|||||||
@@ -465,7 +465,8 @@
|
|||||||
RESEARCH_HEADERS,
|
RESEARCH_HEADERS,
|
||||||
buildResearchLedgerRows,
|
buildResearchLedgerRows,
|
||||||
fetchAllPages,
|
fetchAllPages,
|
||||||
saveCollectionLedgerWorkbook
|
saveCollectionLedgerWorkbook,
|
||||||
|
prepareCollectionLedgerExport
|
||||||
} from '@/utils/collection-ledger-export'
|
} from '@/utils/collection-ledger-export'
|
||||||
import {
|
import {
|
||||||
flattenProtocolAuditRows,
|
flattenProtocolAuditRows,
|
||||||
@@ -545,6 +546,7 @@
|
|||||||
if (exporting.value) return
|
if (exporting.value) return
|
||||||
exporting.value = true
|
exporting.value = true
|
||||||
try {
|
try {
|
||||||
|
await prepareCollectionLedgerExport()
|
||||||
const rows = selectedFlatRows.value.length
|
const rows = selectedFlatRows.value.length
|
||||||
? selectedFlatRows.value
|
? selectedFlatRows.value
|
||||||
: flattenProtocolAuditRows(
|
: flattenProtocolAuditRows(
|
||||||
@@ -567,11 +569,13 @@
|
|||||||
ElMessage.warning('没有可导出的数据')
|
ElMessage.warning('没有可导出的数据')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
const ledger = buildResearchLedgerRows(rows)
|
||||||
await saveCollectionLedgerWorkbook(
|
await saveCollectionLedgerWorkbook(
|
||||||
'科研表',
|
'科研表',
|
||||||
RESEARCH_HEADERS,
|
RESEARCH_HEADERS,
|
||||||
buildResearchLedgerRows(rows),
|
ledger.rows,
|
||||||
'科研表'
|
'科研表',
|
||||||
|
ledger.merges
|
||||||
)
|
)
|
||||||
ElMessage.success('导出成功')
|
ElMessage.success('导出成功')
|
||||||
} catch {
|
} catch {
|
||||||
|
|||||||
@@ -433,7 +433,8 @@
|
|||||||
CELL_STORAGE_HEADERS,
|
CELL_STORAGE_HEADERS,
|
||||||
buildCellStorageLedgerRows,
|
buildCellStorageLedgerRows,
|
||||||
fetchAllPages,
|
fetchAllPages,
|
||||||
saveCollectionLedgerWorkbook
|
saveCollectionLedgerWorkbook,
|
||||||
|
prepareCollectionLedgerExport
|
||||||
} from '@/utils/collection-ledger-export'
|
} from '@/utils/collection-ledger-export'
|
||||||
import {
|
import {
|
||||||
flattenProtocolAuditRows,
|
flattenProtocolAuditRows,
|
||||||
@@ -510,6 +511,7 @@
|
|||||||
if (exporting.value) return
|
if (exporting.value) return
|
||||||
exporting.value = true
|
exporting.value = true
|
||||||
try {
|
try {
|
||||||
|
await prepareCollectionLedgerExport()
|
||||||
const rows = selectedFlatRows.value.length
|
const rows = selectedFlatRows.value.length
|
||||||
? selectedFlatRows.value
|
? selectedFlatRows.value
|
||||||
: flattenProtocolAuditRows(
|
: flattenProtocolAuditRows(
|
||||||
|
|||||||
@@ -525,7 +525,8 @@
|
|||||||
CUSTOMER_SERVICE_HEADERS,
|
CUSTOMER_SERVICE_HEADERS,
|
||||||
buildCustomerServiceLedgerRows,
|
buildCustomerServiceLedgerRows,
|
||||||
fetchAllPages,
|
fetchAllPages,
|
||||||
saveCollectionLedgerWorkbook
|
saveCollectionLedgerWorkbook,
|
||||||
|
prepareCollectionLedgerExport
|
||||||
} from '@/utils/collection-ledger-export'
|
} from '@/utils/collection-ledger-export'
|
||||||
|
|
||||||
defineOptions({ name: 'UnifiedSampleInfoPage' })
|
defineOptions({ name: 'UnifiedSampleInfoPage' })
|
||||||
@@ -653,6 +654,7 @@
|
|||||||
if (exporting.value || !isCellStorage.value) return
|
if (exporting.value || !isCellStorage.value) return
|
||||||
exporting.value = true
|
exporting.value = true
|
||||||
try {
|
try {
|
||||||
|
await prepareCollectionLedgerExport()
|
||||||
const rows = selectedRows.value.length
|
const rows = selectedRows.value.length
|
||||||
? selectedRows.value
|
? selectedRows.value
|
||||||
: await fetchAllPages((page, pageSize) =>
|
: await fetchAllPages((page, pageSize) =>
|
||||||
|
|||||||
Reference in new issue
Block a user