feat(web-admin): add protocol-audit sample-row flatten helpers.
Support Excel-aligned list mode for cell-storage protocol audit. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
1 parent
4904508d9f
commit
0da75fb855
2 files changed
+233
No files matched your search
@@ -0,0 +1,135 @@
|
||||
import type { CollectionProtocolRow } from '../api/collection-protocol'
|
||||
import type { QcProtocolPaymentSummary } from '../api/qc-work-order'
|
||||
|
||||
export type ProtocolAuditSampleTransport = {
|
||||
transportType?: string
|
||||
destSiteName?: string
|
||||
expressCompanyName?: string
|
||||
waybillNo?: string
|
||||
carrierName?: string
|
||||
carrierPhone?: string
|
||||
etaTime?: string
|
||||
}
|
||||
|
||||
export type ProtocolAuditFlatRow = {
|
||||
rowKey: string
|
||||
protocolId: string
|
||||
protocol: CollectionProtocolRow
|
||||
sampleCount: number
|
||||
sampleIndex: number
|
||||
isCoStored: boolean
|
||||
collectDate: string
|
||||
sampleCollectTime: string
|
||||
motherName: string
|
||||
protocolNo: string
|
||||
regionName: string
|
||||
hospitalName: string
|
||||
salesUserName: string
|
||||
regionManagerUserName: string
|
||||
sampleTypeName: string
|
||||
sampleCode: string
|
||||
labStorageCode: string
|
||||
transportType: string
|
||||
transportLabel: string
|
||||
paymentSummary: QcProtocolPaymentSummary | null
|
||||
}
|
||||
|
||||
function asRecord(v: unknown): Record<string, unknown> | null {
|
||||
return v && typeof v === 'object' ? (v as Record<string, unknown>) : null
|
||||
}
|
||||
|
||||
function str(v: unknown): string {
|
||||
return v == null ? '' : String(v).trim()
|
||||
}
|
||||
|
||||
export function extractCollectDate(raw?: string | null): string {
|
||||
const s = str(raw)
|
||||
if (!s) return ''
|
||||
const m = s.match(/^(\d{4}-\d{2}-\d{2})/)
|
||||
return m ? m[1] : ''
|
||||
}
|
||||
|
||||
function readSampleItems(protocol: CollectionProtocolRow): Record<string, unknown>[] {
|
||||
const raw = protocol.sampleItems
|
||||
if (Array.isArray(raw) && raw.length) {
|
||||
return raw.map((x) => asRecord(x) || {})
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
export function flattenProtocolAuditRows(
|
||||
list: CollectionProtocolRow[]
|
||||
): ProtocolAuditFlatRow[] {
|
||||
const out: ProtocolAuditFlatRow[] = []
|
||||
for (const protocol of list || []) {
|
||||
const protocolId = str(protocol.id)
|
||||
const items = readSampleItems(protocol)
|
||||
const sampleCount = items.length
|
||||
const isCoStored = sampleCount >= 2
|
||||
const slots = sampleCount > 0 ? items : [null]
|
||||
slots.forEach((item, sampleIndex) => {
|
||||
const rec = item || {}
|
||||
const transport = asRecord(rec.transport)
|
||||
const transportType = str(transport?.transportType)
|
||||
out.push({
|
||||
rowKey: `${protocolId}|${str(rec.sampleCode) || sampleIndex}`,
|
||||
protocolId,
|
||||
protocol,
|
||||
sampleCount,
|
||||
sampleIndex,
|
||||
isCoStored,
|
||||
collectDate: extractCollectDate(str(protocol.sampleCollectTime)),
|
||||
sampleCollectTime: str(protocol.sampleCollectTime),
|
||||
motherName: str(protocol.motherName),
|
||||
protocolNo: str(protocol.protocolNo),
|
||||
regionName: str(protocol.regionName),
|
||||
hospitalName: str(protocol.hospitalName),
|
||||
salesUserName: str(protocol.salesUserName),
|
||||
regionManagerUserName: str(protocol.regionManagerUserName),
|
||||
sampleTypeName: str(rec.sampleTypeName),
|
||||
sampleCode: str(rec.sampleCode),
|
||||
labStorageCode: str(rec.labStorageCode),
|
||||
transportType,
|
||||
transportLabel: '',
|
||||
paymentSummary:
|
||||
protocol.paymentSummary && typeof protocol.paymentSummary === 'object'
|
||||
? (protocol.paymentSummary as QcProtocolPaymentSummary)
|
||||
: null
|
||||
})
|
||||
})
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
export function uniqueProtocolsFromFlatRows(
|
||||
rows: ProtocolAuditFlatRow[]
|
||||
): CollectionProtocolRow[] {
|
||||
const seen = new Set<string>()
|
||||
const out: CollectionProtocolRow[] = []
|
||||
for (const r of rows) {
|
||||
if (!r.protocolId || seen.has(r.protocolId)) continue
|
||||
seen.add(r.protocolId)
|
||||
out.push(r.protocol)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
export function firstPayTimeLines(
|
||||
summary: QcProtocolPaymentSummary | null | undefined
|
||||
): string[] {
|
||||
const details = summary?.paymentDetails
|
||||
if (!Array.isArray(details) || !details.length) return []
|
||||
const sorted = [...details].sort((a, b) => {
|
||||
const na = a.installmentNo == null ? 10_000 : Number(a.installmentNo)
|
||||
const nb = b.installmentNo == null ? 10_000 : Number(b.installmentNo)
|
||||
return na - nb
|
||||
})
|
||||
const lines: string[] = []
|
||||
for (const d of sorted) {
|
||||
const t = str((d as { transferTime?: string }).transferTime)
|
||||
const due = str(d.installmentDueDate)
|
||||
const pick = t || due
|
||||
if (pick) lines.push(pick)
|
||||
}
|
||||
return lines
|
||||
}
|
||||
Reference in new issue
Block a user