storemw-core-api 1.0.163 → 1.0.165

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/dist/lib/index.d.ts +2 -0
  2. package/dist/lib/index.js +5 -1
  3. package/dist/lib/index.js.map +1 -1
  4. package/dist/lib/model_factory/ModelFactory.d.ts +7 -6
  5. package/dist/lib/model_factory/ModelFactory.js +595 -197
  6. package/dist/lib/model_factory/ModelFactory.js.map +1 -1
  7. package/dist/lib/query_builder/queryBuilder.d.ts +1 -1
  8. package/dist/lib/query_builder/queryBuilder.js +66 -15
  9. package/dist/lib/query_builder/queryBuilder.js.map +1 -1
  10. package/dist/lib/query_builder/queryDocumentProfile.d.ts +7 -0
  11. package/dist/lib/query_builder/queryDocumentProfile.js +87 -0
  12. package/dist/lib/query_builder/queryDocumentProfile.js.map +1 -0
  13. package/dist/lib/query_builder/queryUserBranch.d.ts +10 -0
  14. package/dist/lib/query_builder/queryUserBranch.js +31 -0
  15. package/dist/lib/query_builder/queryUserBranch.js.map +1 -0
  16. package/dist/models/access_control/AccessControlRoleModel.d.ts +4 -5
  17. package/dist/models/access_control/AccessControlRolePolicyModel.d.ts +4 -5
  18. package/dist/models/access_control/AccessControlUserRoleModel.d.ts +4 -5
  19. package/dist/models/account/AccountModel.d.ts +4 -5
  20. package/dist/models/auth/AccessKeyModel.d.ts +4 -5
  21. package/dist/models/branch/UserBranchModel.d.ts +4 -5
  22. package/dist/models/branch_user/BranchUserModel.d.ts +4 -5
  23. package/dist/models/business/BusinessModel.d.ts +4 -5
  24. package/dist/models/document/DocumentAmountModel.d.ts +4 -5
  25. package/dist/models/document/DocumentDocumentModel.d.ts +4 -5
  26. package/dist/models/document/DocumentItemModel.d.ts +4 -5
  27. package/dist/models/document/DocumentLocationModel.d.ts +4 -5
  28. package/dist/models/document/DocumentModel.d.ts +4 -5
  29. package/dist/models/document/DocumentPaymentModel.d.ts +4 -5
  30. package/dist/models/document/DocumentProfileModel.d.ts +4 -5
  31. package/dist/models/document/DocumentTotalModel.d.ts +4 -5
  32. package/dist/models/file/FileModel.d.ts +4 -5
  33. package/dist/models/group/GroupModel.d.ts +4 -5
  34. package/dist/models/group/GroupOwnerModel.d.ts +4 -5
  35. package/dist/models/injection_field/DocumentInjectionFieldModel.d.ts +4 -5
  36. package/dist/models/injection_field/InjectionFieldModel.d.ts +4 -5
  37. package/dist/models/injection_field/ItemInjectionFieldModel.d.ts +4 -5
  38. package/dist/models/injection_field/LogisticInjectionFieldModel.d.ts +4 -5
  39. package/dist/models/injection_field/RepositoryInjectionFieldModel.d.ts +4 -5
  40. package/dist/models/injection_field/UserInjectionFieldModel.d.ts +4 -5
  41. package/dist/models/item/BrandModel.d.ts +4 -5
  42. package/dist/models/item/CategoryModel.d.ts +4 -5
  43. package/dist/models/item/ItemModel.d.ts +4 -5
  44. package/dist/models/item/ProductModel.d.ts +4 -5
  45. package/dist/models/item/UomModel.d.ts +4 -5
  46. package/dist/models/location/LocationModel.d.ts +4 -5
  47. package/dist/models/location/LocationRackModel.d.ts +4 -5
  48. package/dist/models/location/LocationSlotModel.d.ts +4 -5
  49. package/dist/models/others/NumberDateSequenceModel.d.ts +4 -5
  50. package/dist/models/others/OneTimeCodeModel.d.ts +4 -5
  51. package/dist/models/region/AreaModel.d.ts +4 -5
  52. package/dist/models/region/CountryModel.d.ts +4 -5
  53. package/dist/models/region/StateModel.d.ts +4 -5
  54. package/dist/models/repository/RepositoryCartonModel.d.ts +4 -5
  55. package/dist/models/repository/RepositoryContainerModel.d.ts +4 -5
  56. package/dist/models/repository/RepositoryModel.d.ts +4 -5
  57. package/dist/models/repository/RepositoryPackageItemModel.d.ts +4 -5
  58. package/dist/models/repository/RepositoryPackageModel.d.ts +4 -5
  59. package/dist/models/repository/RepositoryPalletModel.d.ts +4 -5
  60. package/dist/models/scheduler/SchedulerLogModel.d.ts +4 -5
  61. package/dist/models/scheduler/SchedulerRequestModel.d.ts +4 -5
  62. package/dist/models/subscription/account/AccountSubscribeModel.d.ts +4 -5
  63. package/dist/models/subscription/plan/SubscribePlanModel.d.ts +4 -5
  64. package/dist/models/user/AdministratorModel.d.ts +4 -5
  65. package/dist/models/user/AgentModel.d.ts +4 -5
  66. package/dist/models/user/CustomerModel.d.ts +4 -5
  67. package/dist/models/user/DriverModel.d.ts +4 -5
  68. package/dist/models/user/MemberModel.d.ts +4 -5
  69. package/dist/models/user/OperatorModel.d.ts +4 -5
  70. package/dist/models/user/RetailerModel.d.ts +4 -5
  71. package/dist/models/user/UserModel.d.ts +4 -5
  72. package/dist/models/user/UserPropModel.d.ts +4 -5
  73. package/dist/models/user/WorkerModel.d.ts +4 -5
  74. package/dist/schema/payload/document/schemaDocumentCashSales.d.ts +64 -64
  75. package/dist/schema/payload/document/schemaDocumentDeliveryOrder.d.ts +64 -64
  76. package/dist/schema/payload/document/schemaDocumentProformaSales.d.ts +64 -64
  77. package/dist/schema/payload/document/schemaDocumentReplacementDeliveryOrder.d.ts +64 -64
  78. package/dist/schema/payload/document/schemaDocumentSalesOrder.d.ts +64 -64
  79. package/dist/services/branch/UserBranchService.d.ts +2 -2
  80. package/dist/services/branch/UserBranchService.js +53 -22
  81. package/dist/services/branch/UserBranchService.js.map +1 -1
  82. package/dist/services/document/DocumentProfileService.js +47 -19
  83. package/dist/services/document/DocumentProfileService.js.map +1 -1
  84. package/dist/utils/serviceUtils.d.ts +2 -0
  85. package/dist/utils/serviceUtils.js.map +1 -1
  86. package/package.json +1 -1
@@ -5,57 +5,159 @@ const default_1 = require("./default");
5
5
  const utils_1 = require("../../utils");
6
6
  const ModelFactory = ({ debug = false,
7
7
  // prisma,
8
- modelName, primaryKey = "id", accountId, actionUserId, authToken = '', isOperator = false,
9
- // isConsoleTable = false
8
+ modelName, primaryKey = "id", accountId, actionUserId, authToken = '', isOperator = false, tx, // ✅ ADD THIS LINE
10
9
  }) => {
11
10
  // load prisma from core configuration
12
11
  const { prisma: coreConfigPrisma } = (0, utils_1.getCoreConfiguration)();
13
- const selectedPrisma = coreConfigPrisma;
12
+ // const selectedPrisma = coreConfigPrisma
13
+ const selectedPrisma = tx ?? coreConfigPrisma;
14
+ const getSelectedPrisma = () => tx ?? coreConfigPrisma;
15
+ const getModel = () => getSelectedPrisma()[modelName];
14
16
  // const delegate = prisma[modelName] as any;
15
- const delegate = selectedPrisma[modelName];
17
+ // const delegate = selectedPrisma[modelName] as unknown as {
18
+ // create: (args: any) => Promise<TModel>;
19
+ // update: (args: any) => Promise<TModel>;
20
+ // delete: (args: any) => Promise<TModel>;
21
+ // findUnique: (args: any) => Promise<TModel | null>;
22
+ // findFirst: (args: any) => Promise<TModel | null>; // ✅ add this
23
+ // findMany: (args: any) => Promise<TModel[]>;
24
+ // updateMany: (args: any) => Promise<{ count: number }>; // ✅ useful for update
25
+ // };
26
+ // const getFields = async (
27
+ // prefix?: string,
28
+ // excludeKeywords: string[] = []
29
+ // ): Promise<Column[]> => {
30
+ // // 👇 Tell TS exactly what comes back from selectedPrisma
31
+ // const fields: ColumnInfo[] = await selectedPrisma.$queryRaw<ColumnInfo[]>`
32
+ // SELECT column_name, data_type
33
+ // FROM information_schema.columns
34
+ // WHERE table_name = ${String(modelName)}
35
+ // `;
36
+ // return fields
37
+ // .map((f: ColumnInfo): Column => ({
38
+ // name: f.column_name,
39
+ // type: f.data_type,
40
+ // }))
41
+ // .filter((c: Column) => !prefix || c.name.startsWith(prefix))
42
+ // .filter((c: Column) => !excludeKeywords.some((kw) => c.name.includes(kw)));
43
+ // };
16
44
  const getFields = async (prefix, excludeKeywords = []) => {
17
- // 👇 Tell TS exactly what comes back from selectedPrisma
18
- const fields = await selectedPrisma.$queryRaw `
45
+ const run = async (client) => {
46
+ const fields = await client.$queryRaw `
19
47
  SELECT column_name, data_type
20
48
  FROM information_schema.columns
21
49
  WHERE table_name = ${String(modelName)}
22
50
  `;
23
- return fields
24
- .map((f) => ({
25
- name: f.column_name,
26
- type: f.data_type,
27
- }))
28
- .filter((c) => !prefix || c.name.startsWith(prefix))
29
- .filter((c) => !excludeKeywords.some((kw) => c.name.includes(kw)));
51
+ return fields
52
+ .map((f) => ({
53
+ name: f.column_name,
54
+ type: f.data_type,
55
+ }))
56
+ .filter((c) => !prefix || c.name.startsWith(prefix))
57
+ .filter((c) => !excludeKeywords.some((kw) => c.name.includes(kw)));
58
+ };
59
+ // 🔥 external transaction support
60
+ if (tx) {
61
+ return run(tx);
62
+ }
63
+ // 🔥 fallback to global prisma
64
+ return run(selectedPrisma);
30
65
  };
31
- // const getFields = async (
32
- // prefix?: string,
33
- // excludeKeywords?: string[]
34
- // ): Promise<{ name: string; type: string }[]> => {
35
- // const fields = await selectedPrisma.$queryRaw<{ column_name: string; data_type: string }[]>`
36
- // SELECT column_name, data_type
37
- // FROM information_schema.columns
38
- // WHERE table_name = ${String(modelName)}
39
- // `;
40
- // let cols = fields.map(f => ({ name: f.column_name, type: f.data_type }));
41
- // if (prefix) {
42
- // cols = cols.filter(c => c.name.startsWith(prefix));
43
- // }
44
- // if (excludeKeywords && excludeKeywords.length > 0) {
45
- // cols = cols.filter(c => !excludeKeywords.some(kw => c.name.includes(kw)));
66
+ // const create = async ({ data }: { data: Omit<any, DefaultOmitFields> }): Promise<TModel> => {
67
+ // // const model = selectedPrisma[modelName] as any;
68
+ // // const model = selectedPrisma[modelName] as TDelegate;
69
+ // const model = getModel() as TDelegate;
70
+ // const _data = {
71
+ // ...data,
72
+ // ...getDefaultCreateFields(actionUserId, accountId),
73
+ // };
74
+ // // if (debug) {
75
+ // // console.log(`[ModelFactory(data)]: ${JSON.stringify(_data)}`)
76
+ // // console.log("[ModelFactory:delegate]", JSON.stringify(Object.keys(selectedPrisma)));
77
+ // // }
78
+ // if (debug) {
79
+ // console.log(`[ModelFactory:create:${String(modelName)}]`, _data);
46
80
  // }
47
- // return cols;
81
+ // // return delegate.create({
82
+ // // data: _data,
83
+ // // });
84
+ // return model.create({
85
+ // data: _data,
86
+ // });
48
87
  // };
49
- const create = async ({ data }) => {
50
- const _data = { ...data, ...(0, default_1.getDefaultCreateFields)(actionUserId, accountId) };
51
- if (debug) {
52
- console.log(`[ModelFactory(data)]: ${JSON.stringify(_data)}`);
53
- console.log("[ModelFactory:delegate]", JSON.stringify(Object.keys(selectedPrisma)));
88
+ const create = async ({ data, }) => {
89
+ const run = async (client) => {
90
+ const model = client[modelName];
91
+ const _data = {
92
+ ...data,
93
+ ...(0, default_1.getDefaultCreateFields)(actionUserId, accountId),
94
+ };
95
+ if (debug) {
96
+ console.log(`[ModelFactory:create:${String(modelName)}]`, _data);
97
+ }
98
+ return model.create({
99
+ data: _data,
100
+ });
101
+ };
102
+ // 🔥 external transaction support
103
+ if (tx) {
104
+ return run(tx);
54
105
  }
55
- return delegate.create({
56
- data: _data,
57
- });
106
+ // 🔥 internal transaction fallback (ensures rollback safety)
107
+ return selectedPrisma.$transaction(run);
58
108
  };
109
+ // const createMany = async ({
110
+ // dataList,
111
+ // disableRollback = false,
112
+ // }: {
113
+ // dataList: Omit<any, DefaultOmitFields>[];
114
+ // disableRollback?: boolean;
115
+ // }): Promise<TModel[]> => {
116
+ // if (!Array.isArray(dataList) || dataList.length === 0) {
117
+ // throw new Error("createMany: dataList cannot be empty.");
118
+ // }
119
+ // if (debug) {
120
+ // console.log(`[ModelFactory(createMany)]: count=${dataList.length}`);
121
+ // }
122
+ // return selectedPrisma.$transaction(async (tx: typeof selectedPrisma) => {
123
+ // const modelTx = (tx as any)[modelName] as {
124
+ // createMany: (args: any) => Promise<{ count: number }>;
125
+ // findMany: (args: any) => Promise<TModel[]>;
126
+ // };
127
+ // // inject system fields for each record
128
+ // const records = dataList.map((d) => ({
129
+ // ...d,
130
+ // ...getDefaultCreateFields(actionUserId, accountId),
131
+ // }));
132
+ // const result = await modelTx.createMany({
133
+ // data: records,
134
+ // });
135
+ // if (disableRollback === false) {
136
+ // if (!result.count || result.count !== dataList.length) {
137
+ // throw new Error("Error: Not all records were inserted.");
138
+ // }
139
+ // }
140
+ // // re-fetch the inserted records (if they have predictable keys)
141
+ // // only works if they share identifiable property (like foreign key)
142
+ // // or you can just return records if no need to verify
143
+ // let inserted: TModel[] = [];
144
+ // try {
145
+ // inserted = await modelTx.findMany({
146
+ // where: {
147
+ // ...(isOperator === false ? { accountid: accountId } : {}),
148
+ // ...getDefaultGetWhere,
149
+ // },
150
+ // orderBy: {
151
+ // [primaryKey as string]: "desc",
152
+ // },
153
+ // take: dataList.length,
154
+ // });
155
+ // } catch (err) {
156
+ // if (debug) console.warn("Could not re-fetch newly created records:", err);
157
+ // }
158
+ // return inserted;
159
+ // });
160
+ // };
59
161
  const createMany = async ({ dataList, disableRollback = false, }) => {
60
162
  if (!Array.isArray(dataList) || dataList.length === 0) {
61
163
  throw new Error("createMany: dataList cannot be empty.");
@@ -63,27 +165,21 @@ modelName, primaryKey = "id", accountId, actionUserId, authToken = '', isOperato
63
165
  if (debug) {
64
166
  console.log(`[ModelFactory(createMany)]: count=${dataList.length}`);
65
167
  }
66
- return selectedPrisma.$transaction(async (tx) => {
67
- const modelTx = tx[modelName];
68
- // inject system fields for each record
168
+ const run = async (client) => {
169
+ const model = client[modelName];
69
170
  const records = dataList.map((d) => ({
70
171
  ...d,
71
172
  ...(0, default_1.getDefaultCreateFields)(actionUserId, accountId),
72
173
  }));
73
- const result = await modelTx.createMany({
174
+ const result = await model.createMany({
74
175
  data: records,
75
176
  });
76
- if (disableRollback === false) {
77
- if (!result.count || result.count !== dataList.length) {
78
- throw new Error("Error: Not all records were inserted.");
79
- }
177
+ if (!disableRollback && result.count !== dataList.length) {
178
+ throw new Error("Error: Not all records were inserted.");
80
179
  }
81
- // re-fetch the inserted records (if they have predictable keys)
82
- // only works if they share identifiable property (like foreign key)
83
- // or you can just return records if no need to verify
84
180
  let inserted = [];
85
181
  try {
86
- inserted = await modelTx.findMany({
182
+ inserted = await model.findMany({
87
183
  where: {
88
184
  ...(isOperator === false ? { accountid: accountId } : {}),
89
185
  ...default_1.getDefaultGetWhere,
@@ -99,126 +195,335 @@ modelName, primaryKey = "id", accountId, actionUserId, authToken = '', isOperato
99
195
  console.warn("Could not re-fetch newly created records:", err);
100
196
  }
101
197
  return inserted;
102
- });
198
+ };
199
+ // 🔥 external transaction support
200
+ if (tx) {
201
+ return run(tx);
202
+ }
203
+ // 🔥 internal transaction fallback
204
+ return selectedPrisma.$transaction(run);
103
205
  };
206
+ // const get = async ({
207
+ // id,
208
+ // where,
209
+ // include,
210
+ // }: {
211
+ // id?: number;
212
+ // where?: Record<string, any>;
213
+ // include?: any;
214
+ // }): Promise<TModel | null> => {
215
+ // const condition = id ? { [primaryKey]: id } : where ?? {};
216
+ // const condition2 = isOperator === false ? { accountid: accountId } : {}
217
+ // if (debug) {
218
+ // console.log("[ModelFactory:delegate]", JSON.stringify(Object.keys(selectedPrisma)));
219
+ // }
220
+ // return delegate.findFirst({
221
+ // where: { ...condition, ...condition2, ...getDefaultGetWhere },
222
+ // include,
223
+ // });
224
+ // };
104
225
  const get = async ({ id, where, include, }) => {
105
226
  const condition = id ? { [primaryKey]: id } : where ?? {};
106
227
  const condition2 = isOperator === false ? { accountid: accountId } : {};
107
228
  if (debug) {
108
- console.log("[ModelFactory:delegate]", JSON.stringify(Object.keys(selectedPrisma)));
229
+ console.log("[ModelFactory:get]", JSON.stringify(Object.keys(selectedPrisma)));
230
+ }
231
+ const run = async (client) => {
232
+ const model = client[modelName];
233
+ return model.findFirst({
234
+ where: {
235
+ ...condition,
236
+ ...condition2,
237
+ ...default_1.getDefaultGetWhere,
238
+ },
239
+ include,
240
+ });
241
+ };
242
+ // 🔥 use external transaction if exists
243
+ if (tx) {
244
+ return run(tx);
109
245
  }
110
- return delegate.findFirst({
111
- where: { ...condition, ...condition2, ...default_1.getDefaultGetWhere },
112
- include,
113
- });
246
+ // 🔥 fallback to normal prisma
247
+ return run(selectedPrisma);
114
248
  };
115
- const list = async ({ where, orderBy, offset, limit, include } = {}) => {
249
+ // const list = async ({ where, orderBy, offset, limit, include }: any = {}): Promise<TModel[]> => {
250
+ // if (debug) {
251
+ // console.log("[ModelFactory:delegate]", JSON.stringify(Object.keys(selectedPrisma)));
252
+ // }
253
+ // return delegate.findMany({
254
+ // where,
255
+ // orderBy,
256
+ // skip: offset,
257
+ // take: limit,
258
+ // include,
259
+ // });
260
+ // };
261
+ const list = async ({ where, orderBy, offset, limit, include, } = {}) => {
116
262
  if (debug) {
117
- console.log("[ModelFactory:delegate]", JSON.stringify(Object.keys(selectedPrisma)));
263
+ console.log("[ModelFactory:list]", JSON.stringify(Object.keys(selectedPrisma)));
264
+ }
265
+ const run = async (client) => {
266
+ const model = client[modelName];
267
+ return model.findMany({
268
+ where,
269
+ orderBy,
270
+ skip: offset,
271
+ take: limit,
272
+ include,
273
+ });
274
+ };
275
+ // 🔥 external transaction support
276
+ if (tx) {
277
+ return run(tx);
118
278
  }
119
- return delegate.findMany({
120
- where,
121
- orderBy,
122
- skip: offset,
123
- take: limit,
124
- include,
125
- });
279
+ // 🔥 normal execution
280
+ return run(selectedPrisma);
126
281
  };
127
- const count = async ({ where } = {}) => {
282
+ // const count = async ({ where }: { where?: Record<string, any> } = {}): Promise<number> => {
283
+ // if (debug) {
284
+ // console.log(`[ModelFactory:count:${String(modelName)}] where =`, where);
285
+ // }
286
+ // // Use Prisma's built-in count
287
+ // const result = await (delegate as any).count({
288
+ // where: {
289
+ // ...where,
290
+ // ...(isOperator === false ? { accountid: accountId } : {}),
291
+ // ...getDefaultGetWhere,
292
+ // },
293
+ // });
294
+ // return result ?? 0;
295
+ // };
296
+ const count = async ({ where, } = {}) => {
128
297
  if (debug) {
129
298
  console.log(`[ModelFactory:count:${String(modelName)}] where =`, where);
130
299
  }
131
- // Use Prisma's built-in count
132
- const result = await delegate.count({
133
- where: {
134
- ...where,
135
- ...(isOperator === false ? { accountid: accountId } : {}),
136
- ...default_1.getDefaultGetWhere,
137
- },
138
- });
139
- return result ?? 0;
300
+ const run = async (client) => {
301
+ const model = client[modelName];
302
+ return model.count({
303
+ where: {
304
+ ...where,
305
+ ...(isOperator === false ? { accountid: accountId } : {}),
306
+ ...default_1.getDefaultGetWhere,
307
+ },
308
+ });
309
+ };
310
+ // 🔥 external transaction case
311
+ if (tx) {
312
+ return run(tx);
313
+ }
314
+ // 🔥 normal case (no transaction needed for count)
315
+ return run(selectedPrisma);
140
316
  };
317
+ // const aggregate = async ({
318
+ // field,
319
+ // operation = "sum",
320
+ // where = {},
321
+ // }: {
322
+ // field: keyof TModel;
323
+ // operation?: "sum" | "avg" | "min" | "max" | "count";
324
+ // where?: Record<string, any>;
325
+ // }): Promise<number> => {
326
+ // if (debug) {
327
+ // console.log(`[ModelFactory:aggregate:${String(modelName)}] ${operation}(${String(field)})`, where);
328
+ // }
329
+ // // Build dynamic aggregation key
330
+ // const aggregateKey = `_${operation}` as
331
+ // | "_sum"
332
+ // | "_avg"
333
+ // | "_min"
334
+ // | "_max"
335
+ // | "_count";
336
+ // // Build only the key you need
337
+ // const aggregateInput: Record<string, any> = {
338
+ // [aggregateKey]: { [field]: true },
339
+ // where: {
340
+ // ...where,
341
+ // ...(isOperator === false ? { accountid: accountId } : {}),
342
+ // ...getDefaultGetWhere,
343
+ // },
344
+ // };
345
+ // // Run Prisma aggregate dynamically
346
+ // const result = await (delegate as any).aggregate(aggregateInput);
347
+ // // Extract inner value
348
+ // const inner = result?.[aggregateKey] ?? {};
349
+ // const value = inner?.[field as string] ?? (operation === "count" ? 0 : 0);
350
+ // return Number(value) || 0;
351
+ // }
141
352
  const aggregate = async ({ field, operation = "sum", where = {}, }) => {
142
- if (debug) {
143
- console.log(`[ModelFactory:aggregate:${String(modelName)}] ${operation}(${String(field)})`, where);
144
- }
145
- // Build dynamic aggregation key
146
- const aggregateKey = `_${operation}`;
147
- // Build only the key you need
148
- const aggregateInput = {
149
- [aggregateKey]: { [field]: true },
150
- where: {
151
- ...where,
152
- ...(isOperator === false ? { accountid: accountId } : {}),
153
- ...default_1.getDefaultGetWhere,
154
- },
353
+ const run = async (client) => {
354
+ const model = client[modelName];
355
+ const aggregateKey = `_${operation}`;
356
+ const aggregateInput = {
357
+ [aggregateKey]: { [field]: true },
358
+ where: {
359
+ ...where,
360
+ ...(isOperator === false ? { accountid: accountId } : {}),
361
+ ...default_1.getDefaultGetWhere,
362
+ },
363
+ };
364
+ const result = await model.aggregate(aggregateInput);
365
+ const inner = result?.[aggregateKey] ?? {};
366
+ const value = inner?.[field] ?? 0;
367
+ return Number(value) || 0;
155
368
  };
156
- // Run Prisma aggregate dynamically
157
- const result = await delegate.aggregate(aggregateInput);
158
- // Extract inner value
159
- const inner = result?.[aggregateKey] ?? {};
160
- const value = inner?.[field] ?? (operation === "count" ? 0 : 0);
161
- return Number(value) || 0;
369
+ // 🔥 external tx support
370
+ if (tx) {
371
+ return run(tx);
372
+ }
373
+ // 🔥 internal fallback
374
+ return selectedPrisma.$transaction(run);
162
375
  };
376
+ // const update = async ({ id, where, data, disableRollback = false }: {
377
+ // id?: number;
378
+ // where?: Record<string, any>;
379
+ // data: Partial<TModel>,
380
+ // disableRollback?: Boolean
381
+ // }): Promise<TModel> => {
382
+ // if (debug) {
383
+ // console.log(`[ModelFactory(data)]: ${JSON.stringify(data)}`)
384
+ // console.log("[ModelFactory:delegate]", JSON.stringify(Object.keys(selectedPrisma)));
385
+ // }
386
+ // return selectedPrisma.$transaction(async (tx: typeof selectedPrisma) => {
387
+ // const modelTx = (tx as any)[modelName] as TxModel<TModel>;
388
+ // // prefer primary key if provided, otherwise fall back to custom where
389
+ // let finalWhere = id ?
390
+ // {
391
+ // [primaryKey]: id,
392
+ // ...getDefaultUpdateWhere,
393
+ // ...(isOperator === false ? { accountid: accountId } : {}),
394
+ // }
395
+ // :
396
+ // {
397
+ // ...where,
398
+ // ...getDefaultUpdateWhere,
399
+ // ...(isOperator === false ? { accountid: accountId } : {}),
400
+ // };
401
+ // const result = await modelTx.updateMany({
402
+ // where: finalWhere,
403
+ // data: { ...data, ...getDefaultUpdateFields(actionUserId) },
404
+ // });
405
+ // if (disableRollback === false) {
406
+ // if (!result.count) {
407
+ // throw new Error(errorRecordNotFoundAlreadyDeleted);
408
+ // }
409
+ // }
410
+ // // const updatedRecord = await modelTx.findUnique({ where: { [primaryKey]: id } });
411
+ // let updatedRecord: TModel | null = null;
412
+ // if (id) {
413
+ // // use findUnique when updating by primary key
414
+ // updatedRecord = await modelTx.findUnique({ where: { [primaryKey]: id } });
415
+ // } else {
416
+ // // use findFirst when updating by other field(s)
417
+ // updatedRecord = await (modelTx as any).findFirst({ where: finalWhere });
418
+ // }
419
+ // if (disableRollback === false) {
420
+ // if (!updatedRecord) {
421
+ // throw new Error(errorRecordNotFoundAfterUpdated);
422
+ // }
423
+ // }
424
+ // return updatedRecord;
425
+ // });
426
+ // };
163
427
  const update = async ({ id, where, data, disableRollback = false }) => {
164
- if (debug) {
165
- console.log(`[ModelFactory(data)]: ${JSON.stringify(data)}`);
166
- console.log("[ModelFactory:delegate]", JSON.stringify(Object.keys(selectedPrisma)));
167
- }
168
- return selectedPrisma.$transaction(async (tx) => {
169
- const modelTx = tx[modelName];
170
- // prefer primary key if provided, otherwise fall back to custom where
171
- let finalWhere = id ?
172
- {
428
+ const run = async (client) => {
429
+ const model = client[modelName];
430
+ const finalWhere = id
431
+ ? {
173
432
  [primaryKey]: id,
174
433
  ...default_1.getDefaultUpdateWhere,
175
434
  ...(isOperator === false ? { accountid: accountId } : {}),
176
435
  }
177
- :
178
- {
179
- ...where,
180
- ...default_1.getDefaultUpdateWhere,
181
- ...(isOperator === false ? { accountid: accountId } : {}),
182
- };
183
- const result = await modelTx.updateMany({
436
+ : {
437
+ ...where,
438
+ ...default_1.getDefaultUpdateWhere,
439
+ ...(isOperator === false ? { accountid: accountId } : {}),
440
+ };
441
+ const result = await model.updateMany({
184
442
  where: finalWhere,
185
- data: { ...data, ...(0, default_1.getDefaultUpdateFields)(actionUserId) },
443
+ data: {
444
+ ...data,
445
+ ...(0, default_1.getDefaultUpdateFields)(actionUserId),
446
+ },
186
447
  });
187
- if (disableRollback === false) {
188
- if (!result.count) {
189
- throw new Error(default_1.errorRecordNotFoundAlreadyDeleted);
190
- }
191
- }
192
- // const updatedRecord = await modelTx.findUnique({ where: { [primaryKey]: id } });
193
- let updatedRecord = null;
194
- if (id) {
195
- // use findUnique when updating by primary key
196
- updatedRecord = await modelTx.findUnique({ where: { [primaryKey]: id } });
197
- }
198
- else {
199
- // use findFirst when updating by other field(s)
200
- updatedRecord = await modelTx.findFirst({ where: finalWhere });
448
+ if (!disableRollback && result.count === 0) {
449
+ throw new Error(default_1.errorRecordNotFoundAlreadyDeleted);
201
450
  }
202
- if (disableRollback === false) {
203
- if (!updatedRecord) {
204
- throw new Error(default_1.errorRecordNotFoundAfterUpdated);
205
- }
451
+ const updated = id
452
+ ? await model.findUnique({ where: { [primaryKey]: id } })
453
+ : await model.findFirst({ where: finalWhere });
454
+ if (!disableRollback && !updated) {
455
+ throw new Error(default_1.errorRecordNotFoundAfterUpdated);
206
456
  }
207
- return updatedRecord;
208
- });
457
+ return updated;
458
+ };
459
+ // ✅ external transaction support
460
+ if (tx) {
461
+ return run(tx);
462
+ }
463
+ // ✅ internal transaction fallback
464
+ return selectedPrisma.$transaction(run);
209
465
  };
466
+ // const updateMany = async ({
467
+ // dataList,
468
+ // disableRollback = false,
469
+ // }: {
470
+ // dataList: { where: Record<string, any>; data: Partial<TModel> }[];
471
+ // disableRollback?: boolean;
472
+ // }): Promise<TModel[]> => {
473
+ // if (!Array.isArray(dataList) || dataList.length === 0) {
474
+ // throw new Error("updateMany: dataList cannot be empty.");
475
+ // }
476
+ // if (debug) {
477
+ // console.log(`[ModelFactory(updateMany)]: count=${dataList.length}`);
478
+ // }
479
+ // return selectedPrisma.$transaction(async (tx: typeof selectedPrisma) => {
480
+ // const modelTx = (tx as any)[modelName] as TxModel<TModel> & {
481
+ // findMany: (args: any) => Promise<TModel[]>;
482
+ // };
483
+ // let totalUpdated = 0;
484
+ // for (const { where, data } of dataList) {
485
+ // const result = await modelTx.updateMany({
486
+ // where: {
487
+ // ...where,
488
+ // ...getDefaultUpdateWhere,
489
+ // },
490
+ // data: {
491
+ // ...data,
492
+ // ...getDefaultUpdateFields(actionUserId),
493
+ // },
494
+ // });
495
+ // totalUpdated += result.count;
496
+ // }
497
+ // if (disableRollback === false && totalUpdated === 0) {
498
+ // throw new Error(errorRecordNotFoundAlreadyDeleted);
499
+ // }
500
+ // // Attempt to refetch updated records for confirmation
501
+ // let updatedRecords: TModel[] = [];
502
+ // try {
503
+ // const allWhere = dataList.map(d => d.where);
504
+ // // Combine OR condition if Prisma supports OR for this table
505
+ // updatedRecords = await modelTx.findMany({
506
+ // where: {
507
+ // OR: allWhere,
508
+ // ...(isOperator === false ? { accountid: accountId } : {}),
509
+ // ...getDefaultGetWhere,
510
+ // },
511
+ // });
512
+ // } catch (err) {
513
+ // if (debug) console.warn("Could not re-fetch updated records:", err);
514
+ // }
515
+ // return updatedRecords;
516
+ // });
517
+ // };
210
518
  const updateMany = async ({ dataList, disableRollback = false, }) => {
211
519
  if (!Array.isArray(dataList) || dataList.length === 0) {
212
520
  throw new Error("updateMany: dataList cannot be empty.");
213
521
  }
214
- if (debug) {
215
- console.log(`[ModelFactory(updateMany)]: count=${dataList.length}`);
216
- }
217
- return selectedPrisma.$transaction(async (tx) => {
218
- const modelTx = tx[modelName];
522
+ const run = async (txClient) => {
523
+ const model = txClient[modelName];
219
524
  let totalUpdated = 0;
220
525
  for (const { where, data } of dataList) {
221
- const result = await modelTx.updateMany({
526
+ const result = await model.updateMany({
222
527
  where: {
223
528
  ...where,
224
529
  ...default_1.getDefaultUpdateWhere,
@@ -230,96 +535,189 @@ modelName, primaryKey = "id", accountId, actionUserId, authToken = '', isOperato
230
535
  });
231
536
  totalUpdated += result.count;
232
537
  }
233
- if (disableRollback === false && totalUpdated === 0) {
538
+ if (!disableRollback && totalUpdated === 0) {
234
539
  throw new Error(default_1.errorRecordNotFoundAlreadyDeleted);
235
540
  }
236
- // Attempt to refetch updated records for confirmation
237
- let updatedRecords = [];
238
- try {
239
- const allWhere = dataList.map(d => d.where);
240
- // Combine OR condition if Prisma supports OR for this table
241
- updatedRecords = await modelTx.findMany({
242
- where: {
243
- OR: allWhere,
244
- ...(isOperator === false ? { accountid: accountId } : {}),
245
- ...default_1.getDefaultGetWhere,
246
- },
247
- });
248
- }
249
- catch (err) {
250
- if (debug)
251
- console.warn("Could not re-fetch updated records:", err);
252
- }
253
- return updatedRecords;
254
- });
541
+ return model.findMany({
542
+ where: {
543
+ OR: dataList.map(d => d.where),
544
+ ...(isOperator === false ? { accountid: accountId } : {}),
545
+ ...default_1.getDefaultGetWhere,
546
+ },
547
+ });
548
+ };
549
+ // 🔥 transaction boundary ONLY here
550
+ if (tx) {
551
+ return run(tx);
552
+ }
553
+ return selectedPrisma.$transaction(run);
255
554
  };
555
+ // const trash = async ({ ids }: { ids: number[] }): Promise<TModel[]> => {
556
+ // if (debug) {
557
+ // console.log("[ModelFactory:delegate]", JSON.stringify(Object.keys(selectedPrisma)));
558
+ // }
559
+ // return selectedPrisma.$transaction(async (tx: typeof selectedPrisma) => {
560
+ // const modelTx = (tx as any)[modelName] as TxModel<TModel>;
561
+ // const result = await modelTx.updateMany({
562
+ // where: { [primaryKey]: { in: ids }, ...getDefaultTrashWhere },
563
+ // data: { ...getDefaultTrashFields(actionUserId) },
564
+ // });
565
+ // if (!result.count || result.count !== ids.length)
566
+ // throw new Error(errorRecordNotFoundAlreadyDeleted);
567
+ // const updated = await modelTx.findMany!({ where: { [primaryKey]: { in: ids } } });
568
+ // if (!updated.length) throw new Error(errorRecordNotFoundAfterTrashed);
569
+ // return updated;
570
+ // });
571
+ // };
256
572
  const trash = async ({ ids }) => {
257
573
  if (debug) {
258
- console.log("[ModelFactory:delegate]", JSON.stringify(Object.keys(selectedPrisma)));
574
+ console.log("[ModelFactory:trash]", JSON.stringify(Object.keys(selectedPrisma)));
259
575
  }
260
- return selectedPrisma.$transaction(async (tx) => {
261
- const modelTx = tx[modelName];
262
- const result = await modelTx.updateMany({
263
- where: { [primaryKey]: { in: ids }, ...default_1.getDefaultTrashWhere },
264
- data: { ...(0, default_1.getDefaultTrashFields)(actionUserId) },
576
+ const run = async (client) => {
577
+ const model = client[modelName];
578
+ const result = await model.updateMany({
579
+ where: {
580
+ [primaryKey]: { in: ids },
581
+ ...default_1.getDefaultTrashWhere,
582
+ },
583
+ data: {
584
+ ...(0, default_1.getDefaultTrashFields)(actionUserId),
585
+ },
265
586
  });
266
- if (!result.count || result.count !== ids.length)
587
+ if (!result.count || result.count !== ids.length) {
267
588
  throw new Error(default_1.errorRecordNotFoundAlreadyDeleted);
268
- const updated = await modelTx.findMany({ where: { [primaryKey]: { in: ids } } });
269
- if (!updated.length)
589
+ }
590
+ const updated = await model.findMany({
591
+ where: { [primaryKey]: { in: ids } },
592
+ });
593
+ if (!updated.length) {
270
594
  throw new Error(default_1.errorRecordNotFoundAfterTrashed);
595
+ }
271
596
  return updated;
272
- });
597
+ };
598
+ // ✅ external transaction support
599
+ if (tx) {
600
+ return run(tx);
601
+ }
602
+ // ✅ internal fallback transaction
603
+ return selectedPrisma.$transaction(run);
273
604
  };
605
+ // const remove = async ({ ids, where }: { ids?: number[], where?: Record<string, any>; }): Promise<TModel[]> => {
606
+ // if (debug) {
607
+ // console.log("[ModelFactory:delegate]", JSON.stringify(Object.keys(selectedPrisma)));
608
+ // }
609
+ // return selectedPrisma.$transaction(async (tx: typeof selectedPrisma) => {
610
+ // const modelTx = (tx as any)[modelName] as TxModel<TModel>;
611
+ // // prefer primary ids if provided, otherwise fall back to custom where
612
+ // const finalWhere = ids
613
+ // ? { [primaryKey]: { in: ids }, ...getDefaultRemoveWhere }
614
+ // : { ...where, ...getDefaultRemoveWhere };
615
+ // const result = await modelTx.updateMany({
616
+ // where: finalWhere,
617
+ // data: { ...getDefaultRemoveFields(actionUserId) },
618
+ // });
619
+ // // if (!result.count) throw new Error(errorRecordNotFoundAlreadyDeleted);
620
+ // if (!result.count) {
621
+ // // no rows touched → just return []
622
+ // return [];
623
+ // }
624
+ // let updated: TModel[] | null;
625
+ // if (ids) {
626
+ // updated = await modelTx.findMany!({ where: { [primaryKey]: { in: ids } } });
627
+ // } else {
628
+ // updated = await modelTx.findMany!({ where });
629
+ // }
630
+ // if (!updated || updated.length === 0) {
631
+ // throw new Error(errorRecordNotFoundAfterRemoved);
632
+ // }
633
+ // return updated;
634
+ // });
635
+ // };
274
636
  const remove = async ({ ids, where }) => {
275
637
  if (debug) {
276
- console.log("[ModelFactory:delegate]", JSON.stringify(Object.keys(selectedPrisma)));
638
+ console.log("[ModelFactory:remove]", JSON.stringify(Object.keys(selectedPrisma)));
277
639
  }
278
- return selectedPrisma.$transaction(async (tx) => {
279
- const modelTx = tx[modelName];
280
- // prefer primary ids if provided, otherwise fall back to custom where
640
+ const run = async (client) => {
641
+ const model = client[modelName];
281
642
  const finalWhere = ids
282
- ? { [primaryKey]: { in: ids }, ...default_1.getDefaultRemoveWhere }
283
- : { ...where, ...default_1.getDefaultRemoveWhere };
284
- const result = await modelTx.updateMany({
643
+ ? {
644
+ [primaryKey]: { in: ids },
645
+ ...default_1.getDefaultRemoveWhere,
646
+ }
647
+ : {
648
+ ...where,
649
+ ...default_1.getDefaultRemoveWhere,
650
+ };
651
+ const result = await model.updateMany({
285
652
  where: finalWhere,
286
- data: { ...(0, default_1.getDefaultRemoveFields)(actionUserId) },
653
+ data: {
654
+ ...(0, default_1.getDefaultRemoveFields)(actionUserId),
655
+ },
287
656
  });
288
- // if (!result.count) throw new Error(errorRecordNotFoundAlreadyDeleted);
289
657
  if (!result.count) {
290
- // no rows touched → just return []
291
658
  return [];
292
659
  }
293
- let updated;
294
- if (ids) {
295
- updated = await modelTx.findMany({ where: { [primaryKey]: { in: ids } } });
296
- }
297
- else {
298
- updated = await modelTx.findMany({ where });
299
- }
660
+ const updated = ids
661
+ ? await model.findMany({
662
+ where: { [primaryKey]: { in: ids } },
663
+ })
664
+ : await model.findMany({
665
+ where,
666
+ });
300
667
  if (!updated || updated.length === 0) {
301
668
  throw new Error(default_1.errorRecordNotFoundAfterRemoved);
302
669
  }
303
670
  return updated;
304
- });
671
+ };
672
+ // 🔥 external transaction support
673
+ if (tx) {
674
+ return run(tx);
675
+ }
676
+ // 🔥 internal transaction fallback
677
+ return selectedPrisma.$transaction(run);
305
678
  };
306
679
  // Used for SELECT queries (read operations)
680
+ // const raw = async <T = any>(query: string, params: any[] = []): Promise<T[]> => {
681
+ // if (debug) {
682
+ // console.log("[ModelFactory:delegate]", JSON.stringify(Object.keys(selectedPrisma)));
683
+ // }
684
+ // // const client = prisma as unknown as PrismaClient;
685
+ // const client = selectedPrisma as unknown as PrismaClient;
686
+ // // return prisma.$queryRawUnsafe<T[]>(query, ...params);
687
+ // return client.$queryRawUnsafe<T[]>(query, ...params);
688
+ // };
307
689
  const raw = async (query, params = []) => {
308
- if (debug) {
309
- console.log("[ModelFactory:delegate]", JSON.stringify(Object.keys(selectedPrisma)));
690
+ const run = async (client) => {
691
+ return client.$queryRawUnsafe(query, ...params);
692
+ };
693
+ // 🔥 use tx if exists
694
+ if (tx) {
695
+ return run(tx);
310
696
  }
311
- // const client = prisma as unknown as PrismaClient;
312
- const client = selectedPrisma;
313
- // return prisma.$queryRawUnsafe<T[]>(query, ...params);
314
- return client.$queryRawUnsafe(query, ...params);
697
+ // 🔥 fallback to global prisma
698
+ return run(selectedPrisma);
315
699
  };
316
700
  // Used for mutations (INSERT, UPDATE, DELETE, DDL like CREATE TABLE etc.)
317
- const rawExec = async (query, params = []) => {
318
- if (debug) {
319
- console.log("[ModelFactory:delegate]", JSON.stringify(Object.keys(selectedPrisma)));
320
- }
321
- return selectedPrisma.$executeRawUnsafe(query, ...params); // returns number of affected rows
322
- };
701
+ // const rawExec = async (query: string, params: any[] = []): Promise<number> => {
702
+ // if (debug) {
703
+ // console.log("[ModelFactory:delegate]", JSON.stringify(Object.keys(selectedPrisma)));
704
+ // }
705
+ // return selectedPrisma.$executeRawUnsafe(query, ...params); // returns number of affected rows
706
+ // };
707
+ // const rawExec = async (
708
+ // query: string,
709
+ // params: any[] = []
710
+ // ): Promise<number> => {
711
+ // const run = async (client: any) => {
712
+ // return client.$executeRawUnsafe(query, ...params);
713
+ // };
714
+ // // 🔥 if external tx exists → use it
715
+ // if (tx) {
716
+ // return run(tx);
717
+ // }
718
+ // // 🔥 otherwise use global prisma (no transaction wrapper needed for raw exec)
719
+ // return run(selectedPrisma);
720
+ // };
323
721
  return {
324
722
  selectedPrisma,
325
723
  primaryKey,
@@ -335,7 +733,7 @@ modelName, primaryKey = "id", accountId, actionUserId, authToken = '', isOperato
335
733
  trash,
336
734
  remove,
337
735
  raw,
338
- rawExec
736
+ // rawExec
339
737
  };
340
738
  };
341
739
  exports.ModelFactory = ModelFactory;