fix(admin): contract preview, package audit detail, empty packages, winery status

Allow HQ to save stores with zero packages, preview contract images/PDFs, inspect package audit images/content, and show gray 无需打款 when winery payable is 0.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-08-10 20:30:55 +08:00
parent 46361ec713
commit 478291e2b3
5 changed files with 301 additions and 57 deletions
@@ -1708,6 +1708,9 @@ export class SettlementService {
const bill = await this.prisma.wineryBill.findUnique({ where: { id } });
if (!bill) throw new NotFoundException('酒厂对账单不存在');
if (bill.status !== 'UNPAID') throw new BadRequestException('仅未打款账单可确认打款');
if (Number(bill.wineryAmount) === 0) {
throw new BadRequestException('应付为 0,无需打款');
}
const updated = await this.prisma.wineryBill.update({
where: { id },
data: { status: 'PAID', paidAt: new Date() },
@@ -1749,11 +1752,17 @@ export class SettlementService {
'配送类型',
'实付金额',
'酒厂比例',
'酒厂应付',
'应付',
'支付时间',
'账单状态',
].join(',');
const rows: string[] = [];
const statusLabel = (b: { status: string; wineryAmount: Prisma.Decimal | number }) => {
if (Number(b.wineryAmount) === 0) return '无需打款';
if (b.status === 'PAID') return '已打款';
if (b.status === 'UNPAID') return '未打款';
return b.status;
};
for (const b of bills) {
if (b.items.length === 0) {
rows.push(
@@ -1766,7 +1775,7 @@ export class SettlementService {
Number(b.wineryRate),
Number(b.wineryAmount),
'',
b.status,
statusLabel(b),
].join(','),
);
continue;
@@ -1782,7 +1791,7 @@ export class SettlementService {
Number(b.wineryRate),
Number(item.wineryAmount),
item.paidAt.toISOString().slice(0, 19).replace('T', ' '),
b.status,
statusLabel(b),
].join(','),
);
}
@@ -1798,7 +1807,15 @@ export class SettlementService {
month?: number;
}): Prisma.WineryBillWhereInput {
const where: Prisma.WineryBillWhereInput = {};
if (query.status === 'UNPAID' || query.status === 'PAID') where.status = query.status;
if (query.status === 'NO_PAYMENT_NEEDED') {
where.wineryAmount = 0;
} else if (query.status === 'UNPAID') {
where.status = 'UNPAID';
where.wineryAmount = { gt: 0 };
} else if (query.status === 'PAID') {
where.status = 'PAID';
where.wineryAmount = { gt: 0 };
}
if (query.year && query.month) {
const start = new Date(query.year, query.month - 1, 1);
const end = new Date(query.year, query.month, 0, 23, 59, 59, 999);