Merge branch 'develop'
All checks were successful
Spell Check / Spell Check with Typos (push) Successful in 6s
All checks were successful
Spell Check / Spell Check with Typos (push) Successful in 6s
This commit is contained in:
commit
5ce356648d
11 changed files with 224 additions and 57 deletions
|
|
@ -8,6 +8,7 @@
|
|||
"dev": "nodemon",
|
||||
"check": "tsc --noEmit",
|
||||
"format": "prettier --write .",
|
||||
"debug": "nodemon",
|
||||
"build": "tsoa spec-and-routes && tsc",
|
||||
"changelog:generate": "git-cliff -o CHANGELOG.md && git add CHANGELOG.md && git commit -m 'Update CHANGELOG.md'",
|
||||
"db:generate": "prisma generate",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
-- AlterTable
|
||||
ALTER TABLE "RequestData" ADD COLUMN "rejectRequestCancel" BOOLEAN,
|
||||
ADD COLUMN "rejectRequestCancelReason" TEXT;
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "RequestWork" ADD COLUMN "rejectRequestCancel" BOOLEAN,
|
||||
ADD COLUMN "rejectRequestCancelReason" TEXT;
|
||||
|
|
@ -1464,6 +1464,8 @@ model RequestData {
|
|||
|
||||
customerRequestCancel Boolean?
|
||||
customerRequestCancelReason String?
|
||||
rejectRequestCancel Boolean?
|
||||
rejectRequestCancelReason String?
|
||||
|
||||
flow Json?
|
||||
|
||||
|
|
@ -1502,6 +1504,8 @@ model RequestWork {
|
|||
|
||||
customerRequestCancel Boolean?
|
||||
customerRequestCancelReason String?
|
||||
rejectRequestCancel Boolean?
|
||||
rejectRequestCancelReason String?
|
||||
|
||||
creditNote CreditNote? @relation(fields: [creditNoteId], references: [id], onDelete: SetNull)
|
||||
creditNoteId String?
|
||||
|
|
|
|||
|
|
@ -61,6 +61,13 @@ const quotationData = (id: string) =>
|
|||
service: true,
|
||||
},
|
||||
},
|
||||
createdBy: {
|
||||
include: {
|
||||
province: true,
|
||||
district: true,
|
||||
subDistrict: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -2,13 +2,9 @@ import config from "../config.json";
|
|||
import {
|
||||
Customer,
|
||||
CustomerBranch,
|
||||
ProductGroup,
|
||||
QuotationStatus,
|
||||
RequestWorkStatus,
|
||||
PaymentStatus,
|
||||
User,
|
||||
Invoice,
|
||||
CustomerType,
|
||||
} from "@prisma/client";
|
||||
import { Controller, Get, Query, Request, Route, Security, Tags } from "tsoa";
|
||||
import prisma from "../db";
|
||||
|
|
@ -64,6 +60,7 @@ export class StatsController extends Controller {
|
|||
code: true,
|
||||
quotationStatus: true,
|
||||
customerBranch: {
|
||||
omit: { otpCode: true, otpExpires: true, userId: true },
|
||||
include: { customer: true },
|
||||
},
|
||||
finalPrice: true,
|
||||
|
|
@ -127,7 +124,10 @@ export class StatsController extends Controller {
|
|||
code: true,
|
||||
quotation: {
|
||||
select: {
|
||||
customerBranch: { include: { customer: true } },
|
||||
customerBranch: {
|
||||
omit: { otpCode: true, otpExpires: true, userId: true },
|
||||
include: { customer: true },
|
||||
},
|
||||
},
|
||||
},
|
||||
payment: {
|
||||
|
|
@ -198,7 +198,12 @@ export class StatsController extends Controller {
|
|||
invoice: {
|
||||
select: {
|
||||
quotation: {
|
||||
select: { customerBranch: { include: { customer: true } } },
|
||||
select: {
|
||||
customerBranch: {
|
||||
omit: { otpCode: true, otpExpires: true, userId: true },
|
||||
include: { customer: true },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -402,6 +407,7 @@ export class StatsController extends Controller {
|
|||
include: {
|
||||
createdBy: true,
|
||||
customerBranch: {
|
||||
omit: { otpCode: true, otpExpires: true, userId: true },
|
||||
include: { customer: true },
|
||||
},
|
||||
},
|
||||
|
|
@ -430,9 +436,9 @@ export class StatsController extends Controller {
|
|||
});
|
||||
|
||||
return list.reduce<{
|
||||
byProductGroup: (ProductGroup & { _count: number })[];
|
||||
bySale: (User & { _count: number })[];
|
||||
byCustomer: ((CustomerBranch & { customer: Customer }) & { _count: number })[];
|
||||
byProductGroup: ((typeof list)[number]["product"]["productGroup"] & { _count: number })[];
|
||||
bySale: ((typeof list)[number]["quotation"]["createdBy"] & { _count: number })[];
|
||||
byCustomer: ((typeof list)[number]["quotation"]["customerBranch"] & { _count: number })[];
|
||||
}>(
|
||||
(a, c) => {
|
||||
{
|
||||
|
|
@ -683,7 +689,9 @@ export class StatsController extends Controller {
|
|||
{
|
||||
paid: number;
|
||||
unpaid: number;
|
||||
customerBranch: CustomerBranch & { customer: Customer };
|
||||
customerBranch: CustomerBranch & {
|
||||
customer: Customer;
|
||||
};
|
||||
}[]
|
||||
>((acc, item) => {
|
||||
const exists = acc.find((v) => v.customerBranch.id === item.customerBranch!.id);
|
||||
|
|
@ -702,6 +710,15 @@ export class StatsController extends Controller {
|
|||
|
||||
return acc;
|
||||
}, [])
|
||||
.map((v) => ({ ...v, _quotation: undefined }));
|
||||
.map((v) => ({
|
||||
...v,
|
||||
customerBranch: {
|
||||
...v.customerBranch,
|
||||
userId: undefined,
|
||||
otpCode: undefined,
|
||||
otpExpires: undefined,
|
||||
},
|
||||
_quotation: undefined,
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -239,9 +239,84 @@ export class RequestDataController extends Controller {
|
|||
@Route("/api/v1/request-data/{requestDataId}")
|
||||
@Tags("Request List")
|
||||
export class RequestDataActionController extends Controller {
|
||||
@Post("reject-request-cancel")
|
||||
@Security("keycloak")
|
||||
async rejectRequestCancel(
|
||||
@Request() req: RequestWithUser,
|
||||
@Path() requestDataId: string,
|
||||
@Body()
|
||||
body: {
|
||||
reason?: string;
|
||||
},
|
||||
) {
|
||||
const result = await prisma.requestData.updateManyAndReturn({
|
||||
where: {
|
||||
id: requestDataId,
|
||||
quotation: {
|
||||
registeredBranch: {
|
||||
OR: permissionCond(req.user),
|
||||
},
|
||||
},
|
||||
},
|
||||
data: {
|
||||
rejectRequestCancel: true,
|
||||
rejectRequestCancelReason: body.reason || "",
|
||||
},
|
||||
});
|
||||
|
||||
if (result.length <= 0) throw notFoundError("Request Data");
|
||||
|
||||
return result[0];
|
||||
}
|
||||
|
||||
@Post("request-work/{requestWorkId}/reject-request-cancel")
|
||||
@Security("keycloak")
|
||||
async rejectWorkRequestCancel(
|
||||
@Request() req: RequestWithUser,
|
||||
@Path() requestWorkId: string,
|
||||
@Body()
|
||||
body: {
|
||||
reason?: string;
|
||||
},
|
||||
) {
|
||||
const result = await prisma.requestWork.updateManyAndReturn({
|
||||
where: {
|
||||
id: requestWorkId,
|
||||
request: {
|
||||
quotation: {
|
||||
registeredBranch: {
|
||||
OR: permissionCond(req.user),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
data: {
|
||||
rejectRequestCancel: true,
|
||||
rejectRequestCancelReason: body.reason || "",
|
||||
},
|
||||
});
|
||||
|
||||
if (result.length <= 0) throw notFoundError("Request Data");
|
||||
|
||||
return result[0];
|
||||
}
|
||||
|
||||
@Post("cancel")
|
||||
@Security("keycloak")
|
||||
async cancelRequestData(@Path() requestDataId: string) {
|
||||
async cancelRequestData(@Request() req: RequestWithUser, @Path() requestDataId: string) {
|
||||
const result = await prisma.requestData.findFirst({
|
||||
where: {
|
||||
id: requestDataId,
|
||||
quotation: {
|
||||
registeredBranch: {
|
||||
OR: permissionCond(req.user),
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (!result) throw notFoundError("Request Data");
|
||||
|
||||
await prisma.$transaction(async (tx) => {
|
||||
const workStepCondition = {
|
||||
requestWork: { requestDataId },
|
||||
|
|
@ -945,13 +1020,22 @@ export class RequestListController extends Controller {
|
|||
quotationStatus: {
|
||||
notIn: [QuotationStatus.Canceled, QuotationStatus.ProcessComplete],
|
||||
},
|
||||
requestData: {
|
||||
every: {
|
||||
requestDataStatus: {
|
||||
in: [RequestDataStatus.Canceled, RequestDataStatus.Completed],
|
||||
AND: [
|
||||
{
|
||||
requestData: {
|
||||
every: {
|
||||
requestDataStatus: {
|
||||
in: [RequestDataStatus.Canceled, RequestDataStatus.Completed],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
requestData: {
|
||||
some: {},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
data: { quotationStatus: QuotationStatus.ProcessComplete, urgent: false },
|
||||
include: {
|
||||
|
|
|
|||
|
|
@ -819,13 +819,22 @@ export class TaskActionController extends Controller {
|
|||
quotationStatus: {
|
||||
notIn: [QuotationStatus.Canceled, QuotationStatus.ProcessComplete],
|
||||
},
|
||||
requestData: {
|
||||
every: {
|
||||
requestDataStatus: {
|
||||
in: [RequestDataStatus.Canceled, RequestDataStatus.Completed],
|
||||
AND: [
|
||||
{
|
||||
requestData: {
|
||||
every: {
|
||||
requestDataStatus: {
|
||||
in: [RequestDataStatus.Canceled, RequestDataStatus.Completed],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
requestData: {
|
||||
some: {},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
data: { quotationStatus: QuotationStatus.ProcessComplete, urgent: false },
|
||||
include: {
|
||||
|
|
|
|||
|
|
@ -146,8 +146,8 @@ export class CreditNoteController extends Controller {
|
|||
) {
|
||||
const where = {
|
||||
OR: queryOrNot<Prisma.CreditNoteWhereInput[]>(query, [
|
||||
{ code: { contains: query, mode: "insensitive" } },
|
||||
{
|
||||
code: { contains: query, mode: "insensitive" },
|
||||
requestWork: {
|
||||
some: {
|
||||
request: {
|
||||
|
|
|
|||
|
|
@ -784,7 +784,7 @@ export class LineController extends Controller {
|
|||
async customerRequestCancel(
|
||||
@Path() requestDataId: string,
|
||||
@Request() req: RequestWithLineUser,
|
||||
@Body() body: { reason: string },
|
||||
@Body() body: { cancel: boolean; reason?: string },
|
||||
) {
|
||||
const result = await prisma.requestData.updateMany({
|
||||
where: {
|
||||
|
|
@ -803,8 +803,10 @@ export class LineController extends Controller {
|
|||
},
|
||||
},
|
||||
data: {
|
||||
customerRequestCancel: true,
|
||||
customerRequestCancelReason: body.reason,
|
||||
customerRequestCancel: body.cancel,
|
||||
customerRequestCancelReason: body.reason || null,
|
||||
rejectRequestCancel: false,
|
||||
rejectRequestCancelReason: null,
|
||||
},
|
||||
});
|
||||
if (result.count <= 0) throw notFoundError("Request Data");
|
||||
|
|
@ -815,7 +817,7 @@ export class LineController extends Controller {
|
|||
async customerRequestCancelWork(
|
||||
@Path() requestWorkId: string,
|
||||
@Request() req: RequestWithLineUser,
|
||||
@Body() body: { reason: string },
|
||||
@Body() body: { cancel: boolean; reason?: string },
|
||||
) {
|
||||
const result = await prisma.requestWork.updateMany({
|
||||
where: {
|
||||
|
|
@ -836,8 +838,10 @@ export class LineController extends Controller {
|
|||
},
|
||||
},
|
||||
data: {
|
||||
customerRequestCancel: true,
|
||||
customerRequestCancelReason: body.reason,
|
||||
customerRequestCancel: body.cancel,
|
||||
customerRequestCancelReason: body.reason || null,
|
||||
rejectRequestCancel: false,
|
||||
rejectRequestCancelReason: null,
|
||||
},
|
||||
});
|
||||
if (result.count <= 0) throw notFoundError("Request Data");
|
||||
|
|
|
|||
25
src/controllers/10-manual-controller.ts
Normal file
25
src/controllers/10-manual-controller.ts
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
import express from "express";
|
||||
import { Controller, Get, Path, Request, Route } from "tsoa";
|
||||
import { getFile } from "../utils/minio";
|
||||
|
||||
@Route("api/v1/manual")
|
||||
export class ManualController extends Controller {
|
||||
@Get()
|
||||
async get(@Request() req: express.Request) {
|
||||
return req.res?.redirect(await getFile(".manual/toc.json"));
|
||||
}
|
||||
|
||||
@Get("{category}/assets/{name}")
|
||||
async getAsset(@Request() req: express.Request, @Path() category: string, @Path() name: string) {
|
||||
return req.res?.redirect(await getFile(`.manual/${category}/assets/${name}`));
|
||||
}
|
||||
|
||||
@Get("{category}/page/{page}")
|
||||
async getContent(
|
||||
@Request() req: express.Request,
|
||||
@Path() category: string,
|
||||
@Path() page: string,
|
||||
) {
|
||||
return req.res?.redirect(await getFile(`.manual/${category}/${page}.md`));
|
||||
}
|
||||
}
|
||||
|
|
@ -55,71 +55,80 @@ export async function deleteFolder(path: string) {
|
|||
});
|
||||
}
|
||||
|
||||
const ROOT = ".system";
|
||||
|
||||
export const fileLocation = {
|
||||
branch: {
|
||||
line: (branchId: string) => `branch/line-qr-${branchId}`,
|
||||
bank: (branchId: string, bankId: string) => `branch/bank-qr-${branchId}-${bankId}`,
|
||||
img: (branchId: string, name?: string) => `branch/img-${branchId}/${name || ""}`,
|
||||
attachment: (branchId: string, name?: string) => `branch/attachment-${branchId}/${name || ""}`,
|
||||
line: (branchId: string) => `${ROOT}/branch/line-qr-${branchId}`,
|
||||
bank: (branchId: string, bankId: string) => `${ROOT}/branch/bank-qr-${branchId}-${bankId}`,
|
||||
img: (branchId: string, name?: string) => `${ROOT}/branch/img-${branchId}/${name || ""}`,
|
||||
attachment: (branchId: string, name?: string) =>
|
||||
`${ROOT}/branch/attachment-${branchId}/${name || ""}`,
|
||||
},
|
||||
user: {
|
||||
profile: (userId: string, name?: string) => `user/profile-image-${userId}/${name || ""}`,
|
||||
attachment: (userId: string, name?: string) => `user/attachment-${userId}/${name || ""}`,
|
||||
profile: (userId: string, name?: string) =>
|
||||
`${ROOT}/user/profile-image-${userId}/${name || ""}`,
|
||||
attachment: (userId: string, name?: string) =>
|
||||
`${ROOT}/user/attachment-${userId}/${name || ""}`,
|
||||
},
|
||||
customer: {
|
||||
img: (customerId: string, name?: string) => `customer/img-${customerId}/${name || ""}`,
|
||||
img: (customerId: string, name?: string) => `${ROOT}/customer/img-${customerId}/${name || ""}`,
|
||||
},
|
||||
customerBranch: {
|
||||
attachment: (customerBranchId: string, name?: string) =>
|
||||
`customer-branch/attachment-${customerBranchId}/${name || ""}`,
|
||||
`${ROOT}/customer-branch/attachment-${customerBranchId}/${name || ""}`,
|
||||
citizen: (customerBranchId: string, citizenId?: string) =>
|
||||
`customer-branch/citizen-${customerBranchId}/${citizenId || ""}`,
|
||||
`${ROOT}/customer-branch/citizen-${customerBranchId}/${citizenId || ""}`,
|
||||
houseRegistration: (customerBranchId: string, houseRegistrationId?: string) =>
|
||||
`customer-branch/house-registration-${customerBranchId}/${houseRegistrationId || ""}`,
|
||||
`${ROOT}/customer-branch/house-registration-${customerBranchId}/${houseRegistrationId || ""}`,
|
||||
commercialRegistration: (customerBranchId: string, commercialRegistrationId?: string) =>
|
||||
`customer-branch/commercial-registration-${customerBranchId}/${commercialRegistrationId || ""}`,
|
||||
`${ROOT}/customer-branch/commercial-registration-${customerBranchId}/${commercialRegistrationId || ""}`,
|
||||
vatRegistration: (customerBranchId: string, vatRegistrationId?: string) =>
|
||||
`customer-branch/vat-registration-${customerBranchId}/${vatRegistrationId || ""}`,
|
||||
`${ROOT}/customer-branch/vat-registration-${customerBranchId}/${vatRegistrationId || ""}`,
|
||||
powerOfAttorney: (customerBranchId: string, powerOfAttorneyId?: string) =>
|
||||
`customer-branch/power-of-attorney-${customerBranchId}/${powerOfAttorneyId || ""}`,
|
||||
`${ROOT}/customer-branch/power-of-attorney-${customerBranchId}/${powerOfAttorneyId || ""}`,
|
||||
},
|
||||
employee: {
|
||||
img: (employeeId: string, name?: string) => `employee/img-${employeeId}/${name || ""}`,
|
||||
img: (employeeId: string, name?: string) => `${ROOT}/employee/img-${employeeId}/${name || ""}`,
|
||||
attachment: (employeeId: string, name?: string) =>
|
||||
`employee/attachment-${employeeId}/${name || ""}`,
|
||||
visa: (employeeId: string, visaId?: string) => `employee/visa-${employeeId}/${visaId || ""}`,
|
||||
`${ROOT}/employee/attachment-${employeeId}/${name || ""}`,
|
||||
visa: (employeeId: string, visaId?: string) =>
|
||||
`${ROOT}/employee/visa-${employeeId}/${visaId || ""}`,
|
||||
passport: (employeeId: string, passportId?: string) =>
|
||||
`employee/passport-${employeeId}/${passportId || ""}`,
|
||||
`${ROOT}/employee/passport-${employeeId}/${passportId || ""}`,
|
||||
inCountryNotice: (employeeId: string, noticeId?: string) =>
|
||||
`employee/in-country-notice-${employeeId}/${noticeId || ""}`,
|
||||
`${ROOT}/employee/in-country-notice-${employeeId}/${noticeId || ""}`,
|
||||
},
|
||||
product: {
|
||||
img: (productId: string, name?: string) => `product/img-${productId}/${name || ""}`,
|
||||
img: (productId: string, name?: string) => `${ROOT}/product/img-${productId}/${name || ""}`,
|
||||
},
|
||||
service: {
|
||||
img: (serviceId: string, name?: string) => `service/img-${serviceId}/${name || ""}`,
|
||||
img: (serviceId: string, name?: string) => `${ROOT}/service/img-${serviceId}/${name || ""}`,
|
||||
},
|
||||
quotation: {
|
||||
attachment: (quotationId: string, name?: string) =>
|
||||
`quotation/attachment-${quotationId}/${name || ""}`,
|
||||
`${ROOT}/quotation/attachment-${quotationId}/${name || ""}`,
|
||||
payment: (quotationId: string, paymentId: string, name?: string) =>
|
||||
`quotation/payment-${quotationId}/${paymentId}/${name || ""}`,
|
||||
`${ROOT}/quotation/payment-${quotationId}/${paymentId}/${name || ""}`,
|
||||
},
|
||||
request: {
|
||||
attachment: (requestId: string, step: number, name?: string) =>
|
||||
`request/attachment-${requestId}-${step}/${name || ""}`,
|
||||
`${ROOT}/request/attachment-${requestId}-${step}/${name || ""}`,
|
||||
},
|
||||
institution: {
|
||||
attachment: (institutionId: string, name?: string) =>
|
||||
`institution/attachment-${institutionId}/${name || ""}`,
|
||||
img: (institutionId: string, name?: string) => `institution/img-${institutionId}/${name || ""}`,
|
||||
`${ROOT}/institution/attachment-${institutionId}/${name || ""}`,
|
||||
img: (institutionId: string, name?: string) =>
|
||||
`${ROOT}/institution/img-${institutionId}/${name || ""}`,
|
||||
},
|
||||
task: {
|
||||
attachment: (taskId: string, name?: string) => `task/attachment-${taskId}/${name || ""}`,
|
||||
attachment: (taskId: string, name?: string) =>
|
||||
`${ROOT}/task/attachment-${taskId}/${name || ""}`,
|
||||
},
|
||||
creditNote: {
|
||||
slip: (creditNoteId: string, name?: string) => `credit-note/slip-${creditNoteId}/${name || ""}`,
|
||||
slip: (creditNoteId: string, name?: string) =>
|
||||
`${ROOT}/credit-note/slip-${creditNoteId}/${name || ""}`,
|
||||
attachment: (creditNoteId: string, name?: string) =>
|
||||
`credit-note/attachment-${creditNoteId}/${name || ""}`,
|
||||
`${ROOT}/credit-note/attachment-${creditNoteId}/${name || ""}`,
|
||||
},
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue