1440 lines
42 KiB
TypeScript
1440 lines
42 KiB
TypeScript
import {
|
|
Body,
|
|
Controller,
|
|
Delete,
|
|
Get,
|
|
Head,
|
|
Path,
|
|
Post,
|
|
Put,
|
|
Query,
|
|
Request,
|
|
Route,
|
|
Security,
|
|
Tags,
|
|
} from "tsoa";
|
|
import { notFoundError } from "../utils/error";
|
|
import prisma from "../db";
|
|
import { RequestWithLineUser, RequestWithUser } from "../interfaces/user";
|
|
import {
|
|
PayCondition,
|
|
Prisma,
|
|
QuotationStatus,
|
|
RequestDataStatus,
|
|
Status,
|
|
TaskStatus,
|
|
RequestWorkStatus,
|
|
} from "@prisma/client";
|
|
import { queryOrNot, whereAddressQuery, whereDateQuery } from "../utils/relation";
|
|
import { filterStatus } from "../services/prisma";
|
|
// import { RequestWorkStatus } from "../generated/kysely/types";
|
|
import { deleteFile, fileLocation, getFile, getPresigned, listFile, setFile } from "../utils/minio";
|
|
import HttpError from "../interfaces/http-error";
|
|
import HttpStatus from "../interfaces/http-status";
|
|
|
|
@Route("api/v1/line")
|
|
@Tags("Line")
|
|
export class LineController extends Controller {
|
|
@Get("employee")
|
|
@Security("line")
|
|
async getEmployeeAll(
|
|
@Request() line: RequestWithLineUser,
|
|
@Query() zipCode?: string,
|
|
@Query() gender?: string,
|
|
@Query() status?: Status,
|
|
@Query() visa?: boolean,
|
|
@Query() passport?: boolean,
|
|
@Query() work?: boolean,
|
|
@Query() customerId?: string,
|
|
@Query() customerBranchId?: string,
|
|
@Query() query: string = "",
|
|
@Query() page: number = 1,
|
|
@Query() pageSize: number = 30,
|
|
@Query() activeOnly?: boolean,
|
|
@Query() startDate?: Date,
|
|
@Query() endDate?: Date,
|
|
) {
|
|
const where = {
|
|
OR: !!query
|
|
? [
|
|
...(queryOrNot<Prisma.EmployeeWhereInput[]>(query, [
|
|
{
|
|
employeePassport: {
|
|
some: { number: { contains: query, mode: "insensitive" } },
|
|
},
|
|
},
|
|
{ firstName: { contains: query, mode: "insensitive" } },
|
|
{ firstNameEN: { contains: query, mode: "insensitive" } },
|
|
{ lastName: { contains: query, mode: "insensitive" } },
|
|
{ lastNameEN: { contains: query, mode: "insensitive" } },
|
|
...whereAddressQuery(query),
|
|
]) ?? []),
|
|
]
|
|
: undefined,
|
|
AND: {
|
|
...filterStatus(activeOnly ? Status.ACTIVE : status),
|
|
customerBranch: {
|
|
status: activeOnly ? { not: Status.INACTIVE } : undefined,
|
|
id: customerBranchId,
|
|
customerId,
|
|
OR: [
|
|
{ userId: line.user.sub },
|
|
{
|
|
customer: {
|
|
branch: { some: { userId: line.user.sub } },
|
|
},
|
|
},
|
|
],
|
|
},
|
|
subDistrict: zipCode ? { zipCode } : undefined,
|
|
gender,
|
|
},
|
|
...whereDateQuery(startDate, endDate),
|
|
} satisfies Prisma.EmployeeWhereInput;
|
|
|
|
const [result, total] = await prisma.$transaction([
|
|
prisma.employee.findMany({
|
|
orderBy: [{ statusOrder: "asc" }, { createdAt: "asc" }],
|
|
include: {
|
|
employeeWork: work ? { orderBy: { workPermitExpireDate: "desc" } } : undefined,
|
|
employeePassport: passport ? { orderBy: { expireDate: "desc" } } : undefined,
|
|
employeeVisa: visa ? { orderBy: { expireDate: "desc" } } : undefined,
|
|
province: true,
|
|
district: true,
|
|
subDistrict: true,
|
|
customerBranch: {
|
|
include: { customer: true },
|
|
},
|
|
createdBy: true,
|
|
updatedBy: true,
|
|
},
|
|
where,
|
|
take: pageSize,
|
|
skip: (page - 1) * pageSize,
|
|
}),
|
|
prisma.employee.count({ where }),
|
|
]);
|
|
|
|
return {
|
|
result,
|
|
page,
|
|
pageSize,
|
|
total,
|
|
};
|
|
}
|
|
|
|
@Get("employee/{employeeId}")
|
|
@Security("line")
|
|
async getEmployeeById(@Path() employeeId: string, @Request() line: RequestWithLineUser) {
|
|
const record = await prisma.employee.findFirst({
|
|
include: {
|
|
employeePassport: true,
|
|
employeeVisa: true,
|
|
employeeWork: true,
|
|
employeeCheckup: true,
|
|
employeeOtherInfo: true,
|
|
customerBranch: {
|
|
include: {
|
|
customer: true,
|
|
},
|
|
},
|
|
province: true,
|
|
district: true,
|
|
subDistrict: true,
|
|
createdBy: true,
|
|
updatedBy: true,
|
|
},
|
|
where: {
|
|
id: employeeId,
|
|
customerBranch: {
|
|
OR: [
|
|
{ userId: line.user.sub },
|
|
{
|
|
customer: {
|
|
branch: { some: { userId: line.user.sub } },
|
|
},
|
|
},
|
|
],
|
|
},
|
|
},
|
|
});
|
|
|
|
if (!record) throw notFoundError("Employee");
|
|
|
|
return record;
|
|
}
|
|
|
|
@Get("request")
|
|
@Security("line")
|
|
async getRequestAll(
|
|
@Request() req: RequestWithUser,
|
|
@Request() line: RequestWithLineUser,
|
|
@Query() page: number = 1,
|
|
@Query() pageSize: number = 30,
|
|
@Query() query: string = "",
|
|
@Query() responsibleOnly?: boolean,
|
|
@Query() requestDataStatus?: RequestDataStatus,
|
|
@Query() quotationId?: string,
|
|
@Query() code?: string,
|
|
@Query() startDate?: Date,
|
|
@Query() endDate?: Date,
|
|
) {
|
|
const where = {
|
|
OR: queryOrNot<Prisma.RequestDataWhereInput[]>(query, [
|
|
{ code: { contains: query, mode: "insensitive" } },
|
|
{ quotation: { code: { contains: query, mode: "insensitive" } } },
|
|
{ quotation: { workName: { contains: query, mode: "insensitive" } } },
|
|
{
|
|
quotation: {
|
|
customerBranch: {
|
|
OR: [
|
|
{ code: { contains: query, mode: "insensitive" } },
|
|
{ registerName: { contains: query, mode: "insensitive" } },
|
|
{ registerNameEN: { contains: query, mode: "insensitive" } },
|
|
{ firstName: { contains: query, mode: "insensitive" } },
|
|
{ firstNameEN: { contains: query, mode: "insensitive" } },
|
|
{ lastName: { contains: query, mode: "insensitive" } },
|
|
{ lastNameEN: { contains: query, mode: "insensitive" } },
|
|
],
|
|
},
|
|
},
|
|
employee: {
|
|
OR: [
|
|
{
|
|
employeePassport: {
|
|
some: { number: { contains: query, mode: "insensitive" } },
|
|
},
|
|
},
|
|
{ code: { contains: query, mode: "insensitive" } },
|
|
{ firstName: { contains: query, mode: "insensitive" } },
|
|
{ firstNameEN: { contains: query, mode: "insensitive" } },
|
|
{ lastName: { contains: query, mode: "insensitive" } },
|
|
{ lastNameEN: { contains: query, mode: "insensitive" } },
|
|
],
|
|
},
|
|
},
|
|
]),
|
|
code,
|
|
requestDataStatus,
|
|
requestWork: responsibleOnly
|
|
? {
|
|
some: {
|
|
productService: {
|
|
service: {
|
|
workflow: {
|
|
step: {
|
|
some: {
|
|
responsiblePerson: {
|
|
some: { userId: req.user.sub },
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
: undefined,
|
|
quotation: {
|
|
id: quotationId,
|
|
// registeredBranch: { OR: permissionCond(req.user) },
|
|
},
|
|
employee: {
|
|
customerBranch: {
|
|
OR: [
|
|
{ userId: line.user.sub },
|
|
{
|
|
customer: {
|
|
branch: { some: { userId: line.user.sub } },
|
|
},
|
|
},
|
|
],
|
|
},
|
|
},
|
|
...whereDateQuery(startDate, endDate),
|
|
} satisfies Prisma.RequestDataWhereInput;
|
|
|
|
const [result, total] = await prisma.$transaction([
|
|
prisma.requestData.findMany({
|
|
where,
|
|
include: {
|
|
quotation: {
|
|
include: {
|
|
productServiceList: {
|
|
include: {
|
|
service: {
|
|
include: {
|
|
workflow: {
|
|
include: {
|
|
step: {
|
|
orderBy: { order: "asc" },
|
|
include: {
|
|
value: true,
|
|
responsiblePerson: {
|
|
include: { user: true },
|
|
},
|
|
responsibleInstitution: true,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
customerBranch: {
|
|
include: { customer: true },
|
|
},
|
|
},
|
|
},
|
|
employee: {
|
|
include: {
|
|
employeePassport: {
|
|
orderBy: { expireDate: "desc" },
|
|
},
|
|
},
|
|
},
|
|
},
|
|
take: pageSize,
|
|
skip: (page - 1) * pageSize,
|
|
orderBy: [{ quotation: { urgent: "desc" } }, { createdAt: "desc" }],
|
|
}),
|
|
prisma.requestData.count({ where }),
|
|
]);
|
|
|
|
return { result, page, pageSize, total };
|
|
}
|
|
|
|
@Get("request/{requestDataId}")
|
|
@Security("line")
|
|
async getRequestById(@Path() requestDataId: string, @Request() line: RequestWithLineUser) {
|
|
const record = await prisma.requestData.findFirst({
|
|
where: {
|
|
id: requestDataId,
|
|
employee: {
|
|
customerBranch: {
|
|
OR: [
|
|
{ userId: line.user.sub },
|
|
{
|
|
customer: {
|
|
branch: { some: { userId: line.user.sub } },
|
|
},
|
|
},
|
|
],
|
|
},
|
|
},
|
|
},
|
|
include: {
|
|
quotation: {
|
|
include: {
|
|
customerBranch: { include: { customer: true } },
|
|
productServiceList: {
|
|
include: {
|
|
service: {
|
|
include: {
|
|
workflow: {
|
|
include: {
|
|
step: {
|
|
orderBy: { order: "asc" },
|
|
include: {
|
|
value: true,
|
|
responsiblePerson: {
|
|
include: { user: true },
|
|
},
|
|
responsibleInstitution: true,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
invoice: {
|
|
include: {
|
|
installments: true,
|
|
payment: true,
|
|
},
|
|
},
|
|
createdBy: true,
|
|
},
|
|
},
|
|
employee: {
|
|
include: {
|
|
employeePassport: {
|
|
orderBy: { expireDate: "desc" },
|
|
},
|
|
},
|
|
},
|
|
requestWork: {
|
|
include: {
|
|
stepStatus: true,
|
|
productService: {
|
|
include: {
|
|
product: true,
|
|
work: true,
|
|
service: true,
|
|
},
|
|
},
|
|
processByUser: true,
|
|
},
|
|
},
|
|
},
|
|
});
|
|
if (!record) throw notFoundError("Request Data");
|
|
return record;
|
|
}
|
|
|
|
@Get("request-work")
|
|
@Security("line")
|
|
async getRequestWorkAll(
|
|
@Query() pageSize: number = 30,
|
|
@Query() page: number = 1,
|
|
@Request() line: RequestWithLineUser,
|
|
@Query() requestDataId?: string,
|
|
@Query() workStatus?: RequestWorkStatus,
|
|
@Query() readyToTask?: boolean,
|
|
@Query() cancelOnly?: boolean,
|
|
@Query() quotationId?: string,
|
|
) {
|
|
let statusCondition: Prisma.RequestWorkWhereInput["stepStatus"] = {};
|
|
if (readyToTask) {
|
|
statusCondition = {
|
|
some: {
|
|
OR: [
|
|
{ workStatus: RequestWorkStatus.Ready },
|
|
{
|
|
workStatus: { in: [RequestWorkStatus.Ready, RequestWorkStatus.InProgress] },
|
|
task: {
|
|
some: {
|
|
taskStatus: TaskStatus.Redo,
|
|
requestWorkStep: {
|
|
workStatus: { notIn: [RequestWorkStatus.Completed, RequestWorkStatus.Ended] },
|
|
},
|
|
},
|
|
},
|
|
},
|
|
],
|
|
},
|
|
};
|
|
}
|
|
if (cancelOnly) {
|
|
statusCondition = {
|
|
some: { workStatus: RequestWorkStatus.Canceled },
|
|
};
|
|
}
|
|
if (workStatus && !readyToTask && !cancelOnly) {
|
|
statusCondition = {
|
|
some: { workStatus },
|
|
};
|
|
}
|
|
const where = {
|
|
stepStatus: readyToTask || cancelOnly || workStatus ? statusCondition : undefined,
|
|
creditNote: cancelOnly ? null : undefined,
|
|
request: {
|
|
id: requestDataId,
|
|
requestDataStatus: readyToTask
|
|
? { notIn: [RequestDataStatus.Canceled, RequestDataStatus.Completed] }
|
|
: undefined,
|
|
quotationId,
|
|
employee: {
|
|
customerBranch: {
|
|
OR: [
|
|
{ userId: line.user.sub },
|
|
{
|
|
customer: {
|
|
branch: { some: { userId: line.user.sub } },
|
|
},
|
|
},
|
|
],
|
|
},
|
|
},
|
|
},
|
|
} satisfies Prisma.RequestWorkWhereInput;
|
|
const [result, total] = await prisma.$transaction([
|
|
prisma.requestWork.findMany({
|
|
where,
|
|
include: {
|
|
request: {
|
|
include: {
|
|
quotation: readyToTask
|
|
? {
|
|
include: {
|
|
customerBranch: {
|
|
include: { customer: true },
|
|
},
|
|
},
|
|
}
|
|
: true,
|
|
employee: true,
|
|
},
|
|
},
|
|
stepStatus: cancelOnly
|
|
? true
|
|
: {
|
|
include: {
|
|
task: { where: { taskStatus: TaskStatus.Complete } },
|
|
},
|
|
},
|
|
productService: {
|
|
include: {
|
|
service: {
|
|
include: {
|
|
workflow: {
|
|
include: {
|
|
step: {
|
|
include: {
|
|
value: true,
|
|
responsiblePerson: {
|
|
include: { user: true },
|
|
},
|
|
responsibleInstitution: true,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
work: true,
|
|
product: {
|
|
include: { document: true },
|
|
},
|
|
},
|
|
},
|
|
},
|
|
take: pageSize,
|
|
skip: (page - 1) * pageSize,
|
|
}),
|
|
prisma.requestWork.count({ where }),
|
|
]);
|
|
return {
|
|
result: result.map((v) => {
|
|
return Object.assign(v, {
|
|
productService: Object.assign(v.productService, {
|
|
product: Object.assign(v.productService.product, {
|
|
document: v.productService.product.document.map((doc) => doc.name),
|
|
}),
|
|
}),
|
|
});
|
|
}),
|
|
page,
|
|
pageSize,
|
|
total,
|
|
};
|
|
}
|
|
|
|
@Get("request-work/{requestWorkId}")
|
|
@Security("line")
|
|
async getReguetWorkById(@Path() requestWorkId: string, @Request() line: RequestWithLineUser) {
|
|
const record = await prisma.requestWork.findFirst({
|
|
include: {
|
|
request: {
|
|
include: {
|
|
quotation: true,
|
|
employee: true,
|
|
},
|
|
},
|
|
stepStatus: true,
|
|
productService: {
|
|
include: {
|
|
service: {
|
|
include: {
|
|
workflow: {
|
|
include: {
|
|
step: {
|
|
include: {
|
|
value: true,
|
|
responsiblePerson: {
|
|
include: { user: true },
|
|
},
|
|
responsibleInstitution: true,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
work: true,
|
|
product: {
|
|
include: {
|
|
document: true,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
where: {
|
|
id: requestWorkId,
|
|
request: {
|
|
employee: {
|
|
customerBranch: {
|
|
OR: [
|
|
{ userId: line.user.sub },
|
|
{
|
|
customer: {
|
|
branch: { some: { userId: line.user.sub } },
|
|
},
|
|
},
|
|
],
|
|
},
|
|
},
|
|
},
|
|
},
|
|
});
|
|
|
|
if (!record) throw notFoundError("Request Work");
|
|
|
|
return Object.assign(record, {
|
|
productService: Object.assign(record.productService, {
|
|
product: Object.assign(record.productService.product, {
|
|
document: record.productService.product.document.map((doc) => doc.name),
|
|
}),
|
|
}),
|
|
});
|
|
}
|
|
|
|
@Get("quotation")
|
|
@Security("line")
|
|
async getQuotationList(
|
|
@Request() line: RequestWithLineUser,
|
|
@Query() page: number = 1,
|
|
@Query() pageSize: number = 30,
|
|
@Query() payCondition?: PayCondition,
|
|
@Query() status?: QuotationStatus,
|
|
@Query() pendingOnly?: boolean,
|
|
@Query() inProgressOnly?: boolean,
|
|
@Query() successOnly?: boolean,
|
|
@Query() canceledOnly?: boolean,
|
|
@Query() urgentFirst?: boolean,
|
|
@Query() includeRegisteredBranch?: boolean,
|
|
@Query() code?: string,
|
|
@Query() query = "",
|
|
@Query() startDate?: Date,
|
|
@Query() endDate?: Date,
|
|
) {
|
|
const where = {
|
|
OR:
|
|
query || pendingOnly
|
|
? [
|
|
...(queryOrNot<Prisma.QuotationWhereInput[]>(query, [
|
|
{ code: { contains: query, mode: "insensitive" } },
|
|
{ workName: { contains: query, mode: "insensitive" } },
|
|
{
|
|
customerBranch: {
|
|
OR: [
|
|
{ code: { contains: query, mode: "insensitive" } },
|
|
{ registerName: { contains: query, mode: "insensitive" } },
|
|
{ firstName: { contains: query, mode: "insensitive" } },
|
|
{ firstNameEN: { contains: query, mode: "insensitive" } },
|
|
{ lastName: { contains: query, mode: "insensitive" } },
|
|
{ lastNameEN: { contains: query, mode: "insensitive" } },
|
|
],
|
|
},
|
|
},
|
|
]) || []),
|
|
...(queryOrNot<Prisma.QuotationWhereInput[]>(!!pendingOnly, [
|
|
{
|
|
requestData: {
|
|
some: {
|
|
requestDataStatus: "Pending",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
requestData: { none: {} },
|
|
},
|
|
]) || []),
|
|
]
|
|
: undefined,
|
|
isDebitNote: false,
|
|
code,
|
|
payCondition,
|
|
quotationStatus: successOnly ? "ProcessComplete" : canceledOnly ? "Canceled" : status,
|
|
customerBranch: {
|
|
OR: [
|
|
{ userId: line.user.sub },
|
|
{
|
|
customer: {
|
|
branch: { some: { userId: line.user.sub } },
|
|
},
|
|
},
|
|
],
|
|
},
|
|
requestData: inProgressOnly
|
|
? {
|
|
some: {
|
|
requestDataStatus: "InProgress",
|
|
},
|
|
}
|
|
: undefined,
|
|
...whereDateQuery(startDate, endDate),
|
|
} satisfies Prisma.QuotationWhereInput;
|
|
|
|
const [result, total] = await prisma.$transaction([
|
|
prisma.quotation.findMany({
|
|
where,
|
|
include: {
|
|
_count: {
|
|
select: { worker: true },
|
|
},
|
|
registeredBranch: includeRegisteredBranch,
|
|
customerBranch: {
|
|
include: {
|
|
customer: {
|
|
include: { registeredBranch: true },
|
|
},
|
|
},
|
|
},
|
|
invoice: {
|
|
include: { payment: true },
|
|
},
|
|
paySplit: {
|
|
orderBy: { no: "asc" },
|
|
},
|
|
createdBy: true,
|
|
updatedBy: true,
|
|
},
|
|
orderBy: urgentFirst ? [{ urgent: "desc" }, { createdAt: "desc" }] : { createdAt: "desc" },
|
|
take: pageSize,
|
|
skip: (page - 1) * pageSize,
|
|
}),
|
|
prisma.quotation.count({ where }),
|
|
]);
|
|
|
|
return { result, page, pageSize, total };
|
|
}
|
|
|
|
@Get("quotation/{quotationId}")
|
|
@Security("line")
|
|
async getQuotationById(@Path() quotationId: string, @Request() line: RequestWithLineUser) {
|
|
const record = await prisma.quotation.findUnique({
|
|
include: {
|
|
_count: {
|
|
select: { worker: true },
|
|
},
|
|
registeredBranch: true,
|
|
customerBranch: {
|
|
include: {
|
|
province: true,
|
|
district: true,
|
|
subDistrict: true,
|
|
},
|
|
},
|
|
worker: {
|
|
include: {
|
|
employee: {
|
|
include: {
|
|
employeePassport: {
|
|
orderBy: { expireDate: "desc" },
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
debitNote: true,
|
|
productServiceList: {
|
|
include: {
|
|
service: {
|
|
include: {
|
|
productGroup: true,
|
|
work: {
|
|
include: {
|
|
productOnWork: {
|
|
include: {
|
|
product: true,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
work: true,
|
|
product: {
|
|
include: { productGroup: true },
|
|
},
|
|
|
|
worker: true,
|
|
},
|
|
},
|
|
paySplit: {
|
|
include: { invoice: true },
|
|
orderBy: { no: "asc" },
|
|
},
|
|
invoice: {
|
|
include: { payment: true },
|
|
},
|
|
createdBy: true,
|
|
updatedBy: true,
|
|
},
|
|
where: {
|
|
id: quotationId,
|
|
isDebitNote: false,
|
|
customerBranch: {
|
|
OR: [
|
|
{ userId: line.user.sub },
|
|
{
|
|
customer: {
|
|
branch: { some: { userId: line.user.sub } },
|
|
},
|
|
},
|
|
],
|
|
},
|
|
},
|
|
});
|
|
|
|
if (!record) throw notFoundError("Quotation");
|
|
|
|
return record;
|
|
}
|
|
|
|
@Post("request/{requestDataId}/request-cancel")
|
|
@Security("line")
|
|
async customerRequestCancel(
|
|
@Path() requestDataId: string,
|
|
@Request() req: RequestWithLineUser,
|
|
@Body() body: { cancel: boolean; reason?: string },
|
|
) {
|
|
const result = await prisma.requestData.updateMany({
|
|
where: {
|
|
id: requestDataId,
|
|
quotation: {
|
|
customerBranch: {
|
|
OR: [
|
|
{ userId: req.user.sub },
|
|
{
|
|
customer: {
|
|
branch: { some: { userId: req.user.sub } },
|
|
},
|
|
},
|
|
],
|
|
},
|
|
},
|
|
},
|
|
data: {
|
|
customerRequestCancel: body.cancel,
|
|
customerRequestCancelReason: body.reason || null,
|
|
rejectRequestCancel: false,
|
|
rejectRequestCancelReason: null,
|
|
},
|
|
});
|
|
if (result.count <= 0) throw notFoundError("Request Data");
|
|
}
|
|
|
|
@Post("request-work/{requestWorkId}/request-cancel")
|
|
@Security("line")
|
|
async customerRequestCancelWork(
|
|
@Path() requestWorkId: string,
|
|
@Request() req: RequestWithLineUser,
|
|
@Body() body: { cancel: boolean; reason?: string },
|
|
) {
|
|
const result = await prisma.requestWork.updateMany({
|
|
where: {
|
|
id: requestWorkId,
|
|
request: {
|
|
quotation: {
|
|
customerBranch: {
|
|
OR: [
|
|
{ userId: req.user.sub },
|
|
{
|
|
customer: {
|
|
branch: { some: { userId: req.user.sub } },
|
|
},
|
|
},
|
|
],
|
|
},
|
|
},
|
|
},
|
|
},
|
|
data: {
|
|
customerRequestCancel: body.cancel,
|
|
customerRequestCancelReason: body.reason || null,
|
|
rejectRequestCancel: false,
|
|
rejectRequestCancelReason: null,
|
|
},
|
|
});
|
|
if (result.count <= 0) throw notFoundError("Request Data");
|
|
}
|
|
}
|
|
|
|
@Route("api/v1/line/customer-branch/{branchId}")
|
|
@Tags("Line")
|
|
export class LineCustomerBranchFileController extends Controller {
|
|
private async checkPermission(_user: RequestWithUser["user"], _id: string) {
|
|
return;
|
|
}
|
|
|
|
@Get("attachment")
|
|
@Security("line")
|
|
async listAttachment(@Request() req: RequestWithUser, @Path() branchId: string) {
|
|
await this.checkPermission(req.user, branchId);
|
|
return await listFile(fileLocation.customerBranch.attachment(branchId));
|
|
}
|
|
|
|
@Get("attachment/{name}")
|
|
@Security("line")
|
|
async getAttachment(@Path() branchId: string, @Path() name: string) {
|
|
return await getFile(fileLocation.customerBranch.attachment(branchId, name));
|
|
}
|
|
|
|
@Head("attachment/{name}")
|
|
@Security("line")
|
|
async headAttachment(@Path() branchId: string, @Path() name: string) {
|
|
return await getPresigned("head", fileLocation.customerBranch.attachment(branchId, name));
|
|
}
|
|
|
|
@Put("attachment/{name}")
|
|
@Security("line")
|
|
async putAttachment(
|
|
@Request() req: RequestWithUser,
|
|
@Path() branchId: string,
|
|
@Path() name: string,
|
|
) {
|
|
await this.checkPermission(req.user, branchId);
|
|
return await setFile(fileLocation.customerBranch.attachment(branchId, name));
|
|
}
|
|
|
|
@Delete("attachment/{name}")
|
|
@Security("line")
|
|
async delAttachment(
|
|
@Request() req: RequestWithUser,
|
|
@Path() branchId: string,
|
|
@Path() name: string,
|
|
) {
|
|
await this.checkPermission(req.user, branchId);
|
|
return await deleteFile(fileLocation.customerBranch.attachment(branchId, name));
|
|
}
|
|
|
|
@Get("file-citizen")
|
|
@Security("line")
|
|
async listCitizen(@Request() req: RequestWithUser, @Path() branchId: string) {
|
|
await this.checkPermission(req.user, branchId);
|
|
return await listFile(fileLocation.customerBranch.citizen(branchId));
|
|
}
|
|
|
|
@Get("file-citizen/{id}")
|
|
@Security("line")
|
|
async getCitizen(@Path() branchId: string, @Path() id: string) {
|
|
return await getFile(fileLocation.customerBranch.citizen(branchId, id));
|
|
}
|
|
|
|
@Put("file-citizen/{id}")
|
|
@Security("line")
|
|
async putCitizen(@Request() req: RequestWithUser, @Path() branchId: string, @Path() id: string) {
|
|
await this.checkPermission(req.user, branchId);
|
|
return req.res?.redirect(await setFile(fileLocation.customerBranch.citizen(branchId, id)));
|
|
}
|
|
|
|
@Delete("file-citizen/{id}")
|
|
@Security("line")
|
|
async delCitizen(@Request() req: RequestWithUser, @Path() branchId: string, @Path() id: string) {
|
|
await this.checkPermission(req.user, branchId);
|
|
return await deleteFile(fileLocation.customerBranch.citizen(branchId, id));
|
|
}
|
|
|
|
@Get("file-power-of-attorney")
|
|
@Security("line")
|
|
async listPoa(@Request() req: RequestWithUser, @Path() branchId: string) {
|
|
await this.checkPermission(req.user, branchId);
|
|
return await listFile(fileLocation.customerBranch.powerOfAttorney(branchId));
|
|
}
|
|
|
|
@Get("file-power-of-attorney/{id}")
|
|
@Security("line")
|
|
async getPoa(@Path() branchId: string, @Path() id: string) {
|
|
return await getFile(fileLocation.customerBranch.powerOfAttorney(branchId, id));
|
|
}
|
|
|
|
@Put("file-power-of-attorney/{id}")
|
|
@Security("line")
|
|
async putPoa(@Request() req: RequestWithUser, @Path() branchId: string, @Path() id: string) {
|
|
await this.checkPermission(req.user, branchId);
|
|
return req.res?.redirect(
|
|
await setFile(fileLocation.customerBranch.powerOfAttorney(branchId, id)),
|
|
);
|
|
}
|
|
|
|
@Delete("file-power-of-attorney/{id}")
|
|
@Security("line")
|
|
async delPoa(@Request() req: RequestWithUser, @Path() branchId: string, @Path() id: string) {
|
|
await this.checkPermission(req.user, branchId);
|
|
return await deleteFile(fileLocation.customerBranch.powerOfAttorney(branchId, id));
|
|
}
|
|
|
|
@Get("file-house-registration")
|
|
@Security("line")
|
|
async listHouseRegis(@Request() req: RequestWithUser, @Path() branchId: string) {
|
|
await this.checkPermission(req.user, branchId);
|
|
return await listFile(fileLocation.customerBranch.houseRegistration(branchId));
|
|
}
|
|
|
|
@Get("file-house-registration/{id}")
|
|
@Security("line")
|
|
async getHouseRegis(@Path() branchId: string, @Path() id: string) {
|
|
return await getFile(fileLocation.customerBranch.houseRegistration(branchId, id));
|
|
}
|
|
|
|
@Put("file-house-registration/{id}")
|
|
@Security("line")
|
|
async putHouseRegis(
|
|
@Request() req: RequestWithUser,
|
|
@Path() branchId: string,
|
|
@Path() id: string,
|
|
) {
|
|
await this.checkPermission(req.user, branchId);
|
|
return req.res?.redirect(
|
|
await setFile(fileLocation.customerBranch.houseRegistration(branchId, id)),
|
|
);
|
|
}
|
|
|
|
@Delete("file-house-registration/{id}")
|
|
@Security("line")
|
|
async delHouseRegis(
|
|
@Request() req: RequestWithUser,
|
|
@Path() branchId: string,
|
|
@Path() id: string,
|
|
) {
|
|
await this.checkPermission(req.user, branchId);
|
|
return await deleteFile(fileLocation.customerBranch.houseRegistration(branchId, id));
|
|
}
|
|
|
|
@Get("file-commercial-registration")
|
|
@Security("line")
|
|
async listCommercialRegis(@Request() req: RequestWithUser, @Path() branchId: string) {
|
|
await this.checkPermission(req.user, branchId);
|
|
return await listFile(fileLocation.customerBranch.commercialRegistration(branchId));
|
|
}
|
|
|
|
@Get("file-commercial-registration/{id}")
|
|
@Security("line")
|
|
async getCommercialRegis(@Path() branchId: string, @Path() id: string) {
|
|
return await getFile(fileLocation.customerBranch.commercialRegistration(branchId, id));
|
|
}
|
|
|
|
@Put("file-commercial-registration/{id}")
|
|
@Security("line")
|
|
async putCommercialRegis(
|
|
@Request() req: RequestWithUser,
|
|
@Path() branchId: string,
|
|
@Path() id: string,
|
|
) {
|
|
await this.checkPermission(req.user, branchId);
|
|
return req.res?.redirect(
|
|
await setFile(fileLocation.customerBranch.commercialRegistration(branchId, id)),
|
|
);
|
|
}
|
|
|
|
@Delete("file-commercial-registration/{id}")
|
|
@Security("line")
|
|
async delCommercialRegis(
|
|
@Request() req: RequestWithUser,
|
|
@Path() branchId: string,
|
|
@Path() id: string,
|
|
) {
|
|
await this.checkPermission(req.user, branchId);
|
|
return await deleteFile(fileLocation.customerBranch.commercialRegistration(branchId, id));
|
|
}
|
|
|
|
@Get("file-vat-registration")
|
|
@Security("line")
|
|
async listVatRegis(@Request() req: RequestWithUser, @Path() branchId: string) {
|
|
await this.checkPermission(req.user, branchId);
|
|
return await listFile(fileLocation.customerBranch.vatRegistration(branchId));
|
|
}
|
|
|
|
@Get("file-vat-registration/{id}")
|
|
@Security("line")
|
|
async getVatRegis(@Path() branchId: string, @Path() id: string) {
|
|
return await getFile(fileLocation.customerBranch.vatRegistration(branchId, id));
|
|
}
|
|
|
|
@Put("file-vat-registration/{id}")
|
|
@Security("line")
|
|
async putVatRegis(@Request() req: RequestWithUser, @Path() branchId: string, @Path() id: string) {
|
|
await this.checkPermission(req.user, branchId);
|
|
return req.res?.redirect(
|
|
await setFile(fileLocation.customerBranch.vatRegistration(branchId, id)),
|
|
);
|
|
}
|
|
|
|
@Delete("file-vat-registration/{id}")
|
|
@Security("line")
|
|
async delVatRegis(@Request() req: RequestWithUser, @Path() branchId: string, @Path() id: string) {
|
|
await this.checkPermission(req.user, branchId);
|
|
return await deleteFile(fileLocation.customerBranch.vatRegistration(branchId, id));
|
|
}
|
|
}
|
|
|
|
@Route("api/v1/line/employee/{employeeId}")
|
|
@Tags("Line")
|
|
export class LineEmployeeFileController extends Controller {
|
|
private async checkPermission(_user: RequestWithUser["user"], _id: string) {
|
|
return;
|
|
}
|
|
|
|
@Get("image")
|
|
@Security("line")
|
|
async listImage(@Request() req: RequestWithUser, @Path() employeeId: string) {
|
|
await this.checkPermission(req.user, employeeId);
|
|
return await listFile(fileLocation.employee.img(employeeId));
|
|
}
|
|
|
|
@Get("image/{name}")
|
|
async getImage(
|
|
@Request() req: RequestWithUser,
|
|
@Path() employeeId: string,
|
|
@Path() name: string,
|
|
) {
|
|
return req.res?.redirect(await getFile(fileLocation.employee.img(employeeId, name)));
|
|
}
|
|
|
|
@Head("image/{name}")
|
|
async headImage(
|
|
@Request() req: RequestWithUser,
|
|
@Path() employeeId: string,
|
|
@Path() name: string,
|
|
) {
|
|
return req.res?.redirect(
|
|
await getPresigned("head", fileLocation.employee.img(employeeId, name)),
|
|
);
|
|
}
|
|
|
|
@Put("image/{name}")
|
|
@Security("line")
|
|
async putImage(
|
|
@Request() req: RequestWithUser,
|
|
@Path() employeeId: string,
|
|
@Path() name: string,
|
|
) {
|
|
if (!req.headers["content-type"]?.startsWith("image/")) {
|
|
throw new HttpError(HttpStatus.BAD_REQUEST, "Not a valid image.", "notValidImage");
|
|
}
|
|
await this.checkPermission(req.user, employeeId);
|
|
return req.res?.redirect(await setFile(fileLocation.employee.img(employeeId, name)));
|
|
}
|
|
|
|
@Delete("image/{name}")
|
|
@Security("line")
|
|
async delImage(
|
|
@Request() req: RequestWithUser,
|
|
@Path() employeeId: string,
|
|
@Path() name: string,
|
|
) {
|
|
await this.checkPermission(req.user, employeeId);
|
|
return await deleteFile(fileLocation.employee.img(employeeId, name));
|
|
}
|
|
|
|
@Get("attachment")
|
|
@Security("line")
|
|
async listAttachment(@Request() req: RequestWithUser, @Path() employeeId: string) {
|
|
await this.checkPermission(req.user, employeeId);
|
|
return await listFile(fileLocation.employee.attachment(employeeId));
|
|
}
|
|
|
|
@Get("attachment/{name}")
|
|
@Security("line")
|
|
async getAttachment(@Path() employeeId: string, @Path() name: string) {
|
|
return await getFile(fileLocation.employee.attachment(employeeId, name));
|
|
}
|
|
|
|
@Head("attachment/{name}")
|
|
@Security("line")
|
|
async headAttachment(
|
|
@Request() req: RequestWithUser,
|
|
@Path() employeeId: string,
|
|
@Path() name: string,
|
|
) {
|
|
return req.res?.redirect(
|
|
await getPresigned("head", fileLocation.employee.attachment(employeeId, name)),
|
|
);
|
|
}
|
|
|
|
@Put("attachment/{name}")
|
|
@Security("line")
|
|
async putAttachment(
|
|
@Request() req: RequestWithUser,
|
|
@Path() employeeId: string,
|
|
@Path() name: string,
|
|
) {
|
|
await this.checkPermission(req.user, employeeId);
|
|
return await setFile(fileLocation.employee.attachment(employeeId, name));
|
|
}
|
|
|
|
@Delete("attachment/{name}")
|
|
@Security("line")
|
|
async delAttachment(
|
|
@Request() req: RequestWithUser,
|
|
@Path() employeeId: string,
|
|
@Path() name: string,
|
|
) {
|
|
await this.checkPermission(req.user, employeeId);
|
|
return await deleteFile(fileLocation.employee.attachment(employeeId, name));
|
|
}
|
|
|
|
@Get("file-passport")
|
|
@Security("line")
|
|
async listPassport(@Request() req: RequestWithUser, @Path() employeeId: string) {
|
|
await this.checkPermission(req.user, employeeId);
|
|
return await listFile(fileLocation.employee.passport(employeeId));
|
|
}
|
|
|
|
@Get("file-passport/{passportId}")
|
|
@Security("line")
|
|
async getPassport(@Path() employeeId: string, @Path() passportId: string) {
|
|
return await getFile(fileLocation.employee.passport(employeeId, passportId));
|
|
}
|
|
|
|
@Head("file-passport/{passportId}")
|
|
@Security("line")
|
|
async headPassport(
|
|
@Request() req: RequestWithUser,
|
|
@Path() employeeId: string,
|
|
@Path() passportId: string,
|
|
) {
|
|
return req.res?.redirect(
|
|
await getPresigned("head", fileLocation.employee.passport(employeeId, passportId)),
|
|
);
|
|
}
|
|
|
|
@Put("file-passport/{passportId}")
|
|
@Security("line")
|
|
async putPassport(
|
|
@Request() req: RequestWithUser,
|
|
@Path() employeeId: string,
|
|
@Path() passportId: string,
|
|
) {
|
|
await this.checkPermission(req.user, employeeId);
|
|
return req.res?.redirect(await setFile(fileLocation.employee.passport(employeeId, passportId)));
|
|
}
|
|
|
|
@Delete("file-passport/{passportId}")
|
|
@Security("line")
|
|
async delPassport(
|
|
@Request() req: RequestWithUser,
|
|
@Path() employeeId: string,
|
|
@Path() passportId: string,
|
|
) {
|
|
await this.checkPermission(req.user, employeeId);
|
|
return await deleteFile(fileLocation.employee.passport(employeeId, passportId));
|
|
}
|
|
|
|
@Get("file-visa")
|
|
@Security("line")
|
|
async listVisa(@Request() req: RequestWithUser, @Path() employeeId: string) {
|
|
await this.checkPermission(req.user, employeeId);
|
|
return await listFile(fileLocation.employee.visa(employeeId));
|
|
}
|
|
|
|
@Get("file-visa/{visaId}")
|
|
@Security("line")
|
|
async getVisa(@Path() employeeId: string, @Path() visaId: string) {
|
|
return await getFile(fileLocation.employee.visa(employeeId, visaId));
|
|
}
|
|
|
|
@Head("file-visa/{visaId}")
|
|
@Security("line")
|
|
async headVisa(
|
|
@Request() req: RequestWithUser,
|
|
@Path() employeeId: string,
|
|
@Path() visaId: string,
|
|
) {
|
|
return req.res?.redirect(
|
|
await getPresigned("head", fileLocation.employee.visa(employeeId, visaId)),
|
|
);
|
|
}
|
|
|
|
@Put("file-visa/{visaId}")
|
|
@Security("line")
|
|
async putVisa(
|
|
@Request() req: RequestWithUser,
|
|
@Path() employeeId: string,
|
|
@Path() visaId: string,
|
|
) {
|
|
await this.checkPermission(req.user, employeeId);
|
|
return req.res?.redirect(await setFile(fileLocation.employee.visa(employeeId, visaId)));
|
|
}
|
|
|
|
@Delete("file-visa/{visaId}")
|
|
@Security("line")
|
|
async delVisa(
|
|
@Request() req: RequestWithUser,
|
|
@Path() employeeId: string,
|
|
@Path() visaId: string,
|
|
) {
|
|
await this.checkPermission(req.user, employeeId);
|
|
return await deleteFile(fileLocation.employee.visa(employeeId, visaId));
|
|
}
|
|
|
|
@Get("file-in-country-notice")
|
|
@Security("line")
|
|
async listNotice(@Request() req: RequestWithUser, @Path() employeeId: string) {
|
|
await this.checkPermission(req.user, employeeId);
|
|
return await listFile(fileLocation.employee.inCountryNotice(employeeId));
|
|
}
|
|
|
|
@Get("file-in-country-notice/{noticeId}")
|
|
@Security("line")
|
|
async getNotice(
|
|
@Request() req: RequestWithUser,
|
|
@Path() employeeId: string,
|
|
@Path() noticeId: string,
|
|
) {
|
|
await this.checkPermission(req.user, employeeId);
|
|
return await getFile(fileLocation.employee.inCountryNotice(employeeId, noticeId));
|
|
}
|
|
|
|
@Head("file-in-country-notice/{noticeId}")
|
|
@Security("line")
|
|
async headNotice(
|
|
@Request() req: RequestWithUser,
|
|
@Path() employeeId: string,
|
|
@Path() noticeId: string,
|
|
) {
|
|
await this.checkPermission(req.user, employeeId);
|
|
return await getPresigned("head", fileLocation.employee.inCountryNotice(employeeId, noticeId));
|
|
}
|
|
|
|
@Put("file-in-country-notice/{noticeId}")
|
|
@Security("line")
|
|
async putNotice(
|
|
@Request() req: RequestWithUser,
|
|
@Path() employeeId: string,
|
|
@Path() noticeId: string,
|
|
) {
|
|
await this.checkPermission(req.user, employeeId);
|
|
return req.res?.redirect(
|
|
await setFile(fileLocation.employee.inCountryNotice(employeeId, noticeId)),
|
|
);
|
|
}
|
|
|
|
@Delete("file-in-country-notice/{noticeId}")
|
|
@Security("line")
|
|
async delNotice(
|
|
@Request() req: RequestWithUser,
|
|
@Path() employeeId: string,
|
|
@Path() noticeId: string,
|
|
) {
|
|
await this.checkPermission(req.user, employeeId);
|
|
return await deleteFile(fileLocation.employee.inCountryNotice(employeeId, noticeId));
|
|
}
|
|
}
|
|
|
|
@Route("api/v1/line/quotation/{quotationId}/attachment")
|
|
@Tags("Line")
|
|
export class LineQuotationFileController extends Controller {
|
|
async #checkPermission(user: RequestWithUser["user"], id: string) {
|
|
return;
|
|
}
|
|
|
|
@Get()
|
|
@Security("line")
|
|
async listAttachment(@Request() req: RequestWithUser, @Path() quotationId: string) {
|
|
await this.#checkPermission(req.user, quotationId);
|
|
return await listFile(fileLocation.quotation.attachment(quotationId));
|
|
}
|
|
|
|
@Head("{name}")
|
|
async headAttachment(
|
|
@Request() req: RequestWithUser,
|
|
@Path() quotationId: string,
|
|
@Path() name: string,
|
|
) {
|
|
return req.res?.redirect(
|
|
await getPresigned("head", fileLocation.quotation.attachment(quotationId, name)),
|
|
);
|
|
}
|
|
|
|
@Get("{name}")
|
|
@Security("line")
|
|
async getAttachment(
|
|
@Request() req: RequestWithUser,
|
|
@Path() quotationId: string,
|
|
@Path() name: string,
|
|
) {
|
|
await this.#checkPermission(req.user, quotationId);
|
|
return await getFile(fileLocation.quotation.attachment(quotationId, name));
|
|
}
|
|
|
|
@Put("{name}")
|
|
@Security("line")
|
|
async putAttachment(
|
|
@Request() req: RequestWithUser,
|
|
@Path() quotationId: string,
|
|
@Path() name: string,
|
|
) {
|
|
await this.#checkPermission(req.user, quotationId);
|
|
return await setFile(fileLocation.quotation.attachment(quotationId, name));
|
|
}
|
|
|
|
@Delete("{name}")
|
|
@Security("line")
|
|
async deleteAttachment(
|
|
@Request() req: RequestWithUser,
|
|
@Path() quotationId: string,
|
|
@Path() name: string,
|
|
) {
|
|
await this.#checkPermission(req.user, quotationId);
|
|
return await deleteFile(fileLocation.quotation.attachment(quotationId, name));
|
|
}
|
|
}
|
|
|
|
@Route("api/v1/line/payment/{paymentId}/attachment")
|
|
@Tags("Line")
|
|
export class PaymentFileLineController extends Controller {
|
|
private async checkPermission(_user: RequestWithUser["user"], id: string) {
|
|
const data = await prisma.payment.findUnique({
|
|
include: {
|
|
invoice: {
|
|
include: {
|
|
quotation: true,
|
|
},
|
|
},
|
|
},
|
|
where: { id },
|
|
});
|
|
|
|
if (!data) throw notFoundError("Payment");
|
|
return { paymentId: id, quotationId: data.invoice.quotationId };
|
|
}
|
|
|
|
@Get()
|
|
@Security("line")
|
|
async listAttachment(@Request() req: RequestWithUser, @Path() paymentId: string) {
|
|
const { quotationId } = await this.checkPermission(req.user, paymentId);
|
|
return await listFile(fileLocation.quotation.payment(quotationId, paymentId));
|
|
}
|
|
|
|
@Head("{name}")
|
|
async headAttachment(
|
|
@Request() req: RequestWithUser,
|
|
@Path() paymentId: string,
|
|
@Path() name: string,
|
|
) {
|
|
const data = await prisma.payment.findUnique({
|
|
where: { id: paymentId },
|
|
include: { invoice: true },
|
|
});
|
|
if (!data) throw notFoundError("Payment");
|
|
return req.res?.redirect(
|
|
await getPresigned(
|
|
"head",
|
|
fileLocation.quotation.payment(data.invoice.quotationId, paymentId, name),
|
|
),
|
|
);
|
|
}
|
|
|
|
@Get("{name}")
|
|
async getAttachment(
|
|
@Request() req: RequestWithUser,
|
|
@Path() paymentId: string,
|
|
@Path() name: string,
|
|
) {
|
|
const data = await prisma.payment.findUnique({
|
|
where: { id: paymentId },
|
|
include: { invoice: true },
|
|
});
|
|
if (!data) throw notFoundError("Payment");
|
|
return req.res?.redirect(
|
|
await getFile(fileLocation.quotation.payment(data.invoice.quotationId, paymentId, name)),
|
|
);
|
|
}
|
|
}
|