refactor: customer create and update process
This commit is contained in:
parent
b167a612b4
commit
5bb8da818c
6 changed files with 261 additions and 462 deletions
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
Warnings:
|
||||
|
||||
- You are about to drop the column `customerName` on the `Customer` table. All the data in the column will be lost.
|
||||
- You are about to drop the column `customerNameEN` on the `Customer` table. All the data in the column will be lost.
|
||||
- You are about to drop the column `personName` on the `Customer` table. All the data in the column will be lost.
|
||||
- You are about to drop the column `personNameEN` on the `Customer` table. All the data in the column will be lost.
|
||||
- You are about to drop the column `taxNo` on the `Customer` table. All the data in the column will be lost.
|
||||
- You are about to drop the column `branchNo` on the `CustomerBranch` table. All the data in the column will be lost.
|
||||
- You are about to drop the column `bussinessType` on the `CustomerBranch` table. All the data in the column will be lost.
|
||||
- You are about to drop the column `bussinessTypeEN` on the `CustomerBranch` table. All the data in the column will be lost.
|
||||
- You are about to drop the column `name` on the `CustomerBranch` table. All the data in the column will be lost.
|
||||
- You are about to drop the column `nameEN` on the `CustomerBranch` table. All the data in the column will be lost.
|
||||
- You are about to drop the column `taxNo` on the `CustomerBranch` table. All the data in the column will be lost.
|
||||
- You are about to drop the column `zipCode` on the `CustomerBranch` table. All the data in the column will be lost.
|
||||
- Added the required column `birthDate` to the `Customer` table without a default value. This is not possible if the table is not empty.
|
||||
- Added the required column `firstName` to the `Customer` table without a default value. This is not possible if the table is not empty.
|
||||
- Added the required column `gender` to the `Customer` table without a default value. This is not possible if the table is not empty.
|
||||
- Added the required column `lastName` to the `Customer` table without a default value. This is not possible if the table is not empty.
|
||||
- Added the required column `businessType` to the `CustomerBranch` table without a default value. This is not possible if the table is not empty.
|
||||
- Added the required column `businessTypeEN` to the `CustomerBranch` table without a default value. This is not possible if the table is not empty.
|
||||
- Added the required column `workplace` to the `CustomerBranch` table without a default value. This is not possible if the table is not empty.
|
||||
- Added the required column `workplaceEN` to the `CustomerBranch` table without a default value. This is not possible if the table is not empty.
|
||||
|
||||
*/
|
||||
-- AlterTable
|
||||
ALTER TABLE "Customer" DROP COLUMN "customerName",
|
||||
DROP COLUMN "customerNameEN",
|
||||
DROP COLUMN "personName",
|
||||
DROP COLUMN "personNameEN",
|
||||
DROP COLUMN "taxNo",
|
||||
ADD COLUMN "birthDate" TIMESTAMP(3) NOT NULL,
|
||||
ADD COLUMN "firstName" TEXT NOT NULL,
|
||||
ADD COLUMN "firstNameEN" TEXT,
|
||||
ADD COLUMN "gender" TEXT NOT NULL,
|
||||
ADD COLUMN "lastName" TEXT NOT NULL,
|
||||
ADD COLUMN "lastNameEN" TEXT,
|
||||
ADD COLUMN "namePrefix" TEXT;
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "CustomerBranch" DROP COLUMN "branchNo",
|
||||
DROP COLUMN "bussinessType",
|
||||
DROP COLUMN "bussinessTypeEN",
|
||||
DROP COLUMN "name",
|
||||
DROP COLUMN "nameEN",
|
||||
DROP COLUMN "taxNo",
|
||||
DROP COLUMN "zipCode",
|
||||
ADD COLUMN "businessType" TEXT NOT NULL,
|
||||
ADD COLUMN "businessTypeEN" TEXT NOT NULL,
|
||||
ADD COLUMN "citizenId" TEXT,
|
||||
ADD COLUMN "workplace" TEXT NOT NULL,
|
||||
ADD COLUMN "workplaceEN" TEXT NOT NULL,
|
||||
ALTER COLUMN "legalPersonNo" DROP NOT NULL,
|
||||
ALTER COLUMN "registerName" DROP NOT NULL,
|
||||
ALTER COLUMN "registerDate" DROP NOT NULL,
|
||||
ALTER COLUMN "authorizedCapital" DROP NOT NULL;
|
||||
2
prisma/migrations/20240820063852_add_field/migration.sql
Normal file
2
prisma/migrations/20240820063852_add_field/migration.sql
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
-- AlterTable
|
||||
ALTER TABLE "CustomerBranch" ADD COLUMN "legalPersonName" TEXT;
|
||||
13
prisma/migrations/20240820084114_update_field/migration.sql
Normal file
13
prisma/migrations/20240820084114_update_field/migration.sql
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
/*
|
||||
Warnings:
|
||||
|
||||
- You are about to drop the column `code` on the `Customer` table. All the data in the column will be lost.
|
||||
- You are about to drop the column `legalPersonName` on the `CustomerBranch` table. All the data in the column will be lost.
|
||||
|
||||
*/
|
||||
-- AlterTable
|
||||
ALTER TABLE "Customer" DROP COLUMN "code";
|
||||
|
||||
-- AlterTable
|
||||
ALTER TABLE "CustomerBranch" DROP COLUMN "legalPersonName",
|
||||
ADD COLUMN "registerNameEN" TEXT;
|
||||
|
|
@ -403,14 +403,17 @@ enum CustomerType {
|
|||
}
|
||||
|
||||
model Customer {
|
||||
id String @id @default(uuid())
|
||||
code String
|
||||
personName String
|
||||
personNameEN String?
|
||||
customerType CustomerType
|
||||
customerName String
|
||||
customerNameEN String
|
||||
taxNo String?
|
||||
id String @id @default(uuid())
|
||||
|
||||
customerType CustomerType
|
||||
|
||||
namePrefix String?
|
||||
firstName String
|
||||
firstNameEN String?
|
||||
lastName String
|
||||
lastNameEN String?
|
||||
gender String
|
||||
birthDate DateTime
|
||||
|
||||
status Status @default(CREATED)
|
||||
statusOrder Int @default(0)
|
||||
|
|
@ -430,24 +433,25 @@ model Customer {
|
|||
}
|
||||
|
||||
model CustomerBranch {
|
||||
id String @id @default(uuid())
|
||||
branchNo Int
|
||||
code String
|
||||
legalPersonNo String
|
||||
|
||||
name String
|
||||
nameEN String
|
||||
|
||||
id String @id @default(uuid())
|
||||
customer Customer @relation(fields: [customerId], references: [id], onDelete: Cascade)
|
||||
customerId String
|
||||
|
||||
taxNo String?
|
||||
registerName String
|
||||
registerDate DateTime
|
||||
authorizedCapital String
|
||||
code String
|
||||
|
||||
address String
|
||||
addressEN String
|
||||
// NOTE: About (Natural Person)
|
||||
citizenId String?
|
||||
// NOTE: About (Legal Entity)
|
||||
legalPersonNo String?
|
||||
registerName String?
|
||||
registerNameEN String?
|
||||
registerDate DateTime?
|
||||
authorizedCapital String?
|
||||
|
||||
workplace String
|
||||
workplaceEN String
|
||||
address String
|
||||
addressEN String
|
||||
|
||||
province Province? @relation(fields: [provinceId], references: [id], onDelete: SetNull)
|
||||
provinceId String?
|
||||
|
|
@ -458,14 +462,12 @@ model CustomerBranch {
|
|||
subDistrict SubDistrict? @relation(fields: [subDistrictId], references: [id], onDelete: SetNull)
|
||||
subDistrictId String?
|
||||
|
||||
zipCode String
|
||||
|
||||
email String
|
||||
telephoneNo String
|
||||
|
||||
employmentOffice String
|
||||
bussinessType String
|
||||
bussinessTypeEN String
|
||||
businessType String
|
||||
businessTypeEN String
|
||||
jobPosition String
|
||||
jobPositionEN String
|
||||
jobDescription String
|
||||
|
|
|
|||
|
|
@ -137,27 +137,30 @@ export class CustomerBranchController extends Controller {
|
|||
|
||||
const where = {
|
||||
OR: [
|
||||
{ nameEN: { contains: query }, zipCode, ...filterStatus(status) },
|
||||
{ name: { contains: query }, zipCode, ...filterStatus(status) },
|
||||
{ email: { contains: query }, zipCode, ...filterStatus(status) },
|
||||
{ code: { contains: query }, zipCode, ...filterStatus(status) },
|
||||
{ address: { contains: query }, zipCode, ...filterStatus(status) },
|
||||
{ addressEN: { contains: query }, zipCode, ...filterStatus(status) },
|
||||
{ province: { name: { contains: query } }, zipCode, ...filterStatus(status) },
|
||||
{ province: { nameEN: { contains: query } }, zipCode, ...filterStatus(status) },
|
||||
{ district: { name: { contains: query } }, zipCode, ...filterStatus(status) },
|
||||
{ district: { nameEN: { contains: query } }, zipCode, ...filterStatus(status) },
|
||||
{ subDistrict: { name: { contains: query } }, zipCode, ...filterStatus(status) },
|
||||
{ subDistrict: { nameEN: { contains: query } }, zipCode, ...filterStatus(status) },
|
||||
{ registerName: { contains: query } },
|
||||
{ registerNameEN: { contains: query } },
|
||||
{ email: { contains: query } },
|
||||
{ code: { contains: query } },
|
||||
{ address: { contains: query } },
|
||||
{ addressEN: { contains: query } },
|
||||
{ province: { name: { contains: query } } },
|
||||
{ province: { nameEN: { contains: query } } },
|
||||
{ district: { name: { contains: query } } },
|
||||
{ district: { nameEN: { contains: query } } },
|
||||
{ subDistrict: { name: { contains: query } } },
|
||||
{ subDistrict: { nameEN: { contains: query } } },
|
||||
{
|
||||
customer: {
|
||||
OR: [{ customerName: { contains: query } }, { customerNameEN: { contains: query } }],
|
||||
OR: [
|
||||
{ firstName: { contains: query } },
|
||||
{ firstNameEN: { contains: query } },
|
||||
{ lastName: { contains: query } },
|
||||
{ lastNameEN: { contains: query } },
|
||||
],
|
||||
},
|
||||
zipCode,
|
||||
status,
|
||||
},
|
||||
],
|
||||
AND: { customerId },
|
||||
AND: { customerId, subDistrict: zipCode ? { zipCode } : undefined, ...filterStatus(status) },
|
||||
} satisfies Prisma.CustomerBranchWhereInput;
|
||||
|
||||
const [result, total] = await prisma.$transaction([
|
||||
|
|
@ -263,7 +266,15 @@ export class CustomerBranchController extends Controller {
|
|||
prisma.province.findFirst({ where: { id: body.provinceId || undefined } }),
|
||||
prisma.district.findFirst({ where: { id: body.districtId || undefined } }),
|
||||
prisma.subDistrict.findFirst({ where: { id: body.subDistrictId || undefined } }),
|
||||
prisma.customer.findFirst({ where: { id: body.customerId || undefined } }),
|
||||
prisma.customer.findFirst({
|
||||
where: { id: body.customerId || undefined },
|
||||
include: {
|
||||
branch: {
|
||||
take: 1,
|
||||
orderBy: { createdAt: "asc" },
|
||||
},
|
||||
},
|
||||
}),
|
||||
]);
|
||||
if (body.provinceId && !province)
|
||||
throw new HttpError(
|
||||
|
|
@ -294,48 +305,37 @@ export class CustomerBranchController extends Controller {
|
|||
|
||||
const record = await prisma.$transaction(
|
||||
async (tx) => {
|
||||
const conflict = await tx.customerBranch.findFirst({
|
||||
where: { customerId, branchNo: rest.branchNo },
|
||||
});
|
||||
if (conflict) {
|
||||
throw new HttpError(
|
||||
HttpStatus.BAD_REQUEST,
|
||||
"Branch with current no already exists.",
|
||||
"branchSameNoExist",
|
||||
);
|
||||
}
|
||||
|
||||
const last = await tx.runningNo.upsert({
|
||||
where: {
|
||||
key: `CUSTOMER_${customer.code.slice(0, -6)}`,
|
||||
},
|
||||
create: {
|
||||
key: `CUSTOMER_${customer.code.slice(0, -6)}`,
|
||||
value: 1,
|
||||
},
|
||||
update: { value: { increment: 1 } },
|
||||
});
|
||||
|
||||
return await tx.customerBranch.create({
|
||||
include: {
|
||||
province: true,
|
||||
district: true,
|
||||
subDistrict: true,
|
||||
createdBy: true,
|
||||
updatedBy: true,
|
||||
},
|
||||
data: {
|
||||
...rest,
|
||||
statusOrder: +(rest.status === "INACTIVE"),
|
||||
code: `${customer.code.slice(0, -6)}${`${last.value - 1}`.padStart(6, "0")}`,
|
||||
customer: { connect: { id: customerId } },
|
||||
province: { connect: provinceId ? { id: provinceId } : undefined },
|
||||
district: { connect: districtId ? { id: districtId } : undefined },
|
||||
subDistrict: { connect: subDistrictId ? { id: subDistrictId } : undefined },
|
||||
createdBy: { connect: { id: req.user.sub } },
|
||||
updatedBy: { connect: { id: req.user.sub } },
|
||||
},
|
||||
});
|
||||
// const last = await tx.runningNo.upsert({
|
||||
// where: {
|
||||
// key: `CUSTOMER_${customer.code.slice(0, -6)}`,
|
||||
// },
|
||||
// create: {
|
||||
// key: `CUSTOMER_${customer.code.slice(0, -6)}`,
|
||||
// value: 1,
|
||||
// },
|
||||
// update: { value: { increment: 1 } },
|
||||
// });
|
||||
//
|
||||
// return await tx.customerBranch.create({
|
||||
// include: {
|
||||
// province: true,
|
||||
// district: true,
|
||||
// subDistrict: true,
|
||||
// createdBy: true,
|
||||
// updatedBy: true,
|
||||
// },
|
||||
// data: {
|
||||
// ...rest,
|
||||
// statusOrder: +(rest.status === "INACTIVE"),
|
||||
// code: `${customer.code.slice(0, -6)}${`${last.value - 1}`.padStart(6, "0")}`,
|
||||
// customer: { connect: { id: customerId } },
|
||||
// province: { connect: provinceId ? { id: provinceId } : undefined },
|
||||
// district: { connect: districtId ? { id: districtId } : undefined },
|
||||
// subDistrict: { connect: subDistrictId ? { id: subDistrictId } : undefined },
|
||||
// createdBy: { connect: { id: req.user.sub } },
|
||||
// updatedBy: { connect: { id: req.user.sub } },
|
||||
// },
|
||||
// });
|
||||
},
|
||||
{ isolationLevel: Prisma.TransactionIsolationLevel.Serializable },
|
||||
);
|
||||
|
|
@ -352,6 +352,12 @@ export class CustomerBranchController extends Controller {
|
|||
@Body() body: CustomerBranchUpdate,
|
||||
@Path() branchId: string,
|
||||
) {
|
||||
const branch = await prisma.customerBranch.findUnique({ where: { id: branchId } });
|
||||
|
||||
if (!branch) {
|
||||
throw new HttpError(HttpStatus.NOT_FOUND, "Branch cannot be found.", "branchNotFound");
|
||||
}
|
||||
|
||||
if (body.provinceId || body.districtId || body.subDistrictId || body.customerId) {
|
||||
const [province, district, subDistrict, customer] = await prisma.$transaction([
|
||||
prisma.province.findFirst({ where: { id: body.provinceId || undefined } }),
|
||||
|
|
@ -385,44 +391,41 @@ export class CustomerBranchController extends Controller {
|
|||
);
|
||||
}
|
||||
|
||||
const { provinceId, districtId, subDistrictId, customerId, ...rest } = body;
|
||||
|
||||
if (!(await prisma.customerBranch.findUnique({ where: { id: branchId } }))) {
|
||||
throw new HttpError(HttpStatus.NOT_FOUND, "Branch cannot be found.", "branchNotFound");
|
||||
}
|
||||
|
||||
const record = await prisma.customerBranch.update({
|
||||
where: { id: branchId },
|
||||
include: {
|
||||
province: true,
|
||||
district: true,
|
||||
subDistrict: true,
|
||||
createdBy: true,
|
||||
updatedBy: true,
|
||||
},
|
||||
data: {
|
||||
...rest,
|
||||
statusOrder: +(rest.status === "INACTIVE"),
|
||||
customer: { connect: customerId ? { id: customerId } : undefined },
|
||||
province: {
|
||||
connect: provinceId ? { id: provinceId } : undefined,
|
||||
disconnect: provinceId === null || undefined,
|
||||
},
|
||||
district: {
|
||||
connect: districtId ? { id: districtId } : undefined,
|
||||
disconnect: districtId === null || undefined,
|
||||
},
|
||||
subDistrict: {
|
||||
connect: subDistrictId ? { id: subDistrictId } : undefined,
|
||||
disconnect: subDistrictId === null || undefined,
|
||||
},
|
||||
updatedBy: { connect: { id: req.user.sub } },
|
||||
},
|
||||
});
|
||||
|
||||
this.setStatus(HttpStatus.CREATED);
|
||||
|
||||
return record;
|
||||
// const { provinceId, districtId, subDistrictId, customerId, ...rest } = body;
|
||||
//
|
||||
//
|
||||
// const record = await prisma.customerBranch.update({
|
||||
// where: { id: branchId },
|
||||
// include: {
|
||||
// province: true,
|
||||
// district: true,
|
||||
// subDistrict: true,
|
||||
// createdBy: true,
|
||||
// updatedBy: true,
|
||||
// },
|
||||
// data: {
|
||||
// ...rest,
|
||||
// statusOrder: +(rest.status === "INACTIVE"),
|
||||
// customer: { connect: customerId ? { id: customerId } : undefined },
|
||||
// province: {
|
||||
// connect: provinceId ? { id: provinceId } : undefined,
|
||||
// disconnect: provinceId === null || undefined,
|
||||
// },
|
||||
// district: {
|
||||
// connect: districtId ? { id: districtId } : undefined,
|
||||
// disconnect: districtId === null || undefined,
|
||||
// },
|
||||
// subDistrict: {
|
||||
// connect: subDistrictId ? { id: subDistrictId } : undefined,
|
||||
// disconnect: subDistrictId === null || undefined,
|
||||
// },
|
||||
// updatedBy: { connect: { id: req.user.sub } },
|
||||
// },
|
||||
// });
|
||||
//
|
||||
// this.setStatus(HttpStatus.CREATED);
|
||||
//
|
||||
// return record;
|
||||
}
|
||||
|
||||
@Delete("{branchId}")
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ import {
|
|||
} from "tsoa";
|
||||
import { RequestWithUser } from "../interfaces/user";
|
||||
import prisma from "../db";
|
||||
import minio, { presignedGetObjectIfExist } from "../services/minio";
|
||||
import minio, { deleteFolder, presignedGetObjectIfExist } from "../services/minio";
|
||||
import HttpStatus from "../interfaces/http-status";
|
||||
import HttpError from "../interfaces/http-error";
|
||||
|
||||
|
|
@ -37,95 +37,31 @@ const MANAGE_ROLES = [
|
|||
export type CustomerCreate = {
|
||||
registeredBranchId?: string;
|
||||
|
||||
code: string;
|
||||
|
||||
status?: Status;
|
||||
personName: string;
|
||||
personNameEN?: string;
|
||||
|
||||
customerType: CustomerType;
|
||||
customerName: string;
|
||||
customerNameEN: string;
|
||||
taxNo?: string | null;
|
||||
customerBranch?: {
|
||||
status?: Status;
|
||||
|
||||
legalPersonNo: string;
|
||||
|
||||
branchNo: number;
|
||||
taxNo: string | null;
|
||||
name: string;
|
||||
nameEN: string;
|
||||
addressEN: string;
|
||||
address: string;
|
||||
zipCode: string;
|
||||
email: string;
|
||||
telephoneNo: string;
|
||||
|
||||
registerName: string;
|
||||
registerDate: Date;
|
||||
authorizedCapital: string;
|
||||
|
||||
employmentOffice: string;
|
||||
bussinessType: string;
|
||||
bussinessTypeEN: string;
|
||||
jobPosition: string;
|
||||
jobPositionEN: string;
|
||||
jobDescription: string;
|
||||
saleEmployee: string;
|
||||
payDate: Date;
|
||||
wageRate: number;
|
||||
|
||||
subDistrictId?: string | null;
|
||||
districtId?: string | null;
|
||||
provinceId?: string | null;
|
||||
}[];
|
||||
namePrefix: string;
|
||||
firstName: string;
|
||||
firstNameEN?: string;
|
||||
lastName: string;
|
||||
lastNameEN?: string;
|
||||
gender: string;
|
||||
birthDate: Date;
|
||||
};
|
||||
|
||||
export type CustomerUpdate = {
|
||||
registeredBranchId?: string;
|
||||
|
||||
status?: "ACTIVE" | "INACTIVE";
|
||||
personName?: string;
|
||||
personNameEN?: string;
|
||||
customerType?: CustomerType;
|
||||
customerName?: string;
|
||||
customerNameEN?: string;
|
||||
taxNo?: string | null;
|
||||
customerBranch?: {
|
||||
id?: string;
|
||||
|
||||
status?: Status;
|
||||
|
||||
legalPersonNo: string;
|
||||
|
||||
branchNo: number;
|
||||
taxNo: string | null;
|
||||
name: string;
|
||||
nameEN: string;
|
||||
addressEN: string;
|
||||
address: string;
|
||||
zipCode: string;
|
||||
email: string;
|
||||
telephoneNo: string;
|
||||
|
||||
registerName: string;
|
||||
registerDate: Date;
|
||||
authorizedCapital: string;
|
||||
|
||||
employmentOffice: string;
|
||||
bussinessType: string;
|
||||
bussinessTypeEN: string;
|
||||
jobPosition: string;
|
||||
jobPositionEN: string;
|
||||
jobDescription: string;
|
||||
saleEmployee: string;
|
||||
payDate: Date;
|
||||
wageRate: number;
|
||||
|
||||
subDistrictId?: string | null;
|
||||
districtId?: string | null;
|
||||
provinceId?: string | null;
|
||||
}[];
|
||||
customerType: CustomerType;
|
||||
namePrefix: string;
|
||||
firstName: string;
|
||||
firstNameEN?: string;
|
||||
lastName: string;
|
||||
lastNameEN?: string;
|
||||
gender: string;
|
||||
birthDate: Date;
|
||||
};
|
||||
|
||||
function imageLocation(id: string) {
|
||||
|
|
@ -167,16 +103,17 @@ export class CustomerController extends Controller {
|
|||
) {
|
||||
const filterStatus = (val?: Status) => {
|
||||
if (!val) return {};
|
||||
|
||||
return val !== Status.CREATED && val !== Status.ACTIVE
|
||||
? { status: val }
|
||||
: { OR: [{ status: Status.CREATED }, { status: Status.ACTIVE }] };
|
||||
};
|
||||
const where = {
|
||||
OR: [
|
||||
{ customerName: { contains: query }, customerType, ...filterStatus(status) },
|
||||
{ customerNameEN: { contains: query }, customerType, ...filterStatus(status) },
|
||||
{ namePrefix: { contains: query } },
|
||||
{ firstName: { contains: query } },
|
||||
{ firstNameEN: { contains: query } },
|
||||
],
|
||||
AND: { customerType, ...filterStatus(status) },
|
||||
} satisfies Prisma.CustomerWhereInput;
|
||||
|
||||
const [result, total] = await prisma.$transaction([
|
||||
|
|
@ -190,9 +127,7 @@ export class CustomerController extends Controller {
|
|||
district: true,
|
||||
subDistrict: true,
|
||||
},
|
||||
orderBy: {
|
||||
branchNo: "asc",
|
||||
},
|
||||
orderBy: { createdAt: "asc" },
|
||||
}
|
||||
: undefined,
|
||||
createdBy: true,
|
||||
|
|
@ -206,21 +141,7 @@ export class CustomerController extends Controller {
|
|||
prisma.customer.count({ where }),
|
||||
]);
|
||||
|
||||
return {
|
||||
result: await Promise.all(
|
||||
result.map(async (v) => ({
|
||||
...v,
|
||||
imageUrl: await presignedGetObjectIfExist(
|
||||
MINIO_BUCKET,
|
||||
imageLocation(v.id),
|
||||
12 * 60 * 60,
|
||||
),
|
||||
})),
|
||||
),
|
||||
page,
|
||||
pageSize,
|
||||
total,
|
||||
};
|
||||
return { result, page, pageSize, total };
|
||||
}
|
||||
|
||||
@Get("{customerId}")
|
||||
|
|
@ -234,71 +155,27 @@ export class CustomerController extends Controller {
|
|||
district: true,
|
||||
subDistrict: true,
|
||||
},
|
||||
orderBy: { branchNo: "asc" },
|
||||
orderBy: { createdAt: "asc" },
|
||||
},
|
||||
createdBy: true,
|
||||
updatedBy: true,
|
||||
},
|
||||
where: { id: customerId },
|
||||
});
|
||||
if (!record)
|
||||
|
||||
if (!record) {
|
||||
throw new HttpError(HttpStatus.NOT_FOUND, "Customer cannot be found.", "customerNotFound");
|
||||
return Object.assign(record, {
|
||||
imageUrl: await presignedGetObjectIfExist(
|
||||
MINIO_BUCKET,
|
||||
imageLocation(record.id),
|
||||
12 * 60 * 60,
|
||||
),
|
||||
});
|
||||
}
|
||||
return record;
|
||||
}
|
||||
|
||||
@Post()
|
||||
@Security("keycloak", MANAGE_ROLES)
|
||||
async create(@Request() req: RequestWithUser, @Body() body: CustomerCreate) {
|
||||
const { customerBranch, ...payload } = body;
|
||||
|
||||
const provinceId = body.customerBranch?.reduce<string[]>((acc, cur) => {
|
||||
if (cur.provinceId && !acc.includes(cur.provinceId)) return acc.concat(cur.provinceId);
|
||||
return acc;
|
||||
}, []);
|
||||
const districtId = body.customerBranch?.reduce<string[]>((acc, cur) => {
|
||||
if (cur.districtId && !acc.includes(cur.districtId)) return acc.concat(cur.districtId);
|
||||
return acc;
|
||||
}, []);
|
||||
const subDistrictId = body.customerBranch?.reduce<string[]>((acc, cur) => {
|
||||
if (cur.subDistrictId && !acc.includes(cur.subDistrictId))
|
||||
return acc.concat(cur.subDistrictId);
|
||||
return acc;
|
||||
}, []);
|
||||
|
||||
const [province, district, subDistrict, branch] = await prisma.$transaction([
|
||||
prisma.province.findMany({ where: { id: { in: provinceId } } }),
|
||||
prisma.district.findMany({ where: { id: { in: districtId } } }),
|
||||
prisma.subDistrict.findMany({ where: { id: { in: subDistrictId } } }),
|
||||
const [branch] = await prisma.$transaction([
|
||||
prisma.branch.findFirst({ where: { id: body.registeredBranchId } }),
|
||||
]);
|
||||
|
||||
if (provinceId && province.length !== provinceId?.length) {
|
||||
throw new HttpError(
|
||||
HttpStatus.BAD_REQUEST,
|
||||
"Some province cannot be found.",
|
||||
"relationProvinceNotFound",
|
||||
);
|
||||
}
|
||||
if (districtId && district.length !== districtId?.length) {
|
||||
throw new HttpError(
|
||||
HttpStatus.BAD_REQUEST,
|
||||
"Some district cannot be found.",
|
||||
"relationDistrictNotFound",
|
||||
);
|
||||
}
|
||||
if (subDistrictId && subDistrict.length !== subDistrictId?.length) {
|
||||
throw new HttpError(
|
||||
HttpStatus.BAD_REQUEST,
|
||||
"Some sub district cannot be found.",
|
||||
"relationSubDistrictNotFound",
|
||||
);
|
||||
}
|
||||
if (!!body.registeredBranchId && !branch) {
|
||||
throw new HttpError(
|
||||
HttpStatus.BAD_REQUEST,
|
||||
|
|
@ -306,27 +183,24 @@ export class CustomerController extends Controller {
|
|||
"relationBranchNotFound",
|
||||
);
|
||||
}
|
||||
|
||||
if (!body.registeredBranchId) {
|
||||
body.registeredBranchId = undefined;
|
||||
}
|
||||
|
||||
const record = await prisma.$transaction(
|
||||
async (tx) => {
|
||||
body.code = body.code.toLocaleUpperCase();
|
||||
|
||||
const exist = await tx.customer.findFirst({
|
||||
where: { code: body.code },
|
||||
await tx.branch.updateMany({
|
||||
where: {
|
||||
id: body.registeredBranchId,
|
||||
status: "CREATED",
|
||||
},
|
||||
data: {
|
||||
status: "INACTIVE",
|
||||
statusOrder: 1,
|
||||
},
|
||||
});
|
||||
|
||||
if (exist) {
|
||||
throw new HttpError(
|
||||
HttpStatus.BAD_REQUEST,
|
||||
"Customer with same code already exists.",
|
||||
"sameCustomerCodeExists",
|
||||
);
|
||||
}
|
||||
|
||||
return await prisma.customer.create({
|
||||
return await tx.customer.create({
|
||||
include: {
|
||||
branch: {
|
||||
include: {
|
||||
|
|
@ -339,20 +213,8 @@ export class CustomerController extends Controller {
|
|||
updatedBy: true,
|
||||
},
|
||||
data: {
|
||||
...payload,
|
||||
statusOrder: +(payload.status === "INACTIVE"),
|
||||
code: `${body.code}000000`,
|
||||
branch: {
|
||||
createMany: {
|
||||
data:
|
||||
customerBranch?.map((v) => ({
|
||||
...v,
|
||||
code: body.code,
|
||||
createdByUserId: req.user.sub,
|
||||
updatedByUserId: req.user.sub,
|
||||
})) || [],
|
||||
},
|
||||
},
|
||||
...body,
|
||||
statusOrder: +(body.status === "INACTIVE"),
|
||||
createdByUserId: req.user.sub,
|
||||
updatedByUserId: req.user.sub,
|
||||
},
|
||||
|
|
@ -363,18 +225,7 @@ export class CustomerController extends Controller {
|
|||
|
||||
this.setStatus(HttpStatus.CREATED);
|
||||
|
||||
return Object.assign(record, {
|
||||
imageUrl: await presignedGetObjectIfExist(
|
||||
MINIO_BUCKET,
|
||||
imageLocation(record.id),
|
||||
12 * 60 * 60,
|
||||
),
|
||||
imageUploadUrl: await minio.presignedPutObject(
|
||||
MINIO_BUCKET,
|
||||
imageLocation(record.id),
|
||||
12 * 60 * 60,
|
||||
),
|
||||
});
|
||||
return record;
|
||||
}
|
||||
|
||||
@Put("{customerId}")
|
||||
|
|
@ -390,80 +241,25 @@ export class CustomerController extends Controller {
|
|||
throw new HttpError(HttpStatus.NOT_FOUND, "Customer cannot be found.", "customerNotFound");
|
||||
}
|
||||
|
||||
const provinceId = body.customerBranch?.reduce<string[]>((acc, cur) => {
|
||||
if (cur.provinceId && !acc.includes(cur.provinceId)) return acc.concat(cur.provinceId);
|
||||
return acc;
|
||||
}, []);
|
||||
const districtId = body.customerBranch?.reduce<string[]>((acc, cur) => {
|
||||
if (cur.districtId && !acc.includes(cur.districtId)) return acc.concat(cur.districtId);
|
||||
return acc;
|
||||
}, []);
|
||||
const subDistrictId = body.customerBranch?.reduce<string[]>((acc, cur) => {
|
||||
if (cur.subDistrictId && !acc.includes(cur.subDistrictId))
|
||||
return acc.concat(cur.subDistrictId);
|
||||
return acc;
|
||||
}, []);
|
||||
|
||||
const [province, district, subDistrict] = await prisma.$transaction([
|
||||
prisma.province.findMany({ where: { id: { in: provinceId } } }),
|
||||
prisma.district.findMany({ where: { id: { in: districtId } } }),
|
||||
prisma.subDistrict.findMany({ where: { id: { in: subDistrictId } } }),
|
||||
const [branch] = await prisma.$transaction([
|
||||
prisma.customer.findUnique({ where: { id: customerId } }),
|
||||
prisma.branch.findFirst({ where: { id: body.registeredBranchId } }),
|
||||
]);
|
||||
|
||||
if (provinceId && province.length !== provinceId?.length) {
|
||||
if (!!body.registeredBranchId && !branch) {
|
||||
throw new HttpError(
|
||||
HttpStatus.BAD_REQUEST,
|
||||
"Some province cannot be found.",
|
||||
"relationProvinceNotFound",
|
||||
);
|
||||
}
|
||||
if (districtId && district.length !== districtId?.length) {
|
||||
throw new HttpError(
|
||||
HttpStatus.BAD_REQUEST,
|
||||
"Some district cannot be found.",
|
||||
"relationDistrictNotFound",
|
||||
);
|
||||
}
|
||||
if (subDistrictId && subDistrict.length !== subDistrictId?.length) {
|
||||
throw new HttpError(
|
||||
HttpStatus.BAD_REQUEST,
|
||||
"Some sub district cannot be found.",
|
||||
"relationSubDistrictNotFound",
|
||||
"Branch cannot be found.",
|
||||
"relationBranchNotFound",
|
||||
);
|
||||
}
|
||||
|
||||
const { customerBranch, ...payload } = body;
|
||||
|
||||
const relation = await prisma.customerBranch.findMany({
|
||||
where: {
|
||||
customerId,
|
||||
},
|
||||
});
|
||||
|
||||
if (
|
||||
customerBranch &&
|
||||
relation.find((a) => !customerBranch.find((b) => a.id === b.id) && a.status !== "CREATED")
|
||||
) {
|
||||
throw new HttpError(
|
||||
HttpStatus.BAD_REQUEST,
|
||||
"One or more branch cannot be delete and is missing.",
|
||||
"oneOrMoreBranchMissing",
|
||||
);
|
||||
if (!body.registeredBranchId) {
|
||||
body.registeredBranchId = undefined;
|
||||
}
|
||||
|
||||
if (
|
||||
customerBranch &&
|
||||
relation.find((a) => customerBranch.find((b) => a.id !== b.id && a.branchNo === b.branchNo))
|
||||
) {
|
||||
throw new HttpError(
|
||||
HttpStatus.BAD_REQUEST,
|
||||
"Branch cannot have same number.",
|
||||
"oneOrMoreBranchNoExist",
|
||||
);
|
||||
}
|
||||
|
||||
const record = await prisma.customer
|
||||
.update({
|
||||
const record = await prisma.$transaction(async (tx) => {
|
||||
return await tx.customer.update({
|
||||
include: {
|
||||
branch: {
|
||||
include: {
|
||||
|
|
@ -477,74 +273,14 @@ export class CustomerController extends Controller {
|
|||
},
|
||||
where: { id: customerId },
|
||||
data: {
|
||||
...payload,
|
||||
statusOrder: +(payload.status === "INACTIVE"),
|
||||
branch:
|
||||
(customerBranch && {
|
||||
deleteMany: {
|
||||
id: {
|
||||
notIn: customerBranch.map((v) => v.id).filter((v): v is string => !!v) || [],
|
||||
},
|
||||
status: Status.CREATED,
|
||||
},
|
||||
upsert: customerBranch.map((v) => ({
|
||||
where: { id: v.id || "" },
|
||||
create: {
|
||||
...v,
|
||||
code: `${customer.code}-${v.branchNo.toString().padStart(2, "0")}`,
|
||||
createdByUserId: req.user.sub,
|
||||
updatedByUserId: req.user.sub,
|
||||
id: undefined,
|
||||
},
|
||||
update: {
|
||||
...v,
|
||||
code: undefined,
|
||||
branchNo: undefined,
|
||||
updatedByUserId: req.user.sub,
|
||||
},
|
||||
})),
|
||||
}) ||
|
||||
undefined,
|
||||
...body,
|
||||
statusOrder: +(body.status === "INACTIVE"),
|
||||
updatedByUserId: req.user.sub,
|
||||
},
|
||||
})
|
||||
.then((v) => {
|
||||
if (customerBranch) {
|
||||
relation
|
||||
.filter((a) => !customerBranch.find((b) => b.id === a.id))
|
||||
.forEach((deleted) => {
|
||||
new Promise<string[]>((resolve, reject) => {
|
||||
const item: string[] = [];
|
||||
|
||||
const stream = minio.listObjectsV2(MINIO_BUCKET, `customer/${deleted.id}`);
|
||||
|
||||
stream.on("data", (v) => v && v.name && item.push(v.name));
|
||||
stream.on("end", () => resolve(item));
|
||||
stream.on("error", () => reject(new Error("MinIO error.")));
|
||||
}).then((list) => {
|
||||
list.map(async (v) => {
|
||||
await minio.removeObject(MINIO_BUCKET, v, {
|
||||
forceDelete: true,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
return v;
|
||||
});
|
||||
|
||||
return Object.assign(record, {
|
||||
imageUrl: await presignedGetObjectIfExist(
|
||||
MINIO_BUCKET,
|
||||
imageLocation(record.id),
|
||||
12 * 60 * 60,
|
||||
),
|
||||
imageUploadUrl: await minio.presignedPutObject(
|
||||
MINIO_BUCKET,
|
||||
imageLocation(record.id),
|
||||
12 * 60 * 60,
|
||||
),
|
||||
});
|
||||
|
||||
return record;
|
||||
}
|
||||
|
||||
@Delete("{customerId}")
|
||||
|
|
@ -560,24 +296,11 @@ export class CustomerController extends Controller {
|
|||
throw new HttpError(HttpStatus.FORBIDDEN, "Customer is in used.", "customerInUsed");
|
||||
}
|
||||
|
||||
return await prisma.customer.delete({ where: { id: customerId } }).then((v) => {
|
||||
new Promise<string[]>((resolve, reject) => {
|
||||
const item: string[] = [];
|
||||
|
||||
const stream = minio.listObjectsV2(MINIO_BUCKET, `customer/${customerId}`);
|
||||
|
||||
stream.on("data", (v) => v && v.name && item.push(v.name));
|
||||
stream.on("end", () => resolve(item));
|
||||
stream.on("error", () => reject(new Error("MinIO error.")));
|
||||
}).then((list) => {
|
||||
list.map(async (v) => {
|
||||
await minio.removeObject(MINIO_BUCKET, v, {
|
||||
forceDelete: true,
|
||||
});
|
||||
});
|
||||
});
|
||||
return v;
|
||||
});
|
||||
return await prisma.customer
|
||||
.delete({ where: { id: customerId } })
|
||||
.then(
|
||||
async (data) => await deleteFolder(MINIO_BUCKET, `customer/${customerId}`).then(() => data),
|
||||
);
|
||||
}
|
||||
|
||||
@Get("{customerId}/image")
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue