浏览代码

Merge branch 'development'

pearlgw 1 天之前
父节点
当前提交
026f7f2090
共有 58 个文件被更改,包括 1687 次插入2121 次删除
  1. 48 0
      prisma/migrations/20250908013400_update_erd_vendor_experience/migration.sql
  2. 11 0
      prisma/migrations/20250908020610_update/migration.sql
  3. 11 0
      prisma/migrations/20250908023150_update/migration.sql
  4. 2 0
      prisma/migrations/20250908065231_add_field_status_archieve_in_table_category/migration.sql
  5. 9 0
      prisma/migrations/20250908065458_add_field_status_archieve_in_table_category_update_type/migration.sql
  6. 2 0
      prisma/migrations/20250908070214_add_field_status_archieve_in_table_category_update_type_add_default/migration.sql
  7. 9 0
      prisma/migrations/20250908071236_add_field_status_archieve_in_table_category_update_type_add_default_edit/migration.sql
  8. 43 35
      prisma/schema.prisma
  9. 43 43
      prisma/seeders/DatabaseSeeder.ts
  10. 2 2
      prisma/seeders/HospitalSeeder.ts
  11. 2 2
      prisma/seeders/UserAreaSeeder.ts
  12. 1 1
      prisma/seeders/VendorSeeder.ts
  13. 9 25
      src/controllers/admin/CategoryController.ts
  14. 3 64
      src/controllers/admin/VendorExperienceController.ts
  15. 1 52
      src/controllers/sales/HospitalController.ts
  16. 2 2
      src/controllers/sales/VendorExperienceController.ts
  17. 65 64
      src/repository/admin/CategoryRepository.ts
  18. 2 2
      src/repository/admin/HospitalRepository.ts
  19. 24 5
      src/repository/admin/ScheduleVisitationRepository.ts
  20. 51 161
      src/repository/admin/VendorExperienceRepository.ts
  21. 2 1
      src/repository/admin/VendorRepository.ts
  22. 3 138
      src/repository/sales/HospitalRepository.ts
  23. 14 4
      src/repository/sales/ScheduleVisitationRepository.ts
  24. 49 105
      src/repository/sales/VendorExperienceRepository.ts
  25. 25 25
      src/resources/admin/hospital/HospitalCollection.ts
  26. 14 14
      src/resources/admin/hospital/HospitalResource.ts
  27. 2 2
      src/resources/admin/schedule_visitation/ScheduleVisitationResource.ts
  28. 26 26
      src/resources/admin/status_history/StatusHistoryCollection.ts
  29. 21 21
      src/resources/admin/vendor/VendorCollection.ts
  30. 18 18
      src/resources/admin/vendor/VendorResource.ts
  31. 32 32
      src/resources/admin/vendor_experience/VendorExperienceCollection.ts
  32. 38 25
      src/resources/admin/vendor_experience/VendorExperienceResource.ts
  33. 25 25
      src/resources/sales/hospital/HospitalCollection.ts
  34. 14 14
      src/resources/sales/hospital/HospitalResource.ts
  35. 2 2
      src/resources/sales/schedule_visitation/ScheduleVisitationResource.ts
  36. 25 25
      src/resources/sales/status_history/StatusHistoryCollection.ts
  37. 33 34
      src/resources/sales/vendor_experience/VendorExperienceCollection.ts
  38. 38 25
      src/resources/sales/vendor_experience/VendorExperienceResource.ts
  39. 4 3
      src/routes/admin/CategoryRoute.ts
  40. 55 55
      src/services/admin/CategoryLinkService.ts
  41. 154 114
      src/services/admin/CategoryService.ts
  42. 1 75
      src/services/admin/CityService.ts
  43. 25 25
      src/services/admin/HospitalService.ts
  44. 9 9
      src/services/admin/StatusHistoryService.ts
  45. 213 445
      src/services/admin/VendorExperienceService.ts
  46. 41 42
      src/services/admin/VendorService.ts
  47. 17 17
      src/services/sales/HospitalService.ts
  48. 9 9
      src/services/sales/StatusHistoryService.ts
  49. 211 168
      src/services/sales/VendorExperienceService.ts
  50. 4 4
      src/types/admin/category/CategoryDTO.ts
  51. 16 4
      src/types/admin/schedule_visitation/ScheduleVisitationDTO.ts
  52. 43 28
      src/types/admin/vendor_experience/VendorExperienceDTO.ts
  53. 16 4
      src/types/sales/schedule_visitation/ScheduleVisitationDTO.ts
  54. 40 28
      src/types/sales/vendor_experience/VendorExperienceDTO.ts
  55. 25 25
      src/validators/admin/category/CategoryValidators.ts
  56. 38 34
      src/validators/admin/vendor_experience/VendorExperienceValidators.ts
  57. 39 34
      src/validators/sales/vendor_experience/VendorExperienceValidators.ts
  58. 6 4
      tsconfig.json

+ 48 - 0
prisma/migrations/20250908013400_update_erd_vendor_experience/migration.sql

@@ -0,0 +1,48 @@
1
+/*
2
+  Warnings:
3
+
4
+  - You are about to drop the column `tag` on the `categories` table. All the data in the column will be lost.
5
+  - You are about to drop the column `contract_expired_date` on the `vendor_experiences` table. All the data in the column will be lost.
6
+  - You are about to drop the column `contract_start_date` on the `vendor_experiences` table. All the data in the column will be lost.
7
+  - You are about to drop the column `contract_value_max` on the `vendor_experiences` table. All the data in the column will be lost.
8
+  - You are about to drop the column `contract_value_min` on the `vendor_experiences` table. All the data in the column will be lost.
9
+  - You are about to drop the column `negative_notes` on the `vendor_experiences` table. All the data in the column will be lost.
10
+  - You are about to drop the column `positive_notes` on the `vendor_experiences` table. All the data in the column will be lost.
11
+  - You are about to drop the column `simrs_type` on the `vendor_experiences` table. All the data in the column will be lost.
12
+  - You are about to drop the column `status` on the `vendor_experiences` table. All the data in the column will be lost.
13
+  - You are about to drop the `category_links` table. If the table is not empty, all the data it contains will be lost.
14
+  - Added the required column `name` to the `categories` table without a default value. This is not possible if the table is not empty.
15
+  - Added the required column `user_id` to the `vendor_experiences` table without a default value. This is not possible if the table is not empty.
16
+
17
+*/
18
+-- DropForeignKey
19
+ALTER TABLE "category_links" DROP CONSTRAINT "category_links_category_id_fkey";
20
+
21
+-- AlterTable
22
+ALTER TABLE "categories" DROP COLUMN "tag",
23
+ADD COLUMN     "name" TEXT NOT NULL;
24
+
25
+-- AlterTable
26
+ALTER TABLE "vendor_experiences" DROP COLUMN "contract_expired_date",
27
+DROP COLUMN "contract_start_date",
28
+DROP COLUMN "contract_value_max",
29
+DROP COLUMN "contract_value_min",
30
+DROP COLUMN "negative_notes",
31
+DROP COLUMN "positive_notes",
32
+DROP COLUMN "simrs_type",
33
+DROP COLUMN "status",
34
+ADD COLUMN     "category_id" TEXT,
35
+ADD COLUMN     "userKeycloakId" TEXT,
36
+ADD COLUMN     "user_id" TEXT NOT NULL;
37
+
38
+-- DropTable
39
+DROP TABLE "category_links";
40
+
41
+-- AddForeignKey
42
+ALTER TABLE "vendor_experiences" ADD CONSTRAINT "vendor_experiences_category_id_fkey" FOREIGN KEY ("category_id") REFERENCES "categories"("id") ON DELETE SET NULL ON UPDATE CASCADE;
43
+
44
+-- AddForeignKey
45
+ALTER TABLE "vendor_experiences" ADD CONSTRAINT "vendor_experiences_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
46
+
47
+-- AddForeignKey
48
+ALTER TABLE "vendor_experiences" ADD CONSTRAINT "vendor_experiences_userKeycloakId_fkey" FOREIGN KEY ("userKeycloakId") REFERENCES "keycloak_users"("id") ON DELETE SET NULL ON UPDATE CASCADE;

+ 11 - 0
prisma/migrations/20250908020610_update/migration.sql

@@ -0,0 +1,11 @@
1
+-- DropForeignKey
2
+ALTER TABLE "vendor_experiences" DROP CONSTRAINT "vendor_experiences_userKeycloakId_fkey";
3
+
4
+-- DropForeignKey
5
+ALTER TABLE "vendor_experiences" DROP CONSTRAINT "vendor_experiences_user_id_fkey";
6
+
7
+-- AlterTable
8
+ALTER TABLE "vendor_experiences" ADD COLUMN     "userId" TEXT;
9
+
10
+-- AddForeignKey
11
+ALTER TABLE "vendor_experiences" ADD CONSTRAINT "vendor_experiences_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "keycloak_users"("id") ON DELETE RESTRICT ON UPDATE CASCADE;

+ 11 - 0
prisma/migrations/20250908023150_update/migration.sql

@@ -0,0 +1,11 @@
1
+/*
2
+  Warnings:
3
+
4
+  - You are about to drop the column `userId` on the `vendor_experiences` table. All the data in the column will be lost.
5
+  - You are about to drop the column `userKeycloakId` on the `vendor_experiences` table. All the data in the column will be lost.
6
+
7
+*/
8
+-- AlterTable
9
+ALTER TABLE "vendor_experiences" DROP COLUMN "userId",
10
+DROP COLUMN "userKeycloakId",
11
+ADD COLUMN     "content" TEXT;

+ 2 - 0
prisma/migrations/20250908065231_add_field_status_archieve_in_table_category/migration.sql

@@ -0,0 +1,2 @@
1
+-- AlterTable
2
+ALTER TABLE "categories" ADD COLUMN     "status_archieve" TEXT;

+ 9 - 0
prisma/migrations/20250908065458_add_field_status_archieve_in_table_category_update_type/migration.sql

@@ -0,0 +1,9 @@
1
+/*
2
+  Warnings:
3
+
4
+  - The `status_archieve` column on the `categories` table would be dropped and recreated. This will lead to data loss if there is data in the column.
5
+
6
+*/
7
+-- AlterTable
8
+ALTER TABLE "categories" DROP COLUMN "status_archieve",
9
+ADD COLUMN     "status_archieve" BOOLEAN;

+ 2 - 0
prisma/migrations/20250908070214_add_field_status_archieve_in_table_category_update_type_add_default/migration.sql

@@ -0,0 +1,2 @@
1
+-- AlterTable
2
+ALTER TABLE "categories" ALTER COLUMN "status_archieve" SET DEFAULT false;

+ 9 - 0
prisma/migrations/20250908071236_add_field_status_archieve_in_table_category_update_type_add_default_edit/migration.sql

@@ -0,0 +1,9 @@
1
+/*
2
+  Warnings:
3
+
4
+  - You are about to drop the column `status_archieve` on the `categories` table. All the data in the column will be lost.
5
+
6
+*/
7
+-- AlterTable
8
+ALTER TABLE "categories" DROP COLUMN "status_archieve",
9
+ADD COLUMN     "status_archive" BOOLEAN DEFAULT false;

+ 43 - 35
prisma/schema.prisma

@@ -67,6 +67,7 @@ model UserKeycloak {
67
   UserArea           UserArea[]
67
   UserArea           UserArea[]
68
   Vendor             Vendor[]
68
   Vendor             Vendor[]
69
   StatusHistory      StatusHistory[]
69
   StatusHistory      StatusHistory[]
70
+  VendorExperience   VendorExperience[]
70
   CreatedVisitations ScheduleVisitation[] @relation("CreatedVisitations")
71
   CreatedVisitations ScheduleVisitation[] @relation("CreatedVisitations")
71
   SalesVisitations   ScheduleVisitation[] @relation("SalesVisitations")
72
   SalesVisitations   ScheduleVisitation[] @relation("SalesVisitations")
72
 
73
 
@@ -181,22 +182,27 @@ model UserArea {
181
 // }
182
 // }
182
 
183
 
183
 model VendorExperience {
184
 model VendorExperience {
184
-  id                    String    @id @default(uuid())
185
-  hospital_id           String
186
-  vendor_id             String?
187
-  status                String?
188
-  contract_start_date   DateTime?
189
-  contract_expired_date DateTime?
190
-  contract_value_min    BigInt?
191
-  contract_value_max    BigInt?
192
-  positive_notes        String?   @db.Text
193
-  negative_notes        String?   @db.Text
194
-  simrs_type            String
195
-  hospital              Hospital  @relation(fields: [hospital_id], references: [id])
196
-  vendor                Vendor?   @relation(fields: [vendor_id], references: [id])
197
-  createdAt             DateTime  @default(now())
198
-  updatedAt             DateTime  @updatedAt
199
-  deletedAt             DateTime?
185
+  id          String       @id @default(uuid())
186
+  hospital_id String
187
+  vendor_id   String?
188
+  category_id String?
189
+  user_id     String
190
+  content     String?      @db.Text
191
+  hospital    Hospital     @relation(fields: [hospital_id], references: [id])
192
+  vendor      Vendor?      @relation(fields: [vendor_id], references: [id])
193
+  category    Category?    @relation(fields: [category_id], references: [id])
194
+  user        UserKeycloak @relation(fields: [user_id], references: [id])
195
+  createdAt   DateTime     @default(now())
196
+  updatedAt   DateTime     @updatedAt
197
+  deletedAt   DateTime?
198
+  // status                String?
199
+  // contract_start_date   DateTime?
200
+  // contract_expired_date DateTime?
201
+  // contract_value_min    BigInt?
202
+  // contract_value_max    BigInt?
203
+  // positive_notes        String?   @db.Text
204
+  // negative_notes        String?   @db.Text
205
+  // simrs_type            String
200
 
206
 
201
   @@map("vendor_experiences")
207
   @@map("vendor_experiences")
202
 }
208
 }
@@ -234,29 +240,31 @@ model StatusHistory {
234
 }
240
 }
235
 
241
 
236
 model Category {
242
 model Category {
237
-  id           String         @id @default(uuid())
238
-  tag          String
239
-  description  String?        @db.Text
240
-  CategoryLink CategoryLink[]
241
-  createdAt    DateTime       @default(now())
242
-  updatedAt    DateTime       @updatedAt
243
-  deletedAt    DateTime?
243
+  id               String             @id @default(uuid())
244
+  name             String
245
+  description      String?            @db.Text
246
+  status_archive   Boolean?           @default(false)
247
+  // CategoryLink CategoryLink[]
248
+  createdAt        DateTime           @default(now())
249
+  updatedAt        DateTime           @updatedAt
250
+  deletedAt        DateTime?
251
+  VendorExperience VendorExperience[]
244
 
252
 
245
   @@map("categories")
253
   @@map("categories")
246
 }
254
 }
247
 
255
 
248
-model CategoryLink {
249
-  id          String    @id @default(uuid())
250
-  category_id String
251
-  source_type String?
252
-  source_id   String?
253
-  createdAt   DateTime  @default(now())
254
-  updatedAt   DateTime  @updatedAt
255
-  deletedAt   DateTime?
256
-  Category    Category? @relation(fields: [category_id], references: [id])
257
-
258
-  @@map("category_links")
259
-}
256
+// model CategoryLink {
257
+//   id          String    @id @default(uuid())
258
+//   category_id String
259
+//   source_type String?
260
+//   source_id   String?
261
+//   createdAt   DateTime  @default(now())
262
+//   updatedAt   DateTime  @updatedAt
263
+//   deletedAt   DateTime?
264
+//   Category    Category? @relation(fields: [category_id], references: [id])
265
+
266
+//   @@map("category_links")
267
+// }
260
 
268
 
261
 model ScheduleVisitation {
269
 model ScheduleVisitation {
262
   id           String       @id @default(uuid())
270
   id           String       @id @default(uuid())

+ 43 - 43
prisma/seeders/DatabaseSeeder.ts

@@ -44,49 +44,49 @@ import { seedUserAreas } from './UserAreaSeeder';
44
 import { seedHospitals } from './HospitalSeeder';
44
 import { seedHospitals } from './HospitalSeeder';
45
 
45
 
46
 async function main(): Promise<void> {
46
 async function main(): Promise<void> {
47
-    await seedProvinces();
48
-    await seedAcehCities();
49
-    await seedBaliCities();
50
-    await seedBantenCities();
51
-    await seedBengkuluCities();
52
-    await seedDIYogyakartaCities();
53
-    await seedDKIJakartaCities();
54
-    await seedGorontaloCities();
55
-    await seedJambiCities();
56
-    await seedJawaBaratCities();
57
-    await seedJawaTengahCities();
58
-    await seedJawaTimurCities();
59
-    await seedKalimantanBaratCities();
60
-    await seedKalimantanSelatanCities();
61
-    await seedKalimantanTengahCities();
62
-    await seedKalimantanTimurCities();
63
-    await seedKalimantanUtaraCities();
64
-    await seedKepulauanBangkaBelitungCities();
65
-    await seedKepulauanRiauCities();
66
-    await seedLampungCities();
67
-    await seedMalukuCities();
68
-    await seedMalukuUtaraCities();
69
-    await seedNusaTenggaraBaratCities();
70
-    await seedNusaTenggaraTimurCities();
71
-    await seedPapuaCities();
72
-    await seedPapuaBaratCities();
73
-    await seedPapuaBaratDayaCities();
74
-    await seedPapuaPegununganCities();
75
-    await seedPapuaTengahCities();
76
-    await seedRiauCities();
77
-    await seedSulawesiBaratCities();
78
-    await seedSulawesiSelatanCities();
79
-    await seedSulawesiTengahCities();
80
-    await seedSulawesiTenggaraCities();
81
-    await seedSulawesiUtaraCities();
82
-    await seedSumateraBaratCities();
83
-    await seedSumateraSelatanCities();
84
-    await seedSumateraUtaraCities();
85
-    await seedPapuaSelatanCities();
86
-    await seedUsers();
87
-    // await seedVendors();
88
-    // await seedUserAreas();
89
-    // await seedHospitals();
47
+    // await seedProvinces();
48
+    // await seedAcehCities();
49
+    // await seedBaliCities();
50
+    // await seedBantenCities();
51
+    // await seedBengkuluCities();
52
+    // await seedDIYogyakartaCities();
53
+    // await seedDKIJakartaCities();
54
+    // await seedGorontaloCities();
55
+    // await seedJambiCities();
56
+    // await seedJawaBaratCities();
57
+    // await seedJawaTengahCities();
58
+    // await seedJawaTimurCities();
59
+    // await seedKalimantanBaratCities();
60
+    // await seedKalimantanSelatanCities();
61
+    // await seedKalimantanTengahCities();
62
+    // await seedKalimantanTimurCities();
63
+    // await seedKalimantanUtaraCities();
64
+    // await seedKepulauanBangkaBelitungCities();
65
+    // await seedKepulauanRiauCities();
66
+    // await seedLampungCities();
67
+    // await seedMalukuCities();
68
+    // await seedMalukuUtaraCities();
69
+    // await seedNusaTenggaraBaratCities();
70
+    // await seedNusaTenggaraTimurCities();
71
+    // await seedPapuaCities();
72
+    // await seedPapuaBaratCities();
73
+    // await seedPapuaBaratDayaCities();
74
+    // await seedPapuaPegununganCities();
75
+    // await seedPapuaTengahCities();
76
+    // await seedRiauCities();
77
+    // await seedSulawesiBaratCities();
78
+    // await seedSulawesiSelatanCities();
79
+    // await seedSulawesiTengahCities();
80
+    // await seedSulawesiTenggaraCities();
81
+    // await seedSulawesiUtaraCities();
82
+    // await seedSumateraBaratCities();
83
+    // await seedSumateraSelatanCities();
84
+    // await seedSumateraUtaraCities();
85
+    // await seedPapuaSelatanCities();
86
+    // await seedUsers();
87
+    await seedVendors();
88
+    await seedUserAreas();
89
+    await seedHospitals();
90
 }
90
 }
91
 
91
 
92
 main()
92
 main()

+ 2 - 2
prisma/seeders/HospitalSeeder.ts

@@ -5,8 +5,8 @@ const prisma = new PrismaClient();
5
 
5
 
6
 export async function seedHospitals(): Promise<void> {
6
 export async function seedHospitals(): Promise<void> {
7
     try {
7
     try {
8
-        const sales1 = await prisma.userKeycloak.findFirst({ where: { id: '00c7e427-cbb7-408c-af44-e04747fd61fd' } });
9
-        const sales2 = await prisma.userKeycloak.findFirst({ where: { id: 'd27994a4-07b9-4ea8-bd62-3d6c51afed0e' } });
8
+        const sales1 = await prisma.userKeycloak.findFirst({ where: { id: '1d750cae-45ac-4aff-b20c-d2c5e54185e1' } });
9
+        const sales2 = await prisma.userKeycloak.findFirst({ where: { id: '5064d1f3-74fc-42bd-bd85-9842eed60ac2' } });
10
 
10
 
11
         if (!sales1 || !sales2) {
11
         if (!sales1 || !sales2) {
12
             throw new Error('User sales1 or sales2 not found');
12
             throw new Error('User sales1 or sales2 not found');

+ 2 - 2
prisma/seeders/UserAreaSeeder.ts

@@ -3,8 +3,8 @@ import prisma from '../../src/prisma/PrismaClient';
3
 export async function seedUserAreas(): Promise<void> {
3
 export async function seedUserAreas(): Promise<void> {
4
     try {
4
     try {
5
         // Ambil user dengan username 'sales1' dan 'sales2'
5
         // Ambil user dengan username 'sales1' dan 'sales2'
6
-        const sales1 = await prisma.userKeycloak.findFirst({ where: { id: '00c7e427-cbb7-408c-af44-e04747fd61fd' } });
7
-        const sales2 = await prisma.userKeycloak.findFirst({ where: { id: 'd27994a4-07b9-4ea8-bd62-3d6c51afed0e' } });
6
+        const sales1 = await prisma.userKeycloak.findFirst({ where: { id: '1d750cae-45ac-4aff-b20c-d2c5e54185e1' } });
7
+        const sales2 = await prisma.userKeycloak.findFirst({ where: { id: '5064d1f3-74fc-42bd-bd85-9842eed60ac2' } });
8
 
8
 
9
         if (!sales1 || !sales2) {
9
         if (!sales1 || !sales2) {
10
             throw new Error('User sales1 or sales2 not found');
10
             throw new Error('User sales1 or sales2 not found');

+ 1 - 1
prisma/seeders/VendorSeeder.ts

@@ -13,7 +13,7 @@ export async function seedVendors(): Promise<void> {
13
         // Cari user dengan username admin1
13
         // Cari user dengan username admin1
14
         const adminUser = await prisma.userKeycloak.findFirst({
14
         const adminUser = await prisma.userKeycloak.findFirst({
15
             where: {
15
             where: {
16
-                id: '06ccc7a6-9f6d-437f-9e1f-501a36077796',
16
+                id: '6471416f-e24e-4d27-815a-9f12a1344e18',
17
             },
17
             },
18
         });
18
         });
19
 
19
 

+ 9 - 25
src/controllers/admin/CategoryController.ts

@@ -2,18 +2,20 @@ import { Request, Response } from 'express';
2
 import * as CategoryService from '../../services/admin/CategoryService';
2
 import * as CategoryService from '../../services/admin/CategoryService';
3
 import { PaginationParam } from '../../utils/PaginationParams';
3
 import { PaginationParam } from '../../utils/PaginationParams';
4
 import { errorResponse, messageSuccessResponse } from '../../utils/Response';
4
 import { errorResponse, messageSuccessResponse } from '../../utils/Response';
5
-import { validateCategoryStoreRequest, validateCategoryUpdateRequest, validateMergeCategoryStoreRequest } from '../../validators/admin/category/CategoryValidators';
5
+import { validateCategoryStoreRequest, validateCategoryUpdateRequest } from '../../validators/admin/category/CategoryValidators';
6
 import { CustomRequest } from '../../types/token/CustomRequest';
6
 import { CustomRequest } from '../../types/token/CustomRequest';
7
 import { CategoryCollection } from '../../resources/admin/category/CategoryCollection';
7
 import { CategoryCollection } from '../../resources/admin/category/CategoryCollection';
8
 import { CategoryResource } from '../../resources/admin/category/CategoryResource';
8
 import { CategoryResource } from '../../resources/admin/category/CategoryResource';
9
-import { CategoryLinkCollection } from '../../resources/admin/category/CategoryUseCollection';
9
+// import { CategoryLinkCollection } from '../../resources/admin/category/CategoryUseCollection';
10
 
10
 
11
 export const getAllCategory = async (req: Request, res: Response): Promise<Response> => {
11
 export const getAllCategory = async (req: Request, res: Response): Promise<Response> => {
12
     try {
12
     try {
13
         const { page, limit, search, sortBy, orderBy } = PaginationParam(req);
13
         const { page, limit, search, sortBy, orderBy } = PaginationParam(req);
14
+        const filter = req.query.filter as 'archive' | 'all' | undefined;
15
+        const usage = req.query.usage as 'unused' | 'used' | undefined;
14
 
16
 
15
         const { categories, total } = await CategoryService.getAllCategoryService({
17
         const { categories, total } = await CategoryService.getAllCategoryService({
16
-            page, limit, search, sortBy, orderBy
18
+            page, limit, search, sortBy, orderBy, filter, usage
17
         });
19
         });
18
 
20
 
19
         return CategoryCollection(req, res, categories, total, page, limit, 'Category data successfully retrieved');
21
         return CategoryCollection(req, res, categories, total, page, limit, 'Category data successfully retrieved');
@@ -63,29 +65,11 @@ export const deleteCategory = async (req: Request, res: Response): Promise<Respo
63
     }
65
     }
64
 };
66
 };
65
 
67
 
66
-export const showUseCategory = async (req: Request, res: Response): Promise<Response> => {
68
+export const archiveCategory = async (req: Request, res: Response): Promise<Response> => {
67
     try {
69
     try {
68
-        const categoryId = req.params.id;
69
-        const { page, limit, search } = PaginationParam(req);
70
-
71
-        const { data, total } = await CategoryService.showUseCategoryService({
72
-            page,
73
-            limit,
74
-            search,
75
-            categoryId,
76
-        });
77
-
78
-        return CategoryLinkCollection(req, res, data, total, page, limit, 'Category usage data successfully retrieved');
79
-    } catch (err) {
80
-        return errorResponse(res, err);
81
-    }
82
-};
83
-
84
-export const mergeCategory = async (req: Request, res: Response): Promise<Response> => {
85
-    try {
86
-        const validatedData = validateMergeCategoryStoreRequest(req.body);
87
-        await CategoryService.mergeCategoryService(validatedData, req as CustomRequest);
88
-        return messageSuccessResponse(res, 'Success merge category', 200);
70
+        const id = req.params.id;
71
+        await CategoryService.archiveCategoryService(id, req as CustomRequest);
72
+        return messageSuccessResponse(res, 'Success archive category');
89
     } catch (err) {
73
     } catch (err) {
90
         return errorResponse(res, err);
74
         return errorResponse(res, err);
91
     }
75
     }

+ 3 - 64
src/controllers/admin/VendorExperienceController.ts

@@ -9,10 +9,10 @@ import { CustomRequest } from '../../types/token/CustomRequest';
9
 
9
 
10
 export const getAllVendorExperience = async (req: Request, res: Response): Promise<Response> => {
10
 export const getAllVendorExperience = async (req: Request, res: Response): Promise<Response> => {
11
     try {
11
     try {
12
-        const { page, limit, search, sortBy, orderBy } = PaginationParam(req);
12
+        const { page, limit, search, sortBy, orderBy, category_id } = PaginationParam(req, ['category_id']);
13
 
13
 
14
         const { vendor_experiences, total } = await VendorExperienceService.getAllVendorExperienceService(
14
         const { vendor_experiences, total } = await VendorExperienceService.getAllVendorExperienceService(
15
-            { page, limit, search, sortBy, orderBy },
15
+            { page, limit, search, sortBy, orderBy, category_id },
16
             req
16
             req
17
         );
17
         );
18
 
18
 
@@ -58,65 +58,4 @@ export const deleteVendorExperience = async (req: Request, res: Response): Promi
58
     } catch (err) {
58
     } catch (err) {
59
         return errorResponse(res, err);
59
         return errorResponse(res, err);
60
     }
60
     }
61
-};
62
-
63
-
64
-// const { VendorExperienceCollection } = require('../../resources/admin/vendor_experience/VendorExperienceCollection.js');
65
-// const { VendorExperienceResource } = require('../../resources/admin/vendor_experience/VendorExperienceResource.js');
66
-// const vendorHistoryService = require('../../services/admin/VendorExperienceService.js');
67
-// const { PaginationParam } = require('../../utils/PaginationParams.js');
68
-// const { errorResponse, messageSuccessResponse } = require('../../utils/Response.js');
69
-// const { validateStoreVendorHistoryRequest, validateUpdateVendorHistoryRequest } = require('../../validators/admin/vendor_experience/VendorExperienceValidators.js');
70
-
71
-// exports.getAllVendorHistory = async (req, res) => {
72
-//     try {
73
-//         const { page, limit, search, sortBy, orderBy } = PaginationParam(req);
74
-
75
-//         const { vendor_histories, total } = await vendorHistoryService.getAllVendorHistoryService({
76
-//             page, limit, search, sortBy, orderBy
77
-//         }, req);
78
-
79
-//         return VendorExperienceCollection(req, res, vendor_histories, total, page, limit, 'Vendor experience successfully retrieved');
80
-
81
-//     } catch (err) {
82
-//         return errorResponse(res, err);
83
-//     }
84
-// };
85
-
86
-// exports.showVendorHistory = async (req, res) => {
87
-//     try {
88
-//         const data = await vendorHistoryService.showVendorHistoryService(req);
89
-//         return VendorExperienceResource(res, data, 'Success show vendor experience');
90
-//     } catch (err) {
91
-//         return errorResponse(res, err);
92
-//     }
93
-// };
94
-
95
-// exports.storeVendorHistory = async (req, res) => {
96
-//     try {
97
-//         const validatedData = validateStoreVendorHistoryRequest(req.body);
98
-//         await vendorHistoryService.storeVendorHistoryService(validatedData, req);
99
-//         return messageSuccessResponse(res, 'Success added vendor experience', 201);
100
-//     } catch (err) {
101
-//         return errorResponse(res, err);
102
-//     }
103
-// }
104
-
105
-// exports.updateVendorHistory = async (req, res) => {
106
-//     try {
107
-//         const validatedData = validateUpdateVendorHistoryRequest(req.body);
108
-//         await vendorHistoryService.updateVendorHistoryService(validatedData, req);
109
-//         return messageSuccessResponse(res, 'Success update vendor experience');
110
-//     } catch (err) {
111
-//         return errorResponse(res, err);
112
-//     }
113
-// }
114
-
115
-// exports.deleteVendorHistory = async (req, res) => {
116
-//     try {
117
-//         await vendorHistoryService.deleteVendorHistoryService(req);
118
-//         return messageSuccessResponse(res, 'Success delete vendor experience');
119
-//     } catch (err) {
120
-//         return errorResponse(res, err);
121
-//     }
122
-// };
61
+};

+ 1 - 52
src/controllers/sales/HospitalController.ts

@@ -54,55 +54,4 @@ export const showHospital = async (req: Request, res: Response): Promise<Respons
54
     } catch (err) {
54
     } catch (err) {
55
         return errorResponse(res, err);
55
         return errorResponse(res, err);
56
     }
56
     }
57
-};
58
-
59
-
60
-// const { HospitalCollection } = require("../../resources/sales/hospital/HospitalCollection.js");
61
-// const { HospitalResource } = require("../../resources/sales/hospital/HospitalResource.js");
62
-// const { getAllHospitalByAreaService, storeHospitalService, updateHospitalService, showHospitalService } = require("../../services/sales/HospitalService");
63
-// const { PaginationParam } = require("../../utils/PaginationParams");
64
-// const { errorResponse, messageSuccessResponse } = require("../../utils/Response");
65
-// const { validateStoreHospitalRequest, validateUpdateHospitalRequest } = require('../../validators/admin/hospital/HospitalValidators.js');
66
-
67
-// exports.getAllHospitalByArea = async (req, res) => {
68
-//     try {
69
-//         const { page, limit, search, sortBy, orderBy, province, city, type, ownership, progress_status } = PaginationParam(req, ['province', 'city', 'type', 'ownership', 'progress_status']);
70
-
71
-//         const { hospitals, total } = await getAllHospitalByAreaService({ page, limit, search, sortBy, orderBy, province, city, type, ownership, progress_status }, req);
72
-
73
-//         return HospitalCollection({ req, res, data: hospitals, total, page, limit, message: 'Hospital data successfully retrieved' });
74
-//     } catch (err) {
75
-//         return errorResponse(res, err);
76
-//     }
77
-// };
78
-
79
-// exports.storeHospital = async (req, res) => {
80
-//     try {
81
-//         const validatedData = validateStoreHospitalRequest(req.body);
82
-//         await storeHospitalService(validatedData, req);
83
-//         return messageSuccessResponse(res, 'Success added hospital', 201);
84
-//     } catch (err) {
85
-//         return errorResponse(res, err);
86
-//     }
87
-// }
88
-
89
-// exports.updateHospital = async (req, res) => {
90
-//     try {
91
-//         const id = req.params.id;
92
-//         const validatedData = validateUpdateHospitalRequest(req.body);
93
-//         await updateHospitalService(validatedData, id, req);
94
-//         return messageSuccessResponse(res, 'Success update hospital');
95
-//     } catch (err) {
96
-//         return errorResponse(res, err);
97
-//     }
98
-// }
99
-
100
-// exports.showHospital = async (req, res) => {
101
-//     try {
102
-//         const id = req.params.id;
103
-//         const { hospital } = await showHospitalService(id);
104
-//         return HospitalResource(res, hospital, 'Success show hospital');
105
-//     } catch (err) {
106
-//         return errorResponse(res, err);
107
-//     }
108
-// };
57
+};

+ 2 - 2
src/controllers/sales/VendorExperienceController.ts

@@ -9,10 +9,10 @@ import { CustomRequest } from '../../types/token/CustomRequest';
9
 
9
 
10
 export const getAllVendorExperience = async (req: Request, res: Response): Promise<Response> => {
10
 export const getAllVendorExperience = async (req: Request, res: Response): Promise<Response> => {
11
     try {
11
     try {
12
-        const { page, limit, search, sortBy, orderBy } = PaginationParam(req);
12
+        const { page, limit, search, sortBy, orderBy, category_id } = PaginationParam(req, ['category_id']);
13
 
13
 
14
         const { vendor_experiences, total } = await VendorExperienceService.getAllVendorExperienceService(
14
         const { vendor_experiences, total } = await VendorExperienceService.getAllVendorExperienceService(
15
-            { page, limit, search, sortBy, orderBy },
15
+            { page, limit, search, sortBy, orderBy, category_id },
16
             req as CustomRequest
16
             req as CustomRequest
17
         );
17
         );
18
 
18
 

+ 65 - 64
src/repository/admin/CategoryRepository.ts

@@ -8,12 +8,12 @@ interface FindAllParams {
8
     orderBy?: Prisma.CategoryOrderByWithRelationInput;
8
     orderBy?: Prisma.CategoryOrderByWithRelationInput;
9
 }
9
 }
10
 
10
 
11
-interface FindAllCategoryLinkParams {
12
-    skip?: number;
13
-    take?: number;
14
-    where?: Prisma.CategoryLinkWhereInput;
15
-    orderBy?: Prisma.CategoryLinkOrderByWithRelationInput;
16
-}
11
+// interface FindAllCategoryLinkParams {
12
+//     skip?: number;
13
+//     take?: number;
14
+//     where?: Prisma.CategoryLinkWhereInput;
15
+//     orderBy?: Prisma.CategoryLinkOrderByWithRelationInput;
16
+// }
17
 
17
 
18
 const CategoryRepository = {
18
 const CategoryRepository = {
19
     findAll: async ({ skip, take, where, orderBy }: FindAllParams) => {
19
     findAll: async ({ skip, take, where, orderBy }: FindAllParams) => {
@@ -24,13 +24,13 @@ const CategoryRepository = {
24
             orderBy,
24
             orderBy,
25
             select: {
25
             select: {
26
                 id: true,
26
                 id: true,
27
-                tag: true,
27
+                name: true,
28
                 description: true,
28
                 description: true,
29
                 createdAt: true,
29
                 createdAt: true,
30
                 updatedAt: true,
30
                 updatedAt: true,
31
                 _count: {
31
                 _count: {
32
                     select: {
32
                     select: {
33
-                        CategoryLink: {
33
+                        VendorExperience: {
34
                             where: {
34
                             where: {
35
                                 deletedAt: null,
35
                                 deletedAt: null,
36
                             },
36
                             },
@@ -44,7 +44,7 @@ const CategoryRepository = {
44
             const { _count, ...rest } = v;
44
             const { _count, ...rest } = v;
45
             return {
45
             return {
46
                 ...rest,
46
                 ...rest,
47
-                count_use_tags: _count.CategoryLink || 0,
47
+                count_use_category: _count.VendorExperience || 0,
48
             };
48
             };
49
         });
49
         });
50
 
50
 
@@ -56,43 +56,44 @@ const CategoryRepository = {
56
     },
56
     },
57
 
57
 
58
     findById: async (id: string) => {
58
     findById: async (id: string) => {
59
-        const category = await prisma.category.findFirst({
59
+        return await prisma.category.findFirst({
60
             where: {
60
             where: {
61
                 id,
61
                 id,
62
                 deletedAt: null,
62
                 deletedAt: null,
63
             },
63
             },
64
             select: {
64
             select: {
65
                 id: true,
65
                 id: true,
66
-                tag: true,
66
+                name: true,
67
                 description: true,
67
                 description: true,
68
+                status_archive: true,
68
                 createdAt: true,
69
                 createdAt: true,
69
                 updatedAt: true,
70
                 updatedAt: true,
70
-                _count: {
71
-                    select: {
72
-                        CategoryLink: {
73
-                            where: {
74
-                                deletedAt: null,
75
-                            },
76
-                        },
77
-                    },
78
-                },
71
+                // _count: {
72
+                //     select: {
73
+                //         CategoryLink: {
74
+                //             where: {
75
+                //                 deletedAt: null,
76
+                //             },
77
+                //         },
78
+                //     },
79
+                // },
79
             },
80
             },
80
         });
81
         });
81
 
82
 
82
-        if (!category) return null;
83
+        // if (!category) return null;
83
 
84
 
84
-        const { _count, ...rest } = category;
85
-        return {
86
-            ...rest,
87
-            count_use: _count.CategoryLink || 0,
88
-        };
85
+        // const { _count, ...rest } = category;
86
+        // return {
87
+        //     ...rest,
88
+        //     count_use: _count.CategoryLink || 0,
89
+        // };
89
     },
90
     },
90
 
91
 
91
-    findByTag: async (tag: string) => {
92
+    findByName: async (name: string) => {
92
         return prisma.category.findFirst({
93
         return prisma.category.findFirst({
93
             where: {
94
             where: {
94
-                tag: {
95
-                    equals: tag,
95
+                name: {
96
+                    equals: name,
96
                     mode: "insensitive",
97
                     mode: "insensitive",
97
                 },
98
                 },
98
                 deletedAt: null,
99
                 deletedAt: null,
@@ -111,41 +112,41 @@ const CategoryRepository = {
111
         });
112
         });
112
     },
113
     },
113
 
114
 
114
-    findByCategoryId: async (categoryId: string) => {
115
-        return prisma.categoryLink.findMany({
116
-            where: {
117
-                category_id: categoryId,
118
-                deletedAt: null
119
-            },
120
-            select: {
121
-                id: true,
122
-                source_id: true,
123
-                source_type: true,
124
-                // category_id: true,
125
-                createdAt: true,
126
-                updatedAt: true,
127
-            }
128
-        });
129
-    },
130
-
131
-    findAllCategoryLink: async ({ skip, take, where, }: FindAllCategoryLinkParams) => {
132
-        return prisma.categoryLink.findMany({
133
-            where,
134
-            skip,
135
-            take,
136
-            select: {
137
-                id: true,
138
-                source_id: true,
139
-                source_type: true,
140
-                createdAt: true,
141
-                updatedAt: true,
142
-            },
143
-        });
144
-    },
145
-
146
-    countAllCategoryLink: async (where: Prisma.CategoryLinkWhereInput) => {
147
-        return prisma.categoryLink.count({ where });
148
-    },
115
+    // findByCategoryId: async (categoryId: string) => {
116
+    //     return prisma.categoryLink.findMany({
117
+    //         where: {
118
+    //             category_id: categoryId,
119
+    //             deletedAt: null
120
+    //         },
121
+    //         select: {
122
+    //             id: true,
123
+    //             source_id: true,
124
+    //             source_type: true,
125
+    //             // category_id: true,
126
+    //             createdAt: true,
127
+    //             updatedAt: true,
128
+    //         }
129
+    //     });
130
+    // },
131
+
132
+    // findAllCategoryLink: async ({ skip, take, where, }: FindAllCategoryLinkParams) => {
133
+    //     return prisma.categoryLink.findMany({
134
+    //         where,
135
+    //         skip,
136
+    //         take,
137
+    //         select: {
138
+    //             id: true,
139
+    //             source_id: true,
140
+    //             source_type: true,
141
+    //             createdAt: true,
142
+    //             updatedAt: true,
143
+    //         },
144
+    //     });
145
+    // },
146
+
147
+    // countAllCategoryLink: async (where: Prisma.CategoryLinkWhereInput) => {
148
+    //     return prisma.categoryLink.count({ where });
149
+    // },
149
 };
150
 };
150
 
151
 
151
 export default CategoryRepository;
152
 export default CategoryRepository;

+ 2 - 2
src/repository/admin/HospitalRepository.ts

@@ -39,7 +39,7 @@ const HospitalRepository = {
39
                 user: { select: { id: true, fullname: true } },
39
                 user: { select: { id: true, fullname: true } },
40
                 vendor_experiences: {
40
                 vendor_experiences: {
41
                     where: {
41
                     where: {
42
-                        status: 'active',
42
+                        // status: 'active',
43
                         deletedAt: null,
43
                         deletedAt: null,
44
                     },
44
                     },
45
                     select: {
45
                     select: {
@@ -101,7 +101,7 @@ const HospitalRepository = {
101
                 user: { select: { id: true, fullname: true } },
101
                 user: { select: { id: true, fullname: true } },
102
                 vendor_experiences: {
102
                 vendor_experiences: {
103
                     where: {
103
                     where: {
104
-                        status: 'active',
104
+                        // status: 'active',
105
                         deletedAt: null,
105
                         deletedAt: null,
106
                     },
106
                     },
107
                     take: 1,
107
                     take: 1,

+ 24 - 5
src/repository/admin/ScheduleVisitationRepository.ts

@@ -92,15 +92,34 @@ const ScheduleVisitationRepository = {
92
                             },
92
                             },
93
                         },
93
                         },
94
                         vendor_experiences: {
94
                         vendor_experiences: {
95
-                            where: { status: "active", deletedAt: null },
95
+                            where: {
96
+                                // status: "active",
97
+                                deletedAt: null
98
+                            },
96
                             select: {
99
                             select: {
97
                                 id: true,
100
                                 id: true,
98
                                 vendor: {
101
                                 vendor: {
99
-                                    select: { id: true, name: true }
102
+                                    select: {
103
+                                        id: true,
104
+                                        name: true
105
+                                    }
106
+                                },
107
+                                user: {
108
+                                    select: {
109
+                                        id: true,
110
+                                        fullname: true
111
+                                    }
112
+                                },
113
+                                category: {
114
+                                    select: {
115
+                                        id: true,
116
+                                        name: true,
117
+                                    }
100
                                 },
118
                                 },
101
-                                contract_start_date: true,
102
-                                contract_expired_date: true,
103
-                                simrs_type: true,
119
+                                content: true
120
+                                // contract_start_date: true,
121
+                                // contract_expired_date: true,
122
+                                // simrs_type: true,
104
                             }
123
                             }
105
                         },
124
                         },
106
                         executives_histories: {
125
                         executives_histories: {

+ 51 - 161
src/repository/admin/VendorExperienceRepository.ts

@@ -1,4 +1,5 @@
1
 import { PrismaClient, Prisma } from '@prisma/client';
1
 import { PrismaClient, Prisma } from '@prisma/client';
2
+import tr from 'zod/v4/locales/tr.cjs';
2
 const prisma = new PrismaClient();
3
 const prisma = new PrismaClient();
3
 
4
 
4
 interface FindAllParams {
5
 interface FindAllParams {
@@ -17,6 +18,7 @@ const VendorExperienceRepository = {
17
             orderBy,
18
             orderBy,
18
             select: {
19
             select: {
19
                 id: true,
20
                 id: true,
21
+                content: true,
20
                 vendor: {
22
                 vendor: {
21
                     select: {
23
                     select: {
22
                         id: true,
24
                         id: true,
@@ -28,14 +30,29 @@ const VendorExperienceRepository = {
28
                         created_by: true,
30
                         created_by: true,
29
                     },
31
                     },
30
                 },
32
                 },
31
-                status: true,
32
-                simrs_type: true,
33
-                contract_value_min: true,
34
-                contract_value_max: true,
35
-                contract_start_date: true,
36
-                contract_expired_date: true,
37
-                positive_notes: true,
38
-                negative_notes: true,
33
+                // category_id: true,
34
+                category: {
35
+                    select: {
36
+                        id: true,
37
+                        name: true,
38
+                        description: true,
39
+                    },
40
+                },
41
+                // user_id: true,
42
+                user: {
43
+                    select: {
44
+                        id: true,
45
+                        fullname: true,
46
+                    },
47
+                },
48
+                // status: true,
49
+                // simrs_type: true,
50
+                // contract_value_min: true,
51
+                // contract_value_max: true,
52
+                // contract_start_date: true,
53
+                // contract_expired_date: true,
54
+                // positive_notes: true,
55
+                // negative_notes: true,
39
                 createdAt: true,
56
                 createdAt: true,
40
                 updatedAt: true,
57
                 updatedAt: true,
41
             },
58
             },
@@ -54,7 +71,8 @@ const VendorExperienceRepository = {
54
             },
71
             },
55
             select: {
72
             select: {
56
                 id: true,
73
                 id: true,
57
-                vendor_id: true,
74
+                content: true,
75
+                // vendor_id: true,
58
                 vendor: {
76
                 vendor: {
59
                     select: {
77
                     select: {
60
                         id: true,
78
                         id: true,
@@ -66,14 +84,29 @@ const VendorExperienceRepository = {
66
                         created_by: true,
84
                         created_by: true,
67
                     },
85
                     },
68
                 },
86
                 },
69
-                status: true,
70
-                simrs_type: true,
71
-                contract_value_min: true,
72
-                contract_value_max: true,
73
-                contract_start_date: true,
74
-                contract_expired_date: true,
75
-                positive_notes: true,
76
-                negative_notes: true,
87
+                // category_id: true,
88
+                category: {
89
+                    select: {
90
+                        id: true,
91
+                        name: true,
92
+                        description: true,
93
+                    },
94
+                },
95
+                // user_id: true,
96
+                user: {
97
+                    select: {
98
+                        id: true,
99
+                        fullname: true,
100
+                    },
101
+                },
102
+                // status: true,
103
+                // simrs_type: true,
104
+                // contract_value_min: true,
105
+                // contract_value_max: true,
106
+                // contract_start_date: true,
107
+                // contract_expired_date: true,
108
+                // positive_notes: true,
109
+                // negative_notes: true,
77
                 createdAt: true,
110
                 createdAt: true,
78
                 updatedAt: true,
111
                 updatedAt: true,
79
             },
112
             },
@@ -92,147 +125,4 @@ const VendorExperienceRepository = {
92
     },
125
     },
93
 };
126
 };
94
 
127
 
95
-export default VendorExperienceRepository;
96
-
97
-// const prisma = require('../../prisma/PrismaClient.js');
98
-
99
-// const VendorExperienceRepository = {
100
-//     findAll: async ({ skip, take, where, orderBy }) => {
101
-//         return prisma.vendorExperience.findMany({
102
-//             where,
103
-//             skip,
104
-//             take,
105
-//             orderBy,
106
-//             select: {
107
-//                 id: true,
108
-//                 // hospital: {
109
-//                 //     select: {
110
-//                 //         id: true,
111
-//                 //         name: true,
112
-//                 //         hospital_code: true,
113
-//                 //         type: true,
114
-//                 //         ownership: true,
115
-//                 //         province: {
116
-//                 //             select: {
117
-//                 //                 id: true,
118
-//                 //                 name: true
119
-//                 //             }
120
-//                 //         },
121
-//                 //         city: {
122
-//                 //             select: {
123
-//                 //                 id: true,
124
-//                 //                 name: true
125
-//                 //             }
126
-//                 //         },
127
-//                 //         address: true,
128
-//                 //         simrs_type: true,
129
-//                 //         contact: true,
130
-//                 //         image: true,
131
-//                 //         progress_status: true,
132
-//                 //         note: true,
133
-//                 //         created_by: true
134
-//                 //     }
135
-//                 // },
136
-//                 vendor: {
137
-//                     select: {
138
-//                         id: true,
139
-//                         name: true,
140
-//                         name_pt: true,
141
-//                         strengths: true,
142
-//                         weaknesses: true,
143
-//                         website: true,
144
-//                         created_by: true,
145
-//                     }
146
-//                 },
147
-//                 status: true,
148
-//                 simrs_type: true,
149
-//                 contract_value_min: true,
150
-//                 contract_value_max: true,
151
-//                 contract_start_date: true,
152
-//                 contract_expired_date: true,
153
-//                 positive_notes: true,
154
-//                 negative_notes: true,
155
-//                 createdAt: true,
156
-//                 updatedAt: true,
157
-//             },
158
-//         });
159
-//     },
160
-
161
-//     countAll: async (where) => {
162
-//         return prisma.vendorExperience.count({ where });
163
-//     },
164
-
165
-//     findById: async (id) => {
166
-//         return prisma.vendorExperience.findFirst({
167
-//             where: {
168
-//                 id,
169
-//                 deletedAt: null
170
-//             },
171
-//             select: {
172
-//                 id: true,
173
-//                 // hospital: {
174
-//                 //     select: {
175
-//                 //         id: true,
176
-//                 //         name: true,
177
-//                 //         hospital_code: true,
178
-//                 //         type: true,
179
-//                 //         ownership: true,
180
-//                 //         province: {
181
-//                 //             select: {
182
-//                 //                 id: true,
183
-//                 //                 name: true
184
-//                 //             }
185
-//                 //         },
186
-//                 //         city: {
187
-//                 //             select: {
188
-//                 //                 id: true,
189
-//                 //                 name: true
190
-//                 //             }
191
-//                 //         },
192
-//                 //         address: true,
193
-//                 //         simrs_type: true,
194
-//                 //         contact: true,
195
-//                 //         image: true,
196
-//                 //         progress_status: true,
197
-//                 //         note: true,
198
-//                 //         created_by: true
199
-//                 //     }
200
-//                 // },
201
-//                 vendor: {
202
-//                     select: {
203
-//                         id: true,
204
-//                         name: true,
205
-//                         name_pt: true,
206
-//                         strengths: true,
207
-//                         weaknesses: true,
208
-//                         website: true,
209
-//                         created_by: true,
210
-//                     }
211
-//                 },
212
-//                 status: true,
213
-//                 simrs_type: true,
214
-//                 contract_value_min: true,
215
-//                 contract_value_max: true,
216
-//                 contract_start_date: true,
217
-//                 contract_expired_date: true,
218
-//                 positive_notes: true,
219
-//                 negative_notes: true,
220
-//                 createdAt: true,
221
-//                 updatedAt: true,
222
-//             },
223
-//         });
224
-//     },
225
-
226
-//     create: async (data) => {
227
-//         return prisma.vendorExperience.create({ data });
228
-//     },
229
-
230
-//     update: async (id, data) => {
231
-//         return prisma.vendorExperience.update({
232
-//             where: { id },
233
-//             data
234
-//         });
235
-//     },
236
-// };
237
-
238
-// module.exports = VendorExperienceRepository;
128
+export default VendorExperienceRepository;

+ 2 - 1
src/repository/admin/VendorRepository.ts

@@ -29,7 +29,7 @@ const VendorRepository = {
29
                         vendor_experiences: {
29
                         vendor_experiences: {
30
                             where: {
30
                             where: {
31
                                 deletedAt: null,
31
                                 deletedAt: null,
32
-                                status: "active"
32
+                                // status: "active"
33
                             },
33
                             },
34
                         },
34
                         },
35
                     },
35
                     },
@@ -73,6 +73,7 @@ const VendorRepository = {
73
                         vendor_experiences: {
73
                         vendor_experiences: {
74
                             where: {
74
                             where: {
75
                                 deletedAt: null,
75
                                 deletedAt: null,
76
+                                // status: "active"
76
                             },
77
                             },
77
                         },
78
                         },
78
                     },
79
                     },

+ 3 - 138
src/repository/sales/HospitalRepository.ts

@@ -37,7 +37,7 @@ const HospitalRepository = {
37
                 user: { select: { id: true, fullname: true } },
37
                 user: { select: { id: true, fullname: true } },
38
                 vendor_experiences: {
38
                 vendor_experiences: {
39
                     where: {
39
                     where: {
40
-                        status: 'active',
40
+                        // status: 'active',
41
                         deletedAt: null,
41
                         deletedAt: null,
42
                     },
42
                     },
43
                     select: {
43
                     select: {
@@ -101,7 +101,7 @@ const HospitalRepository = {
101
                 user: { select: { id: true, fullname: true } },
101
                 user: { select: { id: true, fullname: true } },
102
                 vendor_experiences: {
102
                 vendor_experiences: {
103
                     where: {
103
                     where: {
104
-                        status: 'active',
104
+                        // status: 'active',
105
                         deletedAt: null,
105
                         deletedAt: null,
106
                     },
106
                     },
107
                     take: 1,
107
                     take: 1,
@@ -138,139 +138,4 @@ const HospitalRepository = {
138
     },
138
     },
139
 };
139
 };
140
 
140
 
141
-export default HospitalRepository;
142
-
143
-
144
-// const prisma = require('../../prisma/PrismaClient.js');
145
-
146
-// const HospitalRepository = {
147
-//     findAll: async ({ skip, take, where, orderBy }) => {
148
-//         const hospitalsRaw = await prisma.hospital.findMany({
149
-//             where,
150
-//             skip,
151
-//             take,
152
-//             orderBy,
153
-//             select: {
154
-//                 id: true,
155
-//                 name: true,
156
-//                 hospital_code: true,
157
-//                 type: true,
158
-//                 ownership: true,
159
-//                 province: { select: { id: true, name: true } },
160
-//                 city: { select: { id: true, name: true } },
161
-//                 address: true,
162
-//                 contact: true,
163
-//                 image: true,
164
-//                 progress_status: true,
165
-//                 note: true,
166
-//                 latitude: true,
167
-//                 longitude: true,
168
-//                 gmaps_url: true,
169
-//                 created_by: true,
170
-//                 createdAt: true,
171
-//                 updatedAt: true,
172
-//                 user: { select: { id: true, fullname: true } },
173
-//                 vendor_experiences: {
174
-//                     where: {
175
-//                         status: "active",
176
-//                         deletedAt: null
177
-//                     },
178
-//                     select: {
179
-//                         vendor: {
180
-//                             select: {
181
-//                                 id: true,
182
-//                                 name: true,
183
-//                                 name_pt: true,
184
-//                                 strengths: true,
185
-//                                 weaknesses: true,
186
-//                                 website: true,
187
-//                             }
188
-//                         }
189
-//                     }
190
-//                 }
191
-//             }
192
-//         });
193
-
194
-//         return hospitalsRaw.map(hospital => {
195
-//             const { vendor_experiences, ...rest } = hospital;
196
-//             return {
197
-//                 ...rest,
198
-//                 vendor: vendor_experiences?.[0]?.vendor || null
199
-//             };
200
-//         });
201
-//     },
202
-
203
-//     countAll: async (where) => {
204
-//         return prisma.hospital.count({ where });
205
-//     },
206
-
207
-//     create: async (data) => {
208
-//         return prisma.hospital.create({ data });
209
-//     },
210
-
211
-//     findById: async (id) => {
212
-//         const hospitalRaw = await prisma.hospital.findFirst({
213
-//             where: {
214
-//                 id,
215
-//                 deletedAt: null
216
-//             },
217
-//             select: {
218
-//                 id: true,
219
-//                 name: true,
220
-//                 hospital_code: true,
221
-//                 type: true,
222
-//                 ownership: true,
223
-//                 province: { select: { id: true, name: true } },
224
-//                 city: { select: { id: true, name: true } },
225
-//                 address: true,
226
-//                 contact: true,
227
-//                 image: true,
228
-//                 progress_status: true,
229
-//                 note: true,
230
-//                 latitude: true,
231
-//                 longitude: true,
232
-//                 gmaps_url: true,
233
-//                 created_by: true,
234
-//                 createdAt: true,
235
-//                 updatedAt: true,
236
-//                 user: { select: { id: true, fullname: true } },
237
-//                 vendor_experiences: {
238
-//                     where: {
239
-//                         status: "active",
240
-//                         deletedAt: null
241
-//                     },
242
-//                     take: 1,
243
-//                     select: {
244
-//                         vendor: {
245
-//                             select: {
246
-//                                 id: true,
247
-//                                 name: true,
248
-//                                 name_pt: true,
249
-//                                 strengths: true,
250
-//                                 weaknesses: true,
251
-//                                 website: true,
252
-//                             }
253
-//                         }
254
-//                     }
255
-//                 }
256
-//             }
257
-//         });
258
-
259
-//         if (!hospitalRaw) return null;
260
-
261
-//         const { vendor_experiences, ...rest } = hospitalRaw;
262
-//         return {
263
-//             ...rest,
264
-//             vendor: vendor_experiences?.[0]?.vendor || null
265
-//         };
266
-//     },
267
-
268
-//     update: async (id, data) => {
269
-//         return prisma.hospital.update({
270
-//             where: { id },
271
-//             data
272
-//         });
273
-//     },
274
-// };
275
-
276
-// module.exports = HospitalRepository;
141
+export default HospitalRepository;

+ 14 - 4
src/repository/sales/ScheduleVisitationRepository.ts

@@ -93,15 +93,25 @@ const ScheduleVisitationRepository = {
93
                             },
93
                             },
94
                         },
94
                         },
95
                         vendor_experiences: {
95
                         vendor_experiences: {
96
-                            where: { status: "active", deletedAt: null },
96
+                            where: {
97
+                                // status: "active",
98
+                                deletedAt: null
99
+                            },
97
                             select: {
100
                             select: {
98
                                 id: true,
101
                                 id: true,
99
                                 vendor: {
102
                                 vendor: {
100
                                     select: { id: true, name: true }
103
                                     select: { id: true, name: true }
101
                                 },
104
                                 },
102
-                                contract_start_date: true,
103
-                                contract_expired_date: true,
104
-                                simrs_type: true,
105
+                                category: {
106
+                                    select: { id: true, name: true }
107
+                                },
108
+                                user: {
109
+                                    select: { id: true, fullname: true }
110
+                                },
111
+                                content: true
112
+                                // contract_start_date: true,
113
+                                // contract_expired_date: true,
114
+                                // simrs_type: true,
105
                             }
115
                             }
106
                         },
116
                         },
107
                         executives_histories: {
117
                         executives_histories: {

+ 49 - 105
src/repository/sales/VendorExperienceRepository.ts

@@ -17,6 +17,7 @@ const VendorExperienceRepository = {
17
             orderBy,
17
             orderBy,
18
             select: {
18
             select: {
19
                 id: true,
19
                 id: true,
20
+                content: true,
20
                 vendor: {
21
                 vendor: {
21
                     select: {
22
                     select: {
22
                         id: true,
23
                         id: true,
@@ -28,14 +29,29 @@ const VendorExperienceRepository = {
28
                         created_by: true,
29
                         created_by: true,
29
                     },
30
                     },
30
                 },
31
                 },
31
-                status: true,
32
-                simrs_type: true,
33
-                contract_value_min: true,
34
-                contract_value_max: true,
35
-                contract_start_date: true,
36
-                contract_expired_date: true,
37
-                positive_notes: true,
38
-                negative_notes: true,
32
+                // category_id: true,
33
+                category: {
34
+                    select: {
35
+                        id: true,
36
+                        name: true,
37
+                        description: true,
38
+                    },
39
+                },
40
+                // user_id: true,
41
+                user: {
42
+                    select: {
43
+                        id: true,
44
+                        fullname: true,
45
+                    },
46
+                },
47
+                // status: true,
48
+                // simrs_type: true,
49
+                // contract_value_min: true,
50
+                // contract_value_max: true,
51
+                // contract_start_date: true,
52
+                // contract_expired_date: true,
53
+                // positive_notes: true,
54
+                // negative_notes: true,
39
                 createdAt: true,
55
                 createdAt: true,
40
                 updatedAt: true,
56
                 updatedAt: true,
41
             },
57
             },
@@ -54,7 +70,7 @@ const VendorExperienceRepository = {
54
             },
70
             },
55
             select: {
71
             select: {
56
                 id: true,
72
                 id: true,
57
-                vendor_id: true,
73
+                content: true,
58
                 vendor: {
74
                 vendor: {
59
                     select: {
75
                     select: {
60
                         id: true,
76
                         id: true,
@@ -66,14 +82,29 @@ const VendorExperienceRepository = {
66
                         created_by: true,
82
                         created_by: true,
67
                     },
83
                     },
68
                 },
84
                 },
69
-                status: true,
70
-                simrs_type: true,
71
-                contract_value_min: true,
72
-                contract_value_max: true,
73
-                contract_start_date: true,
74
-                contract_expired_date: true,
75
-                positive_notes: true,
76
-                negative_notes: true,
85
+                // category_id: true,
86
+                category: {
87
+                    select: {
88
+                        id: true,
89
+                        name: true,
90
+                        description: true,
91
+                    },
92
+                },
93
+                // user_id: true,
94
+                user: {
95
+                    select: {
96
+                        id: true,
97
+                        fullname: true,
98
+                    },
99
+                },
100
+                // status: true,
101
+                // simrs_type: true,
102
+                // contract_value_min: true,
103
+                // contract_value_max: true,
104
+                // contract_start_date: true,
105
+                // contract_expired_date: true,
106
+                // positive_notes: true,
107
+                // negative_notes: true,
77
                 createdAt: true,
108
                 createdAt: true,
78
                 updatedAt: true,
109
                 updatedAt: true,
79
             },
110
             },
@@ -92,91 +123,4 @@ const VendorExperienceRepository = {
92
     },
123
     },
93
 };
124
 };
94
 
125
 
95
-export default VendorExperienceRepository;
96
-
97
-// const prisma = require('../../prisma/PrismaClient.js');
98
-
99
-// const VendorExperienceRepository = {
100
-//     findAll: async ({ skip, take, where, orderBy }) => {
101
-//         return prisma.vendorExperience.findMany({
102
-//             where,
103
-//             skip,
104
-//             take,
105
-//             orderBy,
106
-//             select: {
107
-//                 id: true,
108
-//                 vendor: {
109
-//                     select: {
110
-//                         id: true,
111
-//                         name: true,
112
-//                         name_pt: true,
113
-//                         strengths: true,
114
-//                         weaknesses: true,
115
-//                         website: true,
116
-//                         created_by: true,
117
-//                     }
118
-//                 },
119
-//                 status: true,
120
-//                 simrs_type: true,
121
-//                 contract_value_min: true,
122
-//                 contract_value_max: true,
123
-//                 contract_start_date: true,
124
-//                 contract_expired_date: true,
125
-//                 positive_notes: true,
126
-//                 negative_notes: true,
127
-//                 createdAt: true,
128
-//                 updatedAt: true,
129
-//             },
130
-//         });
131
-//     },
132
-
133
-//     countAll: async (where) => {
134
-//         return prisma.vendorExperience.count({ where });
135
-//     },
136
-
137
-//     findById: async (id) => {
138
-//         return prisma.vendorExperience.findFirst({
139
-//             where: {
140
-//                 id,
141
-//                 deletedAt: null
142
-//             },
143
-//             select: {
144
-//                 id: true,
145
-//                 vendor: {
146
-//                     select: {
147
-//                         id: true,
148
-//                         name: true,
149
-//                         name_pt: true,
150
-//                         strengths: true,
151
-//                         weaknesses: true,
152
-//                         website: true,
153
-//                         created_by: true,
154
-//                     }
155
-//                 },
156
-//                 status: true,
157
-//                 simrs_type: true,
158
-//                 contract_value_min: true,
159
-//                 contract_value_max: true,
160
-//                 contract_start_date: true,
161
-//                 contract_expired_date: true,
162
-//                 positive_notes: true,
163
-//                 negative_notes: true,
164
-//                 createdAt: true,
165
-//                 updatedAt: true,
166
-//             },
167
-//         });
168
-//     },
169
-
170
-//     create: async (data) => {
171
-//         return prisma.vendorExperience.create({ data });
172
-//     },
173
-
174
-//     update: async (id, data) => {
175
-//         return prisma.vendorExperience.update({
176
-//             where: { id },
177
-//             data
178
-//         });
179
-//     },
180
-// };
181
-
182
-// module.exports = VendorExperienceRepository;
126
+export default VendorExperienceRepository;

+ 25 - 25
src/resources/admin/hospital/HospitalCollection.ts

@@ -14,40 +14,40 @@ export const HospitalCollection = async (req: Request, res: Response, data: Hosp
14
     const ids = data.map(item => item.id);
14
     const ids = data.map(item => item.id);
15
 
15
 
16
     // Ambil tags dari category_links yang relevan
16
     // Ambil tags dari category_links yang relevan
17
-    const allTags = await prisma.categoryLink.findMany({
18
-        where: {
19
-            source_id: { in: ids },
20
-            source_type: { in: ['hospital_notes'] },
21
-            deletedAt: null,
22
-        },
23
-        include: {
24
-            Category: true,
25
-        },
26
-    });
17
+    // const allTags = await prisma.categoryLink.findMany({
18
+    //     where: {
19
+    //         source_id: { in: ids },
20
+    //         source_type: { in: ['hospital_notes'] },
21
+    //         deletedAt: null,
22
+    //     },
23
+    //     include: {
24
+    //         Category: true,
25
+    //     },
26
+    // });
27
 
27
 
28
     // Kelompokkan tags berdasarkan source_type dan source_id
28
     // Kelompokkan tags berdasarkan source_type dan source_id
29
-    const tagMap = new Map<string, { note: string[] }>();
30
-    for (const id of ids) {
31
-        tagMap.set(id, { note: [] });
32
-    }
29
+    // const tagMap = new Map<string, { note: string[] }>();
30
+    // for (const id of ids) {
31
+    //     tagMap.set(id, { note: [] });
32
+    // }
33
 
33
 
34
-    for (const tag of allTags) {
35
-        const id = tag.source_id!;
36
-        const categoryTag = tag.Category?.tag ?? '';
37
-        const current = tagMap.get(id);
38
-        if (!current) continue;
34
+    // for (const tag of allTags) {
35
+    //     const id = tag.source_id!;
36
+    //     const categoryTag = tag.Category?.tag ?? '';
37
+    //     const current = tagMap.get(id);
38
+    //     if (!current) continue;
39
 
39
 
40
-        if (tag.source_type === 'hospital_notes') {
41
-            current.note.push(categoryTag);
42
-        }
43
-    }
40
+    //     if (tag.source_type === 'hospital_notes') {
41
+    //         current.note.push(categoryTag);
42
+    //     }
43
+    // }
44
 
44
 
45
     const formattedData = data.map(item => {
45
     const formattedData = data.map(item => {
46
         const { created_by, ...rest } = item;
46
         const { created_by, ...rest } = item;
47
-        const tags = tagMap.get(item.id);
47
+        // const tags = tagMap.get(item.id);
48
         return formatItem({
48
         return formatItem({
49
             ...rest,
49
             ...rest,
50
-            note_tags: tags?.note ?? [],
50
+            // note_tags: tags?.note ?? [],
51
         });
51
         });
52
     });
52
     });
53
 
53
 

+ 14 - 14
src/resources/admin/hospital/HospitalResource.ts

@@ -10,26 +10,26 @@ const formatItem = (item: HospitalDTO) => ({
10
 });
10
 });
11
 
11
 
12
 export const HospitalResource = async (res: Response, data: HospitalDTO, message: string = 'Success'): Promise<Response> => {
12
 export const HospitalResource = async (res: Response, data: HospitalDTO, message: string = 'Success'): Promise<Response> => {
13
-    const tags = await prisma.categoryLink.findMany({
14
-        where: {
15
-            source_id: data.id,
16
-            source_type: { in: ['hospital_notes'] },
17
-            deletedAt: null,
18
-        },
19
-        include: {
20
-            Category: true,
21
-        },
22
-    });
13
+    // const tags = await prisma.categoryLink.findMany({
14
+    //     where: {
15
+    //         source_id: data.id,
16
+    //         source_type: { in: ['hospital_notes'] },
17
+    //         deletedAt: null,
18
+    //     },
19
+    //     include: {
20
+    //         Category: true,
21
+    //     },
22
+    // });
23
 
23
 
24
-    const note_tags = tags
25
-        .filter(t => t.source_type === 'hospital_notes')
26
-        .map(t => t.Category?.tag ?? '');
24
+    // const note_tags = tags
25
+    //     .filter(t => t.source_type === 'hospital_notes')
26
+    //     .map(t => t.Category?.tag ?? '');
27
 
27
 
28
     const { created_by, ...cleanedData } = data;
28
     const { created_by, ...cleanedData } = data;
29
 
29
 
30
     const formatted = {
30
     const formatted = {
31
         ...formatItem(cleanedData),
31
         ...formatItem(cleanedData),
32
-        note_tags,
32
+        // note_tags,
33
     };
33
     };
34
 
34
 
35
     return res.status(200).json({
35
     return res.status(200).json({

+ 2 - 2
src/resources/admin/schedule_visitation/ScheduleVisitationResource.ts

@@ -10,8 +10,8 @@ const formatItem = (item: ShowScheduleVisitationDTO) => ({
10
         ...item.hospital,
10
         ...item.hospital,
11
         vendor_experiences: item.hospital.vendor_experiences.map((vendor) => ({
11
         vendor_experiences: item.hospital.vendor_experiences.map((vendor) => ({
12
             ...vendor,
12
             ...vendor,
13
-            contract_start_date: formatDateOnly(vendor.contract_start_date),
14
-            contract_expired_date: formatDateOnly(vendor.contract_expired_date),
13
+            // contract_start_date: formatDateOnly(vendor.contract_start_date),
14
+            // contract_expired_date: formatDateOnly(vendor.contract_expired_date),
15
         })),
15
         })),
16
         executives_histories: item.hospital.executives_histories.map((exec) => ({
16
         executives_histories: item.hospital.executives_histories.map((exec) => ({
17
             ...exec,
17
             ...exec,

+ 26 - 26
src/resources/admin/status_history/StatusHistoryCollection.ts

@@ -14,40 +14,40 @@ export const StatusHistoryCollection = async (req: Request, res: Response, data:
14
     const ids = data.map(item => item.id);
14
     const ids = data.map(item => item.id);
15
 
15
 
16
     // Ambil tags dari category_links yang relevan
16
     // Ambil tags dari category_links yang relevan
17
-    const allTags = await prisma.categoryLink.findMany({
18
-        where: {
19
-            source_id: { in: ids },
20
-            source_type: { in: ['status_history_notes'] },
21
-            deletedAt: null,
22
-        },
23
-        include: {
24
-            Category: true,
25
-        },
26
-    });
17
+    // const allTags = await prisma.categoryLink.findMany({
18
+    //     where: {
19
+    //         source_id: { in: ids },
20
+    //         source_type: { in: ['status_history_notes'] },
21
+    //         deletedAt: null,
22
+    //     },
23
+    //     include: {
24
+    //         Category: true,
25
+    //     },
26
+    // });
27
 
27
 
28
-    // Kelompokkan tags berdasarkan source_type dan source_id
29
-    const tagMap = new Map<string, { note: string[]; }>();
30
-    for (const id of ids) {
31
-        tagMap.set(id, { note: [] });
32
-    }
28
+    // // Kelompokkan tags berdasarkan source_type dan source_id
29
+    // const tagMap = new Map<string, { note: string[]; }>();
30
+    // for (const id of ids) {
31
+    //     tagMap.set(id, { note: [] });
32
+    // }
33
 
33
 
34
-    for (const tag of allTags) {
35
-        const id = tag.source_id!;
36
-        const categoryTag = tag.Category?.tag ?? '';
37
-        const current = tagMap.get(id);
38
-        if (!current) continue;
34
+    // for (const tag of allTags) {
35
+    //     const id = tag.source_id!;
36
+    //     const categoryTag = tag.Category?.tag ?? '';
37
+    //     const current = tagMap.get(id);
38
+    //     if (!current) continue;
39
 
39
 
40
-        if (tag.source_type === 'status_history_notes') {
41
-            current.note.push(categoryTag);
42
-        }
43
-    }
40
+    //     if (tag.source_type === 'status_history_notes') {
41
+    //         current.note.push(categoryTag);
42
+    //     }
43
+    // }
44
 
44
 
45
     // Gabungkan dan format
45
     // Gabungkan dan format
46
     const formattedData = data.map(item => {
46
     const formattedData = data.map(item => {
47
-        const tags = tagMap.get(item.id);
47
+        // const tags = tagMap.get(item.id);
48
         return formatItem({
48
         return formatItem({
49
             ...item,
49
             ...item,
50
-            note_tags: tags?.note ?? [],
50
+            // note_tags: tags?.note ?? [],
51
         });
51
         });
52
     });
52
     });
53
 
53
 

+ 21 - 21
src/resources/admin/vendor/VendorCollection.ts

@@ -14,16 +14,16 @@ export const VendorCollection = async (req: Request, res: Response, data: Vendor
14
     const ids = data.map(item => item.id);
14
     const ids = data.map(item => item.id);
15
 
15
 
16
     // Ambil tags dari category_links yang relevan
16
     // Ambil tags dari category_links yang relevan
17
-    const allTags = await prisma.categoryLink.findMany({
18
-        where: {
19
-            source_id: { in: ids },
20
-            source_type: { in: ['vendor_strength_notes', 'vendor_weaknesses_notes'] },
21
-            deletedAt: null,
22
-        },
23
-        include: {
24
-            Category: true,
25
-        },
26
-    });
17
+    // const allTags = await prisma.categoryLink.findMany({
18
+    //     where: {
19
+    //         source_id: { in: ids },
20
+    //         source_type: { in: ['vendor_strength_notes', 'vendor_weaknesses_notes'] },
21
+    //         deletedAt: null,
22
+    //     },
23
+    //     include: {
24
+    //         Category: true,
25
+    //     },
26
+    // });
27
 
27
 
28
     // Kelompokkan tags berdasarkan source_type dan source_id
28
     // Kelompokkan tags berdasarkan source_type dan source_id
29
     const tagMap = new Map<string, { strength: string[]; weaknesses: string[] }>();
29
     const tagMap = new Map<string, { strength: string[]; weaknesses: string[] }>();
@@ -31,18 +31,18 @@ export const VendorCollection = async (req: Request, res: Response, data: Vendor
31
         tagMap.set(id, { strength: [], weaknesses: [] });
31
         tagMap.set(id, { strength: [], weaknesses: [] });
32
     }
32
     }
33
 
33
 
34
-    for (const tag of allTags) {
35
-        const id = tag.source_id!;
36
-        const categoryTag = tag.Category?.tag ?? '';
37
-        const current = tagMap.get(id);
38
-        if (!current) continue;
34
+    // for (const tag of allTags) {
35
+    //     const id = tag.source_id!;
36
+    //     const categoryTag = tag.Category?.tag ?? '';
37
+    //     const current = tagMap.get(id);
38
+    //     if (!current) continue;
39
 
39
 
40
-        if (tag.source_type === 'vendor_strength_notes') {
41
-            current.strength.push(categoryTag);
42
-        } else if (tag.source_type === 'vendor_weaknesses_notes') {
43
-            current.weaknesses.push(categoryTag);
44
-        }
45
-    }
40
+    //     if (tag.source_type === 'vendor_strength_notes') {
41
+    //         current.strength.push(categoryTag);
42
+    //     } else if (tag.source_type === 'vendor_weaknesses_notes') {
43
+    //         current.weaknesses.push(categoryTag);
44
+    //     }
45
+    // }
46
 
46
 
47
     // Gabungkan dan format
47
     // Gabungkan dan format
48
     const formattedData = data.map(item => {
48
     const formattedData = data.map(item => {

+ 18 - 18
src/resources/admin/vendor/VendorResource.ts

@@ -4,24 +4,24 @@ import { VendorDTO } from '../../../types/admin/vendor/VendorDTO';
4
 import prisma from '../../../prisma/PrismaClient';
4
 import prisma from '../../../prisma/PrismaClient';
5
 
5
 
6
 export const VendorResource = async (res: Response, data: VendorDTO, message: string = 'Success'): Promise<Response> => {
6
 export const VendorResource = async (res: Response, data: VendorDTO, message: string = 'Success'): Promise<Response> => {
7
-    const tags = await prisma.categoryLink.findMany({
8
-        where: {
9
-            source_id: data.id,
10
-            source_type: { in: ['vendor_strength_notes', 'vendor_weaknesses_notes'] },
11
-            deletedAt: null,
12
-        },
13
-        include: {
14
-            Category: true,
15
-        },
16
-    });
7
+    // const tags = await prisma.categoryLink.findMany({
8
+    //     where: {
9
+    //         source_id: data.id,
10
+    //         source_type: { in: ['vendor_strength_notes', 'vendor_weaknesses_notes'] },
11
+    //         deletedAt: null,
12
+    //     },
13
+    //     include: {
14
+    //         Category: true,
15
+    //     },
16
+    // });
17
 
17
 
18
-    const strengths_tags = tags
19
-        .filter(t => t.source_type === 'vendor_strength_notes')
20
-        .map(t => t.Category?.tag ?? '');
18
+    // const strengths_tags = tags
19
+    //     .filter(t => t.source_type === 'vendor_strength_notes')
20
+    //     .map(t => t.Category?.tag ?? '');
21
 
21
 
22
-    const weaknesses_tags = tags
23
-        .filter(t => t.source_type === 'vendor_weaknesses_notes')
24
-        .map(t => t.Category?.tag ?? '');
22
+    // const weaknesses_tags = tags
23
+    //     .filter(t => t.source_type === 'vendor_weaknesses_notes')
24
+    //     .map(t => t.Category?.tag ?? '');
25
 
25
 
26
     const formatted = {
26
     const formatted = {
27
         ...data,
27
         ...data,
@@ -29,8 +29,8 @@ export const VendorResource = async (res: Response, data: VendorDTO, message: st
29
         updatedAt: formatISOWithoutTimezone(data.updatedAt),
29
         updatedAt: formatISOWithoutTimezone(data.updatedAt),
30
         strengths: data.strengths,
30
         strengths: data.strengths,
31
         weaknesses: data.weaknesses,
31
         weaknesses: data.weaknesses,
32
-        strengths_tags,
33
-        weaknesses_tags,
32
+        // strengths_tags,
33
+        // weaknesses_tags,
34
     };
34
     };
35
 
35
 
36
     return res.status(200).json({
36
     return res.status(200).json({

+ 32 - 32
src/resources/admin/vendor_experience/VendorExperienceCollection.ts

@@ -6,10 +6,10 @@ import prisma from '../../../prisma/PrismaClient';
6
 
6
 
7
 const formatItem = (item: VendorExperienceDTO) => ({
7
 const formatItem = (item: VendorExperienceDTO) => ({
8
     ...item,
8
     ...item,
9
-    contract_value_min: item.contract_value_min !== null ? Number(item.contract_value_min) : null,
10
-    contract_value_max: item.contract_value_max !== null ? Number(item.contract_value_max) : null,
11
-    contract_start_date: formatDateOnly(item.contract_start_date),
12
-    contract_expired_date: formatDateOnly(item.contract_expired_date),
9
+    // contract_value_min: item.contract_value_min !== null ? Number(item.contract_value_min) : null,
10
+    // contract_value_max: item.contract_value_max !== null ? Number(item.contract_value_max) : null,
11
+    // contract_start_date: formatDateOnly(item.contract_start_date),
12
+    // contract_expired_date: formatDateOnly(item.contract_expired_date),
13
     createdAt: formatISOWithoutTimezone(item.createdAt),
13
     createdAt: formatISOWithoutTimezone(item.createdAt),
14
     updatedAt: formatISOWithoutTimezone(item.updatedAt),
14
     updatedAt: formatISOWithoutTimezone(item.updatedAt),
15
 });
15
 });
@@ -26,43 +26,43 @@ export const VendorExperienceCollection = async (
26
     const ids = data.map(item => item.id);
26
     const ids = data.map(item => item.id);
27
 
27
 
28
     // Ambil tags dari category_links yang relevan
28
     // Ambil tags dari category_links yang relevan
29
-    const allTags = await prisma.categoryLink.findMany({
30
-        where: {
31
-            source_id: { in: ids },
32
-            source_type: { in: ['vendor_experience_positive_notes', 'vendor_experience_negative_notes'] },
33
-            deletedAt: null,
34
-        },
35
-        include: {
36
-            Category: true,
37
-        },
38
-    });
29
+    // const allTags = await prisma.categoryLink.findMany({
30
+    //     where: {
31
+    //         source_id: { in: ids },
32
+    //         source_type: { in: ['vendor_experience_positive_notes', 'vendor_experience_negative_notes'] },
33
+    //         deletedAt: null,
34
+    //     },
35
+    //     include: {
36
+    //         Category: true,
37
+    //     },
38
+    // });
39
 
39
 
40
     // Kelompokkan tags berdasarkan source_type dan source_id
40
     // Kelompokkan tags berdasarkan source_type dan source_id
41
-    const tagMap = new Map<string, { positive: string[]; negative: string[] }>();
42
-    for (const id of ids) {
43
-        tagMap.set(id, { positive: [], negative: [] });
44
-    }
41
+    // const tagMap = new Map<string, { positive: string[]; negative: string[] }>();
42
+    // for (const id of ids) {
43
+    //     tagMap.set(id, { positive: [], negative: [] });
44
+    // }
45
 
45
 
46
-    for (const tag of allTags) {
47
-        const id = tag.source_id!;
48
-        const categoryTag = tag.Category?.tag ?? '';
49
-        const current = tagMap.get(id);
50
-        if (!current) continue;
46
+    // for (const tag of allTags) {
47
+    //     const id = tag.source_id!;
48
+    //     const categoryTag = tag.Category?.tag ?? '';
49
+    //     const current = tagMap.get(id);
50
+    //     if (!current) continue;
51
 
51
 
52
-        if (tag.source_type === 'vendor_experience_positive_notes') {
53
-            current.positive.push(categoryTag);
54
-        } else if (tag.source_type === 'vendor_experience_negative_notes') {
55
-            current.negative.push(categoryTag);
56
-        }
57
-    }
52
+    //     if (tag.source_type === 'vendor_experience_positive_notes') {
53
+    //         current.positive.push(categoryTag);
54
+    //     } else if (tag.source_type === 'vendor_experience_negative_notes') {
55
+    //         current.negative.push(categoryTag);
56
+    //     }
57
+    // }
58
 
58
 
59
     // Gabungkan dan format
59
     // Gabungkan dan format
60
     const formattedData = data.map(item => {
60
     const formattedData = data.map(item => {
61
-        const tags = tagMap.get(item.id);
61
+        // const tags = tagMap.get(item.id);
62
         return formatItem({
62
         return formatItem({
63
             ...item,
63
             ...item,
64
-            positive_notes_tags: tags?.positive ?? [],
65
-            negative_notes_tags: tags?.negative ?? [],
64
+            // positive_notes_tags: tags?.positive ?? [],
65
+            // negative_notes_tags: tags?.negative ?? [],
66
         });
66
         });
67
     });
67
     });
68
 
68
 

+ 38 - 25
src/resources/admin/vendor_experience/VendorExperienceResource.ts

@@ -1,29 +1,29 @@
1
 import { Response } from 'express';
1
 import { Response } from 'express';
2
-import { formatDateOnly, formatISOWithoutTimezone } from '../../../utils/FormatDate';
2
+import { formatISOWithoutTimezone } from '../../../utils/FormatDate';
3
 import { VendorExperienceDTO } from '../../../types/admin/vendor_experience/VendorExperienceDTO';
3
 import { VendorExperienceDTO } from '../../../types/admin/vendor_experience/VendorExperienceDTO';
4
-import prisma from '../../../prisma/PrismaClient';
5
 
4
 
6
 export const VendorExperienceResource = async (res: Response, data: VendorExperienceDTO, message: string = 'Success'): Promise<Response> => {
5
 export const VendorExperienceResource = async (res: Response, data: VendorExperienceDTO, message: string = 'Success'): Promise<Response> => {
7
-    const tags = await prisma.categoryLink.findMany({
8
-        where: {
9
-            source_id: data.id,
10
-            source_type: { in: ['vendor_experience_positive_notes', 'vendor_experience_negative_notes'] },
11
-            deletedAt: null,
12
-        },
13
-        include: {
14
-            Category: true,
15
-        },
16
-    });
6
+    // const tags = await prisma.categoryLink.findMany({
7
+    //     where: {
8
+    //         source_id: data.id,
9
+    //         source_type: { in: ['vendor_experience_positive_notes', 'vendor_experience_negative_notes'] },
10
+    //         deletedAt: null,
11
+    //     },
12
+    //     include: {
13
+    //         Category: true,
14
+    //     },
15
+    // });
17
 
16
 
18
-    const positive_notes_tags = tags
19
-        .filter(t => t.source_type === 'vendor_experience_positive_notes')
20
-        .map(t => t.Category?.tag ?? '');
17
+    // const positive_notes_tags = tags
18
+    //     .filter(t => t.source_type === 'vendor_experience_positive_notes')
19
+    //     .map(t => t.Category?.tag ?? '');
21
 
20
 
22
-    const negative_notes_tags = tags
23
-        .filter(t => t.source_type === 'vendor_experience_negative_notes')
24
-        .map(t => t.Category?.tag ?? '');
21
+    // const negative_notes_tags = tags
22
+    //     .filter(t => t.source_type === 'vendor_experience_negative_notes')
23
+    //     .map(t => t.Category?.tag ?? '');
25
 
24
 
26
-    const { vendor_id, ...restData } = data;
25
+    // const { vendor_id, ...restData } = data;
26
+    const restData = data;
27
 
27
 
28
     const formatted = {
28
     const formatted = {
29
         ...restData,
29
         ...restData,
@@ -38,12 +38,25 @@ export const VendorExperienceResource = async (res: Response, data: VendorExperi
38
                 created_by: data.vendor.created_by,
38
                 created_by: data.vendor.created_by,
39
             }
39
             }
40
             : null,
40
             : null,
41
-        contract_start_date: formatDateOnly(data.contract_start_date),
42
-        contract_expired_date: formatDateOnly(data.contract_expired_date),
43
-        contract_value_min: data.contract_value_min !== null ? Number(data.contract_value_min) : null,
44
-        contract_value_max: data.contract_value_max !== null ? Number(data.contract_value_max) : null,
45
-        positive_notes_tags,
46
-        negative_notes_tags,
41
+        category: data.category
42
+            ? {
43
+                id: data.category.id,
44
+                name: data.category.name,
45
+                description: data.category.description,
46
+            }
47
+            : null,
48
+        user: data.user
49
+            ? {
50
+                id: data.user.id,
51
+                name: data.user.fullname,
52
+            } : null,
53
+        content: data.content,
54
+        // contract_start_date: formatDateOnly(data.contract_start_date),
55
+        // contract_expired_date: formatDateOnly(data.contract_expired_date),
56
+        // contract_value_min: data.contract_value_min !== null ? Number(data.contract_value_min) : null,
57
+        // contract_value_max: data.contract_value_max !== null ? Number(data.contract_value_max) : null,
58
+        // positive_notes_tags,
59
+        // negative_notes_tags,
47
         createdAt: formatISOWithoutTimezone(data.createdAt),
60
         createdAt: formatISOWithoutTimezone(data.createdAt),
48
         updatedAt: formatISOWithoutTimezone(data.updatedAt),
61
         updatedAt: formatISOWithoutTimezone(data.updatedAt),
49
     };
62
     };

+ 25 - 25
src/resources/sales/hospital/HospitalCollection.ts

@@ -27,41 +27,41 @@ export const HospitalCollection = async ({
27
     limit: number;
27
     limit: number;
28
     message?: string;
28
     message?: string;
29
 }) => {
29
 }) => {
30
-    const ids = data.map(item => item.id);
30
+    // const ids = data.map(item => item.id);
31
 
31
 
32
     // Ambil tags dari category_links yang relevan
32
     // Ambil tags dari category_links yang relevan
33
-    const allTags = await prisma.categoryLink.findMany({
34
-        where: {
35
-            source_id: { in: ids },
36
-            source_type: 'hospital_notes',
37
-            deletedAt: null,
38
-        },
39
-        include: {
40
-            Category: true,
41
-        },
42
-    });
33
+    // const allTags = await prisma.categoryLink.findMany({
34
+    //     where: {
35
+    //         source_id: { in: ids },
36
+    //         source_type: 'hospital_notes',
37
+    //         deletedAt: null,
38
+    //     },
39
+    //     include: {
40
+    //         Category: true,
41
+    //     },
42
+    // });
43
 
43
 
44
-    // Kelompokkan tags berdasarkan source_id
45
-    const tagMap = new Map<string, { note: string[] }>();
46
-    for (const id of ids) {
47
-        tagMap.set(id, { note: [] });
48
-    }
44
+    // // Kelompokkan tags berdasarkan source_id
45
+    // const tagMap = new Map<string, { note: string[] }>();
46
+    // for (const id of ids) {
47
+    //     tagMap.set(id, { note: [] });
48
+    // }
49
 
49
 
50
-    for (const tag of allTags) {
51
-        const id = tag.source_id!;
52
-        const categoryTag = tag.Category?.tag ?? '';
53
-        const current = tagMap.get(id);
54
-        if (!current) continue;
50
+    // for (const tag of allTags) {
51
+    //     const id = tag.source_id!;
52
+    //     const categoryTag = tag.Category?.tag ?? '';
53
+    //     const current = tagMap.get(id);
54
+    //     if (!current) continue;
55
 
55
 
56
-        current.note.push(categoryTag);
57
-    }
56
+    //     current.note.push(categoryTag);
57
+    // }
58
 
58
 
59
     const formattedData = data.map(item => {
59
     const formattedData = data.map(item => {
60
         const { created_by, ...rest } = item;
60
         const { created_by, ...rest } = item;
61
-        const tags = tagMap.get(item.id);
61
+        // const tags = tagMap.get(item.id);
62
         return formatItem({
62
         return formatItem({
63
             ...rest,
63
             ...rest,
64
-            note_tags: tags?.note ?? [],
64
+            // note_tags: tags?.note ?? [],
65
         });
65
         });
66
     });
66
     });
67
 
67
 

+ 14 - 14
src/resources/sales/hospital/HospitalResource.ts

@@ -10,26 +10,26 @@ const formatItem = (item: HospitalDTO) => ({
10
 });
10
 });
11
 
11
 
12
 export const HospitalResource = async (res: Response, data: HospitalDTO, message: string = 'Success'): Promise<Response> => {
12
 export const HospitalResource = async (res: Response, data: HospitalDTO, message: string = 'Success'): Promise<Response> => {
13
-    const tags = await prisma.categoryLink.findMany({
14
-        where: {
15
-            source_id: data.id,
16
-            source_type: { in: ['hospital_notes'] },
17
-            deletedAt: null,
18
-        },
19
-        include: {
20
-            Category: true,
21
-        },
22
-    });
13
+    // const tags = await prisma.categoryLink.findMany({
14
+    //     where: {
15
+    //         source_id: data.id,
16
+    //         source_type: { in: ['hospital_notes'] },
17
+    //         deletedAt: null,
18
+    //     },
19
+    //     include: {
20
+    //         Category: true,
21
+    //     },
22
+    // });
23
 
23
 
24
-    const note_tags = tags
25
-        .filter(t => t.source_type === 'hospital_notes')
26
-        .map(t => t.Category?.tag ?? '');
24
+    // const note_tags = tags
25
+    //     .filter(t => t.source_type === 'hospital_notes')
26
+    //     .map(t => t.Category?.tag ?? '');
27
 
27
 
28
     const { created_by, ...cleanedData } = data;
28
     const { created_by, ...cleanedData } = data;
29
 
29
 
30
     const formatted = {
30
     const formatted = {
31
         ...formatItem(cleanedData),
31
         ...formatItem(cleanedData),
32
-        note_tags,
32
+        // note_tags,
33
     };
33
     };
34
 
34
 
35
     return res.status(200).json({
35
     return res.status(200).json({

+ 2 - 2
src/resources/sales/schedule_visitation/ScheduleVisitationResource.ts

@@ -10,8 +10,8 @@ const formatItem = (item: ShowScheduleVisitationDTO) => ({
10
         ...item.hospital,
10
         ...item.hospital,
11
         vendor_experiences: item.hospital.vendor_experiences.map((vendor) => ({
11
         vendor_experiences: item.hospital.vendor_experiences.map((vendor) => ({
12
             ...vendor,
12
             ...vendor,
13
-            contract_start_date: formatDateOnly(vendor.contract_start_date),
14
-            contract_expired_date: formatDateOnly(vendor.contract_expired_date),
13
+            // contract_start_date: formatDateOnly(vendor.contract_start_date),
14
+            // contract_expired_date: formatDateOnly(vendor.contract_expired_date),
15
         })),
15
         })),
16
         executives_histories: item.hospital.executives_histories.map((exec) => ({
16
         executives_histories: item.hospital.executives_histories.map((exec) => ({
17
             ...exec,
17
             ...exec,

+ 25 - 25
src/resources/sales/status_history/StatusHistoryCollection.ts

@@ -14,40 +14,40 @@ export const StatusHistoryCollection = async (req: Request, res: Response, data:
14
     const ids = data.map(item => item.id);
14
     const ids = data.map(item => item.id);
15
 
15
 
16
     // Ambil tags dari category_links yang relevan
16
     // Ambil tags dari category_links yang relevan
17
-    const allTags = await prisma.categoryLink.findMany({
18
-        where: {
19
-            source_id: { in: ids },
20
-            source_type: { in: ['status_history_notes'] },
21
-            deletedAt: null,
22
-        },
23
-        include: {
24
-            Category: true,
25
-        },
26
-    });
17
+    // const allTags = await prisma.categoryLink.findMany({
18
+    //     where: {
19
+    //         source_id: { in: ids },
20
+    //         source_type: { in: ['status_history_notes'] },
21
+    //         deletedAt: null,
22
+    //     },
23
+    //     include: {
24
+    //         Category: true,
25
+    //     },
26
+    // });
27
 
27
 
28
     // Kelompokkan tags berdasarkan source_type dan source_id
28
     // Kelompokkan tags berdasarkan source_type dan source_id
29
-    const tagMap = new Map<string, { note: string[]; }>();
30
-    for (const id of ids) {
31
-        tagMap.set(id, { note: [] });
32
-    }
29
+    // const tagMap = new Map<string, { note: string[]; }>();
30
+    // for (const id of ids) {
31
+    //     tagMap.set(id, { note: [] });
32
+    // }
33
 
33
 
34
-    for (const tag of allTags) {
35
-        const id = tag.source_id!;
36
-        const categoryTag = tag.Category?.tag ?? '';
37
-        const current = tagMap.get(id);
38
-        if (!current) continue;
34
+    // for (const tag of allTags) {
35
+    //     const id = tag.source_id!;
36
+    //     const categoryTag = tag.Category?.tag ?? '';
37
+    //     const current = tagMap.get(id);
38
+    //     if (!current) continue;
39
 
39
 
40
-        if (tag.source_type === 'status_history_notes') {
41
-            current.note.push(categoryTag);
42
-        }
43
-    }
40
+    //     if (tag.source_type === 'status_history_notes') {
41
+    //         current.note.push(categoryTag);
42
+    //     }
43
+    // }
44
 
44
 
45
     // Gabungkan dan format
45
     // Gabungkan dan format
46
     const formattedData = data.map(item => {
46
     const formattedData = data.map(item => {
47
-        const tags = tagMap.get(item.id);
47
+        // const tags = tagMap.get(item.id);
48
         return formatItem({
48
         return formatItem({
49
             ...item,
49
             ...item,
50
-            note_tags: tags?.note ?? [],
50
+            // note_tags: tags?.note ?? [],
51
         });
51
         });
52
     });
52
     });
53
 
53
 

+ 33 - 34
src/resources/sales/vendor_experience/VendorExperienceCollection.ts

@@ -1,15 +1,14 @@
1
 import { Request, Response } from 'express';
1
 import { Request, Response } from 'express';
2
 import { ListResponse } from '../../../utils/ListResponse';
2
 import { ListResponse } from '../../../utils/ListResponse';
3
-import { formatDateOnly, formatISOWithoutTimezone } from '../../../utils/FormatDate';
3
+import { formatISOWithoutTimezone } from '../../../utils/FormatDate';
4
 import { VendorExperienceDTO } from '../../../types/sales/vendor_experience/VendorExperienceDTO';
4
 import { VendorExperienceDTO } from '../../../types/sales/vendor_experience/VendorExperienceDTO';
5
-import prisma from '../../../prisma/PrismaClient';
6
 
5
 
7
 const formatItem = (item: VendorExperienceDTO) => ({
6
 const formatItem = (item: VendorExperienceDTO) => ({
8
     ...item,
7
     ...item,
9
-    contract_value_min: item.contract_value_min !== null ? Number(item.contract_value_min) : null,
10
-    contract_value_max: item.contract_value_max !== null ? Number(item.contract_value_max) : null,
11
-    contract_start_date: formatDateOnly(item.contract_start_date),
12
-    contract_expired_date: formatDateOnly(item.contract_expired_date),
8
+    // contract_value_min: item.contract_value_min !== null ? Number(item.contract_value_min) : null,
9
+    // contract_value_max: item.contract_value_max !== null ? Number(item.contract_value_max) : null,
10
+    // contract_start_date: formatDateOnly(item.contract_start_date),
11
+    // contract_expired_date: formatDateOnly(item.contract_expired_date),
13
     createdAt: formatISOWithoutTimezone(item.createdAt),
12
     createdAt: formatISOWithoutTimezone(item.createdAt),
14
     updatedAt: formatISOWithoutTimezone(item.updatedAt),
13
     updatedAt: formatISOWithoutTimezone(item.updatedAt),
15
 });
14
 });
@@ -26,43 +25,43 @@ export const VendorExperienceCollection = async (
26
     const ids = data.map(item => item.id);
25
     const ids = data.map(item => item.id);
27
 
26
 
28
     // Ambil tags dari category_links yang relevan
27
     // Ambil tags dari category_links yang relevan
29
-    const allTags = await prisma.categoryLink.findMany({
30
-        where: {
31
-            source_id: { in: ids },
32
-            source_type: { in: ['vendor_experience_positive_notes', 'vendor_experience_negative_notes'] },
33
-            deletedAt: null,
34
-        },
35
-        include: {
36
-            Category: true,
37
-        },
38
-    });
28
+    // const allTags = await prisma.categoryLink.findMany({
29
+    //     where: {
30
+    //         source_id: { in: ids },
31
+    //         source_type: { in: ['vendor_experience_positive_notes', 'vendor_experience_negative_notes'] },
32
+    //         deletedAt: null,
33
+    //     },
34
+    //     include: {
35
+    //         Category: true,
36
+    //     },
37
+    // });
39
 
38
 
40
     // Kelompokkan tags berdasarkan source_type dan source_id
39
     // Kelompokkan tags berdasarkan source_type dan source_id
41
-    const tagMap = new Map<string, { positive: string[]; negative: string[] }>();
42
-    for (const id of ids) {
43
-        tagMap.set(id, { positive: [], negative: [] });
44
-    }
40
+    // const tagMap = new Map<string, { positive: string[]; negative: string[] }>();
41
+    // for (const id of ids) {
42
+    //     tagMap.set(id, { positive: [], negative: [] });
43
+    // }
45
 
44
 
46
-    for (const tag of allTags) {
47
-        const id = tag.source_id!;
48
-        const categoryTag = tag.Category?.tag ?? '';
49
-        const current = tagMap.get(id);
50
-        if (!current) continue;
45
+    // for (const tag of allTags) {
46
+    //     const id = tag.source_id!;
47
+    //     const categoryTag = tag.Category?.tag ?? '';
48
+    //     const current = tagMap.get(id);
49
+    //     if (!current) continue;
51
 
50
 
52
-        if (tag.source_type === 'vendor_experience_positive_notes') {
53
-            current.positive.push(categoryTag);
54
-        } else if (tag.source_type === 'vendor_experience_negative_notes') {
55
-            current.negative.push(categoryTag);
56
-        }
57
-    }
51
+    //     if (tag.source_type === 'vendor_experience_positive_notes') {
52
+    //         current.positive.push(categoryTag);
53
+    //     } else if (tag.source_type === 'vendor_experience_negative_notes') {
54
+    //         current.negative.push(categoryTag);
55
+    //     }
56
+    // }
58
 
57
 
59
     // Gabungkan dan format
58
     // Gabungkan dan format
60
     const formattedData = data.map(item => {
59
     const formattedData = data.map(item => {
61
-        const tags = tagMap.get(item.id);
60
+        // const tags = tagMap.get(item.id);
62
         return formatItem({
61
         return formatItem({
63
             ...item,
62
             ...item,
64
-            positive_notes_tags: tags?.positive ?? [],
65
-            negative_notes_tags: tags?.negative ?? [],
63
+            // positive_notes_tags: tags?.positive ?? [],
64
+            // negative_notes_tags: tags?.negative ?? [],
66
         });
65
         });
67
     });
66
     });
68
 
67
 

+ 38 - 25
src/resources/sales/vendor_experience/VendorExperienceResource.ts

@@ -1,29 +1,29 @@
1
 import { Response } from 'express';
1
 import { Response } from 'express';
2
-import { formatDateOnly, formatISOWithoutTimezone } from '../../../utils/FormatDate';
2
+import { formatISOWithoutTimezone } from '../../../utils/FormatDate';
3
 import { VendorExperienceDTO } from '../../../types/sales/vendor_experience/VendorExperienceDTO';
3
 import { VendorExperienceDTO } from '../../../types/sales/vendor_experience/VendorExperienceDTO';
4
-import prisma from '../../../prisma/PrismaClient';
5
 
4
 
6
 export const VendorExperienceResource = async (res: Response, data: VendorExperienceDTO, message: string = 'Success'): Promise<Response> => {
5
 export const VendorExperienceResource = async (res: Response, data: VendorExperienceDTO, message: string = 'Success'): Promise<Response> => {
7
-    const tags = await prisma.categoryLink.findMany({
8
-        where: {
9
-            source_id: data.id,
10
-            source_type: { in: ['vendor_experience_positive_notes', 'vendor_experience_negative_notes'] },
11
-            deletedAt: null,
12
-        },
13
-        include: {
14
-            Category: true,
15
-        },
16
-    });
6
+    // const tags = await prisma.categoryLink.findMany({
7
+    //     where: {
8
+    //         source_id: data.id,
9
+    //         source_type: { in: ['vendor_experience_positive_notes', 'vendor_experience_negative_notes'] },
10
+    //         deletedAt: null,
11
+    //     },
12
+    //     include: {
13
+    //         Category: true,
14
+    //     },
15
+    // });
17
 
16
 
18
-    const positive_notes_tags = tags
19
-        .filter(t => t.source_type === 'vendor_experience_positive_notes')
20
-        .map(t => t.Category?.tag ?? '');
17
+    // const positive_notes_tags = tags
18
+    //     .filter(t => t.source_type === 'vendor_experience_positive_notes')
19
+    //     .map(t => t.Category?.tag ?? '');
21
 
20
 
22
-    const negative_notes_tags = tags
23
-        .filter(t => t.source_type === 'vendor_experience_negative_notes')
24
-        .map(t => t.Category?.tag ?? '');
21
+    // const negative_notes_tags = tags
22
+    //     .filter(t => t.source_type === 'vendor_experience_negative_notes')
23
+    //     .map(t => t.Category?.tag ?? '');
25
 
24
 
26
-    const { vendor_id, ...restData } = data;
25
+    // const { vendor_id, ...restData } = data;
26
+    const restData = data;
27
 
27
 
28
     const formatted = {
28
     const formatted = {
29
         ...restData,
29
         ...restData,
@@ -38,12 +38,25 @@ export const VendorExperienceResource = async (res: Response, data: VendorExperi
38
                 created_by: data.vendor.created_by,
38
                 created_by: data.vendor.created_by,
39
             }
39
             }
40
             : null,
40
             : null,
41
-        contract_start_date: formatDateOnly(data.contract_start_date),
42
-        contract_expired_date: formatDateOnly(data.contract_expired_date),
43
-        contract_value_min: data.contract_value_min !== null ? Number(data.contract_value_min) : null,
44
-        contract_value_max: data.contract_value_max !== null ? Number(data.contract_value_max) : null,
45
-        positive_notes_tags,
46
-        negative_notes_tags,
41
+        category: data.category
42
+            ? {
43
+                id: data.category.id,
44
+                name: data.category.name,
45
+                description: data.category.description,
46
+            }
47
+            : null,
48
+        user: data.user
49
+            ? {
50
+                id: data.user.id,
51
+                name: data.user.fullname,
52
+            } : null,
53
+        content: data.content,
54
+        // contract_start_date: formatDateOnly(data.contract_start_date),
55
+        // contract_expired_date: formatDateOnly(data.contract_expired_date),
56
+        // contract_value_min: data.contract_value_min !== null ? Number(data.contract_value_min) : null,
57
+        // contract_value_max: data.contract_value_max !== null ? Number(data.contract_value_max) : null,
58
+        // positive_notes_tags,
59
+        // negative_notes_tags,
47
         createdAt: formatISOWithoutTimezone(data.createdAt),
60
         createdAt: formatISOWithoutTimezone(data.createdAt),
48
         updatedAt: formatISOWithoutTimezone(data.updatedAt),
61
         updatedAt: formatISOWithoutTimezone(data.updatedAt),
49
     };
62
     };

+ 4 - 3
src/routes/admin/CategoryRoute.ts

@@ -6,13 +6,14 @@ import checkRoles from '../../middleware/CheckRoles';
6
 
6
 
7
 const router: Router = express.Router();
7
 const router: Router = express.Router();
8
 
8
 
9
-router.get('/', [keycloak.protect(), extractToken, checkRoles(["admin"])], CategoryController.getAllCategory);
9
+router.get('/', [keycloak.protect(), extractToken, checkRoles(["admin", "sales"])], CategoryController.getAllCategory);
10
 router.post('/', [keycloak.protect(), extractToken, checkRoles(["admin"])], CategoryController.storeCategory);
10
 router.post('/', [keycloak.protect(), extractToken, checkRoles(["admin"])], CategoryController.storeCategory);
11
 router.get('/:id', [keycloak.protect(), extractToken, checkRoles(["admin"])], CategoryController.showCategory);
11
 router.get('/:id', [keycloak.protect(), extractToken, checkRoles(["admin"])], CategoryController.showCategory);
12
 router.patch('/:id', [keycloak.protect(), extractToken, checkRoles(["admin"])], CategoryController.updateCategory);
12
 router.patch('/:id', [keycloak.protect(), extractToken, checkRoles(["admin"])], CategoryController.updateCategory);
13
 router.delete('/:id', [keycloak.protect(), extractToken, checkRoles(["admin"])], CategoryController.deleteCategory);
13
 router.delete('/:id', [keycloak.protect(), extractToken, checkRoles(["admin"])], CategoryController.deleteCategory);
14
+router.patch('/:id/archive', [keycloak.protect(), extractToken, checkRoles(["admin"])], CategoryController.archiveCategory);
14
 
15
 
15
-router.get('/:id/use', [keycloak.protect(), extractToken, checkRoles(["admin"])], CategoryController.showUseCategory);
16
-router.post('/merge', [keycloak.protect(), extractToken, checkRoles(["admin"])], CategoryController.mergeCategory);
16
+// router.get('/:id/use', [keycloak.protect(), extractToken, checkRoles(["admin"])], CategoryController.showUseCategory);
17
+// router.post('/merge', [keycloak.protect(), extractToken, checkRoles(["admin"])], CategoryController.mergeCategory);
17
 
18
 
18
 export default router;
19
 export default router;

+ 55 - 55
src/services/admin/CategoryLinkService.ts

@@ -3,58 +3,58 @@ import CategoryLinkRepository from '../../repository/admin/CategoryLinkRepositor
3
 import { createLog, updateLog } from '../../utils/LogActivity';
3
 import { createLog, updateLog } from '../../utils/LogActivity';
4
 import { CustomRequest } from '../../types/token/CustomRequest';
4
 import { CustomRequest } from '../../types/token/CustomRequest';
5
 
5
 
6
-export const storeCategoryLinkService = async (tags: string[], source_type: string, source_id: string, req: CustomRequest) => {
7
-    const result = [];
8
-
9
-    for (let i = 0; i < tags.length; i++) {
10
-        const tag = tags[i];
11
-
12
-        const existCategoryTag = await CategoryRepository.findByTag(tag);
13
-
14
-        let categoryId: string = "";
15
-        if (!existCategoryTag) {
16
-            const created = await CategoryRepository.create({ tag: tag, description: null });
17
-            categoryId = created.id;
18
-            await createLog(req, created);
19
-        } else {
20
-            categoryId = existCategoryTag.id;
21
-        }
22
-
23
-        const data = await CategoryLinkRepository.create({
24
-            category_id: categoryId,
25
-            source_type: source_type,
26
-            source_id: source_id,
27
-        });
28
-
29
-        await createLog(req, data);
30
-        result.push(data);
31
-    }
32
-};
33
-export const updateCategoryLinkService = async (newTags: string[], source_type: string, source_id: string, req: CustomRequest) => {
34
-    const result = [];
35
-
36
-    const oldLinks = await CategoryLinkRepository.findBySource(source_type, source_id);
37
-
38
-    for (const link of oldLinks) {
39
-        await CategoryLinkRepository.deleteById(link.id);
40
-    }
41
-
42
-    for (const tag of newTags) {
43
-        let category = await CategoryRepository.findByTag(tag);
44
-        if (!category) {
45
-            category = await CategoryRepository.create({ tag, description: null });
46
-            await createLog(req, category);
47
-        }
48
-
49
-        const newLink = await CategoryLinkRepository.create({
50
-            category_id: category.id,
51
-            source_type,
52
-            source_id,
53
-        });
54
-
55
-        await updateLog(req, newLink);
56
-        result.push(newLink);
57
-    }
58
-
59
-    return result;
60
-};
6
+// export const storeCategoryLinkService = async (tags: string[], source_type: string, source_id: string, req: CustomRequest) => {
7
+//     const result = [];
8
+
9
+//     for (let i = 0; i < tags.length; i++) {
10
+//         const tag = tags[i];
11
+
12
+//         const existCategoryTag = await CategoryRepository.findByTag(tag);
13
+
14
+//         let categoryId: string = "";
15
+//         if (!existCategoryTag) {
16
+//             const created = await CategoryRepository.create({ tag: tag, description: null });
17
+//             categoryId = created.id;
18
+//             await createLog(req, created);
19
+//         } else {
20
+//             categoryId = existCategoryTag.id;
21
+//         }
22
+
23
+//         const data = await CategoryLinkRepository.create({
24
+//             category_id: categoryId,
25
+//             source_type: source_type,
26
+//             source_id: source_id,
27
+//         });
28
+
29
+//         await createLog(req, data);
30
+//         result.push(data);
31
+//     }
32
+// };
33
+// export const updateCategoryLinkService = async (newTags: string[], source_type: string, source_id: string, req: CustomRequest) => {
34
+//     const result = [];
35
+
36
+//     const oldLinks = await CategoryLinkRepository.findBySource(source_type, source_id);
37
+
38
+//     for (const link of oldLinks) {
39
+//         await CategoryLinkRepository.deleteById(link.id);
40
+//     }
41
+
42
+//     for (const tag of newTags) {
43
+//         let category = await CategoryRepository.findByTag(tag);
44
+//         if (!category) {
45
+//             category = await CategoryRepository.create({ tag, description: null });
46
+//             await createLog(req, category);
47
+//         }
48
+
49
+//         const newLink = await CategoryLinkRepository.create({
50
+//             category_id: category.id,
51
+//             source_type,
52
+//             source_id,
53
+//         });
54
+
55
+//         await updateLog(req, newLink);
56
+//         result.push(newLink);
57
+//     }
58
+
59
+//     return result;
60
+// };

+ 154 - 114
src/services/admin/CategoryService.ts

@@ -17,23 +17,39 @@ interface GetAllCategoryParams {
17
     search?: string;
17
     search?: string;
18
     sortBy: string;
18
     sortBy: string;
19
     orderBy: 'asc' | 'desc';
19
     orderBy: 'asc' | 'desc';
20
+    filter?: 'archive' | 'all';
21
+    usage?: 'unused' | 'used'
20
 }
22
 }
21
 
23
 
22
-interface GetAllCategoryLinkParams {
23
-    page: number;
24
-    limit: number;
25
-    search?: string;
26
-    categoryId: string;
27
-}
28
-
29
-export const getAllCategoryService = async ({ page, limit, search, sortBy, orderBy }: GetAllCategoryParams) => {
24
+// interface GetAllCategoryLinkParams {
25
+//     page: number;
26
+//     limit: number;
27
+//     search?: string;
28
+//     categoryId: string;
29
+// }
30
+export const getAllCategoryService = async ({ page, limit, search, sortBy, orderBy, filter, usage }: GetAllCategoryParams) => {
30
     const skip = (page - 1) * limit;
31
     const skip = (page - 1) * limit;
31
 
32
 
32
-    const where: Prisma.CategoryWhereInput = {
33
-        ...SearchFilter(search, ['tag']),
33
+    // Default filter: only active (not archived, not deleted)
34
+    let where: Prisma.CategoryWhereInput = {
35
+        ...SearchFilter(search, ['name']),
36
+        status_archive: false,
34
         deletedAt: null,
37
         deletedAt: null,
35
     };
38
     };
36
 
39
 
40
+    if (filter === 'archive') {
41
+        where = {
42
+            ...SearchFilter(search, ['name']),
43
+            status_archive: true,
44
+            deletedAt: null,
45
+        };
46
+    } else if (filter === 'all') {
47
+        where = {
48
+            ...SearchFilter(search, ['name']),
49
+            deletedAt: null, // ignore status_archive
50
+        };
51
+    }
52
+
37
     const [categories, total] = await Promise.all([
53
     const [categories, total] = await Promise.all([
38
         CategoryRepository.findAll({
54
         CategoryRepository.findAll({
39
             skip,
55
             skip,
@@ -43,8 +59,16 @@ export const getAllCategoryService = async ({ page, limit, search, sortBy, order
43
         }),
59
         }),
44
         CategoryRepository.countAll(where),
60
         CategoryRepository.countAll(where),
45
     ]);
61
     ]);
62
+    
63
+    let filteredCategories = categories;
64
+
65
+    if (usage === 'unused') {
66
+        filteredCategories = categories.filter(c => c.count_use_category === 0);
67
+    } else if (usage === 'used') {
68
+        filteredCategories = categories.filter(c => c.count_use_category > 0);
69
+    }
46
 
70
 
47
-    return { categories, total };
71
+    return { categories: filteredCategories, total };
48
 };
72
 };
49
 
73
 
50
 export const showCategoryService = async (id: string) => {
74
 export const showCategoryService = async (id: string) => {
@@ -57,14 +81,14 @@ export const showCategoryService = async (id: string) => {
57
 };
81
 };
58
 
82
 
59
 export const storeCategoryService = async (validateData: CategoryRequestDTO, req: CustomRequest) => {
83
 export const storeCategoryService = async (validateData: CategoryRequestDTO, req: CustomRequest) => {
60
-    const existingCategory = await CategoryRepository.findByTag(validateData.tag);
84
+    const existingCategory = await CategoryRepository.findByName(validateData.name);
61
     if (existingCategory && !existingCategory.deletedAt) {
85
     if (existingCategory && !existingCategory.deletedAt) {
62
-        throw new HttpException('Category with this tag already exists and may not be duplicated.', 400);
86
+        throw new HttpException('Category with this name already exists and may not be duplicated.', 400);
63
     }
87
     }
64
 
88
 
65
     const data = await CategoryRepository.create(validateData);
89
     const data = await CategoryRepository.create(validateData);
66
     await createLog(req, data);
90
     await createLog(req, data);
67
-    return data;
91
+    // return data;
68
 };
92
 };
69
 
93
 
70
 export const updateCategoryService = async (validateData: CategoryRequestDTO, id: string, req: CustomRequest) => {
94
 export const updateCategoryService = async (validateData: CategoryRequestDTO, id: string, req: CustomRequest) => {
@@ -73,16 +97,16 @@ export const updateCategoryService = async (validateData: CategoryRequestDTO, id
73
         throw new HttpException('Data category not found', 404);
97
         throw new HttpException('Data category not found', 404);
74
     }
98
     }
75
 
99
 
76
-    if (validateData.tag) {
77
-        const existingCategory = await CategoryRepository.findByTag(validateData.tag);
100
+    if (validateData.name) {
101
+        const existingCategory = await CategoryRepository.findByName(validateData.name);
78
         if (existingCategory && existingCategory.id !== id) {
102
         if (existingCategory && existingCategory.id !== id) {
79
-            throw new HttpException('Category with this tag already exists and may not be duplicated.', 400);
103
+            throw new HttpException('Category with this name already exists and may not be duplicated.', 400);
80
         }
104
         }
81
     }
105
     }
82
 
106
 
83
     const data = await CategoryRepository.update(id, validateData);
107
     const data = await CategoryRepository.update(id, validateData);
84
     await updateLog(req, data);
108
     await updateLog(req, data);
85
-    return data;
109
+    // return data;
86
 };
110
 };
87
 
111
 
88
 export const deleteCategoryService = async (id: string, req: CustomRequest) => {
112
 export const deleteCategoryService = async (id: string, req: CustomRequest) => {
@@ -96,108 +120,124 @@ export const deleteCategoryService = async (id: string, req: CustomRequest) => {
96
     });
120
     });
97
 
121
 
98
     await deleteLog(req, data);
122
     await deleteLog(req, data);
99
-    return data;
100
-};
101
-
102
-export const showUseCategoryService = async ({ page, limit, search, categoryId }: GetAllCategoryLinkParams) => {
103
-    const skip = (page - 1) * limit;
104
-
105
-    const where: Prisma.CategoryLinkWhereInput = {
106
-        ...SearchFilter(search, ['source_type']),
107
-        category_id: categoryId,
108
-        deletedAt: null,
109
-    };
110
-
111
-    const [links, total] = await Promise.all([
112
-        CategoryRepository.findAllCategoryLink({ skip, take: limit, where }),
113
-        CategoryRepository.countAllCategoryLink(where),
114
-    ]);
115
-
116
-    const result: CategoryLinkUseDTO[] = [];
117
-
118
-    for (const link of links) {
119
-        const { source_id, source_type } = link;
120
-        if (!source_id || !source_type) continue;
121
-
122
-        const sourceData = await GetSourceDataByType(source_type, source_id);
123
-        if (!sourceData) continue;
124
-
125
-        result.push(TransformCategoryLinkUse(link, source_type, sourceData));
126
-    }
127
-
128
-    return { data: result, total, page, limit };
123
+    // return data;
129
 };
124
 };
130
 
125
 
131
-export const mergeCategoryService = async (validateData: MergeCategoryRequestDTO, req: CustomRequest) => {
132
-    // Soft delete old categories
133
-    for (const id of validateData.category_id) {
134
-        const category = await CategoryRepository.findById(id);
135
-        if (!category) {
136
-            throw new HttpException(`Category with tag ${validateData.tag} not found`, 404);
137
-        }
138
-    }
139
-
140
-    // Check tag uniqueness
141
-    const existingCategory = await CategoryRepository.findByTag(validateData.tag);
142
-    if (existingCategory && !existingCategory.deletedAt) {
143
-        throw new HttpException('Category with this tag already exists and may not be duplicated.', 400);
126
+export const archiveCategoryService = async (id: string, req: CustomRequest) => {
127
+    const category = await CategoryRepository.findById(id);
128
+    if (!category) {
129
+        throw new HttpException('Data category not found', 404);
144
     }
130
     }
145
 
131
 
146
-    // Create new merged category
147
-    const data = await CategoryRepository.create({
148
-        tag: validateData.tag,
149
-        description: validateData.description ?? null,
150
-    });
151
-
152
-    await createLog(req, data);
132
+    const newStatus = !category.status_archive;
153
 
133
 
154
-    await prisma.categoryLink.updateMany({
155
-        where: {
156
-            category_id: { in: validateData.category_id },
157
-            deletedAt: null,
158
-        },
159
-        data: {
160
-            category_id: data.id,
161
-        },
162
-    });
163
-
164
-    await prisma.category.updateMany({
165
-        where: {
166
-            id: { in: validateData.category_id },
167
-            deletedAt: null,
168
-        },
169
-        data: {
170
-            deletedAt: now().toDate(),
171
-        },
134
+    const data = await CategoryRepository.update(id, {
135
+        status_archive: newStatus,
172
     });
136
     });
173
 
137
 
174
-    // Remove duplicate category links (same category_id, source_type, source_id, deletedAt: null)
175
-    const links = await prisma.categoryLink.findMany({
176
-        where: {
177
-            category_id: data.id,
178
-            deletedAt: null,
179
-        },
180
-    });
138
+    await updateLog(req, data);
181
 
139
 
182
-    // Group by source_type + source_id
183
-    const grouped: Record<string, typeof links> = {};
184
-    for (const link of links) {
185
-        const key = `${link.source_type}_${link.source_id}`;
186
-        if (!grouped[key]) grouped[key] = [];
187
-        grouped[key].push(link);
188
-    }
140
+}
189
 
141
 
190
-    for (const group of Object.values(grouped)) {
191
-        if (group.length > 1) {
192
-            // Sort by createdAt, keep the earliest, delete the rest
193
-            const sorted = group.sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime());
194
-            const toDelete = sorted.slice(1);
195
-            for (const link of toDelete) {
196
-                await prisma.categoryLink.update({
197
-                    where: { id: link.id },
198
-                    data: { deletedAt: now().toDate() },
199
-                });
200
-            }
201
-        }
202
-    }
203
-};
142
+// export const showUseCategoryService = async ({ page, limit, search, categoryId }: GetAllCategoryLinkParams) => {
143
+//     const skip = (page - 1) * limit;
144
+
145
+//     const where: Prisma.CategoryLinkWhereInput = {
146
+//         ...SearchFilter(search, ['source_type']),
147
+//         category_id: categoryId,
148
+//         deletedAt: null,
149
+//     };
150
+
151
+//     const [links, total] = await Promise.all([
152
+//         CategoryRepository.findAllCategoryLink({ skip, take: limit, where }),
153
+//         CategoryRepository.countAllCategoryLink(where),
154
+//     ]);
155
+
156
+//     const result: CategoryLinkUseDTO[] = [];
157
+
158
+//     for (const link of links) {
159
+//         const { source_id, source_type } = link;
160
+//         if (!source_id || !source_type) continue;
161
+
162
+//         const sourceData = await GetSourceDataByType(source_type, source_id);
163
+//         if (!sourceData) continue;
164
+
165
+//         result.push(TransformCategoryLinkUse(link, source_type, sourceData));
166
+//     }
167
+
168
+//     return { data: result, total, page, limit };
169
+// };
170
+
171
+// export const mergeCategoryService = async (validateData: MergeCategoryRequestDTO, req: CustomRequest) => {
172
+//     // Soft delete old categories
173
+//     for (const id of validateData.category_id) {
174
+//         const category = await CategoryRepository.findById(id);
175
+//         if (!category) {
176
+//             throw new HttpException(`Category with tag ${validateData.tag} not found`, 404);
177
+//         }
178
+//     }
179
+
180
+//     // Check tag uniqueness
181
+//     const existingCategory = await CategoryRepository.findByTag(validateData.tag);
182
+//     if (existingCategory && !existingCategory.deletedAt) {
183
+//         throw new HttpException('Category with this tag already exists and may not be duplicated.', 400);
184
+//     }
185
+
186
+//     // Create new merged category
187
+//     const data = await CategoryRepository.create({
188
+//         tag: validateData.tag,
189
+//         description: validateData.description ?? null,
190
+//     });
191
+
192
+//     await createLog(req, data);
193
+
194
+//     await prisma.categoryLink.updateMany({
195
+//         where: {
196
+//             category_id: { in: validateData.category_id },
197
+//             deletedAt: null,
198
+//         },
199
+//         data: {
200
+//             category_id: data.id,
201
+//         },
202
+//     });
203
+
204
+//     await prisma.category.updateMany({
205
+//         where: {
206
+//             id: { in: validateData.category_id },
207
+//             deletedAt: null,
208
+//         },
209
+//         data: {
210
+//             deletedAt: now().toDate(),
211
+//         },
212
+//     });
213
+
214
+//     // Remove duplicate category links (same category_id, source_type, source_id, deletedAt: null)
215
+//     const links = await prisma.categoryLink.findMany({
216
+//         where: {
217
+//             category_id: data.id,
218
+//             deletedAt: null,
219
+//         },
220
+//     });
221
+
222
+//     // Group by source_type + source_id
223
+//     const grouped: Record<string, typeof links> = {};
224
+//     for (const link of links) {
225
+//         const key = `${link.source_type}_${link.source_id}`;
226
+//         if (!grouped[key]) grouped[key] = [];
227
+//         grouped[key].push(link);
228
+//     }
229
+
230
+//     for (const group of Object.values(grouped)) {
231
+//         if (group.length > 1) {
232
+//             // Sort by createdAt, keep the earliest, delete the rest
233
+//             const sorted = group.sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime());
234
+//             const toDelete = sorted.slice(1);
235
+//             for (const link of toDelete) {
236
+//                 await prisma.categoryLink.update({
237
+//                     where: { id: link.id },
238
+//                     data: { deletedAt: now().toDate() },
239
+//                 });
240
+//             }
241
+//         }
242
+//     }
243
+// };

+ 1 - 75
src/services/admin/CityService.ts

@@ -125,78 +125,4 @@ export const deleteCityService = async (id: string, req: CustomRequest) => {
125
 
125
 
126
     await deleteLog(req, data);
126
     await deleteLog(req, data);
127
     return data;
127
     return data;
128
-};
129
-
130
-// const CityRepository = require('../../repository/admin/CityRepository.js');
131
-// const HttpException = require('../../utils/HttpException.js');
132
-// const { SearchFilter } = require('../../utils/SearchFilter.js');
133
-// const timeLocal = require('../../utils/TimeLocal.js');
134
-// const { createLog, updateLog, deleteLog } = require('../../utils/LogActivity.js');
135
-// const ProvinceRepository = require('../../repository/admin/ProvinceRepository.js');
136
-// const { formatISOWithoutTimezone } = require('../../utils/FormatDate.js');
137
-
138
-// exports.getAllCityService = async ({ page, limit, search, sortBy, orderBy }) => {
139
-//     const skip = (page - 1) * limit;
140
-
141
-//     const where = {
142
-//         ...SearchFilter(search, ['id', 'name', 'province.id']),
143
-//         deletedAt: null
144
-//     };
145
-
146
-//     const [cities, total] = await Promise.all([
147
-//         CityRepository.findAll({ skip, take: limit, where, orderBy: { [sortBy]: orderBy } }),
148
-//         CityRepository.countAll(where)
149
-//     ]);
150
-
151
-//     return { cities, total };
152
-// };
153
-
154
-// exports.showCityService = async (id) => {
155
-//     const city = await CityRepository.findById(id);
156
-//     if (!city) {
157
-//         throw new HttpException("Data city not found", 404);
158
-//     }
159
-
160
-//     return city;
161
-// };
162
-
163
-// exports.storeCityService = async (validateData, req) => {
164
-//     const province = await ProvinceRepository.findById(validateData.province_id);
165
-//     if (!province) {
166
-//         throw new HttpException('Province not found', 404);
167
-//     }
168
-
169
-//     const data = await CityRepository.create(validateData);
170
-//     await createLog(req, data);
171
-// };
172
-
173
-// exports.updateCityService = async (validateData, id, req) => {
174
-//     const city = await CityRepository.findById(id);
175
-//     if (!city) {
176
-//         throw new HttpException("Data city not found", 404);
177
-//     }
178
-
179
-//     if (validateData.province_id) {
180
-//         const province = await ProvinceRepository.findById(validateData.province_id);
181
-//         if (!province) {
182
-//             throw new HttpException('Province not found', 404);
183
-//         }
184
-//     }
185
-
186
-//     const data = await CityRepository.update(id, validateData);
187
-//     await updateLog(req, data);
188
-// };
189
-
190
-// exports.deleteCityService = async (id, req) => {
191
-//     const city = await CityRepository.findById(id);
192
-
193
-//     if (!city) {
194
-//         throw new HttpException('City not found', 404);
195
-//     }
196
-
197
-//     const data = await CityRepository.update(id, {
198
-//         deletedAt: now().toDate()
199
-//     });
200
-
201
-//     await deleteLog(req, data);
202
-// };
128
+};

+ 25 - 25
src/services/admin/HospitalService.ts

@@ -13,7 +13,7 @@ import path from 'path';
13
 import fs from 'fs/promises';
13
 import fs from 'fs/promises';
14
 import sharp from 'sharp';
14
 import sharp from 'sharp';
15
 import * as XLSX from "xlsx";
15
 import * as XLSX from "xlsx";
16
-import { storeCategoryLinkService, updateCategoryLinkService } from './CategoryLinkService';
16
+// import { storeCategoryLinkService, updateCategoryLinkService } from './CategoryLinkService';
17
 import { validateStoreHospitalRequest } from '../../validators/admin/hospital/HospitalValidators';
17
 import { validateStoreHospitalRequest } from '../../validators/admin/hospital/HospitalValidators';
18
 
18
 
19
 interface PaginationParams {
19
 interface PaginationParams {
@@ -172,14 +172,14 @@ export const storeHospitalService = async (validateData: HospitalRequestDTO, req
172
     };
172
     };
173
 
173
 
174
     const data = await HospitalRepository.create(payload);
174
     const data = await HospitalRepository.create(payload);
175
-    if (validateData.tags?.length) {
176
-        await storeCategoryLinkService(
177
-            validateData.tags,
178
-            'hospital_notes',
179
-            data.id,
180
-            req
181
-        );
182
-    }
175
+    // if (validateData.tags?.length) {
176
+    //     await storeCategoryLinkService(
177
+    //         validateData.tags,
178
+    //         'hospital_notes',
179
+    //         data.id,
180
+    //         req
181
+    //     );
182
+    // }
183
 
183
 
184
     await createLog(req, data);
184
     await createLog(req, data);
185
 };
185
 };
@@ -301,14 +301,14 @@ export const updateHospitalService = async (validateData: Partial<HospitalReques
301
     };
301
     };
302
 
302
 
303
     const data = await HospitalRepository.update(id, payload);
303
     const data = await HospitalRepository.update(id, payload);
304
-    if (validateData.tags?.length) {
305
-        await updateCategoryLinkService(
306
-            validateData.tags,
307
-            'hospital_notes',
308
-            id,
309
-            req
310
-        );
311
-    }
304
+    // if (validateData.tags?.length) {
305
+    //     await updateCategoryLinkService(
306
+    //         validateData.tags,
307
+    //         'hospital_notes',
308
+    //         id,
309
+    //         req
310
+    //     );
311
+    // }
312
     await updateLog(req, data);
312
     await updateLog(req, data);
313
 };
313
 };
314
 
314
 
@@ -410,14 +410,14 @@ export const importHospitalService = async (file: Express.Multer.File, req: Cust
410
         const data = await HospitalRepository.create(payload);
410
         const data = await HospitalRepository.create(payload);
411
 
411
 
412
         // tags kategori kalau ada
412
         // tags kategori kalau ada
413
-        if (validatedData.tags?.length) {
414
-            await storeCategoryLinkService(
415
-                validatedData.tags,
416
-                'hospital_notes',
417
-                data.id,
418
-                req
419
-            );
420
-        }
413
+        // if (validatedData.tags?.length) {
414
+        //     await storeCategoryLinkService(
415
+        //         validatedData.tags,
416
+        //         'hospital_notes',
417
+        //         data.id,
418
+        //         req
419
+        //     );
420
+        // }
421
 
421
 
422
         await createLog(req, data);
422
         await createLog(req, data);
423
     }
423
     }

+ 9 - 9
src/services/admin/StatusHistoryService.ts

@@ -5,7 +5,7 @@ import { createLog } from '../../utils/LogActivity';
5
 import StatusHistoryRepository from '../../repository/admin/StatusHistoryRepository';
5
 import StatusHistoryRepository from '../../repository/admin/StatusHistoryRepository';
6
 import { CustomRequest } from '../../types/token/CustomRequest';
6
 import { CustomRequest } from '../../types/token/CustomRequest';
7
 import { StatusHistoryRequestDTO } from '../../types/admin/status_history/StatusHistoryDTO';
7
 import { StatusHistoryRequestDTO } from '../../types/admin/status_history/StatusHistoryDTO';
8
-import { storeCategoryLinkService } from './CategoryLinkService';
8
+// import { storeCategoryLinkService } from './CategoryLinkService';
9
 
9
 
10
 const prisma = new PrismaClient();
10
 const prisma = new PrismaClient();
11
 
11
 
@@ -95,14 +95,14 @@ export const storeStatusHistoryService = async (validateData: StatusHistoryReque
95
         data: { progress_status: validateData.new_status as ProgressStatus },
95
         data: { progress_status: validateData.new_status as ProgressStatus },
96
     });
96
     });
97
 
97
 
98
-    if (validateData.note?.tags?.length) {
99
-        await storeCategoryLinkService(
100
-            validateData.note.tags,
101
-            'status_history_notes',
102
-            data.id,
103
-            req
104
-        );
105
-    }
98
+    // if (validateData.note?.tags?.length) {
99
+    //     await storeCategoryLinkService(
100
+    //         validateData.note.tags,
101
+    //         'status_history_notes',
102
+    //         data.id,
103
+    //         req
104
+    //     );
105
+    // }
106
 
106
 
107
     await createLog(req, data);
107
     await createLog(req, data);
108
 };
108
 };

+ 213 - 445
src/services/admin/VendorExperienceService.ts

@@ -6,7 +6,9 @@ import { createLog, updateLog, deleteLog } from '../../utils/LogActivity';
6
 import VendorExperienceRepository from '../../repository/admin/VendorExperienceRepository';
6
 import VendorExperienceRepository from '../../repository/admin/VendorExperienceRepository';
7
 import { CustomRequest } from '../../types/token/CustomRequest';
7
 import { CustomRequest } from '../../types/token/CustomRequest';
8
 import { VendorExperienceRequestDTO } from '../../types/admin/vendor_experience/VendorExperienceDTO';
8
 import { VendorExperienceRequestDTO } from '../../types/admin/vendor_experience/VendorExperienceDTO';
9
-import { storeCategoryLinkService, updateCategoryLinkService } from './CategoryLinkService';
9
+import { connect } from 'http2';
10
+import { Prisma } from '@prisma/client';
11
+// import { storeCategoryLinkService, updateCategoryLinkService } from './CategoryLinkService';
10
 
12
 
11
 interface PaginationParams {
13
 interface PaginationParams {
12
     page: number;
14
     page: number;
@@ -14,20 +16,24 @@ interface PaginationParams {
14
     search?: string;
16
     search?: string;
15
     sortBy: string;
17
     sortBy: string;
16
     orderBy: 'asc' | 'desc';
18
     orderBy: 'asc' | 'desc';
19
+    category_id: string;
17
 }
20
 }
18
 
21
 
19
-export const getAllVendorExperienceService = async ({ page, limit, search, sortBy, orderBy }: PaginationParams, req: Request) => {
22
+export const getAllVendorExperienceService = async ({ page, limit, search, sortBy, orderBy, category_id }: PaginationParams, req: Request) => {
20
     const skip = (page - 1) * limit;
23
     const skip = (page - 1) * limit;
24
+
25
+    const where: Prisma.VendorExperienceWhereInput = {
26
+        hospital_id: req.params.id,
27
+        // ...SearchFilter(search, ['id', 'name', 'province.id']),
28
+        ...(category_id ? { category_id: category_id } : {}),
29
+        deletedAt: null,
30
+    };
31
+
21
     const hospitalId = req.params.id;
32
     const hospitalId = req.params.id;
22
 
33
 
23
     const hospital = await prisma.hospital.findFirst({ where: { id: hospitalId } });
34
     const hospital = await prisma.hospital.findFirst({ where: { id: hospitalId } });
24
     if (!hospital) throw new HttpException('Hospital not found', 404);
35
     if (!hospital) throw new HttpException('Hospital not found', 404);
25
 
36
 
26
-    const where: any = {
27
-        hospital_id: req.params.id,
28
-        deletedAt: null
29
-    };
30
-
31
     const [vendor_experiences, total] = await Promise.all([
37
     const [vendor_experiences, total] = await Promise.all([
32
         VendorExperienceRepository.findAll({ skip, take: limit, where, orderBy: { [sortBy]: orderBy } }),
38
         VendorExperienceRepository.findAll({ skip, take: limit, where, orderBy: { [sortBy]: orderBy } }),
33
         VendorExperienceRepository.countAll(where)
39
         VendorExperienceRepository.countAll(where)
@@ -51,6 +57,7 @@ export const showVendorExperienceService = async (req: Request) => {
51
 
57
 
52
 export const storeVendorExperienceService = async (validateData: VendorExperienceRequestDTO, req: CustomRequest) => {
58
 export const storeVendorExperienceService = async (validateData: VendorExperienceRequestDTO, req: CustomRequest) => {
53
     const hospitalId = req.params.id;
59
     const hospitalId = req.params.id;
60
+    const userId = req.tokenData.sub;
54
 
61
 
55
     const hospital = await prisma.hospital.findFirst({ where: { id: hospitalId } });
62
     const hospital = await prisma.hospital.findFirst({ where: { id: hospitalId } });
56
     if (!hospital) throw new HttpException('Hospital not found', 404);
63
     if (!hospital) throw new HttpException('Hospital not found', 404);
@@ -60,92 +67,99 @@ export const storeVendorExperienceService = async (validateData: VendorExperienc
60
         if (!vendor) throw new HttpException('Vendor not found', 404);
67
         if (!vendor) throw new HttpException('Vendor not found', 404);
61
     }
68
     }
62
 
69
 
63
-    const SimrsType = ['vendor', 'in house', 'gratis'];
64
-    if (validateData.simrs_type && !SimrsType.includes(validateData.simrs_type)) {
65
-        throw new HttpException('Simrs type must be vendor, in house, or gratis', 400);
70
+    if (validateData.category_id) {
71
+        const category = await prisma.category.findFirst({ where: { id: validateData.category_id } });
72
+        if (!category) throw new HttpException('Category not found', 404);
66
     }
73
     }
67
 
74
 
68
-    if (validateData.contract_start_date && validateData.contract_expired_date) {
69
-        if (validateData.contract_start_date >= validateData.contract_expired_date) {
70
-            throw new HttpException('Contract expired date must be after contract date', 400);
71
-        }
72
-    }
73
-
74
-    if (validateData.contract_value_min && validateData.contract_value_max) {
75
-        if (validateData.contract_value_min >= validateData.contract_value_max) {
76
-            throw new HttpException('Contract value max must be after contract value min', 400);
77
-        }
78
-    }
79
-
80
-    if (validateData.simrs_type) {
81
-        const existingActiveVendors = await prisma.vendorExperience.findMany({
82
-            where: {
83
-                hospital_id: hospitalId,
84
-                status: 'active',
85
-                deletedAt: null
86
-            }
87
-        });
88
-
89
-        if (existingActiveVendors.length > 0) {
90
-            await prisma.vendorExperience.updateMany({
91
-                where: {
92
-                    hospital_id: hospitalId,
93
-                    status: 'active',
94
-                    deletedAt: null
95
-                },
96
-                data: {
97
-                    status: 'inactive'
98
-                }
99
-            });
100
-        }
101
-
102
-        validateData.status = 'active';
103
-    }
75
+    // const SimrsType = ['vendor', 'in house', 'gratis'];
76
+    // if (validateData.simrs_type && !SimrsType.includes(validateData.simrs_type)) {
77
+    //     throw new HttpException('Simrs type must be vendor, in house, or gratis', 400);
78
+    // }
79
+
80
+    // if (validateData.contract_start_date && validateData.contract_expired_date) {
81
+    //     if (validateData.contract_start_date >= validateData.contract_expired_date) {
82
+    //         throw new HttpException('Contract expired date must be after contract date', 400);
83
+    //     }
84
+    // }
85
+
86
+    // if (validateData.contract_value_min && validateData.contract_value_max) {
87
+    //     if (validateData.contract_value_min >= validateData.contract_value_max) {
88
+    //         throw new HttpException('Contract value max must be after contract value min', 400);
89
+    //     }
90
+    // }
91
+
92
+    // if (validateData.simrs_type) {
93
+    //     const existingActiveVendors = await prisma.vendorExperience.findMany({
94
+    //         where: {
95
+    //             hospital_id: hospitalId,
96
+    //             status: 'active',
97
+    //             deletedAt: null
98
+    //         }
99
+    //     });
100
+
101
+    //     if (existingActiveVendors.length > 0) {
102
+    //         await prisma.vendorExperience.updateMany({
103
+    //             where: {
104
+    //                 hospital_id: hospitalId,
105
+    //                 status: 'active',
106
+    //                 deletedAt: null
107
+    //             },
108
+    //             data: {
109
+    //                 status: 'inactive'
110
+    //             }
111
+    //         });
112
+    //     }
113
+
114
+    //     validateData.status = 'active';
115
+    // }
104
 
116
 
105
     const payload = {
117
     const payload = {
106
-        ...(validateData.vendor_id && {
107
-            vendor: {
108
-                connect: { id: validateData.vendor_id }
109
-            }
110
-        }),
111
-        simrs_type: validateData.simrs_type,
112
-        status: validateData.status,
113
-        contract_start_date: validateData.contract_start_date ? new Date(validateData.contract_start_date) : null,
114
-        contract_expired_date: validateData.contract_expired_date ? new Date(validateData.contract_expired_date) : null,
115
-        contract_value_min: validateData.contract_value_min ? Number(validateData.contract_value_min) : null,
116
-        contract_value_max: validateData.contract_value_max ? Number(validateData.contract_value_max) : null,
117
-        positive_notes: validateData.positive_notes?.note,
118
-        negative_notes: validateData.negative_notes?.note,
119
-        hospital: {
120
-            connect: { id: hospitalId }
121
-        },
118
+        content: validateData.content,
119
+        vendor: validateData.vendor_id
120
+            ? { connect: { id: validateData.vendor_id } }
121
+            : undefined,
122
+        category: validateData.category_id
123
+            ? { connect: { id: validateData.category_id } }
124
+            : undefined,
125
+        hospital: { connect: { id: hospitalId } },
126
+        user: { connect: { id: userId } },
127
+        // simrs_type: validateData.simrs_type,
128
+        // status: validateData.status,
129
+        // contract_start_date: validateData.contract_start_date ? new Date(validateData.contract_start_date) : null,
130
+        // contract_expired_date: validateData.contract_expired_date ? new Date(validateData.contract_expired_date) : null,
131
+        // contract_value_min: validateData.contract_value_min ? Number(validateData.contract_value_min) : null,
132
+        // contract_value_max: validateData.contract_value_max ? Number(validateData.contract_value_max) : null,
133
+        // positive_notes: validateData.positive_notes?.note,
134
+        // negative_notes: validateData.negative_notes?.note,
122
     };
135
     };
123
 
136
 
124
     const data = await VendorExperienceRepository.create(payload);
137
     const data = await VendorExperienceRepository.create(payload);
125
 
138
 
126
     // Setelah data berhasil disimpan
139
     // Setelah data berhasil disimpan
127
-    if (validateData.positive_notes?.tags?.length) {
128
-        await storeCategoryLinkService(
129
-            validateData.positive_notes.tags,
130
-            'vendor_experience_positive_notes',
131
-            data.id,
132
-            req
133
-        );
134
-    }
135
-
136
-    if (validateData.negative_notes?.tags?.length) {
137
-        await storeCategoryLinkService(
138
-            validateData.negative_notes.tags,
139
-            'vendor_experience_negative_notes',
140
-            data.id,
141
-            req
142
-        );
143
-    }
140
+    // if (validateData.positive_notes?.tags?.length) {
141
+    //     await storeCategoryLinkService(
142
+    //         validateData.positive_notes.tags,
143
+    //         'vendor_experience_positive_notes',
144
+    //         data.id,
145
+    //         req
146
+    //     );
147
+    // }
148
+
149
+    // if (validateData.negative_notes?.tags?.length) {
150
+    //     await storeCategoryLinkService(
151
+    //         validateData.negative_notes.tags,
152
+    //         'vendor_experience_negative_notes',
153
+    //         data.id,
154
+    //         req
155
+    //     );
156
+    // }
144
     await createLog(req, data);
157
     await createLog(req, data);
145
 };
158
 };
146
 
159
 
147
 export const updateVendorExperienceService = async (validateData: Partial<VendorExperienceRequestDTO>, req: CustomRequest) => {
160
 export const updateVendorExperienceService = async (validateData: Partial<VendorExperienceRequestDTO>, req: CustomRequest) => {
148
     const id_hospital = req.params.id;
161
     const id_hospital = req.params.id;
162
+    const id_user = req.tokenData.sub;
149
     const id_vendor_experience = req.params.id_vendor_experience;
163
     const id_vendor_experience = req.params.id_vendor_experience;
150
 
164
 
151
     const hospital = await prisma.hospital.findFirst({ where: { id: id_hospital } });
165
     const hospital = await prisma.hospital.findFirst({ where: { id: id_hospital } });
@@ -159,116 +173,135 @@ export const updateVendorExperienceService = async (validateData: Partial<Vendor
159
         if (!existVendor) throw new HttpException('Vendor not found', 404);
173
         if (!existVendor) throw new HttpException('Vendor not found', 404);
160
     }
174
     }
161
 
175
 
162
-    const SimrsType = ['vendor', 'in house', 'gratis'];
163
-    if (validateData.simrs_type && !SimrsType.includes(validateData.simrs_type)) {
164
-        throw new HttpException('Simrs type must be vendor, in house, or gratis', 400);
165
-    }
166
-
167
-    if (
168
-        validateData.simrs_type &&
169
-        vendorHistory.simrs_type === 'vendor' &&
170
-        vendorHistory.vendor_id !== null &&
171
-        validateData.simrs_type !== 'vendor'
172
-    ) {
173
-        await prisma.vendorExperience.update({
174
-            where: {
175
-                id: id_vendor_experience,
176
-                deletedAt: null
177
-            },
178
-            data: {
179
-                vendor_id: null
180
-            }
181
-        });
182
-    }
183
-
184
-    if (
185
-        validateData.contract_value_min &&
186
-        validateData.contract_value_min >= vendorHistory.contract_value_max!
187
-    ) {
188
-        throw new HttpException('Contract value min must be less than contract value max.', 400);
189
-    }
190
-
191
-    if (
192
-        validateData.contract_value_max &&
193
-        validateData.contract_value_max <= vendorHistory.contract_value_min!
194
-    ) {
195
-        throw new HttpException('Contract value max must be greater than contract value min.', 400);
196
-    }
197
-
198
-    if (
199
-        validateData.contract_start_date &&
200
-        validateData.contract_start_date >= vendorHistory.contract_expired_date!
201
-    ) {
202
-        throw new HttpException('Contract start date must be before contract expired date.', 400);
176
+    if (validateData.category_id) {
177
+        const existCategory = await prisma.category.findFirst({ where: { id: validateData.category_id } });
178
+        if (!existCategory) throw new HttpException('Category not found', 404);
203
     }
179
     }
204
 
180
 
205
-    if (
206
-        validateData.contract_expired_date &&
207
-        validateData.contract_expired_date <= vendorHistory.contract_start_date!
208
-    ) {
209
-        throw new HttpException('Contract expired date must be after contract start date.', 400);
210
-    }
211
-
212
-    if (validateData.contract_start_date && validateData.contract_expired_date) {
213
-        if (validateData.contract_start_date >= validateData.contract_expired_date) {
214
-            throw new HttpException('Contract expired date must be after contract date', 400);
215
-        }
216
-    }
217
-
218
-    if (validateData.contract_value_min && validateData.contract_value_max) {
219
-        if (validateData.contract_value_min >= validateData.contract_value_max) {
220
-            throw new HttpException('Contract value max must be after contract value min', 400);
221
-        }
222
-    }
223
-
224
-    if (validateData.status === 'active') {
225
-        await prisma.vendorExperience.updateMany({
226
-            where: {
227
-                hospital_id: id_hospital,
228
-                status: 'active',
229
-                deletedAt: null,
230
-                NOT: { id: id_vendor_experience }
231
-            },
232
-            data: {
233
-                status: 'inactive'
234
-            }
235
-        });
236
-    }
181
+    // if (validateData.user_id) {
182
+    //     const existUser = await prisma.userKeycloak.findFirst({ where: { id: validateData.user_id } });
183
+    //     if (!existUser) throw new HttpException('User not found', 404);
184
+    // }
185
+
186
+    // const SimrsType = ['vendor', 'in house', 'gratis'];
187
+    // if (validateData.simrs_type && !SimrsType.includes(validateData.simrs_type)) {
188
+    //     throw new HttpException('Simrs type must be vendor, in house, or gratis', 400);
189
+    // }
190
+
191
+    // if (
192
+    //     validateData.simrs_type &&
193
+    //     vendorHistory.simrs_type === 'vendor' &&
194
+    //     vendorHistory.vendor_id !== null &&
195
+    //     validateData.simrs_type !== 'vendor'
196
+    // ) {
197
+    //     await prisma.vendorExperience.update({
198
+    //         where: {
199
+    //             id: id_vendor_experience,
200
+    //             deletedAt: null
201
+    //         },
202
+    //         data: {
203
+    //             vendor_id: null
204
+    //         }
205
+    //     });
206
+    // }
207
+
208
+    // if (
209
+    //     validateData.contract_value_min &&
210
+    //     validateData.contract_value_min >= vendorHistory.contract_value_max!
211
+    // ) {
212
+    //     throw new HttpException('Contract value min must be less than contract value max.', 400);
213
+    // }
214
+
215
+    // if (
216
+    //     validateData.contract_value_max &&
217
+    //     validateData.contract_value_max <= vendorHistory.contract_value_min!
218
+    // ) {
219
+    //     throw new HttpException('Contract value max must be greater than contract value min.', 400);
220
+    // }
221
+
222
+    // if (
223
+    //     validateData.contract_start_date &&
224
+    //     validateData.contract_start_date >= vendorHistory.contract_expired_date!
225
+    // ) {
226
+    //     throw new HttpException('Contract start date must be before contract expired date.', 400);
227
+    // }
228
+
229
+    // if (
230
+    //     validateData.contract_expired_date &&
231
+    //     validateData.contract_expired_date <= vendorHistory.contract_start_date!
232
+    // ) {
233
+    //     throw new HttpException('Contract expired date must be after contract start date.', 400);
234
+    // }
235
+
236
+    // if (validateData.contract_start_date && validateData.contract_expired_date) {
237
+    //     if (validateData.contract_start_date >= validateData.contract_expired_date) {
238
+    //         throw new HttpException('Contract expired date must be after contract date', 400);
239
+    //     }
240
+    // }
241
+
242
+    // if (validateData.contract_value_min && validateData.contract_value_max) {
243
+    //     if (validateData.contract_value_min >= validateData.contract_value_max) {
244
+    //         throw new HttpException('Contract value max must be after contract value min', 400);
245
+    //     }
246
+    // }
247
+
248
+    // if (validateData.status === 'active') {
249
+    //     await prisma.vendorExperience.updateMany({
250
+    //         where: {
251
+    //             hospital_id: id_hospital,
252
+    //             status: 'active',
253
+    //             deletedAt: null,
254
+    //             NOT: { id: id_vendor_experience }
255
+    //         },
256
+    //         data: {
257
+    //             status: 'inactive'
258
+    //         }
259
+    //     });
260
+    // }
237
 
261
 
238
     const payload = {
262
     const payload = {
239
-        status: validateData.status,
240
-        contract_start_date: validateData.contract_start_date ? new Date(validateData.contract_start_date) : vendorHistory.contract_start_date,
241
-        contract_expired_date: validateData.contract_expired_date ? new Date(validateData.contract_expired_date) : vendorHistory.contract_expired_date,
242
-        contract_value_min: validateData.contract_value_min ? Number(validateData.contract_value_min) : vendorHistory.contract_value_min,
243
-        contract_value_max: validateData.contract_value_max ? Number(validateData.contract_value_max) : vendorHistory.contract_value_max,
244
-        positive_notes: validateData.positive_notes?.note || vendorHistory.positive_notes,
245
-        negative_notes: validateData.negative_notes?.note || vendorHistory.negative_notes,
246
-        simrs_type: validateData.simrs_type,
247
-        vendor_id: validateData.vendor_id
263
+        content: validateData.content,
264
+        vendor: validateData.vendor_id
265
+            ? { connect: { id: validateData.vendor_id } }
266
+            : undefined,
267
+        category: validateData.category_id
268
+            ? { connect: { id: validateData.category_id } }
269
+            : undefined,
270
+        user: {
271
+            connect: { id: id_user }
272
+        },
273
+
274
+        // contract_start_date: validateData.contract_start_date ? new Date(validateData.contract_start_date) : vendorHistory.contract_start_date,
275
+        // contract_expired_date: validateData.contract_expired_date ? new Date(validateData.contract_expired_date) : vendorHistory.contract_expired_date,
276
+        // contract_value_min: validateData.contract_value_min ? Number(validateData.contract_value_min) : vendorHistory.contract_value_min,
277
+        // contract_value_max: validateData.contract_value_max ? Number(validateData.contract_value_max) : vendorHistory.contract_value_max,
278
+        // positive_notes: validateData.positive_notes?.note || vendorHistory.positive_notes,
279
+        // negative_notes: validateData.negative_notes?.note || vendorHistory.negative_notes,
280
+        // simrs_type: validateData.simrs_type,
248
     };
281
     };
249
 
282
 
250
     const data = await VendorExperienceRepository.update(id_vendor_experience, payload);
283
     const data = await VendorExperienceRepository.update(id_vendor_experience, payload);
251
     await updateLog(req, data);
284
     await updateLog(req, data);
252
 
285
 
253
     // Positive Notes Tags
286
     // Positive Notes Tags
254
-    if (validateData.positive_notes?.tags?.length) {
255
-        await updateCategoryLinkService(
256
-            validateData.positive_notes.tags,
257
-            'vendor_experience_positive_notes',
258
-            id_vendor_experience,
259
-            req
260
-        );
261
-    }
262
-
263
-    // Negative Notes Tags
264
-    if (validateData.negative_notes?.tags?.length) {
265
-        await updateCategoryLinkService(
266
-            validateData.negative_notes.tags,
267
-            'vendor_experience_negative_notes',
268
-            id_vendor_experience,
269
-            req
270
-        );
271
-    }
287
+    // if (validateData.positive_notes?.tags?.length) {
288
+    //     await updateCategoryLinkService(
289
+    //         validateData.positive_notes.tags,
290
+    //         'vendor_experience_positive_notes',
291
+    //         id_vendor_experience,
292
+    //         req
293
+    //     );
294
+    // }
295
+
296
+    // // Negative Notes Tags
297
+    // if (validateData.negative_notes?.tags?.length) {
298
+    //     await updateCategoryLinkService(
299
+    //         validateData.negative_notes.tags,
300
+    //         'vendor_experience_negative_notes',
301
+    //         id_vendor_experience,
302
+    //         req
303
+    //     );
304
+    // }
272
 };
305
 };
273
 
306
 
274
 export const deleteVendorExperienceService = async (req: CustomRequest) => {
307
 export const deleteVendorExperienceService = async (req: CustomRequest) => {
@@ -286,269 +319,4 @@ export const deleteVendorExperienceService = async (req: CustomRequest) => {
286
     });
319
     });
287
 
320
 
288
     await deleteLog(req, data);
321
     await deleteLog(req, data);
289
-};
290
-
291
-// const HttpException = require('../../utils/HttpException.js');
292
-// const prisma = require('../../prisma/PrismaClient.js');
293
-// const { SearchFilter } = require('../../utils/SearchFilter.js');
294
-// const timeLocal = require('../../utils/TimeLocal.js');
295
-// const { createLog, updateLog, deleteLog } = require('../../utils/LogActivity.js');
296
-// const { formatDateOnly, formatISOWithoutTimezone } = require('../../utils/FormatDate.js');
297
-// const VendorExperienceRepository = require('../../repository/admin/VendorExperienceRepository.js');
298
-
299
-// exports.getAllVendorHistoryService = async ({ page, limit, search, sortBy, orderBy }, req) => {
300
-//     const skip = (page - 1) * limit;
301
-
302
-//     const hospitalId = req.params.id;
303
-//     const hospital = await prisma.hospital.findFirst({
304
-//         where: {
305
-//             id: hospitalId
306
-//         }
307
-//     })
308
-//     if (!hospital) {
309
-//         throw new HttpException("Hospital not found", 404)
310
-//     }
311
-
312
-//     const where = {
313
-//         // ...SearchFilter(search, ['name', 'name_pt']),
314
-//         hospital_id: req.params.id,
315
-//         deletedAt: null
316
-//     };
317
-
318
-//     const [vendor_histories, total] = await Promise.all([
319
-//         VendorExperienceRepository.findAll({ skip, take: limit, where, orderBy: { [sortBy]: orderBy } }),
320
-//         VendorExperienceRepository.countAll(where)
321
-//     ]);
322
-
323
-//     return { vendor_histories, total };
324
-// };
325
-
326
-// exports.showVendorHistoryService = async (req) => {
327
-//     const id_hospital = req.params.id;
328
-//     const id_vendor_experience = req.params.id_vendor_experience;
329
-
330
-//     const hospital = await prisma.hospital.findFirst({
331
-//         where: {
332
-//             id: id_hospital
333
-//         }
334
-//     })
335
-//     if (!hospital) {
336
-//         throw new HttpException("Hospital not found", 404)
337
-//     }
338
-
339
-//     const vendorHistory = await VendorExperienceRepository.findById(id_vendor_experience);
340
-//     if (!vendorHistory) {
341
-//         throw new HttpException("Vendor experience not found", 404);
342
-//     }
343
-
344
-//     return vendorHistory;
345
-// };
346
-
347
-// exports.storeVendorHistoryService = async (validateData, req) => {
348
-//     const hospitalId = req.params.id;
349
-
350
-//     const hospital = await prisma.hospital.findFirst({
351
-//         where: {
352
-//             id: hospitalId
353
-//         }
354
-//     });
355
-
356
-//     if (!hospital) {
357
-//         throw new HttpException("Hospital not found", 404)
358
-//     }
359
-
360
-//     if (validateData.vendor_id) {
361
-//         const vendor = await prisma.vendor.findFirst({
362
-//             where: {
363
-//                 id: validateData.vendor_id
364
-//             }
365
-//         });
366
-
367
-//         if (!vendor) {
368
-//             throw new HttpException("Vendor not found", 404)
369
-//         }
370
-//     }
371
-
372
-//     const SimrsType = ["vendor", "in house", "gratis"];
373
-//     if (validateData.simrs_type && !SimrsType.includes(validateData.simrs_type)) {
374
-//         throw new HttpException("Simrs type must be vendor, in house, or gratis", 400);
375
-//     }
376
-
377
-//     if (validateData.contract_start_date && validateData.contract_expired_date) {
378
-//         if (validateData.contract_start_date >= validateData.contract_expired_date) {
379
-//             throw new HttpException("Contract expired date must be after contract date", 400)
380
-//         }
381
-//     }
382
-
383
-//     if (validateData.contract_value_min && validateData.contract_value_max) {
384
-//         if (validateData.contract_value_min >= validateData.contract_value_max) {
385
-//             throw new HttpException("Contract value max must be after contract value min", 400)
386
-//         }
387
-//     }
388
-
389
-//     // await prisma.hospital.update({
390
-//     //     where: { id: hospitalId },
391
-//     //     data: {
392
-//     //         simrs_type: validateData.simrs_type
393
-//     //     }
394
-//     // });
395
-
396
-//     if (validateData.simrs_type) {
397
-//         const existingActiveVendors = await prisma.vendorExperience.findMany({
398
-//             where: {
399
-//                 hospital_id: hospitalId,
400
-//                 status: "active",
401
-//                 deletedAt: null
402
-//             }
403
-//         });
404
-
405
-//         if (existingActiveVendors.length > 0) {
406
-//             await prisma.vendorExperience.updateMany({
407
-//                 where: {
408
-//                     hospital_id: hospitalId,
409
-//                     status: "active",
410
-//                     deletedAt: null
411
-//                 },
412
-//                 data: {
413
-//                     status: "inactive"
414
-//                 }
415
-//             });
416
-//         }
417
-
418
-//         validateData.status = "active";
419
-//     }
420
-
421
-//     const payload = {
422
-//         vendor_id: validateData.vendor_id,
423
-//         simrs_type: validateData.simrs_type,
424
-//         status: validateData.status,
425
-//         contract_start_date: validateData.contract_start_date ? new Date(validateData.contract_start_date) : null,
426
-//         contract_expired_date: validateData.contract_expired_date ? new Date(validateData.contract_expired_date) : null,
427
-//         contract_value_min: validateData.contract_value_min ? Number(validateData.contract_value_min) : null,
428
-//         contract_value_max: validateData.contract_value_max ? Number(validateData.contract_value_max) : null,
429
-//         positive_notes: validateData.positive_notes,
430
-//         negative_notes: validateData.negative_notes,
431
-//         hospital_id: hospitalId
432
-//     };
433
-
434
-//     const data = await VendorExperienceRepository.create(payload);
435
-//     await createLog(req, data);
436
-// };
437
-
438
-// exports.updateVendorHistoryService = async (validateData, req) => {
439
-//     const id_hospital = req.params.id;
440
-//     const id_vendor_experience = req.params.id_vendor_experience;
441
-
442
-//     const hospital = await prisma.hospital.findFirst({
443
-//         where: {
444
-//             id: id_hospital
445
-//         }
446
-//     })
447
-//     if (!hospital) {
448
-//         throw new HttpException("Hospital not found", 404)
449
-//     }
450
-
451
-//     const vendorHistory = await VendorExperienceRepository.findById(id_vendor_experience);
452
-//     if (!vendorHistory) {
453
-//         throw new HttpException("Vendor experience not found", 404);
454
-//     }
455
-
456
-//     if (validateData.vendor_id) {
457
-//         const existVendor = await prisma.vendor.findFirst({
458
-//             where: {
459
-//                 id: validateData.vendor_id
460
-//             }
461
-//         });
462
-//         if (!existVendor) {
463
-//             throw new HttpException("Vendor not found", 404)
464
-//         }
465
-//     }
466
-
467
-//     const SimrsType = ["vendor", "in house", "gratis"];
468
-//     if (validateData.simrs_type && !SimrsType.includes(validateData.simrs_type)) {
469
-//         throw new HttpException("Simrs type must be vendor, in house, or gratis", 400);
470
-//     }
471
-
472
-//     if (
473
-//         validateData.simrs_type &&
474
-//         vendorHistory.simrs_type === "vendor" &&
475
-//         vendorHistory.vendor_id !== null &&
476
-//         validateData.simrs_type !== "vendor"
477
-//     ) {
478
-//         await prisma.vendorExperience.update({
479
-//             where: {
480
-//                 id: id_vendor_experience,
481
-//                 deletedAt: null
482
-//             },
483
-//             data: {
484
-//                 vendor_id: null
485
-//             }
486
-//         });
487
-//     }
488
-
489
-//     if (validateData.contract_start_date && validateData.contract_expired_date) {
490
-//         if (validateData.contract_start_date >= validateData.contract_expired_date) {
491
-//             throw new HttpException("Contract expired date must be after contract date", 400)
492
-//         }
493
-//     }
494
-
495
-//     if (validateData.contract_value_min && validateData.contract_value_max) {
496
-//         if (validateData.contract_value_min >= validateData.contract_value_max) {
497
-//             throw new HttpException("Contract value max must be after contract value min", 400)
498
-//         }
499
-//     }
500
-
501
-//     if (validateData.status === "active") {
502
-//         await prisma.vendorExperience.updateMany({
503
-//             where: {
504
-//                 hospital_id: id_hospital,
505
-//                 status: "active",
506
-//                 deletedAt: null,
507
-//                 NOT: { id: id_vendor_experience },
508
-//             },
509
-//             data: {
510
-//                 status: "inactive",
511
-//             },
512
-//         });
513
-//     }
514
-
515
-//     const payload = {
516
-//         status: validateData.status,
517
-//         contract_start_date: validateData.contract_start_date ? new Date(validateData.contract_start_date) : vendorHistory.contract_start_date,
518
-//         contract_expired_date: validateData.contract_expired_date ? new Date(validateData.contract_expired_date) : vendorHistory.contract_expired_date,
519
-//         contract_value_min: validateData.contract_value_min ? Number(validateData.contract_value_min) : vendorHistory.contract_value_min,
520
-//         contract_value_max: validateData.contract_value_max ? Number(validateData.contract_value_max) : vendorHistory.contract_value_max,
521
-//         positive_notes: validateData.positive_notes,
522
-//         negative_notes: validateData.negative_notes,
523
-//         simrs_type: validateData.simrs_type,
524
-//         vendor_id: validateData.vendor_id,
525
-//     };
526
-
527
-//     const data = await VendorExperienceRepository.update(id_vendor_experience, payload);
528
-//     await updateLog(req, data);
529
-// };
530
-
531
-// exports.deleteVendorHistoryService = async (req) => {
532
-//     const id_hospital = req.params.id;
533
-//     const id_vendor_experience = req.params.id_vendor_experience;
534
-
535
-//     const hospital = await prisma.hospital.findFirst({
536
-//         where: {
537
-//             id: id_hospital
538
-//         }
539
-//     })
540
-//     if (!hospital) {
541
-//         throw new HttpException("Hospital not found", 404)
542
-//     }
543
-
544
-//     const vendor = await VendorExperienceRepository.findById(id_vendor_experience);
545
-//     if (!vendor) {
546
-//         throw new HttpException("Vendor experience not found", 404);
547
-//     }
548
-
549
-//     const data = await VendorExperienceRepository.update(id_vendor_experience, {
550
-//         deletedAt: timeLocal.now().toDate()
551
-//     });
552
-
553
-//     await deleteLog(req, data);
554
-// };
322
+};

+ 41 - 42
src/services/admin/VendorService.ts

@@ -8,7 +8,7 @@ import { Prisma } from '@prisma/client';
8
 import { VendorRequestDTO } from '../../types/admin/vendor/VendorDTO';
8
 import { VendorRequestDTO } from '../../types/admin/vendor/VendorDTO';
9
 import { CustomRequest } from '../../types/token/CustomRequest';
9
 import { CustomRequest } from '../../types/token/CustomRequest';
10
 import * as XLSX from "xlsx";
10
 import * as XLSX from "xlsx";
11
-import { storeCategoryLinkService, updateCategoryLinkService } from './CategoryLinkService';
11
+// import { storeCategoryLinkService, updateCategoryLinkService } from './CategoryLinkService';
12
 import { validateStoreVendorRequest } from '../../validators/admin/vendor/VendorValidators';
12
 import { validateStoreVendorRequest } from '../../validators/admin/vendor/VendorValidators';
13
 
13
 
14
 interface PaginationParams {
14
 interface PaginationParams {
@@ -79,23 +79,23 @@ export const storeVendorService = async (validateData: VendorRequestDTO, req: Cu
79
     const data = await VendorRepository.create(payload);
79
     const data = await VendorRepository.create(payload);
80
     await createLog(req, data);
80
     await createLog(req, data);
81
     // Setelah data berhasil disimpan
81
     // Setelah data berhasil disimpan
82
-    if (validateData.strengths?.tags?.length) {
83
-        await storeCategoryLinkService(
84
-            validateData.strengths.tags,
85
-            'vendor_strength_notes',
86
-            data.id,
87
-            req
88
-        );
89
-    }
90
-
91
-    if (validateData.weaknesses?.tags?.length) {
92
-        await storeCategoryLinkService(
93
-            validateData.weaknesses.tags,
94
-            'vendor_weaknesses_notes',
95
-            data.id,
96
-            req
97
-        );
98
-    }
82
+    // if (validateData.strengths?.tags?.length) {
83
+    //     await storeCategoryLinkService(
84
+    //         validateData.strengths.tags,
85
+    //         'vendor_strength_notes',
86
+    //         data.id,
87
+    //         req
88
+    //     );
89
+    // }
90
+
91
+    // if (validateData.weaknesses?.tags?.length) {
92
+    //     await storeCategoryLinkService(
93
+    //         validateData.weaknesses.tags,
94
+    //         'vendor_weaknesses_notes',
95
+    //         data.id,
96
+    //         req
97
+    //     );
98
+    // }
99
     await createLog(req, data);
99
     await createLog(req, data);
100
 };
100
 };
101
 
101
 
@@ -129,24 +129,23 @@ export const updateVendorService = async (validateData: Partial<VendorRequestDTO
129
     const data = await VendorRepository.update(id_vendor, payload);
129
     const data = await VendorRepository.update(id_vendor, payload);
130
     await updateLog(req, data);
130
     await updateLog(req, data);
131
 
131
 
132
-
133
-    if (validateData.strengths?.tags?.length) {
134
-        await updateCategoryLinkService(
135
-            validateData.strengths.tags,
136
-            'vendor_strength_notes',
137
-            id_vendor,
138
-            req
139
-        );
140
-    }
141
-
142
-    if (validateData.weaknesses?.tags?.length) {
143
-        await updateCategoryLinkService(
144
-            validateData.weaknesses.tags,
145
-            'vendor_weaknesses_notes',
146
-            id_vendor,
147
-            req
148
-        );
149
-    }
132
+    // if (validateData.strengths?.tags?.length) {
133
+    //     await updateCategoryLinkService(
134
+    //         validateData.strengths.tags,
135
+    //         'vendor_strength_notes',
136
+    //         id_vendor,
137
+    //         req
138
+    //     );
139
+    // }
140
+
141
+    // if (validateData.weaknesses?.tags?.length) {
142
+    //     await updateCategoryLinkService(
143
+    //         validateData.weaknesses.tags,
144
+    //         'vendor_weaknesses_notes',
145
+    //         id_vendor,
146
+    //         req
147
+    //     );
148
+    // }
150
 };
149
 };
151
 
150
 
152
 export const deleteVendorService = async (id: string, req: CustomRequest) => {
151
 export const deleteVendorService = async (id: string, req: CustomRequest) => {
@@ -188,12 +187,12 @@ export const importVendorService = async (file: Express.Multer.File, req: Custom
188
         const data = await VendorRepository.create(payload);
187
         const data = await VendorRepository.create(payload);
189
 
188
 
190
         // category links
189
         // category links
191
-        if (validatedData.strengths?.tags?.length) {
192
-            await storeCategoryLinkService(validatedData.strengths.tags, "vendor_strength_notes", data.id, req);
193
-        }
194
-        if (validatedData.weaknesses?.tags?.length) {
195
-            await storeCategoryLinkService(validatedData.weaknesses.tags, "vendor_weaknesses_notes", data.id, req);
196
-        }
190
+        // if (validatedData.strengths?.tags?.length) {
191
+        //     await storeCategoryLinkService(validatedData.strengths.tags, "vendor_strength_notes", data.id, req);
192
+        // }
193
+        // if (validatedData.weaknesses?.tags?.length) {
194
+        //     await storeCategoryLinkService(validatedData.weaknesses.tags, "vendor_weaknesses_notes", data.id, req);
195
+        // }
197
 
196
 
198
         await createLog(req, data);
197
         await createLog(req, data);
199
     }
198
     }

+ 17 - 17
src/services/sales/HospitalService.ts

@@ -11,7 +11,7 @@ import { HospitalRequestDTO } from '../../types/sales/hospital/HospitalDTO';
11
 import path from 'path';
11
 import path from 'path';
12
 import fs from 'fs/promises';
12
 import fs from 'fs/promises';
13
 import sharp from 'sharp';
13
 import sharp from 'sharp';
14
-import { storeCategoryLinkService, updateCategoryLinkService } from '../admin/CategoryLinkService';
14
+// import { storeCategoryLinkService, updateCategoryLinkService } from '../admin/CategoryLinkService';
15
 
15
 
16
 const prisma = new PrismaClient();
16
 const prisma = new PrismaClient();
17
 
17
 
@@ -150,14 +150,14 @@ export const storeHospitalService = async (validateData: HospitalRequestDTO, req
150
     };
150
     };
151
 
151
 
152
     const data = await salesHospitalRepository.create(payload);
152
     const data = await salesHospitalRepository.create(payload);
153
-    if (validateData.tags?.length) {
154
-        await storeCategoryLinkService(
155
-            validateData.tags,
156
-            'hospital_notes',
157
-            data.id,
158
-            req
159
-        );
160
-    }
153
+    // if (validateData.tags?.length) {
154
+    //     await storeCategoryLinkService(
155
+    //         validateData.tags,
156
+    //         'hospital_notes',
157
+    //         data.id,
158
+    //         req
159
+    //     );
160
+    // }
161
     await createLog(req, data);
161
     await createLog(req, data);
162
 };
162
 };
163
 
163
 
@@ -295,14 +295,14 @@ export const updateHospitalService = async (validateData: Partial<HospitalReques
295
     };
295
     };
296
 
296
 
297
     const data = await salesHospitalRepository.update(id, payload);
297
     const data = await salesHospitalRepository.update(id, payload);
298
-    if (validateData.tags?.length) {
299
-        await updateCategoryLinkService(
300
-            validateData.tags,
301
-            'hospital_notes',
302
-            id,
303
-            req
304
-        );
305
-    }
298
+    // if (validateData.tags?.length) {
299
+    //     await updateCategoryLinkService(
300
+    //         validateData.tags,
301
+    //         'hospital_notes',
302
+    //         id,
303
+    //         req
304
+    //     );
305
+    // }
306
     await updateLog(req, data);
306
     await updateLog(req, data);
307
 };
307
 };
308
 
308
 

+ 9 - 9
src/services/sales/StatusHistoryService.ts

@@ -4,7 +4,7 @@ import { createLog } from '../../utils/LogActivity';
4
 import StatusHistoryRepository from '../../repository/sales/StatusHistoryRepository';
4
 import StatusHistoryRepository from '../../repository/sales/StatusHistoryRepository';
5
 import { CustomRequest } from '../../types/token/CustomRequest';
5
 import { CustomRequest } from '../../types/token/CustomRequest';
6
 import { StatusHistoryRequestDTO } from '../../types/sales/status_history/StatusHistoryDTO';
6
 import { StatusHistoryRequestDTO } from '../../types/sales/status_history/StatusHistoryDTO';
7
-import { storeCategoryLinkService } from '../admin/CategoryLinkService';
7
+// import { storeCategoryLinkService } from '../admin/CategoryLinkService';
8
 
8
 
9
 const prisma = new PrismaClient();
9
 const prisma = new PrismaClient();
10
 
10
 
@@ -126,14 +126,14 @@ export const storeStatusHistoryService = async (validateData: StatusHistoryReque
126
         data: { progress_status: validateData.new_status as ProgressStatus },
126
         data: { progress_status: validateData.new_status as ProgressStatus },
127
     });
127
     });
128
 
128
 
129
-    if (validateData.note?.tags?.length) {
130
-        await storeCategoryLinkService(
131
-            validateData.note.tags,
132
-            'status_history_notes',
133
-            data.id,
134
-            req
135
-        );
136
-    }
129
+    // if (validateData.note?.tags?.length) {
130
+    //     await storeCategoryLinkService(
131
+    //         validateData.note.tags,
132
+    //         'status_history_notes',
133
+    //         data.id,
134
+    //         req
135
+    //     );
136
+    // }
137
 
137
 
138
     await createLog(req, data);
138
     await createLog(req, data);
139
 };
139
 };

+ 211 - 168
src/services/sales/VendorExperienceService.ts

@@ -5,7 +5,8 @@ import { createLog, updateLog, deleteLog } from '../../utils/LogActivity';
5
 import VendorExperienceRepository from '../../repository/sales/VendorExperienceRepository';
5
 import VendorExperienceRepository from '../../repository/sales/VendorExperienceRepository';
6
 import { CustomRequest } from '../../types/token/CustomRequest';
6
 import { CustomRequest } from '../../types/token/CustomRequest';
7
 import { VendorExperienceRequestDTO } from '../../types/sales/vendor_experience/VendorExperienceDTO';
7
 import { VendorExperienceRequestDTO } from '../../types/sales/vendor_experience/VendorExperienceDTO';
8
-import { storeCategoryLinkService, updateCategoryLinkService } from '../admin/CategoryLinkService';
8
+import { Prisma } from '@prisma/client';
9
+// import { storeCategoryLinkService, updateCategoryLinkService } from '../admin/CategoryLinkService';
9
 
10
 
10
 interface PaginationParams {
11
 interface PaginationParams {
11
     page: number;
12
     page: number;
@@ -13,10 +14,19 @@ interface PaginationParams {
13
     search?: string;
14
     search?: string;
14
     sortBy: string;
15
     sortBy: string;
15
     orderBy: 'asc' | 'desc';
16
     orderBy: 'asc' | 'desc';
17
+    category_id: string;
16
 }
18
 }
17
 
19
 
18
-export const getAllVendorExperienceService = async ({ page, limit, search, sortBy, orderBy }: PaginationParams, req: CustomRequest) => {
20
+export const getAllVendorExperienceService = async ({ page, limit, search, sortBy, orderBy, category_id }: PaginationParams, req: CustomRequest) => {
19
     const skip = (page - 1) * limit;
21
     const skip = (page - 1) * limit;
22
+
23
+    const where: Prisma.VendorExperienceWhereInput = {
24
+        hospital_id: req.params.id,
25
+        // ...SearchFilter(search, ['id', 'name', 'province.id']),
26
+        ...(category_id ? { category_id: category_id } : {}),
27
+        deletedAt: null,
28
+    };
29
+
20
     const hospitalId = req.params.id;
30
     const hospitalId = req.params.id;
21
 
31
 
22
     const hospital = await prisma.hospital.findFirst({ where: { id: hospitalId } });
32
     const hospital = await prisma.hospital.findFirst({ where: { id: hospitalId } });
@@ -38,10 +48,10 @@ export const getAllVendorExperienceService = async ({ page, limit, search, sortB
38
         throw new HttpException('You are not authorized to access this hospital', 403);
48
         throw new HttpException('You are not authorized to access this hospital', 403);
39
     }
49
     }
40
 
50
 
41
-    const where: any = {
42
-        hospital_id: req.params.id,
43
-        deletedAt: null
44
-    };
51
+    // const where: any = {
52
+    //     hospital_id: req.params.id,
53
+    //     deletedAt: null
54
+    // };
45
 
55
 
46
     const [vendor_experiences, total] = await Promise.all([
56
     const [vendor_experiences, total] = await Promise.all([
47
         VendorExperienceRepository.findAll({ skip, take: limit, where, orderBy: { [sortBy]: orderBy } }),
57
         VendorExperienceRepository.findAll({ skip, take: limit, where, orderBy: { [sortBy]: orderBy } }),
@@ -82,6 +92,7 @@ export const showVendorExperienceService = async (req: CustomRequest) => {
82
 
92
 
83
 export const storeVendorExperienceService = async (validateData: VendorExperienceRequestDTO, req: CustomRequest) => {
93
 export const storeVendorExperienceService = async (validateData: VendorExperienceRequestDTO, req: CustomRequest) => {
84
     const hospitalId = req.params.id;
94
     const hospitalId = req.params.id;
95
+    const userId = req.tokenData.sub;
85
 
96
 
86
     const hospital = await prisma.hospital.findFirst({ where: { id: hospitalId } });
97
     const hospital = await prisma.hospital.findFirst({ where: { id: hospitalId } });
87
     if (!hospital) throw new HttpException('Hospital not found', 404);
98
     if (!hospital) throw new HttpException('Hospital not found', 404);
@@ -107,47 +118,52 @@ export const storeVendorExperienceService = async (validateData: VendorExperienc
107
         if (!vendor) throw new HttpException('Vendor not found', 404);
118
         if (!vendor) throw new HttpException('Vendor not found', 404);
108
     }
119
     }
109
 
120
 
110
-    const SimrsType = ['vendor', 'in house', 'gratis'];
111
-    if (validateData.simrs_type && !SimrsType.includes(validateData.simrs_type)) {
112
-        throw new HttpException('Simrs type must be vendor, in house, or gratis', 400);
121
+    if (validateData.category_id) {
122
+        const category = await prisma.category.findFirst({ where: { id: validateData.category_id } });
123
+        if (!category) throw new HttpException('Category not found', 404);
113
     }
124
     }
114
 
125
 
115
-    if (validateData.contract_start_date && validateData.contract_expired_date) {
116
-        if (validateData.contract_start_date >= validateData.contract_expired_date) {
117
-            throw new HttpException('Contract expired date must be after contract date', 400);
118
-        }
119
-    }
120
-
121
-    if (validateData.contract_value_min && validateData.contract_value_max) {
122
-        if (validateData.contract_value_min >= validateData.contract_value_max) {
123
-            throw new HttpException('Contract value max must be after contract value min', 400);
124
-        }
125
-    }
126
-
127
-    if (validateData.simrs_type) {
128
-        const existingActiveVendors = await prisma.vendorExperience.findMany({
129
-            where: {
130
-                hospital_id: hospitalId,
131
-                status: 'active',
132
-                deletedAt: null
133
-            }
134
-        });
135
-
136
-        if (existingActiveVendors.length > 0) {
137
-            await prisma.vendorExperience.updateMany({
138
-                where: {
139
-                    hospital_id: hospitalId,
140
-                    status: 'active',
141
-                    deletedAt: null
142
-                },
143
-                data: {
144
-                    status: 'inactive'
145
-                }
146
-            });
147
-        }
148
-
149
-        validateData.status = 'active';
150
-    }
126
+    // const SimrsType = ['vendor', 'in house', 'gratis'];
127
+    // if (validateData.simrs_type && !SimrsType.includes(validateData.simrs_type)) {
128
+    //     throw new HttpException('Simrs type must be vendor, in house, or gratis', 400);
129
+    // }
130
+
131
+    // if (validateData.contract_start_date && validateData.contract_expired_date) {
132
+    //     if (validateData.contract_start_date >= validateData.contract_expired_date) {
133
+    //         throw new HttpException('Contract expired date must be after contract date', 400);
134
+    //     }
135
+    // }
136
+
137
+    // if (validateData.contract_value_min && validateData.contract_value_max) {
138
+    //     if (validateData.contract_value_min >= validateData.contract_value_max) {
139
+    //         throw new HttpException('Contract value max must be after contract value min', 400);
140
+    //     }
141
+    // }
142
+
143
+    // if (validateData.simrs_type) {
144
+    //     const existingActiveVendors = await prisma.vendorExperience.findMany({
145
+    //         where: {
146
+    //             hospital_id: hospitalId,
147
+    //             status: 'active',
148
+    //             deletedAt: null
149
+    //         }
150
+    //     });
151
+
152
+    //     if (existingActiveVendors.length > 0) {
153
+    //         await prisma.vendorExperience.updateMany({
154
+    //             where: {
155
+    //                 hospital_id: hospitalId,
156
+    //                 status: 'active',
157
+    //                 deletedAt: null
158
+    //             },
159
+    //             data: {
160
+    //                 status: 'inactive'
161
+    //             }
162
+    //         });
163
+    //     }
164
+
165
+    //     validateData.status = 'active';
166
+    // }
151
 
167
 
152
     const payload = {
168
     const payload = {
153
         ...(validateData.vendor_id && {
169
         ...(validateData.vendor_id && {
@@ -155,44 +171,53 @@ export const storeVendorExperienceService = async (validateData: VendorExperienc
155
                 connect: { id: validateData.vendor_id }
171
                 connect: { id: validateData.vendor_id }
156
             }
172
             }
157
         }),
173
         }),
158
-        simrs_type: validateData.simrs_type,
159
-        status: validateData.status,
160
-        contract_start_date: validateData.contract_start_date ? new Date(validateData.contract_start_date) : null,
161
-        contract_expired_date: validateData.contract_expired_date ? new Date(validateData.contract_expired_date) : null,
162
-        contract_value_min: validateData.contract_value_min ? Number(validateData.contract_value_min) : null,
163
-        contract_value_max: validateData.contract_value_max ? Number(validateData.contract_value_max) : null,
164
-        positive_notes: validateData.positive_notes?.note,
165
-        negative_notes: validateData.negative_notes?.note,
174
+        ...(validateData.category_id && {
175
+            category: {
176
+                connect: { id: validateData.category_id }
177
+            }
178
+        }),
179
+        content: validateData.content,
180
+        // status: validateData.status,
181
+        // contract_start_date: validateData.contract_start_date ? new Date(validateData.contract_start_date) : null,
182
+        // contract_expired_date: validateData.contract_expired_date ? new Date(validateData.contract_expired_date) : null,
183
+        // contract_value_min: validateData.contract_value_min ? Number(validateData.contract_value_min) : null,
184
+        // contract_value_max: validateData.contract_value_max ? Number(validateData.contract_value_max) : null,
185
+        // positive_notes: validateData.positive_notes?.note,
186
+        // negative_notes: validateData.negative_notes?.note,
166
         hospital: {
187
         hospital: {
167
             connect: { id: hospitalId }
188
             connect: { id: hospitalId }
168
         },
189
         },
190
+        user: {
191
+            connect: { id: userId }
192
+        },
169
     };
193
     };
170
 
194
 
171
     const data = await VendorExperienceRepository.create(payload);
195
     const data = await VendorExperienceRepository.create(payload);
172
 
196
 
173
-    if (validateData.positive_notes?.tags?.length) {
174
-        await storeCategoryLinkService(
175
-            validateData.positive_notes.tags,
176
-            'vendor_experience_positive_notes',
177
-            data.id,
178
-            req
179
-        );
180
-    }
181
-
182
-    if (validateData.negative_notes?.tags?.length) {
183
-        await storeCategoryLinkService(
184
-            validateData.negative_notes.tags,
185
-            'vendor_experience_negative_notes',
186
-            data.id,
187
-            req
188
-        );
189
-    }
197
+    // if (validateData.positive_notes?.tags?.length) {
198
+    //     await storeCategoryLinkService(
199
+    //         validateData.positive_notes.tags,
200
+    //         'vendor_experience_positive_notes',
201
+    //         data.id,
202
+    //         req
203
+    //     );
204
+    // }
205
+
206
+    // if (validateData.negative_notes?.tags?.length) {
207
+    //     await storeCategoryLinkService(
208
+    //         validateData.negative_notes.tags,
209
+    //         'vendor_experience_negative_notes',
210
+    //         data.id,
211
+    //         req
212
+    //     );
213
+    // }
190
 
214
 
191
     await createLog(req, data);
215
     await createLog(req, data);
192
 };
216
 };
193
 
217
 
194
 export const updateVendorExperienceService = async (validateData: Partial<VendorExperienceRequestDTO>, req: CustomRequest) => {
218
 export const updateVendorExperienceService = async (validateData: Partial<VendorExperienceRequestDTO>, req: CustomRequest) => {
195
     const id_hospital = req.params.id;
219
     const id_hospital = req.params.id;
220
+    const id_user = req.tokenData.sub;
196
     const id_vendor_experience = req.params.id_vendor_experience;
221
     const id_vendor_experience = req.params.id_vendor_experience;
197
 
222
 
198
     const hospital = await prisma.hospital.findFirst({ where: { id: id_hospital } });
223
     const hospital = await prisma.hospital.findFirst({ where: { id: id_hospital } });
@@ -222,115 +247,133 @@ export const updateVendorExperienceService = async (validateData: Partial<Vendor
222
         if (!existVendor) throw new HttpException('Vendor not found', 404);
247
         if (!existVendor) throw new HttpException('Vendor not found', 404);
223
     }
248
     }
224
 
249
 
225
-    const SimrsType = ['vendor', 'in house', 'gratis'];
226
-    if (validateData.simrs_type && !SimrsType.includes(validateData.simrs_type)) {
227
-        throw new HttpException('Simrs type must be vendor, in house, or gratis', 400);
228
-    }
229
-
230
-    if (
231
-        validateData.simrs_type &&
232
-        vendorHistory.simrs_type === 'vendor' &&
233
-        vendorHistory.vendor_id !== null &&
234
-        validateData.simrs_type !== 'vendor'
235
-    ) {
236
-        await prisma.vendorExperience.update({
237
-            where: {
238
-                id: id_vendor_experience,
239
-                deletedAt: null
240
-            },
241
-            data: {
242
-                vendor_id: null
243
-            }
244
-        });
250
+    if (validateData.category_id) {
251
+        const existCategory = await prisma.category.findFirst({ where: { id: validateData.category_id } });
252
+        if (!existCategory) throw new HttpException('Category not found', 404);
245
     }
253
     }
246
 
254
 
247
-    if (
248
-        validateData.contract_value_min &&
249
-        validateData.contract_value_min >= vendorHistory.contract_value_max!
250
-    ) {
251
-        throw new HttpException('Contract value min must be less than contract value max.', 400);
252
-    }
253
-
254
-    if (
255
-        validateData.contract_value_max &&
256
-        validateData.contract_value_max <= vendorHistory.contract_value_min!
257
-    ) {
258
-        throw new HttpException('Contract value max must be greater than contract value min.', 400);
259
-    }
260
-
261
-    if (
262
-        validateData.contract_start_date &&
263
-        validateData.contract_start_date >= vendorHistory.contract_expired_date!
264
-    ) {
265
-        throw new HttpException('Contract start date must be before contract expired date.', 400);
266
-    }
267
-
268
-    if (
269
-        validateData.contract_expired_date &&
270
-        validateData.contract_expired_date <= vendorHistory.contract_start_date!
271
-    ) {
272
-        throw new HttpException('Contract expired date must be after contract start date.', 400);
273
-    }
274
-
275
-    if (validateData.contract_start_date && validateData.contract_expired_date) {
276
-        if (validateData.contract_start_date >= validateData.contract_expired_date) {
277
-            throw new HttpException('Contract expired date must be after contract date', 400);
278
-        }
279
-    }
280
-
281
-    if (validateData.contract_value_min && validateData.contract_value_max) {
282
-        if (validateData.contract_value_min >= validateData.contract_value_max) {
283
-            throw new HttpException('Contract value max must be after contract value min', 400);
284
-        }
285
-    }
286
-
287
-    if (validateData.status === 'active') {
288
-        await prisma.vendorExperience.updateMany({
289
-            where: {
290
-                hospital_id: id_hospital,
291
-                status: 'active',
292
-                deletedAt: null,
293
-                NOT: { id: id_vendor_experience }
294
-            },
295
-            data: {
296
-                status: 'inactive'
297
-            }
298
-        });
299
-    }
255
+    // const SimrsType = ['vendor', 'in house', 'gratis'];
256
+    // if (validateData.simrs_type && !SimrsType.includes(validateData.simrs_type)) {
257
+    //     throw new HttpException('Simrs type must be vendor, in house, or gratis', 400);
258
+    // }
259
+
260
+    // if (
261
+    //     validateData.simrs_type &&
262
+    //     vendorHistory.simrs_type === 'vendor' &&
263
+    //     vendorHistory.vendor_id !== null &&
264
+    //     validateData.simrs_type !== 'vendor'
265
+    // ) {
266
+    //     await prisma.vendorExperience.update({
267
+    //         where: {
268
+    //             id: id_vendor_experience,
269
+    //             deletedAt: null
270
+    //         },
271
+    //         data: {
272
+    //             vendor_id: null
273
+    //         }
274
+    //     });
275
+    // }
276
+
277
+    // if (
278
+    //     validateData.contract_value_min &&
279
+    //     validateData.contract_value_min >= vendorHistory.contract_value_max!
280
+    // ) {
281
+    //     throw new HttpException('Contract value min must be less than contract value max.', 400);
282
+    // }
283
+
284
+    // if (
285
+    //     validateData.contract_value_max &&
286
+    //     validateData.contract_value_max <= vendorHistory.contract_value_min!
287
+    // ) {
288
+    //     throw new HttpException('Contract value max must be greater than contract value min.', 400);
289
+    // }
290
+
291
+    // if (
292
+    //     validateData.contract_start_date &&
293
+    //     validateData.contract_start_date >= vendorHistory.contract_expired_date!
294
+    // ) {
295
+    //     throw new HttpException('Contract start date must be before contract expired date.', 400);
296
+    // }
297
+
298
+    // if (
299
+    //     validateData.contract_expired_date &&
300
+    //     validateData.contract_expired_date <= vendorHistory.contract_start_date!
301
+    // ) {
302
+    //     throw new HttpException('Contract expired date must be after contract start date.', 400);
303
+    // }
304
+
305
+    // if (validateData.contract_start_date && validateData.contract_expired_date) {
306
+    //     if (validateData.contract_start_date >= validateData.contract_expired_date) {
307
+    //         throw new HttpException('Contract expired date must be after contract date', 400);
308
+    //     }
309
+    // }
310
+
311
+    // if (validateData.contract_value_min && validateData.contract_value_max) {
312
+    //     if (validateData.contract_value_min >= validateData.contract_value_max) {
313
+    //         throw new HttpException('Contract value max must be after contract value min', 400);
314
+    //     }
315
+    // }
316
+
317
+    // if (validateData.status === 'active') {
318
+    //     await prisma.vendorExperience.updateMany({
319
+    //         where: {
320
+    //             hospital_id: id_hospital,
321
+    //             status: 'active',
322
+    //             deletedAt: null,
323
+    //             NOT: { id: id_vendor_experience }
324
+    //         },
325
+    //         data: {
326
+    //             status: 'inactive'
327
+    //         }
328
+    //     });
329
+    // }
300
 
330
 
301
     const payload = {
331
     const payload = {
302
-        status: validateData.status,
303
-        contract_start_date: validateData.contract_start_date ? new Date(validateData.contract_start_date) : vendorHistory.contract_start_date,
304
-        contract_expired_date: validateData.contract_expired_date ? new Date(validateData.contract_expired_date) : vendorHistory.contract_expired_date,
305
-        contract_value_min: validateData.contract_value_min ? Number(validateData.contract_value_min) : vendorHistory.contract_value_min,
306
-        contract_value_max: validateData.contract_value_max ? Number(validateData.contract_value_max) : vendorHistory.contract_value_max,
307
-        positive_notes: validateData.positive_notes?.note,
308
-        negative_notes: validateData.negative_notes?.note,
309
-        simrs_type: validateData.simrs_type,
310
-        vendor_id: validateData.vendor_id
332
+        // status: validateData.status,
333
+        // contract_start_date: validateData.contract_start_date ? new Date(validateData.contract_start_date) : vendorHistory.contract_start_date,
334
+        // contract_expired_date: validateData.contract_expired_date ? new Date(validateData.contract_expired_date) : vendorHistory.contract_expired_date,
335
+        // contract_value_min: validateData.contract_value_min ? Number(validateData.contract_value_min) : vendorHistory.contract_value_min,
336
+        // contract_value_max: validateData.contract_value_max ? Number(validateData.contract_value_max) : vendorHistory.contract_value_max,
337
+        // positive_notes: validateData.positive_notes?.note,
338
+        // negative_notes: validateData.negative_notes?.note,
339
+        // simrs_type: validateData.simrs_type,
340
+        content: validateData.content,
341
+        ...(validateData.vendor_id && {
342
+            vendor: {
343
+                connect: { id: validateData.vendor_id }
344
+            }
345
+        }),
346
+        ...(validateData.category_id && {
347
+            category: {
348
+                connect: { id: validateData.category_id }
349
+            }
350
+        }),
351
+        user: {
352
+            connect: { id: id_user }
353
+        }
311
     };
354
     };
312
 
355
 
313
     const data = await VendorExperienceRepository.update(id_vendor_experience, payload);
356
     const data = await VendorExperienceRepository.update(id_vendor_experience, payload);
314
 
357
 
315
     // Positive Notes Tags
358
     // Positive Notes Tags
316
-    if (validateData.positive_notes?.tags?.length) {
317
-        await updateCategoryLinkService(
318
-            validateData.positive_notes.tags,
319
-            'vendor_experience_positive_notes',
320
-            id_vendor_experience,
321
-            req
322
-        );
323
-    }
359
+    // if (validateData.positive_notes?.tags?.length) {
360
+    //     await updateCategoryLinkService(
361
+    //         validateData.positive_notes.tags,
362
+    //         'vendor_experience_positive_notes',
363
+    //         id_vendor_experience,
364
+    //         req
365
+    //     );
366
+    // }
324
 
367
 
325
     // Negative Notes Tags
368
     // Negative Notes Tags
326
-    if (validateData.negative_notes?.tags?.length) {
327
-        await updateCategoryLinkService(
328
-            validateData.negative_notes.tags,
329
-            'vendor_experience_negative_notes',
330
-            id_vendor_experience,
331
-            req
332
-        );
333
-    }
369
+    // if (validateData.negative_notes?.tags?.length) {
370
+    //     await updateCategoryLinkService(
371
+    //         validateData.negative_notes.tags,
372
+    //         'vendor_experience_negative_notes',
373
+    //         id_vendor_experience,
374
+    //         req
375
+    //     );
376
+    // }
334
 
377
 
335
     await updateLog(req, data);
378
     await updateLog(req, data);
336
 };
379
 };

+ 4 - 4
src/types/admin/category/CategoryDTO.ts

@@ -1,19 +1,19 @@
1
 export interface CategoryRequestDTO {
1
 export interface CategoryRequestDTO {
2
-    tag: string;
2
+    name: string;
3
     description?: string | null;
3
     description?: string | null;
4
 }
4
 }
5
 
5
 
6
 export interface CategoryDTO {
6
 export interface CategoryDTO {
7
     id: string;
7
     id: string;
8
-    tag: string;
8
+    name: string;
9
     description?: string | null;
9
     description?: string | null;
10
-    count_use_tags?: number | null;
10
+    count_use_category?: number | null;
11
     createdAt: Date;
11
     createdAt: Date;
12
     updatedAt: Date;
12
     updatedAt: Date;
13
 }
13
 }
14
 
14
 
15
 export interface MergeCategoryRequestDTO {
15
 export interface MergeCategoryRequestDTO {
16
     category_id: string[];
16
     category_id: string[];
17
-    tag: string;
17
+    name: string;
18
     description?: string | null;
18
     description?: string | null;
19
 }
19
 }

+ 16 - 4
src/types/admin/schedule_visitation/ScheduleVisitationDTO.ts

@@ -61,10 +61,22 @@ export type ShowScheduleVisitationDTO = {
61
 
61
 
62
         vendor_experiences: {
62
         vendor_experiences: {
63
             id: string;
63
             id: string;
64
-            vendor: { id: string; name: string } | null;
65
-            contract_start_date: Date | null;
66
-            contract_expired_date: Date | null;
67
-            simrs_type: string;
64
+            vendor: {
65
+                id: string;
66
+                name: string;
67
+            } | null;
68
+            category: {
69
+                id: string;
70
+                name: string;
71
+            } | null;
72
+            content: string | null;
73
+            user: {
74
+                id: string;
75
+                fullname: string;
76
+            }
77
+            // contract_start_date: Date | null;
78
+            // contract_expired_date: Date | null;
79
+            // simrs_type: string;
68
         }[];
80
         }[];
69
 
81
 
70
         executives_histories: {
82
         executives_histories: {

+ 43 - 28
src/types/admin/vendor_experience/VendorExperienceDTO.ts

@@ -1,36 +1,27 @@
1
 export interface VendorExperienceRequestDTO {
1
 export interface VendorExperienceRequestDTO {
2
-    simrs_type: string;
3
-    vendor_id: string | null;
4
-    status?: string;
5
-    contract_start_date?: Date | null;
6
-    contract_expired_date?: Date | null;
7
-    contract_value_min?: number | null;
8
-    contract_value_max?: number | null;
9
-    positive_notes?: {
10
-        note: string;
11
-        tags: string[];
12
-    };
13
-    negative_notes?: {
14
-        note: string;
15
-        tags: string[];
16
-    };
2
+    // simrs_type: string;
3
+    vendor_id?: string | null;
4
+    category_id?: string | null;
5
+    content?: string | null;
6
+    // user_id: string;
7
+    // status?: string;
8
+    // contract_start_date?: Date | null;
9
+    // contract_expired_date?: Date | null;
10
+    // contract_value_min?: number | null;
11
+    // contract_value_max?: number | null;
12
+    // positive_notes?: {
13
+    //     note: string;
14
+    //     tags: string[];
15
+    // };
16
+    // negative_notes?: {
17
+    //     note: string;
18
+    //     tags: string[];
19
+    // };
17
 }
20
 }
18
 
21
 
19
 export interface VendorExperienceDTO {
22
 export interface VendorExperienceDTO {
20
     id: string;
23
     id: string;
21
-    contract_start_date: Date | null;
22
-    contract_expired_date: Date | null;
23
-    contract_value_min: bigint | null;
24
-    contract_value_max: bigint | null;
25
-    positive_notes: string | null;
26
-    negative_notes: string | null;
27
-    positive_notes_tags?: string[];
28
-    negative_notes_tags?: string[];
29
-    status: string | null;
30
-    simrs_type: string;
31
-    createdAt: Date;
32
-    updatedAt: Date;
33
-    vendor_id?: string | null;
24
+    content: string | null;
34
     vendor: {
25
     vendor: {
35
         id: string;
26
         id: string;
36
         name: string;
27
         name: string;
@@ -40,4 +31,28 @@ export interface VendorExperienceDTO {
40
         website: string | null;
31
         website: string | null;
41
         created_by: string;
32
         created_by: string;
42
     } | null;
33
     } | null;
34
+    category: {
35
+        id: string;
36
+        name: string;
37
+        description: string | null;
38
+    } | null;
39
+    user: {
40
+        id: string;
41
+        fullname: string;
42
+    };
43
+    createdAt: Date;
44
+    updatedAt: Date;
45
+    // contract_start_date: Date | null;
46
+    // contract_expired_date: Date | null;
47
+    // contract_value_min: bigint | null;
48
+    // contract_value_max: bigint | null;
49
+    // positive_notes: string | null;
50
+    // negative_notes: string | null;
51
+    // positive_notes_tags?: string[];
52
+    // negative_notes_tags?: string[];
53
+    // status: string | null;
54
+    // simrs_type: string;
55
+    // vendor_id?: string | null;
56
+    // category_id?: string | null;
57
+    // user_id: string
43
 }
58
 }

+ 16 - 4
src/types/sales/schedule_visitation/ScheduleVisitationDTO.ts

@@ -61,10 +61,22 @@ export type ShowScheduleVisitationDTO = {
61
 
61
 
62
         vendor_experiences: {
62
         vendor_experiences: {
63
             id: string;
63
             id: string;
64
-            vendor: { id: string; name: string } | null;
65
-            contract_start_date: Date | null;
66
-            contract_expired_date: Date | null;
67
-            simrs_type: string;
64
+            vendor: {
65
+                id: string;
66
+                name: string;
67
+            } | null;
68
+            category: {
69
+                id: string;
70
+                name: string;
71
+            } | null;
72
+            content: string | null;
73
+            user: {
74
+                id: string;
75
+                fullname: string;
76
+            }
77
+            // contract_start_date: Date | null;
78
+            // contract_expired_date: Date | null;
79
+            // simrs_type: string;
68
         }[];
80
         }[];
69
 
81
 
70
         executives_histories: {
82
         executives_histories: {

+ 40 - 28
src/types/sales/vendor_experience/VendorExperienceDTO.ts

@@ -1,36 +1,27 @@
1
 export interface VendorExperienceRequestDTO {
1
 export interface VendorExperienceRequestDTO {
2
-    simrs_type: string;
3
-    vendor_id: string | null;
4
-    status?: string;
5
-    contract_start_date?: Date | null;
6
-    contract_expired_date?: Date | null;
7
-    contract_value_min?: number | null;
8
-    contract_value_max?: number | null;
9
-    positive_notes?: {
10
-        note: string;
11
-        tags: string[];
12
-    };
13
-    negative_notes?: {
14
-        note: string;
15
-        tags: string[];
16
-    };
2
+    vendor_id?: string | null;
3
+    category_id?: string | null;
4
+    // user_id: string;
5
+    content?: string | null;
6
+    // simrs_type: string;
7
+    // status?: string;
8
+    // contract_start_date?: Date | null;
9
+    // contract_expired_date?: Date | null;
10
+    // contract_value_min?: number | null;
11
+    // contract_value_max?: number | null;
12
+    // positive_notes?: {
13
+    //     note: string;
14
+    //     tags: string[];
15
+    // };
16
+    // negative_notes?: {
17
+    //     note: string;
18
+    //     tags: string[];
19
+    // };
17
 }
20
 }
18
 
21
 
19
 export interface VendorExperienceDTO {
22
 export interface VendorExperienceDTO {
20
     id: string;
23
     id: string;
21
-    contract_start_date: Date | null;
22
-    contract_expired_date: Date | null;
23
-    contract_value_min: bigint | null;
24
-    contract_value_max: bigint | null;
25
-    positive_notes: string | null;
26
-    negative_notes: string | null;
27
-    positive_notes_tags?: string[];
28
-    negative_notes_tags?: string[];
29
-    status: string | null;
30
-    simrs_type: string;
31
-    createdAt: Date;
32
-    updatedAt: Date;
33
-    vendor_id?: string | null;
24
+    content: string | null;
34
     vendor: {
25
     vendor: {
35
         id: string;
26
         id: string;
36
         name: string;
27
         name: string;
@@ -40,4 +31,25 @@ export interface VendorExperienceDTO {
40
         website: string | null;
31
         website: string | null;
41
         created_by: string;
32
         created_by: string;
42
     } | null;
33
     } | null;
34
+    category: {
35
+        id: string;
36
+        name: string;
37
+        description: string | null;
38
+    } | null;
39
+    user: {
40
+        id: string;
41
+        fullname: string;
42
+    };
43
+    createdAt: Date;
44
+    updatedAt: Date;
45
+    // simrs_type: string;
46
+    // contract_start_date: Date | null;
47
+    // contract_expired_date: Date | null;
48
+    // contract_value_min: bigint | null;
49
+    // contract_value_max: bigint | null;
50
+    // positive_notes: string | null;
51
+    // negative_notes: string | null;
52
+    // positive_notes_tags?: string[];
53
+    // negative_notes_tags?: string[];
54
+    // status: string | null;
43
 }
55
 }

+ 25 - 25
src/validators/admin/category/CategoryValidators.ts

@@ -3,38 +3,38 @@ import { validateWithSchema } from '../../ValidateSchema';
3
 import { CategoryRequestDTO, MergeCategoryRequestDTO } from '../../../types/admin/category/CategoryDTO';
3
 import { CategoryRequestDTO, MergeCategoryRequestDTO } from '../../../types/admin/category/CategoryDTO';
4
 
4
 
5
 const storeCategorySchema = Joi.object<CategoryRequestDTO>({
5
 const storeCategorySchema = Joi.object<CategoryRequestDTO>({
6
-    tag: Joi.string().trim().required().messages({
7
-        'string.empty': 'Tag is required',
6
+    name: Joi.string().trim().required().messages({
7
+        'string.empty': 'Name is required',
8
     }),
8
     }),
9
     description: Joi.string().trim().optional().allow(''),
9
     description: Joi.string().trim().optional().allow(''),
10
 });
10
 });
11
 
11
 
12
 const updateCategorySchema = Joi.object<Partial<CategoryRequestDTO>>({
12
 const updateCategorySchema = Joi.object<Partial<CategoryRequestDTO>>({
13
-    tag: Joi.string().trim().optional().messages({
14
-        'string.empty': 'Tag is required',
13
+    name: Joi.string().trim().optional().messages({
14
+        'string.empty': 'Name is required',
15
     }),
15
     }),
16
     description: Joi.string().trim().optional().allow(''),
16
     description: Joi.string().trim().optional().allow(''),
17
 });
17
 });
18
 
18
 
19
-const mergeCategorySchema = Joi.object<MergeCategoryRequestDTO>({
20
-    category_id: Joi.array()
21
-        .items(Joi.string().trim().min(2))
22
-        .min(1)
23
-        .required()
24
-        .messages({
25
-            'any.required': 'Category ID is required',
26
-            'array.base': 'Category ID must be an array of strings',
27
-            'array.min': 'At least one category ID is required',
28
-            'string.empty': 'Each Category ID must not be empty',
29
-            'string.min': 'Each Category ID must not be empty',
30
-        }),
19
+// const mergeCategorySchema = Joi.object<MergeCategoryRequestDTO>({
20
+//     category_id: Joi.array()
21
+//         .items(Joi.string().trim().min(2))
22
+//         .min(1)
23
+//         .required()
24
+//         .messages({
25
+//             'any.required': 'Category ID is required',
26
+//             'array.base': 'Category ID must be an array of strings',
27
+//             'array.min': 'At least one category ID is required',
28
+//             'string.empty': 'Each Category ID must not be empty',
29
+//             'string.min': 'Each Category ID must not be empty',
30
+//         }),
31
 
31
 
32
-    tag: Joi.string().trim().required().messages({
33
-        'string.empty': 'Tag is required',
34
-        'any.required': 'Tag is required',
35
-    }),
36
-    description: Joi.string().trim().optional().allow(''),
37
-});
32
+//     name: Joi.string().trim().required().messages({
33
+//         'string.empty': 'Name is required',
34
+//         'any.required': 'Name is required',
35
+//     }),
36
+//     description: Joi.string().trim().optional().allow(''),
37
+// });
38
 
38
 
39
 export const validateCategoryStoreRequest = (body: unknown): CategoryRequestDTO => {
39
 export const validateCategoryStoreRequest = (body: unknown): CategoryRequestDTO => {
40
     return validateWithSchema<CategoryRequestDTO>(storeCategorySchema, body);
40
     return validateWithSchema<CategoryRequestDTO>(storeCategorySchema, body);
@@ -44,6 +44,6 @@ export const validateCategoryUpdateRequest = (body: unknown): CategoryRequestDTO
44
     return validateWithSchema<CategoryRequestDTO>(updateCategorySchema, body);
44
     return validateWithSchema<CategoryRequestDTO>(updateCategorySchema, body);
45
 }
45
 }
46
 
46
 
47
-export const validateMergeCategoryStoreRequest = (body: unknown): MergeCategoryRequestDTO => {
48
-    return validateWithSchema<MergeCategoryRequestDTO>(mergeCategorySchema, body);
49
-};
47
+// export const validateMergeCategoryStoreRequest = (body: unknown): MergeCategoryRequestDTO => {
48
+//     return validateWithSchema<MergeCategoryRequestDTO>(mergeCategorySchema, body);
49
+// };

+ 38 - 34
src/validators/admin/vendor_experience/VendorExperienceValidators.ts

@@ -3,47 +3,51 @@ import { validateWithSchema } from '../../ValidateSchema';
3
 import { VendorExperienceRequestDTO } from '../../../types/admin/vendor_experience/VendorExperienceDTO';
3
 import { VendorExperienceRequestDTO } from '../../../types/admin/vendor_experience/VendorExperienceDTO';
4
 
4
 
5
 export const storeVendorExperienceSchema = Joi.object({
5
 export const storeVendorExperienceSchema = Joi.object({
6
-    simrs_type: Joi.string().trim().required().messages({
7
-        'string.empty': 'Simrs type is required',
8
-        'string.base': 'Simrs type must be a string',
9
-    }),
10
     vendor_id: Joi.string().uuid().optional(),
6
     vendor_id: Joi.string().uuid().optional(),
11
-    status: Joi.string().trim().required().messages({
12
-        'string.empty': 'Status is required',
13
-        'string.base': 'Status must be a string',
14
-    }),
15
-    contract_start_date: Joi.date().optional().allow(null).messages({ 'date.format': 'Contract start date must be a valid date' }),
16
-    contract_expired_date: Joi.date().optional().allow(null).messages({ 'date.format': 'Contract expired date must be a valid date' }),
17
-    contract_value_min: Joi.number().optional().allow(null).messages({ 'number.format': 'Contract value min must be a number' }),
18
-    contract_value_max: Joi.number().optional().allow(null).messages({ 'number.format': 'Contract value max must be a number' }),
19
-    positive_notes: Joi.object({
20
-        note: Joi.string().allow('', null),
21
-        tags: Joi.array().items(Joi.string()).optional().default([]),
22
-    }).optional().allow(null),
7
+    category_id: Joi.string().uuid().optional(),
8
+    content: Joi.string().trim().allow('', null),
9
+    // simrs_type: Joi.string().trim().required().messages({
10
+    //     'string.empty': 'Simrs type is required',
11
+    //     'string.base': 'Simrs type must be a string',
12
+    // }),
13
+    // status: Joi.string().trim().required().messages({
14
+    //     'string.empty': 'Status is required',
15
+    //     'string.base': 'Status must be a string',
16
+    // }),
17
+    // contract_start_date: Joi.date().optional().allow(null).messages({ 'date.format': 'Contract start date must be a valid date' }),
18
+    // contract_expired_date: Joi.date().optional().allow(null).messages({ 'date.format': 'Contract expired date must be a valid date' }),
19
+    // contract_value_min: Joi.number().optional().allow(null).messages({ 'number.format': 'Contract value min must be a number' }),
20
+    // contract_value_max: Joi.number().optional().allow(null).messages({ 'number.format': 'Contract value max must be a number' }),
21
+    // positive_notes: Joi.object({
22
+    //     note: Joi.string().allow('', null),
23
+    //     tags: Joi.array().items(Joi.string()).optional().default([]),
24
+    // }).optional().allow(null),
23
 
25
 
24
-    negative_notes: Joi.object({
25
-        note: Joi.string().allow('', null),
26
-        tags: Joi.array().items(Joi.string()).optional().default([]),
27
-    }).optional().allow(null),
26
+    // negative_notes: Joi.object({
27
+    //     note: Joi.string().allow('', null),
28
+    //     tags: Joi.array().items(Joi.string()).optional().default([]),
29
+    // }).optional().allow(null),
28
 });
30
 });
29
 
31
 
30
 export const updateVendorExperienceSchema = Joi.object({
32
 export const updateVendorExperienceSchema = Joi.object({
31
-    simrs_type: Joi.string().trim().optional(),
32
     vendor_id: Joi.string().uuid().optional(),
33
     vendor_id: Joi.string().uuid().optional(),
33
-    status: Joi.string().trim().optional(),
34
-    contract_start_date: Joi.date().optional().allow(null).messages({ 'date.format': 'Contract start date must be a valid date' }),
35
-    contract_expired_date: Joi.date().optional().allow(null).messages({ 'date.format': 'Contract expired date must be a valid date' }),
36
-    contract_value_min: Joi.number().optional().allow(null).messages({ 'number.format': 'Contract value min must be a number' }),
37
-    contract_value_max: Joi.number().optional().allow(null).messages({ 'number.format': 'Contract value max must be a number' }),
38
-    positive_notes: Joi.object({
39
-        note: Joi.string().allow('', null),
40
-        tags: Joi.array().items(Joi.string()).optional().default([]),
41
-    }).optional().allow(null),
34
+    category_id: Joi.string().uuid().optional(),
35
+    content: Joi.string().trim().allow('', null),
36
+    // simrs_type: Joi.string().trim().optional(),
37
+    // status: Joi.string().trim().optional(),
38
+    // contract_start_date: Joi.date().optional().allow(null).messages({ 'date.format': 'Contract start date must be a valid date' }),
39
+    // contract_expired_date: Joi.date().optional().allow(null).messages({ 'date.format': 'Contract expired date must be a valid date' }),
40
+    // contract_value_min: Joi.number().optional().allow(null).messages({ 'number.format': 'Contract value min must be a number' }),
41
+    // contract_value_max: Joi.number().optional().allow(null).messages({ 'number.format': 'Contract value max must be a number' }),
42
+    // positive_notes: Joi.object({
43
+    //     note: Joi.string().allow('', null),
44
+    //     tags: Joi.array().items(Joi.string()).optional().default([]),
45
+    // }).optional().allow(null),
42
 
46
 
43
-    negative_notes: Joi.object({
44
-        note: Joi.string().allow('', null),
45
-        tags: Joi.array().items(Joi.string()).optional().default([]),
46
-    }).optional().allow(null),
47
+    // negative_notes: Joi.object({
48
+    //     note: Joi.string().allow('', null),
49
+    //     tags: Joi.array().items(Joi.string()).optional().default([]),
50
+    // }).optional().allow(null),
47
 });
51
 });
48
 
52
 
49
 export const validateStoreVendorExperienceRequest = (body: unknown): VendorExperienceRequestDTO => {
53
 export const validateStoreVendorExperienceRequest = (body: unknown): VendorExperienceRequestDTO => {

+ 39 - 34
src/validators/sales/vendor_experience/VendorExperienceValidators.ts

@@ -3,47 +3,52 @@ import { validateWithSchema } from '../../ValidateSchema';
3
 import { VendorExperienceRequestDTO } from '../../../types/admin/vendor_experience/VendorExperienceDTO';
3
 import { VendorExperienceRequestDTO } from '../../../types/admin/vendor_experience/VendorExperienceDTO';
4
 
4
 
5
 export const storeVendorExperienceSchema = Joi.object({
5
 export const storeVendorExperienceSchema = Joi.object({
6
-    simrs_type: Joi.string().trim().required().messages({
7
-        'string.empty': 'Simrs type is required',
8
-        'string.base': 'Simrs type must be a string',
9
-    }),
10
     vendor_id: Joi.string().uuid().optional(),
6
     vendor_id: Joi.string().uuid().optional(),
11
-    status: Joi.string().trim().required().messages({
12
-        'string.empty': 'Status is required',
13
-        'string.base': 'Status must be a string',
14
-    }),
15
-    contract_start_date: Joi.date().optional().allow(null).messages({ 'date.format': 'Contract start date must be a valid date' }),
16
-    contract_expired_date: Joi.date().optional().allow(null).messages({ 'date.format': 'Contract expired date must be a valid date' }),
17
-    contract_value_min: Joi.number().optional().allow(null).messages({ 'number.format': 'Contract value min must be a number' }),
18
-    contract_value_max: Joi.number().optional().allow(null).messages({ 'number.format': 'Contract value max must be a number' }),
19
-    positive_notes: Joi.object({
20
-        note: Joi.string().allow('', null),
21
-        tags: Joi.array().items(Joi.string()).optional().default([]),
22
-    }).optional().allow(null),
7
+    category_id: Joi.string().uuid().optional(),
8
+    content: Joi.string().trim().allow('', null),
9
+    // simrs_type: Joi.string().trim().required().messages({
10
+    //     'string.empty': 'Simrs type is required',
11
+    //     'string.base': 'Simrs type must be a string',
12
+    // }),
13
+    // status: Joi.string().trim().required().messages({
14
+    //     'string.empty': 'Status is required',
15
+    //     'string.base': 'Status must be a string',
16
+    // }),
17
+    // contract_start_date: Joi.date().optional().allow(null).messages({ 'date.format': 'Contract start date must be a valid date' }),
18
+    // contract_expired_date: Joi.date().optional().allow(null).messages({ 'date.format': 'Contract expired date must be a valid date' }),
19
+    // contract_value_min: Joi.number().optional().allow(null).messages({ 'number.format': 'Contract value min must be a number' }),
20
+    // contract_value_max: Joi.number().optional().allow(null).messages({ 'number.format': 'Contract value max must be a number' }),
21
+    // positive_notes: Joi.object({
22
+    //     note: Joi.string().allow('', null),
23
+    //     tags: Joi.array().items(Joi.string()).optional().default([]),
24
+    // }).optional().allow(null),
23
 
25
 
24
-    negative_notes: Joi.object({
25
-        note: Joi.string().allow('', null),
26
-        tags: Joi.array().items(Joi.string()).optional().default([]),
27
-    }).optional().allow(null),
26
+    // negative_notes: Joi.object({
27
+    //     note: Joi.string().allow('', null),
28
+    //     tags: Joi.array().items(Joi.string()).optional().default([]),
29
+    // }).optional().allow(null),
28
 });
30
 });
29
 
31
 
30
 export const updateVendorExperienceSchema = Joi.object({
32
 export const updateVendorExperienceSchema = Joi.object({
31
-    simrs_type: Joi.string().trim().optional(),
32
     vendor_id: Joi.string().uuid().optional(),
33
     vendor_id: Joi.string().uuid().optional(),
33
-    status: Joi.string().trim().optional(),
34
-    contract_start_date: Joi.date().optional().allow(null).messages({ 'date.format': 'Contract start date must be a valid date' }),
35
-    contract_expired_date: Joi.date().optional().allow(null).messages({ 'date.format': 'Contract expired date must be a valid date' }),
36
-    contract_value_min: Joi.number().optional().allow(null).messages({ 'number.format': 'Contract value min must be a number' }),
37
-    contract_value_max: Joi.number().optional().allow(null).messages({ 'number.format': 'Contract value max must be a number' }),
38
-    positive_notes: Joi.object({
39
-        note: Joi.string().allow('', null),
40
-        tags: Joi.array().items(Joi.string()).optional().default([]),
41
-    }).optional().allow(null),
34
+    category_id: Joi.string().uuid().optional(),
35
+    content: Joi.string().trim().allow('', null),
36
+    // simrs_type: Joi.string().trim().optional(),
37
+    // vendor_id: Joi.string().uuid().optional(),
38
+    // status: Joi.string().trim().optional(),
39
+    // contract_start_date: Joi.date().optional().allow(null).messages({ 'date.format': 'Contract start date must be a valid date' }),
40
+    // contract_expired_date: Joi.date().optional().allow(null).messages({ 'date.format': 'Contract expired date must be a valid date' }),
41
+    // contract_value_min: Joi.number().optional().allow(null).messages({ 'number.format': 'Contract value min must be a number' }),
42
+    // contract_value_max: Joi.number().optional().allow(null).messages({ 'number.format': 'Contract value max must be a number' }),
43
+    // positive_notes: Joi.object({
44
+    //     note: Joi.string().allow('', null),
45
+    //     tags: Joi.array().items(Joi.string()).optional().default([]),
46
+    // }).optional().allow(null),
42
 
47
 
43
-    negative_notes: Joi.object({
44
-        note: Joi.string().allow('', null),
45
-        tags: Joi.array().items(Joi.string()).optional().default([]),
46
-    }).optional().allow(null),
48
+    // negative_notes: Joi.object({
49
+    //     note: Joi.string().allow('', null),
50
+    //     tags: Joi.array().items(Joi.string()).optional().default([]),
51
+    // }).optional().allow(null),
47
 });
52
 });
48
 
53
 
49
 export const validateStoreVendorExperienceRequest = (body: unknown): VendorExperienceRequestDTO => {
54
 export const validateStoreVendorExperienceRequest = (body: unknown): VendorExperienceRequestDTO => {

+ 6 - 4
tsconfig.json

@@ -27,7 +27,7 @@
27
 
27
 
28
     /* Modules */
28
     /* Modules */
29
     "module": "CommonJS" /* Specify what module code is generated. */,
29
     "module": "CommonJS" /* Specify what module code is generated. */,
30
-    "rootDir": "./" /* Specify the root folder within your source files. */,
30
+    "rootDir": "./index.ts" /* Specify the root folder within your source files. */,
31
     "moduleResolution": "node" /* Specify how TypeScript looks up a file from a given module specifier. */,
31
     "moduleResolution": "node" /* Specify how TypeScript looks up a file from a given module specifier. */,
32
     // "baseUrl": "./",                                  /* Specify the base directory to resolve non-relative module names. */
32
     // "baseUrl": "./",                                  /* Specify the base directory to resolve non-relative module names. */
33
     // "paths": {},                                      /* Specify a set of entries that re-map imports to additional lookup locations. */
33
     // "paths": {},                                      /* Specify a set of entries that re-map imports to additional lookup locations. */
@@ -111,10 +111,12 @@
111
     "skipLibCheck": true /* Skip type checking all .d.ts files. */
111
     "skipLibCheck": true /* Skip type checking all .d.ts files. */
112
   },
112
   },
113
   "include": [
113
   "include": [
114
-    "./src",
114
+    "./",
115
+    "./storage/img",
116
+    "./config",
115
     "./prisma",
117
     "./prisma",
116
     "index.ts",
118
     "index.ts",
117
-    "./src/**/*.ts",
119
+    "./src/**/*.ts"
118
   ],
120
   ],
119
   "exclude": ["node_modules"]
121
   "exclude": ["node_modules"]
120
-}
122
+}