import { PrismaClient } from "@prisma/client" import InvoiceItem from "./InvoiceItem" class Invoice { /** * 创建新的收据实体 */ constructor(invoiceId?: number, issueDate?: Date, newInvoiceInfo?: { period: Date[], items: InvoiceItem[], payerId: number, dueDate?: Date }) { (async () => { const prismaClient = new PrismaClient() if (invoiceId && issueDate) { // 从数据库查找收据 const invoice = await prismaClient.invoice.findUnique({ where: { invoice_date_invoice_suffix_code: { invoice_suffix_code: invoiceId % 1000, invoice_date: new Date(invoiceId / 1000) } } }) if (!invoice) throw new Error('invoice not found') // 设置收据后缀 this.suffixCode = invoice.invoice_suffix_code // 设置签发时间 this.issueTime = invoice.invoice_date // 设置账单周期 this.period = [invoice.invoice_billing_period_start, invoice.invoice_billing_period_end] // 设置项目列表 const items = await prismaClient.invoiceItem.findMany({ where: { invoice_date: this.issueTime, invoice_suffix_code: this.suffixCode } }) if (!items) this.items = [] else { this.items = [] items.forEach((item) => { this.items.push(new InvoiceItem(item.item_id, item.item_description, item.item_quantity, item.item_unit, item.item_unit_price)) }) } // 设置收款日期 this.dueDate = invoice.invoice_due_date // 设置付款人 this.payer = { id: invoice.payer_id, name: invoice.invoice_payer_name, address: invoice.invoice_payer_address, abn: invoice.invoice_payer_abn ? invoice.invoice_payer_abn : undefined, } // 设置备注 this.note = invoice.invoice_note ?? undefined } else if (newInvoiceInfo) { // 设置账单签发时间 this.issueTime = new Date() // 设置账单周期 if (newInvoiceInfo.period.length !== 2) throw new Error('period should contain two dates') this.period = newInvoiceInfo.period // 设置项目列表 this.items = newInvoiceInfo.items // 设置收款日期 this.dueDate = newInvoiceInfo.dueDate || new Date() // 设置付款人 const payer = await prismaClient.payer.findUnique({ where: { payer_id: newInvoiceInfo.payerId } }) if (!payer) throw new Error('payer not found') this.payer = { id: payer.payer_id, name: payer.payer_name, address: payer.payer_address, abn: payer.payer_abn ? payer.payer_abn : undefined, email: payer.payer_email } // 将收据保存到数据库 await prismaClient.invoice.create({ data: { invoice_suffix_code: this.suffixCode, 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_abn: this.payer.abn, invoice_payer_name: this.payer.name, invoice_total_amount: this.getTotal() } }) // 将项目保存到数据库 await Promise.all(this.items.map(async (item) => { await prismaClient.invoiceItem.create({ data: { invoice_suffix_code: this.suffixCode, invoice_date: this.issueTime, item_description: item.description ?? '', item_quantity: item.quantity ?? 0, item_unit: item.unit ?? '', item_unit_price: item.unitPrice?.toNumber() ?? 0, item_id: item.id } }) })) } prismaClient.$disconnect() })() } /** * 收据后缀。仅在当日唯一。 */ 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 const prismaClient = new PrismaClient() await prismaClient.invoice.update({ where: { invoice_date_invoice_suffix_code: { invoice_suffix_code: this.suffixCode, invoice_date: this.issueTime } }, data: { invoice_note: note } }) } }