196 lines
4.5 KiB
TypeScript
196 lines
4.5 KiB
TypeScript
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
|
|
}
|
|
})
|
|
}
|
|
} |