feat: implement bearer token validation and add functionality to retrieve specific invoice details
This commit is contained in:
parent
520b191da0
commit
b9324ff45e
|
@ -144,7 +144,20 @@ app.use(route.post('/invoice', async (ctx) => {
|
||||||
}))
|
}))
|
||||||
|
|
||||||
app.use(route.get('/invoice/INV-:date(\\d{8})-:suffix(\\d+)', async (ctx, invoiceId, suffix) => {
|
app.use(route.get('/invoice/INV-:date(\\d{8})-:suffix(\\d+)', async (ctx, invoiceId, suffix) => {
|
||||||
ctx.body = `Invoice ID: INV-${invoiceId}-${suffix}`
|
// 请求头验证 bearer token
|
||||||
|
const bearerToken = ctx.request.headers['authorization']?.split(' ')
|
||||||
|
if (!bearerToken) throw new HttpError(ErrorDescEnum.unauthorized, 401)
|
||||||
|
if (bearerToken[0] !== 'Bearer') throw new HttpError(ErrorDescEnum.unauthorized, 401)
|
||||||
|
if (!bearerToken[1]) throw new HttpError(ErrorDescEnum.unauthorized, 401)
|
||||||
|
await func.verifyBearerToken(bearerToken[1])
|
||||||
|
|
||||||
|
// 验证 invoiceId 格式
|
||||||
|
const date = invoiceId.slice(0, 4) + '-' + invoiceId.slice(4, 6) + '-' + invoiceId.slice(6, 8)
|
||||||
|
|
||||||
|
// 获取特定收据
|
||||||
|
const invoice = await func.getSpecificInvoice(ctx.prisma, date, parseInt(suffix))
|
||||||
|
console.log(invoice.exportJSON())
|
||||||
|
ctx.body = invoice.exportJSON()
|
||||||
}))
|
}))
|
||||||
|
|
||||||
const port = parseInt(process.env.PORT ?? '3000')
|
const port = parseInt(process.env.PORT ?? '3000')
|
||||||
|
|
|
@ -19,6 +19,8 @@ class Invoice {
|
||||||
this.suffixCode = suffixCode
|
this.suffixCode = suffixCode
|
||||||
// 设置签发时间
|
// 设置签发时间
|
||||||
this.issueTime = issueDate
|
this.issueTime = issueDate
|
||||||
|
// 设置为当天零点零秒
|
||||||
|
this.issueTime.setHours(0, 0, 0, 0)
|
||||||
// 设置账单周期
|
// 设置账单周期
|
||||||
console.log(period)
|
console.log(period)
|
||||||
// 首先验证周期有两个日期,且第一个日期早于第二个日期
|
// 首先验证周期有两个日期,且第一个日期早于第二个日期
|
||||||
|
@ -154,6 +156,23 @@ class Invoice {
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导出为 JSON
|
||||||
|
* @returns JSON 格式的收据
|
||||||
|
*/
|
||||||
|
exportJSON() {
|
||||||
|
return {
|
||||||
|
invoiceNumber: `INV-${this.issueTime.getFullYear()}${(this.issueTime.getMonth() + 1).toString().padStart(2, '0')}${this.issueTime.getDate().toString().padStart(2, '0')}-${this.suffixCode}`,
|
||||||
|
periodStart: this.period[0],
|
||||||
|
periodEnd: this.period[1],
|
||||||
|
items: this.items.map(item => item.exportJSON()),
|
||||||
|
dueDate: this.dueDate,
|
||||||
|
payerInfoSnap: this.payer,
|
||||||
|
payerId: this.payer.id,
|
||||||
|
note: this.note
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Invoice
|
export default Invoice
|
|
@ -48,6 +48,19 @@ class InvoiceItem {
|
||||||
getSubtotal() {
|
getSubtotal() {
|
||||||
return (this.unitPrice ? Number(this.unitPrice) : 0) * (this.quantity ?? 0);
|
return (this.unitPrice ? Number(this.unitPrice) : 0) * (this.quantity ?? 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导出为 JSON 对象。
|
||||||
|
*/
|
||||||
|
exportJSON() {
|
||||||
|
return {
|
||||||
|
id: this.id,
|
||||||
|
description: this.description,
|
||||||
|
quantity: this.quantity,
|
||||||
|
unit: this.unit,
|
||||||
|
unitPrice: this.unitPrice?.toNumber()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default InvoiceItem
|
export default InvoiceItem
|
44
backend/src/func/getSpecificInvoice.ts
Normal file
44
backend/src/func/getSpecificInvoice.ts
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
import { PrismaClient } from '@prisma/client'
|
||||||
|
import dayjs from 'dayjs'
|
||||||
|
import { ErrorDescEnum, HttpError } from '../classes/HttpError'
|
||||||
|
import Invoice from '../classes/Invoice'
|
||||||
|
import InvoiceItem from '../classes/InvoiceItem'
|
||||||
|
|
||||||
|
export default async (prisma: PrismaClient, invoiceIssueDateString: string, invoiceSuffix: number) => {
|
||||||
|
const invoiceIssueDate = dayjs(invoiceIssueDateString, 'YYYYMMDD').toDate()
|
||||||
|
|
||||||
|
const invoice = await prisma.invoice.findUnique({
|
||||||
|
where: {
|
||||||
|
invoice_date_invoice_suffix_code: {
|
||||||
|
invoice_date: invoiceIssueDate,
|
||||||
|
invoice_suffix_code: invoiceSuffix
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
console.log(invoiceIssueDate, invoiceSuffix)
|
||||||
|
console.log(invoice)
|
||||||
|
if (!invoice) throw new HttpError(ErrorDescEnum.related_item_not_found, 404)
|
||||||
|
|
||||||
|
const items = await prisma.invoiceItem.findMany({
|
||||||
|
where: {
|
||||||
|
invoice_suffix_code: invoiceSuffix,
|
||||||
|
invoice_date: invoiceIssueDate
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const payer = {
|
||||||
|
id: invoice.payer_id,
|
||||||
|
name: invoice.invoice_payer_name,
|
||||||
|
address: invoice.invoice_payer_address,
|
||||||
|
abn: invoice.invoice_payer_abn ?? undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
const invoiceItems = items.map(item => {
|
||||||
|
return new InvoiceItem(item.item_id, item.item_description, item.item_quantity, item.item_unit, item.item_unit_price)
|
||||||
|
})
|
||||||
|
|
||||||
|
const invoiceInstance = new Invoice(invoice.invoice_suffix_code, invoice.invoice_date, [invoice.invoice_billing_period_start, invoice.invoice_billing_period_end], invoiceItems, invoice.invoice_due_date, payer)
|
||||||
|
if (invoice.invoice_note) await invoiceInstance.setNote(invoice.invoice_note)
|
||||||
|
|
||||||
|
return invoiceInstance
|
||||||
|
}
|
|
@ -1,9 +1,11 @@
|
||||||
import createPayer from "./createPayer"
|
import createPayer from "./createPayer"
|
||||||
import issueInvoice from "./issueInvoice"
|
import issueInvoice from "./issueInvoice"
|
||||||
import verifyBearerToken from "./verifyBearerToken"
|
import verifyBearerToken from "./verifyBearerToken"
|
||||||
|
import getSpecificInvoice from "./getSpecificInvoice"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
createPayer,
|
createPayer,
|
||||||
issueInvoice,
|
issueInvoice,
|
||||||
verifyBearerToken
|
verifyBearerToken,
|
||||||
|
getSpecificInvoice
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user