invoice-issuer/backend/src/classes/Invoice.ts

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