Merge branch 'develop'

This commit is contained in:
Methapon2001 2025-03-10 11:11:44 +07:00
commit 2c6205d01a

View file

@ -5,16 +5,19 @@ import {
ProductGroup,
QuotationStatus,
RequestWorkStatus,
PaymentStatus,
User,
Invoice,
CustomerType,
} from "@prisma/client";
import { Controller, Get, Query, Request, Route, Security, Tags } from "tsoa";
import prisma from "../db";
import { createPermCondition } from "../services/permission";
import { RequestWithUser } from "../interfaces/user";
import { PaymentStatus } from "../generated/kysely/types";
import { precisionRound } from "../utils/arithmetic";
import dayjs from "dayjs";
import { json2csv } from "json-2-csv";
import { isSystem } from "../utils/keycloak";
const permissionCondCompany = createPermCondition((_) => true);
@ -638,4 +641,129 @@ export class StatsController extends Controller {
});
return data;
}
@Get("customer-dept")
async reportCustomerDept(@Request() req: RequestWithUser) {
let query = prisma.$kysely
.selectFrom("Quotation")
.leftJoin("Invoice", "Quotation.id", "Invoice.quotationId")
.leftJoin("Payment", "Invoice.id", "Payment.invoiceId")
.leftJoin("CustomerBranch", "CustomerBranch.id", "Quotation.customerBranchId")
.leftJoin("Customer", "Customer.id", "CustomerBranch.customerId")
.select([
"CustomerBranch.id as customerBranchId",
"CustomerBranch.code as customerBranchCode",
"CustomerBranch.registerName as customerBranchRegisterName",
"CustomerBranch.registerNameEN as customerBranchRegisterNameEN",
"CustomerBranch.firstName as customerBranchFirstName",
"CustomerBranch.firstNameEN as customerBranchFirstNameEN",
"CustomerBranch.lastName as customerBranchFirstName",
"CustomerBranch.lastNameEN as customerBranchFirstNameEN",
"Customer.customerType",
"Quotation.id as quotationId",
"Quotation.code as quotationCode",
"Quotation.finalPrice as quotationValue",
])
.select(["Payment.paymentStatus"])
.selectAll(["Invoice"])
.distinctOn("Quotation.id");
if (!isSystem(req.user)) {
query = query.where(({ eb, exists }) =>
exists(
eb
.selectFrom("Branch")
.leftJoin("BranchUser", "BranchUser.branchId", "Branch.id")
.leftJoin("Branch as SubBranch", "SubBranch.headOfficeId", "Branch.id")
.leftJoin("BranchUser as SubBranchUser", "SubBranchUser.branchId", "SubBranch.id")
.leftJoin("Branch as HeadBranch", "HeadBranch.id", "Branch.id")
.leftJoin("BranchUser as HeadBranchUser", "HeadBranchUser.branchId", "HeadBranch.id")
.leftJoin("Branch as SubHeadBranch", "SubHeadBranch.headOfficeId", "HeadBranch.id")
.leftJoin(
"BranchUser as SubHeadBranchUser",
"SubHeadBranchUser.branchId",
"SubHeadBranch.id",
)
.where((eb) => {
const cond = [
eb("BranchUser.userId", "=", req.user.sub), // NOTE: if user belong to current branch.
eb("SubBranchUser.userId", "=", req.user.sub), // NOTE: if user belong to branch under current branch.
eb("HeadBranchUser.userId", "=", req.user.sub), // NOTE: if the current branch is under head branch user belong to.
eb("SubHeadBranchUser.userId", "=", req.user.sub), // NOTE: if the current branch is under the same head branch user belong to.
];
return eb.or(cond);
})
.select("Branch.id"),
),
);
}
const ret = await query.execute();
const arr = ret.map((item) => {
const data: Record<string, any> = {};
for (const [key, val] of Object.entries(item)) {
if (key.startsWith("customerBranch")) {
if (!data["customerBranch"]) data["customerBranch"] = {};
data["customerBranch"][key.slice(14).slice(0, 1).toLowerCase() + key.slice(14).slice(1)] =
val;
} else if (key.startsWith("customerType")) {
data["customerBranch"]["customer"] = { customerType: val };
} else {
data[key as keyof typeof data] = val;
}
}
return data as Invoice & {
quotationId: string;
quotationCode: string;
quotationValue: number;
paymentStatus: PaymentStatus;
customerBranch: CustomerBranch & { customer: { customerType: CustomerType } };
};
});
return arr
.reduce<
{
paid: number;
unpaid: number;
customerBranch: CustomerBranch & { customer: { customerType: CustomerType } };
_quotation: { id: string; code: string; value: number }[];
}[]
>((acc, item) => {
const exists = acc.find((v) => v.customerBranch.id === item.customerBranch.id);
const quotation = {
id: item.quotationId,
code: item.quotationCode,
value:
item.quotationValue -
(item.paymentStatus === "PaymentSuccess" && item.amount ? item.amount : 0),
};
if (!exists) {
return acc.concat({
_quotation: [quotation],
customerBranch: item.customerBranch,
paid: item.paymentStatus === "PaymentSuccess" && item.amount ? item.amount : 0,
unpaid: quotation.value,
});
}
const same = exists._quotation.find((v) => v.id === item.quotationId);
if (item.paymentStatus === "PaymentSuccess" && item.amount) {
exists.paid += item.amount;
if (same) same.value -= item.amount;
}
if (!same) exists._quotation.push(quotation);
exists.unpaid = exists._quotation.reduce((a, c) => a + c.value, 0);
return acc;
}, [])
.map((v) => {
return { ...v, _quotation: undefined };
});
}
}