Merge branch 'patch-08-04-2025' into develop
All checks were successful
Spell Check / Spell Check with Typos (push) Successful in 5s

This commit is contained in:
Methapon2001 2025-04-10 08:41:50 +07:00
commit 08483c162a
21 changed files with 214 additions and 145 deletions

View file

@ -2,6 +2,7 @@ import { Body, Controller, Get, Path, Post, Query, Route, Tags } from "tsoa";
import prisma from "../db";
import { queryOrNot } from "../utils/relation";
import { notFoundError } from "../utils/error";
import { Prisma } from "@prisma/client";
@Route("/api/v1/employment-office")
@Tags("Employment Office")
@ -40,11 +41,14 @@ export class EmploymentOfficeController extends Controller {
],
[],
),
...queryOrNot(
...(queryOrNot(
query,
[{ name: { contains: query } }, { nameEN: { contains: query } }],
[
{ name: { contains: query, mode: "insensitive" } },
{ nameEN: { contains: query, mode: "insensitive" } },
],
[],
),
) satisfies Prisma.EmploymentOfficeWhereInput["OR"]),
...queryOrNot(!!body?.id, [{ id: { in: body?.id } }], []),
]
: undefined,

View file

@ -36,8 +36,8 @@ export class NotificationController extends Controller {
AND: [
{
OR: queryOrNot<(typeof where)[]>(query, [
{ title: { contains: query } },
{ detail: { contains: query } },
{ title: { contains: query, mode: "insensitive" } },
{ detail: { contains: query, mode: "insensitive" } },
]),
},
{

View file

@ -265,20 +265,20 @@ export class BranchController extends Controller {
},
OR: queryOrNot<Prisma.BranchWhereInput[]>(query, [
{ code: { contains: query, mode: "insensitive" } },
{ nameEN: { contains: query } },
{ name: { contains: query } },
{ email: { contains: query } },
{ telephoneNo: { contains: query } },
{ nameEN: { contains: query, mode: "insensitive" } },
{ name: { contains: query, mode: "insensitive" } },
{ email: { contains: query, mode: "insensitive" } },
{ telephoneNo: { contains: query, mode: "insensitive" } },
...whereAddressQuery(query),
{
branch: {
some: {
OR: [
{ code: { contains: query, mode: "insensitive" } },
{ nameEN: { contains: query } },
{ name: { contains: query } },
{ email: { contains: query } },
{ telephoneNo: { contains: query } },
{ nameEN: { contains: query, mode: "insensitive" } },
{ name: { contains: query, mode: "insensitive" } },
{ email: { contains: query, mode: "insensitive" } },
{ telephoneNo: { contains: query, mode: "insensitive" } },
...whereAddressQuery(query),
],
},
@ -309,10 +309,10 @@ export class BranchController extends Controller {
where: {
AND: { OR: permissionCond(req.user) },
OR: [
{ nameEN: { contains: query } },
{ name: { contains: query } },
{ email: { contains: query } },
{ telephoneNo: { contains: query } },
{ nameEN: { contains: query, mode: "insensitive" } },
{ name: { contains: query, mode: "insensitive" } },
{ email: { contains: query, mode: "insensitive" } },
{ telephoneNo: { contains: query, mode: "insensitive" } },
...whereAddressQuery(query),
],
},

View file

@ -104,8 +104,8 @@ export class UserBranchController extends Controller {
userId,
},
OR: queryOrNot<Prisma.BranchUserWhereInput[]>(query, [
{ branch: { name: { contains: query } } },
{ branch: { nameEN: { contains: query } } },
{ branch: { name: { contains: query, mode: "insensitive" } } },
{ branch: { nameEN: { contains: query, mode: "insensitive" } } },
]),
} satisfies Prisma.BranchUserWhereInput;
@ -157,12 +157,12 @@ export class BranchUserController extends Controller {
branchId,
},
OR: [
{ user: { firstName: { contains: query } } },
{ user: { firstNameEN: { contains: query } } },
{ user: { lastName: { contains: query } } },
{ user: { lastNameEN: { contains: query } } },
{ user: { email: { contains: query } } },
{ user: { telephoneNo: { contains: query } } },
{ user: { firstName: { contains: query, mode: "insensitive" } } },
{ user: { firstNameEN: { contains: query, mode: "insensitive" } } },
{ user: { lastName: { contains: query, mode: "insensitive" } } },
{ user: { lastNameEN: { contains: query, mode: "insensitive" } } },
{ user: { email: { contains: query, mode: "insensitive" } } },
{ user: { telephoneNo: { contains: query, mode: "insensitive" } } },
],
} satisfies Prisma.BranchUserWhereInput;

View file

@ -324,12 +324,12 @@ export class UserController extends Controller {
const where = {
OR: queryOrNot<Prisma.UserWhereInput[]>(query, [
{ code: { contains: query, mode: "insensitive" } },
{ firstName: { contains: query } },
{ firstNameEN: { contains: query } },
{ lastName: { contains: query } },
{ lastNameEN: { contains: query } },
{ email: { contains: query } },
{ telephoneNo: { contains: query } },
{ firstName: { contains: query, mode: "insensitive" } },
{ firstNameEN: { contains: query, mode: "insensitive" } },
{ lastName: { contains: query, mode: "insensitive" } },
{ lastNameEN: { contains: query, mode: "insensitive" } },
{ email: { contains: query, mode: "insensitive" } },
{ telephoneNo: { contains: query, mode: "insensitive" } },
...whereAddressQuery(query),
]),
AND: {

View file

@ -198,15 +198,15 @@ export class CustomerBranchController extends Controller {
) {
const where = {
OR: queryOrNot<Prisma.CustomerBranchWhereInput[]>(query, [
{ customerName: { contains: query } },
{ registerName: { contains: query } },
{ registerNameEN: { contains: query } },
{ email: { contains: query } },
{ code: { contains: query } },
{ firstName: { contains: query } },
{ firstNameEN: { contains: query } },
{ lastName: { contains: query } },
{ lastNameEN: { contains: query } },
{ customerName: { contains: query, mode: "insensitive" } },
{ registerName: { contains: query, mode: "insensitive" } },
{ registerNameEN: { contains: query, mode: "insensitive" } },
{ email: { 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" } },
...whereAddressQuery(query),
]),
AND: {
@ -288,10 +288,10 @@ export class CustomerBranchController extends Controller {
) {
const where = {
OR: queryOrNot<Prisma.EmployeeWhereInput[]>(query, [
{ firstName: { contains: query } },
{ firstNameEN: { contains: query } },
{ lastName: { contains: query } },
{ lastNameEN: { contains: query } },
{ firstName: { contains: query, mode: "insensitive" } },
{ firstNameEN: { contains: query, mode: "insensitive" } },
{ lastName: { contains: query, mode: "insensitive" } },
{ lastNameEN: { contains: query, mode: "insensitive" } },
...whereAddressQuery(query),
]),
AND: {

View file

@ -168,14 +168,14 @@ export class CustomerController extends Controller {
) {
const where = {
OR: queryOrNot<Prisma.CustomerWhereInput[]>(query, [
{ branch: { some: { namePrefix: { contains: query } } } },
{ branch: { some: { customerName: { contains: query } } } },
{ branch: { some: { registerName: { contains: query } } } },
{ branch: { some: { registerNameEN: { contains: query } } } },
{ branch: { some: { firstName: { contains: query } } } },
{ branch: { some: { firstNameEN: { contains: query } } } },
{ branch: { some: { lastName: { contains: query } } } },
{ branch: { some: { lastNameEN: { contains: query } } } },
{ branch: { some: { namePrefix: { contains: query, mode: "insensitive" } } } },
{ branch: { some: { customerName: { contains: query, mode: "insensitive" } } } },
{ branch: { some: { registerName: { contains: query, mode: "insensitive" } } } },
{ branch: { some: { registerNameEN: { contains: query, mode: "insensitive" } } } },
{ branch: { some: { firstName: { contains: query, mode: "insensitive" } } } },
{ branch: { some: { firstNameEN: { contains: query, mode: "insensitive" } } } },
{ branch: { some: { lastName: { contains: query, mode: "insensitive" } } } },
{ branch: { some: { lastNameEN: { contains: query, mode: "insensitive" } } } },
]),
AND: {
customerType,

View file

@ -163,13 +163,13 @@ export class EmployeeController extends Controller {
OR: queryOrNot<Prisma.EmployeeWhereInput[]>(query, [
{
employeePassport: {
some: { number: { contains: query } },
some: { number: { contains: query, mode: "insensitive" } },
},
},
{ firstName: { contains: query } },
{ firstNameEN: { contains: query } },
{ lastName: { contains: query } },
{ lastNameEN: { contains: query } },
{ firstName: { contains: query, mode: "insensitive" } },
{ firstNameEN: { contains: query, mode: "insensitive" } },
{ lastName: { contains: query, mode: "insensitive" } },
{ lastNameEN: { contains: query, mode: "insensitive" } },
...whereAddressQuery(query),
]),
AND: {
@ -252,13 +252,13 @@ export class EmployeeController extends Controller {
...(queryOrNot<Prisma.EmployeeWhereInput[]>(query, [
{
employeePassport: {
some: { number: { contains: query } },
some: { number: { contains: query, mode: "insensitive" } },
},
},
{ firstName: { contains: query } },
{ firstNameEN: { contains: query } },
{ lastName: { contains: query } },
{ lastNameEN: { contains: query } },
{ firstName: { contains: query, mode: "insensitive" } },
{ firstNameEN: { contains: query, mode: "insensitive" } },
{ lastName: { contains: query, mode: "insensitive" } },
{ lastNameEN: { contains: query, mode: "insensitive" } },
...whereAddressQuery(query),
]) ?? []),
...(queryOrNot<Prisma.EmployeeWhereInput[]>(!!body, [

View file

@ -61,10 +61,10 @@ export class FlowTemplateController extends Controller {
) {
const where = {
OR: queryOrNot(query, [
{ name: { contains: query } },
{ name: { contains: query, mode: "insensitive" } },
{
step: {
some: { name: { contains: query } },
some: { name: { contains: query, mode: "insensitive" } },
},
},
]),

View file

@ -131,7 +131,7 @@ export class InstitutionController extends Controller {
...filterStatus(activeOnly ? Status.ACTIVE : status),
group: body?.group ? { in: body.group } : group,
OR: queryOrNot<Prisma.InstitutionWhereInput[]>(query, [
{ name: { contains: query } },
{ name: { contains: query, mode: "insensitive" } },
{ code: { contains: query, mode: "insensitive" } },
]),
} satisfies Prisma.InstitutionWhereInput;

View file

@ -99,19 +99,19 @@ export class InvoiceController extends Controller {
const where: Prisma.InvoiceWhereInput = {
OR: [
{ code: { contains: query, mode: "insensitive" } },
{ quotation: { workName: { contains: query } } },
{ quotation: { workName: { contains: query, mode: "insensitive" } } },
{
quotation: {
customerBranch: {
OR: [
{ code: { contains: query, mode: "insensitive" } },
{ customerName: { contains: query } },
{ registerName: { contains: query } },
{ registerNameEN: { contains: query } },
{ firstName: { contains: query } },
{ firstNameEN: { contains: query } },
{ lastName: { contains: query } },
{ lastNameEN: { contains: query } },
{ customerName: { 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" } },
],
},
},

View file

@ -154,8 +154,8 @@ export class ProductController extends Controller {
const where = {
OR: queryOrNot<Prisma.ProductWhereInput[]>(query, [
{ name: { contains: query } },
{ detail: { contains: query } },
{ name: { contains: query, mode: "insensitive" } },
{ detail: { contains: query, mode: "insensitive" } },
{ code: { contains: query, mode: "insensitive" } },
]),
AND: {

View file

@ -93,8 +93,8 @@ export class ProductGroup extends Controller {
) {
const where = {
OR: queryOrNot<Prisma.ProductGroupWhereInput[]>(query, [
{ name: { contains: query } },
{ detail: { contains: query } },
{ name: { contains: query, mode: "insensitive" } },
{ detail: { contains: query, mode: "insensitive" } },
{ code: { contains: query, mode: "insensitive" } },
]),
AND: [

View file

@ -51,7 +51,10 @@ export class PropertiesController extends Controller {
@Query() activeOnly?: boolean,
) {
const where = {
OR: queryOrNot(query, [{ name: { contains: query } }, { nameEN: { contains: query } }]),
OR: queryOrNot(query, [
{ name: { contains: query, mode: "insensitive" } },
{ nameEN: { contains: query, mode: "insensitive" } },
]),
AND: {
...filterStatus(activeOnly ? Status.ACTIVE : status),
registeredBranch: {

View file

@ -179,8 +179,8 @@ export class ServiceController extends Controller {
const where = {
OR: queryOrNot<Prisma.ServiceWhereInput[]>(query, [
{ name: { contains: query } },
{ detail: { contains: query } },
{ name: { contains: query, mode: "insensitive" } },
{ detail: { contains: query, mode: "insensitive" } },
{ code: { contains: query, mode: "insensitive" } },
]),
AND: {

View file

@ -210,16 +210,16 @@ export class QuotationController extends Controller {
const where = {
OR: queryOrNot<Prisma.QuotationWhereInput[]>(query, [
{ code: { contains: query, mode: "insensitive" } },
{ workName: { contains: query } },
{ workName: { contains: query, mode: "insensitive" } },
{
customerBranch: {
OR: [
{ code: { contains: query, mode: "insensitive" } },
{ customerName: { contains: query } },
{ firstName: { contains: query } },
{ firstNameEN: { contains: query } },
{ lastName: { contains: query } },
{ lastNameEN: { contains: query } },
{ customerName: { contains: query, mode: "insensitive" } },
{ firstName: { contains: query, mode: "insensitive" } },
{ firstNameEN: { contains: query, mode: "insensitive" } },
{ lastName: { contains: query, mode: "insensitive" } },
{ lastNameEN: { contains: query, mode: "insensitive" } },
],
},
},

View file

@ -91,13 +91,13 @@ export class RequestDataController extends Controller {
customerBranch: {
OR: [
{ code: { contains: query, mode: "insensitive" } },
{ customerName: { contains: query } },
{ registerName: { contains: query } },
{ registerNameEN: { contains: query } },
{ firstName: { contains: query } },
{ firstNameEN: { contains: query } },
{ lastName: { contains: query } },
{ lastNameEN: { contains: query } },
{ customerName: { 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" } },
],
},
},
@ -105,14 +105,14 @@ export class RequestDataController extends Controller {
OR: [
{
employeePassport: {
some: { number: { contains: query } },
some: { number: { contains: query, mode: "insensitive" } },
},
},
{ code: { contains: query, mode: "insensitive" } },
{ firstName: { contains: query } },
{ firstNameEN: { contains: query } },
{ lastName: { contains: query } },
{ lastNameEN: { contains: query } },
{ firstName: { contains: query, mode: "insensitive" } },
{ firstNameEN: { contains: query, mode: "insensitive" } },
{ lastName: { contains: query, mode: "insensitive" } },
{ lastNameEN: { contains: query, mode: "insensitive" } },
],
},
},

View file

@ -121,9 +121,9 @@ export class TaskController extends Controller {
code: body?.code ? { in: body.code } : undefined,
OR: queryOrNot(query, [
{ code: { contains: query, mode: "insensitive" } },
{ taskName: { contains: query } },
{ contactName: { contains: query } },
{ contactTel: { contains: query } },
{ taskName: { contains: query, mode: "insensitive" } },
{ contactName: { contains: query, mode: "insensitive" } },
{ contactTel: { contains: query, mode: "insensitive" } },
]),
} satisfies Prisma.TaskOrderWhereInput;
@ -1021,9 +1021,9 @@ export class UserTaskController extends Controller {
: undefined,
OR: queryOrNot(query, [
{ code: { contains: query, mode: "insensitive" } },
{ taskName: { contains: query } },
{ contactName: { contains: query } },
{ contactTel: { contains: query } },
{ taskName: { contains: query, mode: "insensitive" } },
{ contactName: { contains: query, mode: "insensitive" } },
{ contactTel: { contains: query, mode: "insensitive" } },
]),
} satisfies Prisma.TaskOrderWhereInput;

View file

@ -153,17 +153,17 @@ export class CreditNoteController extends Controller {
request: {
OR: queryOrNot<Prisma.RequestDataWhereInput[]>(query, [
{ quotation: { code: { contains: query, mode: "insensitive" } } },
{ quotation: { workName: { contains: query } } },
{ quotation: { workName: { contains: query, mode: "insensitive" } } },
{
quotation: {
customerBranch: {
OR: [
{ code: { contains: query, mode: "insensitive" } },
{ customerName: { contains: query } },
{ firstName: { contains: query } },
{ firstNameEN: { contains: query } },
{ lastName: { contains: query } },
{ lastNameEN: { contains: query } },
{ customerName: { contains: query, mode: "insensitive" } },
{ firstName: { contains: query, mode: "insensitive" } },
{ firstNameEN: { contains: query, mode: "insensitive" } },
{ lastName: { contains: query, mode: "insensitive" } },
{ lastNameEN: { contains: query, mode: "insensitive" } },
],
},
},
@ -171,14 +171,14 @@ export class CreditNoteController extends Controller {
OR: [
{
employeePassport: {
some: { number: { contains: query } },
some: { number: { contains: query, mode: "insensitive" } },
},
},
{ code: { contains: query, mode: "insensitive" } },
{ firstName: { contains: query } },
{ firstNameEN: { contains: query } },
{ lastName: { contains: query } },
{ lastNameEN: { contains: query } },
{ firstName: { contains: query, mode: "insensitive" } },
{ firstNameEN: { contains: query, mode: "insensitive" } },
{ lastName: { contains: query, mode: "insensitive" } },
{ lastNameEN: { contains: query, mode: "insensitive" } },
],
},
},

View file

@ -200,16 +200,16 @@ export class DebitNoteController extends Controller {
const where = {
OR: queryOrNot<Prisma.QuotationWhereInput[]>(query, [
{ code: { contains: query, mode: "insensitive" } },
{ workName: { contains: query } },
{ workName: { contains: query, mode: "insensitive" } },
{
customerBranch: {
OR: [
{ code: { contains: query, mode: "insensitive" } },
{ customerName: { contains: query } },
{ firstName: { contains: query } },
{ firstNameEN: { contains: query } },
{ lastName: { contains: query } },
{ lastNameEN: { contains: query } },
{ customerName: { contains: query, mode: "insensitive" } },
{ firstName: { contains: query, mode: "insensitive" } },
{ firstNameEN: { contains: query, mode: "insensitive" } },
{ lastName: { contains: query, mode: "insensitive" } },
{ lastNameEN: { contains: query, mode: "insensitive" } },
],
},
},

View file

@ -58,13 +58,13 @@ export class LineController extends Controller {
...(queryOrNot<Prisma.EmployeeWhereInput[]>(query, [
{
employeePassport: {
some: { number: { contains: query } },
some: { number: { contains: query, mode: "insensitive" } },
},
},
{ firstName: { contains: query } },
{ firstNameEN: { contains: query } },
{ lastName: { contains: query } },
{ lastNameEN: { contains: query } },
{ firstName: { contains: query, mode: "insensitive" } },
{ firstNameEN: { contains: query, mode: "insensitive" } },
{ lastName: { contains: query, mode: "insensitive" } },
{ lastNameEN: { contains: query, mode: "insensitive" } },
...whereAddressQuery(query),
]) ?? []),
]
@ -178,19 +178,19 @@ export class LineController extends Controller {
OR: queryOrNot<Prisma.RequestDataWhereInput[]>(query, [
{ code: { contains: query, mode: "insensitive" } },
{ quotation: { code: { contains: query, mode: "insensitive" } } },
{ quotation: { workName: { contains: query } } },
{ quotation: { workName: { contains: query, mode: "insensitive" } } },
{
quotation: {
customerBranch: {
OR: [
{ code: { contains: query, mode: "insensitive" } },
{ customerName: { contains: query } },
{ registerName: { contains: query } },
{ registerNameEN: { contains: query } },
{ firstName: { contains: query } },
{ firstNameEN: { contains: query } },
{ lastName: { contains: query } },
{ lastNameEN: { contains: query } },
{ customerName: { 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" } },
],
},
},
@ -198,14 +198,14 @@ export class LineController extends Controller {
OR: [
{
employeePassport: {
some: { number: { contains: query } },
some: { number: { contains: query, mode: "insensitive" } },
},
},
{ code: { contains: query, mode: "insensitive" } },
{ firstName: { contains: query } },
{ firstNameEN: { contains: query } },
{ lastName: { contains: query } },
{ lastNameEN: { contains: query } },
{ firstName: { contains: query, mode: "insensitive" } },
{ firstNameEN: { contains: query, mode: "insensitive" } },
{ lastName: { contains: query, mode: "insensitive" } },
{ lastNameEN: { contains: query, mode: "insensitive" } },
],
},
},
@ -611,16 +611,16 @@ export class LineController extends Controller {
? [
...(queryOrNot<Prisma.QuotationWhereInput[]>(query, [
{ code: { contains: query, mode: "insensitive" } },
{ workName: { contains: query } },
{ workName: { contains: query, mode: "insensitive" } },
{
customerBranch: {
OR: [
{ code: { contains: query, mode: "insensitive" } },
{ customerName: { contains: query } },
{ firstName: { contains: query } },
{ firstNameEN: { contains: query } },
{ lastName: { contains: query } },
{ lastNameEN: { contains: query } },
{ customerName: { contains: query, mode: "insensitive" } },
{ firstName: { contains: query, mode: "insensitive" } },
{ firstNameEN: { contains: query, mode: "insensitive" } },
{ lastName: { contains: query, mode: "insensitive" } },
{ lastNameEN: { contains: query, mode: "insensitive" } },
],
},
},
@ -1368,3 +1368,65 @@ export class LineQuotationFileController extends Controller {
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)),
);
}
}