152 lines
3.5 KiB
TypeScript
152 lines
3.5 KiB
TypeScript
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 |