invoice item total and subtotal

This commit is contained in:
2026-05-16 15:59:40 +03:30
parent 8017484f54
commit 7133b47c95
7 changed files with 58 additions and 17 deletions
+11
View File
@@ -0,0 +1,11 @@
node_modules
dist
.git
.gitignore
*.md
.env*
coverage
.nyc_output
logs
*.log
npm-debug.log*
+3 -4
View File
@@ -1,9 +1,8 @@
# Stage 1: Base
FROM node:22-alpine AS base
# Install timezone support
RUN apk add --no-cache tzdata
RUN cp /usr/share/zoneinfo/Asia/Tehran /etc/localtime && echo "Asia/Tehran" > /etc/timezone
# Set timezone (Node.js respects TZ env variable natively)
ENV TZ=Asia/Tehran
# Set workdir for clarity
WORKDIR /app
@@ -12,7 +11,7 @@ WORKDIR /app
FROM base AS deps
WORKDIR /temp-deps
COPY package*.json ./
RUN npm ci --ignore-scripts
RUN npm ci --ignore-scripts --no-fund --no-audit
# Stage 3: Build
FROM base AS builder
@@ -2831,6 +2831,16 @@
"nullable": false,
"mappedType": "integer"
},
"sub_total": {
"name": "sub_total",
"type": "int",
"generated": "(COALESCE(unit_price, 0) * quantity) STORED",
"unsigned": false,
"autoincrement": false,
"primary": false,
"nullable": false,
"mappedType": "integer"
},
"discount": {
"name": "discount",
"type": "int",
@@ -2840,6 +2850,16 @@
"nullable": true,
"mappedType": "integer"
},
"total": {
"name": "total",
"type": "int",
"generated": "((COALESCE(unit_price, 0) * quantity) - COALESCE(discount, 0)) STORED",
"unsigned": false,
"autoincrement": false,
"primary": false,
"nullable": false,
"mappedType": "integer"
},
"description": {
"name": "description",
"type": "text",
@@ -0,0 +1,9 @@
import { Migration } from '@mikro-orm/migrations';
export class Migration20260516121012 extends Migration {
override async up(): Promise<void> {
this.addSql(`alter table "invoice_items" add column "sub_total" int generated always as (COALESCE(unit_price, 0) * quantity) STORED not null, add column "total" int generated always as ((COALESCE(unit_price, 0) * quantity) - COALESCE(discount, 0)) STORED not null;`);
}
}
@@ -88,7 +88,8 @@ export class CreateInvoiceDto {
description?: string;
@IsArray()
@IsOptional()
@Type(() => IAttachmentDto)
@ApiProperty({ type: [IAttachmentDto] })
attachments: IAttachmentDto[];
attachments?: IAttachmentDto[];
}
@@ -29,7 +29,6 @@ export class InvoiceItem extends BaseEntity {
@Property({
type: 'int',
columnType: 'int GENERATED ALWAYS AS (COALESCE(unit_price, 0) * quantity) STORED',
persist: false,
})
subTotal!: number & Opt;
@@ -42,7 +41,6 @@ export class InvoiceItem extends BaseEntity {
@Property({
type: 'int',
columnType: 'int GENERATED ALWAYS AS ((COALESCE(unit_price, 0) * quantity) - COALESCE(discount, 0)) STORED',
persist: false
})
total!: number & Opt;
+8 -5
View File
@@ -59,13 +59,16 @@ export class InvoiceService {
...(request && { request }),
enableTax,
approvalDeadline,
// discount,
discount: 0,
paidAmount: 0,
// balance: 0,
attachments: [],
balance: 0,
attachments: dto.attachments ?? [],
paymentMethod: dto.paymentMethod,
invoiceNumber: 20, // TODO : invoice number
description: dto.description
description: dto.description,
subTotal: 0,
taxAmount: 0,
total: 0,
});
em.persist(invoice);
@@ -95,7 +98,7 @@ export class InvoiceService {
// const total = Math.max(0, subTotal - discount + taxAmount);
// invoice.subTotal = subTotal;
invoice.attachments = dto.attachments;
// invoice.attachments = dto.attachments;
// invoice.taxAmount = taxAmount;
// invoice.total = total;
// invoice.balance = total - invoice.paidAmount;