import type { PrismaClient } from '@prisma/client'; export type StoreBankAccountSnapshot = { bankAccountName: string | null; bankAccountNo: string | null; bankBranch: string | null; }; export type StoreBankAccountRow = StoreBankAccountSnapshot & { id: bigint; storeId: bigint; isDefault: boolean; status: string; sortOrder: number; }; /** 门店收款账户列表(默认账户优先,其次 sortOrder/创建顺序) */ export async function loadStoreBankAccounts( prisma: PrismaClient, storeId: bigint, ): Promise { const rows = await prisma.storeBankAccount.findMany({ where: { storeId, status: 'ACTIVE' }, orderBy: [{ isDefault: 'desc' }, { sortOrder: 'asc' }, { id: 'asc' }], }); return rows.map((r) => ({ id: r.id, storeId: r.storeId, bankAccountName: r.bankAccountName, bankAccountNo: r.bankAccountNo, bankBranch: r.bankBranch, isDefault: r.isDefault === 1, status: r.status, sortOrder: r.sortOrder, })); } /** * 门店默认收款账户:优先 is_default=1;否则第一个 ACTIVE;再退回旧主账号字段(兼容未迁移数据)。 * 返回 null 表示无收款账户。 */ export async function loadStoreDefaultBank( prisma: PrismaClient, storeId: bigint, ): Promise { const accounts = await loadStoreBankAccounts(prisma, storeId); if (accounts.length) { const def = accounts.find((a) => a.isDefault) ?? accounts[0]; return { bankAccountName: def.bankAccountName, bankAccountNo: def.bankAccountNo, bankBranch: def.bankBranch, }; } return loadStorePrimaryBank(prisma, storeId); } export async function loadStorePrimaryBank( prisma: PrismaClient, storeId: bigint, ): Promise { const binding = await prisma.storeAccountStore.findFirst({ where: { storeId, storeAccount: { isPrimary: 1 } }, include: { storeAccount: { select: { bankAccountName: true, bankAccountNo: true, bankBranch: true }, }, }, }); if (binding) return binding.storeAccount; const fallback = await prisma.storeAccountStore.findFirst({ where: { storeId }, orderBy: { storeAccountId: 'asc' }, include: { storeAccount: { select: { bankAccountName: true, bankAccountNo: true, bankBranch: true }, }, }, }); return fallback?.storeAccount ?? null; } export async function loadStorePrimaryBanksMap( prisma: PrismaClient, storeIds: bigint[], ): Promise> { const map = new Map(); if (!storeIds.length) return map; // 优先从门店多账户表读取默认账户 const accounts = await prisma.storeBankAccount.findMany({ where: { storeId: { in: storeIds }, status: 'ACTIVE' }, orderBy: [{ storeId: 'asc' }, { isDefault: 'desc' }, { sortOrder: 'asc' }, { id: 'asc' }], }); const seenStoreIds = new Set(); for (const a of accounts) { const key = String(a.storeId); if (map.has(key)) continue; map.set(key, { bankAccountName: a.bankAccountName, bankAccountNo: a.bankAccountNo, bankBranch: a.bankBranch, }); seenStoreIds.add(key); } // 未迁移/无多账户的门店,回退旧主账号字段 const missingIds = storeIds.filter((id) => !seenStoreIds.has(String(id))); if (missingIds.length) { const bindings = await prisma.storeAccountStore.findMany({ where: { storeId: { in: missingIds } }, include: { storeAccount: { select: { isPrimary: true, bankAccountName: true, bankAccountNo: true, bankBranch: true, }, }, }, orderBy: [{ storeAccount: { isPrimary: 'desc' } }, { storeAccountId: 'asc' }], }); for (const binding of bindings) { const key = String(binding.storeId); if (map.has(key)) continue; map.set(key, { bankAccountName: binding.storeAccount.bankAccountName, bankAccountNo: binding.storeAccount.bankAccountNo, bankBranch: binding.storeAccount.bankBranch, }); } } return map; } export function formatWecomBankAccount(bank?: { bankAccountName?: string | null; bankName?: string | null; bankBranch?: string | null; bankAccountNo?: string | null; } | null): string { if (!bank) return '未登记收款账户'; const name = bank.bankAccountName?.trim() || ''; const no = bank.bankAccountNo?.trim() || ''; if (!name && !no) return '未登记收款账户'; const bankLine = bank.bankName?.trim() || bank.bankBranch?.trim() || ''; return [name, bankLine, no].filter(Boolean).join(' / '); } export async function loadWineryBankConfig( prisma: PrismaClient, ): Promise { const keys = [ 'WINERY_BANK_ACCOUNT_NAME', 'WINERY_BANK_NAME', 'WINERY_BANK_BRANCH', 'WINERY_BANK_ACCOUNT_NO', ]; const rows = await prisma.systemConfig.findMany({ where: { configKey: { in: keys } }, select: { configKey: true, value: true }, }); const map = new Map(rows.map((r) => [r.configKey, r.value])); return { bankAccountName: map.get('WINERY_BANK_ACCOUNT_NAME') ?? null, bankName: map.get('WINERY_BANK_NAME') ?? null, bankBranch: map.get('WINERY_BANK_BRANCH') ?? null, bankAccountNo: map.get('WINERY_BANK_ACCOUNT_NO') ?? null, }; }