feat: add fee workspace and polish AI presentation
This commit is contained in:
212
modules/billing/lib/presentation-data.ts
Normal file
212
modules/billing/lib/presentation-data.ts
Normal file
@@ -0,0 +1,212 @@
|
||||
import type { BillingCharge, BillingPayment, BillingStatement, PaymentMethod } from "@/modules/billing/types";
|
||||
|
||||
type StatementSeed = {
|
||||
id: string;
|
||||
elderId: string;
|
||||
elderName: string;
|
||||
roomLabel: string;
|
||||
contactName: string;
|
||||
contactPhone: string;
|
||||
dueOffsetDays: number;
|
||||
charges: Array<Omit<BillingCharge, "id" | "serviceDate">>;
|
||||
payments: Array<{
|
||||
amountCents: number;
|
||||
method: PaymentMethod;
|
||||
paidOffsetDays: number;
|
||||
reference: string;
|
||||
operator: string;
|
||||
note: string;
|
||||
}>;
|
||||
invoiceStatus?: BillingStatement["invoiceStatus"];
|
||||
invoiceNumber?: string;
|
||||
receiptCount?: number;
|
||||
};
|
||||
|
||||
const STATEMENT_SEEDS: StatementSeed[] = [
|
||||
{
|
||||
id: "bill-wgl",
|
||||
elderId: "elder-wgl",
|
||||
elderName: "王桂兰",
|
||||
roomLabel: "A101-1",
|
||||
contactName: "张敏",
|
||||
contactPhone: "13800000001",
|
||||
dueOffsetDays: 6,
|
||||
charges: [
|
||||
{ category: "床位服务", description: "标准护理房床位费", quantity: 1, unitPriceCents: 360000 },
|
||||
{ category: "护理服务", description: "重点照护服务包", quantity: 1, unitPriceCents: 390000 },
|
||||
{ category: "膳食服务", description: "低盐营养膳食", quantity: 1, unitPriceCents: 180000 },
|
||||
{ category: "健康管理", description: "血压跟踪与健康复核", quantity: 1, unitPriceCents: 30000 },
|
||||
],
|
||||
payments: [
|
||||
{
|
||||
amountCents: 960000,
|
||||
method: "wechat",
|
||||
paidOffsetDays: -2,
|
||||
reference: "WX202607090018",
|
||||
operator: "前台收费组",
|
||||
note: "家属线上支付",
|
||||
},
|
||||
],
|
||||
invoiceStatus: "issued",
|
||||
invoiceNumber: "FP20260709001",
|
||||
receiptCount: 1,
|
||||
},
|
||||
{
|
||||
id: "bill-ljg",
|
||||
elderId: "elder-ljg",
|
||||
elderName: "李建国",
|
||||
roomLabel: "A102-1",
|
||||
contactName: "李明",
|
||||
contactPhone: "13800000002",
|
||||
dueOffsetDays: 8,
|
||||
charges: [
|
||||
{ category: "床位服务", description: "半护理房床位费", quantity: 1, unitPriceCents: 320000 },
|
||||
{ category: "护理服务", description: "半护理服务包", quantity: 1, unitPriceCents: 250000 },
|
||||
{ category: "膳食服务", description: "日常营养膳食", quantity: 1, unitPriceCents: 170000 },
|
||||
{ category: "活动服务", description: "康体活动与陪同", quantity: 1, unitPriceCents: 40000 },
|
||||
],
|
||||
payments: [
|
||||
{
|
||||
amountCents: 400000,
|
||||
method: "bank_transfer",
|
||||
paidOffsetDays: -1,
|
||||
reference: "BANK20260708032",
|
||||
operator: "财务值班",
|
||||
note: "首笔转账已确认",
|
||||
},
|
||||
],
|
||||
invoiceStatus: "pending",
|
||||
},
|
||||
{
|
||||
id: "bill-zyz",
|
||||
elderId: "elder-zyz",
|
||||
elderName: "周玉珍",
|
||||
roomLabel: "A201-1",
|
||||
contactName: "周强",
|
||||
contactPhone: "13800000003",
|
||||
dueOffsetDays: 10,
|
||||
charges: [
|
||||
{ category: "床位服务", description: "记忆照护专区床位费", quantity: 1, unitPriceCents: 370000 },
|
||||
{ category: "护理服务", description: "协助护理服务包", quantity: 1, unitPriceCents: 285000 },
|
||||
{ category: "膳食服务", description: "糖尿病营养膳食", quantity: 1, unitPriceCents: 185000 },
|
||||
],
|
||||
payments: [],
|
||||
},
|
||||
{
|
||||
id: "bill-zgh",
|
||||
elderId: "elder-zgh",
|
||||
elderName: "赵国华",
|
||||
roomLabel: "A202-1",
|
||||
contactName: "赵琳",
|
||||
contactPhone: "13800000004",
|
||||
dueOffsetDays: -3,
|
||||
charges: [
|
||||
{ category: "床位服务", description: "重点护理房床位费", quantity: 1, unitPriceCents: 380000 },
|
||||
{ category: "护理服务", description: "失能照护服务包", quantity: 1, unitPriceCents: 420000 },
|
||||
{ category: "膳食服务", description: "软食营养膳食", quantity: 1, unitPriceCents: 185000 },
|
||||
{ category: "生活用品", description: "护理耗材包", quantity: 1, unitPriceCents: 60000 },
|
||||
],
|
||||
payments: [
|
||||
{
|
||||
amountCents: 200000,
|
||||
method: "cash",
|
||||
paidOffsetDays: -6,
|
||||
reference: "CASH20260703009",
|
||||
operator: "前台收费组",
|
||||
note: "现金预缴",
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "bill-msf",
|
||||
elderId: "elder-msf",
|
||||
elderName: "马淑芬",
|
||||
roomLabel: "A301-1",
|
||||
contactName: "马晨",
|
||||
contactPhone: "13800000011",
|
||||
dueOffsetDays: -5,
|
||||
charges: [
|
||||
{ category: "床位服务", description: "失能照护区床位费", quantity: 1, unitPriceCents: 390000 },
|
||||
{ category: "护理服务", description: "全护理服务包", quantity: 1, unitPriceCents: 460000 },
|
||||
{ category: "膳食服务", description: "吞咽困难软食套餐", quantity: 1, unitPriceCents: 205000 },
|
||||
{ category: "营养服务", description: "营养师评估与加餐", quantity: 1, unitPriceCents: 65000 },
|
||||
],
|
||||
payments: [],
|
||||
},
|
||||
{
|
||||
id: "bill-qsb",
|
||||
elderId: "elder-qsb",
|
||||
elderName: "钱松柏",
|
||||
roomLabel: "S101-1",
|
||||
contactName: "钱宁",
|
||||
contactPhone: "13800000014",
|
||||
dueOffsetDays: 4,
|
||||
charges: [
|
||||
{ category: "床位服务", description: "医养观察房床位费", quantity: 1, unitPriceCents: 430000 },
|
||||
{ category: "护理服务", description: "医养重点照护服务包", quantity: 1, unitPriceCents: 480000 },
|
||||
{ category: "膳食服务", description: "呼吸慢病营养膳食", quantity: 1, unitPriceCents: 190000 },
|
||||
{ category: "设备服务", description: "制氧与血氧监测服务", quantity: 1, unitPriceCents: 150000 },
|
||||
],
|
||||
payments: [
|
||||
{
|
||||
amountCents: 1250000,
|
||||
method: "card",
|
||||
paidOffsetDays: -1,
|
||||
reference: "POS20260708017",
|
||||
operator: "医养前台",
|
||||
note: "银行卡支付",
|
||||
},
|
||||
],
|
||||
receiptCount: 1,
|
||||
},
|
||||
];
|
||||
|
||||
function addDays(reference: Date, days: number): string {
|
||||
const result = new Date(reference);
|
||||
result.setDate(result.getDate() + days);
|
||||
return result.toISOString();
|
||||
}
|
||||
|
||||
function getPeriod(reference: Date): string {
|
||||
const year = reference.getFullYear();
|
||||
const month = String(reference.getMonth() + 1).padStart(2, "0");
|
||||
return `${year}-${month}`;
|
||||
}
|
||||
|
||||
function createCharges(seed: StatementSeed, reference: Date): BillingCharge[] {
|
||||
return seed.charges.map((charge, index) => ({
|
||||
...charge,
|
||||
id: `${seed.id}-charge-${index + 1}`,
|
||||
serviceDate: addDays(reference, -Math.max(1, 12 - index * 2)),
|
||||
}));
|
||||
}
|
||||
|
||||
function createPayments(seed: StatementSeed, reference: Date): BillingPayment[] {
|
||||
return seed.payments.map((payment, index) => ({
|
||||
id: `${seed.id}-payment-${index + 1}`,
|
||||
amountCents: payment.amountCents,
|
||||
method: payment.method,
|
||||
paidAt: addDays(reference, payment.paidOffsetDays),
|
||||
reference: payment.reference,
|
||||
operator: payment.operator,
|
||||
note: payment.note,
|
||||
}));
|
||||
}
|
||||
|
||||
export function createInitialBillingStatements(referenceDate = new Date()): BillingStatement[] {
|
||||
return STATEMENT_SEEDS.map((seed) => ({
|
||||
id: seed.id,
|
||||
elderId: seed.elderId,
|
||||
elderName: seed.elderName,
|
||||
roomLabel: seed.roomLabel,
|
||||
contactName: seed.contactName,
|
||||
contactPhone: seed.contactPhone,
|
||||
period: getPeriod(referenceDate),
|
||||
dueAt: addDays(referenceDate, seed.dueOffsetDays),
|
||||
charges: createCharges(seed, referenceDate),
|
||||
payments: createPayments(seed, referenceDate),
|
||||
invoiceStatus: seed.invoiceStatus ?? "not_requested",
|
||||
invoiceNumber: seed.invoiceNumber,
|
||||
receiptCount: seed.receiptCount ?? 0,
|
||||
}));
|
||||
}
|
||||
Reference in New Issue
Block a user