import { PrismaClient } from "@prisma/client" import InvoiceItem from "./InvoiceItem" class Invoice { /** * 创建新的收据实体 * @param suffixCode 收据 ID * @param issueDate 签发时间 * @param newInvoiceInfo 新收据信息 * @returns 新的收据实体 * */ constructor(suffixCode: number, issueDate: Date, period: Date[], items: InvoiceItem[], dueDate: Date, payer: { id: number; name: string; address: string; abn?: string; email?: string }) { // 设置收据后缀 this.suffixCode = suffixCode // 设置签发时间 this.issueTime = issueDate // 设置账单周期 // 首先验证周期有两个日期,且第一个日期早于第二个日期 if (period.length !== 2) throw new Error('Period should have two dates.') if (period[0] > period[1]) throw new Error('The first date should be earlier than the second date.') this.period = period // 设置项目列表 this.items = items // 设置收款日期 this.dueDate = dueDate // 设置付款人 this.payer = payer } /** * 收据后缀。仅在当日唯一。 */ suffixCode: number; /** * 签发时间。与后缀一起构成发票的唯一标识。 */ issueTime: Date; /** * 账单周期 */ period: Date[] /** * 项目列表 */ items: InvoiceItem[] /** * 收款日期 */ dueDate: Date /** * 付款人 */ payer: { id: number name: string address: string abn?: string email?: string } /** * 备注 */ note?: string; /** * 获取账单总额 */ getTotal() { let total = 0 this.items.forEach((item) => { total += item.getSubtotal() }) return total } /** * 更改备注 * @param note 新的备注 */ async setNote(note: string) { this.note = note } /** * 保存收据到数据库 * @param prisma Prisma 客户端 */ async save(prisma: PrismaClient) { if (this.suffixCode === 0) { // 创建新收据 // 获取当天最大收据后缀 const today = new Date() const todayStart = new Date(today.getFullYear(), today.getMonth(), today.getDate()) const todayEnd = new Date(today.getFullYear(), today.getMonth(), today.getDate() + 1) const maxSuffix = await prisma.invoice.findFirst({ where: { AND: [ { invoice_date: { gte: todayStart } }, { invoice_date: { lt: todayEnd } } ] }, orderBy: { invoice_suffix_code: 'desc' } }) // 更新收据后缀 this.suffixCode = maxSuffix ? maxSuffix.invoice_suffix_code + 1 : 1 // 在数据库中创建新收据 const newInvoice = await prisma.invoice.create({ data: { invoice_suffix_code: maxSuffix ? maxSuffix.invoice_suffix_code + 1 : 1, invoice_date: this.issueTime, invoice_billing_period_start: this.period[0], invoice_billing_period_end: this.period[1], invoice_due_date: this.dueDate, payer_id: this.payer.id, invoice_payer_address: this.payer.address, invoice_payer_name: this.payer.name, invoice_payer_abn: this.payer.abn, invoice_note: this.note, invoice_total_amount: this.getTotal() } }) // 保存收据项目 await Promise.all(this.items.map(async (item) => { await prisma.invoiceItem.create({ data: { invoice_date: this.issueTime, invoice_suffix_code: newInvoice.invoice_suffix_code, item_id: item.id, item_description: item.description ?? '', item_quantity: item.quantity ?? 0, item_unit: item.unit ?? '', item_unit_price: item.unitPrice ? item.unitPrice.toNumber() : 0, } }) })) } } } export default Invoice