@eeplatform/core 1.4.4 → 1.5.0

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.
package/dist/index.js CHANGED
@@ -10384,7 +10384,7 @@ var require_ms = __commonJS({
10384
10384
  options = options || {};
10385
10385
  var type = typeof val;
10386
10386
  if (type === "string" && val.length > 0) {
10387
- return parse(val);
10387
+ return parse4(val);
10388
10388
  } else if (type === "number" && isNaN(val) === false) {
10389
10389
  return options.long ? fmtLong(val) : fmtShort(val);
10390
10390
  }
@@ -10392,7 +10392,7 @@ var require_ms = __commonJS({
10392
10392
  "val is not a non-empty string or a valid number. val=" + JSON.stringify(val)
10393
10393
  );
10394
10394
  };
10395
- function parse(str) {
10395
+ function parse4(str) {
10396
10396
  str = String(str);
10397
10397
  if (str.length > 100) {
10398
10398
  return;
@@ -10839,7 +10839,7 @@ var require_follow_redirects = __commonJS({
10839
10839
  (function detectUnsupportedEnvironment() {
10840
10840
  var looksLikeNode = typeof process !== "undefined";
10841
10841
  var looksLikeBrowser = typeof window !== "undefined" && typeof document !== "undefined";
10842
- var looksLikeV8 = isFunction2(Error.captureStackTrace);
10842
+ var looksLikeV8 = isFunction3(Error.captureStackTrace);
10843
10843
  if (!looksLikeNode && (looksLikeBrowser || !looksLikeV8)) {
10844
10844
  console.warn("The follow-redirects package should be excluded from browser builds.");
10845
10845
  }
@@ -10934,7 +10934,7 @@ var require_follow_redirects = __commonJS({
10934
10934
  if (!isString2(data) && !isBuffer2(data)) {
10935
10935
  throw new TypeError("data should be a string, Buffer or Uint8Array");
10936
10936
  }
10937
- if (isFunction2(encoding)) {
10937
+ if (isFunction3(encoding)) {
10938
10938
  callback = encoding;
10939
10939
  encoding = null;
10940
10940
  }
@@ -10954,10 +10954,10 @@ var require_follow_redirects = __commonJS({
10954
10954
  }
10955
10955
  };
10956
10956
  RedirectableRequest.prototype.end = function(data, encoding, callback) {
10957
- if (isFunction2(data)) {
10957
+ if (isFunction3(data)) {
10958
10958
  callback = data;
10959
10959
  data = encoding = null;
10960
- } else if (isFunction2(encoding)) {
10960
+ } else if (isFunction3(encoding)) {
10961
10961
  callback = encoding;
10962
10962
  encoding = null;
10963
10963
  }
@@ -11158,7 +11158,7 @@ var require_follow_redirects = __commonJS({
11158
11158
  if (redirectUrl.protocol !== currentUrlParts.protocol && redirectUrl.protocol !== "https:" || redirectUrl.host !== currentHost && !isSubdomain(redirectUrl.host, currentHost)) {
11159
11159
  removeMatchingHeaders(/^(?:(?:proxy-)?authorization|cookie)$/i, this._options.headers);
11160
11160
  }
11161
- if (isFunction2(beforeRedirect)) {
11161
+ if (isFunction3(beforeRedirect)) {
11162
11162
  var responseDetails = {
11163
11163
  headers: response.headers,
11164
11164
  statusCode
@@ -11193,7 +11193,7 @@ var require_follow_redirects = __commonJS({
11193
11193
  options = validateUrl(input);
11194
11194
  input = { protocol };
11195
11195
  }
11196
- if (isFunction2(options)) {
11196
+ if (isFunction3(options)) {
11197
11197
  callback = options;
11198
11198
  options = null;
11199
11199
  }
@@ -11273,7 +11273,7 @@ var require_follow_redirects = __commonJS({
11273
11273
  }
11274
11274
  function createErrorType(code, message, baseClass) {
11275
11275
  function CustomError(properties) {
11276
- if (isFunction2(Error.captureStackTrace)) {
11276
+ if (isFunction3(Error.captureStackTrace)) {
11277
11277
  Error.captureStackTrace(this, this.constructor);
11278
11278
  }
11279
11279
  Object.assign(this, properties || {});
@@ -11308,7 +11308,7 @@ var require_follow_redirects = __commonJS({
11308
11308
  function isString2(value) {
11309
11309
  return typeof value === "string" || value instanceof String;
11310
11310
  }
11311
- function isFunction2(value) {
11311
+ function isFunction3(value) {
11312
11312
  return typeof value === "function";
11313
11313
  }
11314
11314
  function isBuffer2(value) {
@@ -11345,12 +11345,14 @@ __export(src_exports, {
11345
11345
  MAsset: () => MAsset,
11346
11346
  MBuilding: () => MBuilding,
11347
11347
  MBuildingUnit: () => MBuildingUnit,
11348
+ MCurriculum: () => MCurriculum,
11348
11349
  MDivision: () => MDivision,
11349
11350
  MEntity: () => MEntity,
11350
11351
  MFile: () => MFile,
11351
11352
  MMember: () => MMember,
11352
11353
  MONGO_DB: () => MONGO_DB,
11353
11354
  MONGO_URI: () => MONGO_URI,
11355
+ MOffice: () => MOffice,
11354
11356
  MOrder: () => MOrder,
11355
11357
  MOrg: () => MOrg,
11356
11358
  MPaymentMethod: () => MPaymentMethod,
@@ -11391,7 +11393,9 @@ __export(src_exports, {
11391
11393
  schemaAssetUpdateOption: () => schemaAssetUpdateOption,
11392
11394
  schemaBuilding: () => schemaBuilding,
11393
11395
  schemaBuildingUnit: () => schemaBuildingUnit,
11396
+ schemaCurriculum: () => schemaCurriculum,
11394
11397
  schemaDivision: () => schemaDivision,
11398
+ schemaOffice: () => schemaOffice,
11395
11399
  schemaPlantilla: () => schemaPlantilla,
11396
11400
  schemaRegion: () => schemaRegion,
11397
11401
  schemaSchool: () => schemaSchool,
@@ -11409,6 +11413,8 @@ __export(src_exports, {
11409
11413
  useBuildingUnitRepo: () => useBuildingUnitRepo,
11410
11414
  useCounterModel: () => useCounterModel,
11411
11415
  useCounterRepo: () => useCounterRepo,
11416
+ useCurriculumController: () => useCurriculumController,
11417
+ useCurriculumRepo: () => useCurriculumRepo,
11412
11418
  useDivisionController: () => useDivisionController,
11413
11419
  useDivisionRepo: () => useDivisionRepo,
11414
11420
  useDivisionService: () => useDivisionService,
@@ -11424,6 +11430,9 @@ __export(src_exports, {
11424
11430
  useInvoiceService: () => useInvoiceService,
11425
11431
  useMemberController: () => useMemberController,
11426
11432
  useMemberRepo: () => useMemberRepo,
11433
+ useOfficeController: () => useOfficeController,
11434
+ useOfficeRepo: () => useOfficeRepo,
11435
+ useOfficeService: () => useOfficeService,
11427
11436
  useOrderController: () => useOrderController,
11428
11437
  useOrderRepo: () => useOrderRepo,
11429
11438
  useOrgController: () => useOrgController,
@@ -13652,7 +13661,7 @@ var _global = (() => {
13652
13661
  })();
13653
13662
  var isContextDefined = (context) => !isUndefined(context) && context !== _global;
13654
13663
  function merge() {
13655
- const { caseless } = isContextDefined(this) && this || {};
13664
+ const { caseless, skipUndefined } = isContextDefined(this) && this || {};
13656
13665
  const result = {};
13657
13666
  const assignValue = (val, key) => {
13658
13667
  const targetKey = caseless && findKey(result, key) || key;
@@ -13662,7 +13671,7 @@ function merge() {
13662
13671
  result[targetKey] = merge({}, val);
13663
13672
  } else if (isArray(val)) {
13664
13673
  result[targetKey] = val.slice();
13665
- } else {
13674
+ } else if (!skipUndefined || !isUndefined(val)) {
13666
13675
  result[targetKey] = val;
13667
13676
  }
13668
13677
  };
@@ -13998,9 +14007,13 @@ AxiosError.from = (error, code, config2, request, response, customProps) => {
13998
14007
  }, (prop) => {
13999
14008
  return prop !== "isAxiosError";
14000
14009
  });
14001
- AxiosError.call(axiosError, error.message, code, config2, request, response);
14002
- axiosError.cause = error;
14003
- axiosError.name = error.name;
14010
+ const msg = error && error.message ? error.message : "Error";
14011
+ const errCode = code == null && error ? error.code : code;
14012
+ AxiosError.call(axiosError, msg, errCode, config2, request, response);
14013
+ if (error && axiosError.cause == null) {
14014
+ Object.defineProperty(axiosError, "cause", { value: error, configurable: true });
14015
+ }
14016
+ axiosError.name = error && error.name || "Error";
14004
14017
  customProps && Object.assign(axiosError, customProps);
14005
14018
  return axiosError;
14006
14019
  };
@@ -14163,7 +14176,7 @@ var AxiosURLSearchParams_default = AxiosURLSearchParams;
14163
14176
 
14164
14177
  // node_modules/axios/lib/helpers/buildURL.js
14165
14178
  function encode2(val) {
14166
- return encodeURIComponent(val).replace(/%3A/gi, ":").replace(/%24/g, "$").replace(/%2C/gi, ",").replace(/%20/g, "+").replace(/%5B/gi, "[").replace(/%5D/gi, "]");
14179
+ return encodeURIComponent(val).replace(/%3A/gi, ":").replace(/%24/g, "$").replace(/%2C/gi, ",").replace(/%20/g, "+");
14167
14180
  }
14168
14181
  function buildURL(url2, params, options) {
14169
14182
  if (!params) {
@@ -14461,7 +14474,7 @@ var defaults = {
14461
14474
  const silentJSONParsing = transitional2 && transitional2.silentJSONParsing;
14462
14475
  const strictJSONParsing = !silentJSONParsing && JSONRequested;
14463
14476
  try {
14464
- return JSON.parse(data);
14477
+ return JSON.parse(data, this.parseReviver);
14465
14478
  } catch (e) {
14466
14479
  if (strictJSONParsing) {
14467
14480
  if (e.name === "SyntaxError") {
@@ -14848,7 +14861,7 @@ var import_follow_redirects = __toESM(require_follow_redirects(), 1);
14848
14861
  var import_zlib = __toESM(require("zlib"), 1);
14849
14862
 
14850
14863
  // node_modules/axios/lib/env/data.js
14851
- var VERSION = "1.11.0";
14864
+ var VERSION = "1.12.2";
14852
14865
 
14853
14866
  // node_modules/axios/lib/helpers/parseProtocol.js
14854
14867
  function parseProtocol(url2) {
@@ -15247,6 +15260,60 @@ var progressEventDecorator = (total, throttled) => {
15247
15260
  };
15248
15261
  var asyncDecorator = (fn) => (...args) => utils_default.asap(() => fn(...args));
15249
15262
 
15263
+ // node_modules/axios/lib/helpers/estimateDataURLDecodedBytes.js
15264
+ function estimateDataURLDecodedBytes(url2) {
15265
+ if (!url2 || typeof url2 !== "string")
15266
+ return 0;
15267
+ if (!url2.startsWith("data:"))
15268
+ return 0;
15269
+ const comma = url2.indexOf(",");
15270
+ if (comma < 0)
15271
+ return 0;
15272
+ const meta = url2.slice(5, comma);
15273
+ const body = url2.slice(comma + 1);
15274
+ const isBase64 = /;base64/i.test(meta);
15275
+ if (isBase64) {
15276
+ let effectiveLen = body.length;
15277
+ const len = body.length;
15278
+ for (let i = 0; i < len; i++) {
15279
+ if (body.charCodeAt(i) === 37 && i + 2 < len) {
15280
+ const a = body.charCodeAt(i + 1);
15281
+ const b = body.charCodeAt(i + 2);
15282
+ const isHex = (a >= 48 && a <= 57 || a >= 65 && a <= 70 || a >= 97 && a <= 102) && (b >= 48 && b <= 57 || b >= 65 && b <= 70 || b >= 97 && b <= 102);
15283
+ if (isHex) {
15284
+ effectiveLen -= 2;
15285
+ i += 2;
15286
+ }
15287
+ }
15288
+ }
15289
+ let pad = 0;
15290
+ let idx = len - 1;
15291
+ const tailIsPct3D = (j) => j >= 2 && body.charCodeAt(j - 2) === 37 && // '%'
15292
+ body.charCodeAt(j - 1) === 51 && // '3'
15293
+ (body.charCodeAt(j) === 68 || body.charCodeAt(j) === 100);
15294
+ if (idx >= 0) {
15295
+ if (body.charCodeAt(idx) === 61) {
15296
+ pad++;
15297
+ idx--;
15298
+ } else if (tailIsPct3D(idx)) {
15299
+ pad++;
15300
+ idx -= 3;
15301
+ }
15302
+ }
15303
+ if (pad === 1 && idx >= 0) {
15304
+ if (body.charCodeAt(idx) === 61) {
15305
+ pad++;
15306
+ } else if (tailIsPct3D(idx)) {
15307
+ pad++;
15308
+ }
15309
+ }
15310
+ const groups = Math.floor(effectiveLen / 4);
15311
+ const bytes = groups * 3 - (pad || 0);
15312
+ return bytes > 0 ? bytes : 0;
15313
+ }
15314
+ return Buffer.byteLength(body, "utf8");
15315
+ }
15316
+
15250
15317
  // node_modules/axios/lib/adapters/http.js
15251
15318
  var zlibOptions = {
15252
15319
  flush: import_zlib.default.constants.Z_SYNC_FLUSH,
@@ -15390,6 +15457,17 @@ var http_default = isHttpAdapterSupported && function httpAdapter(config2) {
15390
15457
  const parsed = new URL(fullPath, platform_default.hasBrowserEnv ? platform_default.origin : void 0);
15391
15458
  const protocol = parsed.protocol || supportedProtocols[0];
15392
15459
  if (protocol === "data:") {
15460
+ if (config2.maxContentLength > -1) {
15461
+ const dataUrl = String(config2.url || fullPath || "");
15462
+ const estimated = estimateDataURLDecodedBytes(dataUrl);
15463
+ if (estimated > config2.maxContentLength) {
15464
+ return reject(new AxiosError_default(
15465
+ "maxContentLength size of " + config2.maxContentLength + " exceeded",
15466
+ AxiosError_default.ERR_BAD_RESPONSE,
15467
+ config2
15468
+ ));
15469
+ }
15470
+ }
15393
15471
  let convertedData;
15394
15472
  if (method !== "GET") {
15395
15473
  return settle(resolve, reject, {
@@ -15885,13 +15963,17 @@ var resolveConfig_default = (config2) => {
15885
15963
  "Basic " + btoa((auth.username || "") + ":" + (auth.password ? unescape(encodeURIComponent(auth.password)) : ""))
15886
15964
  );
15887
15965
  }
15888
- let contentType;
15889
15966
  if (utils_default.isFormData(data)) {
15890
15967
  if (platform_default.hasStandardBrowserEnv || platform_default.hasStandardBrowserWebWorkerEnv) {
15891
15968
  headers.setContentType(void 0);
15892
- } else if ((contentType = headers.getContentType()) !== false) {
15893
- const [type, ...tokens] = contentType ? contentType.split(";").map((token) => token.trim()).filter(Boolean) : [];
15894
- headers.setContentType([type || "multipart/form-data", ...tokens].join("; "));
15969
+ } else if (utils_default.isFunction(data.getHeaders)) {
15970
+ const formHeaders = data.getHeaders();
15971
+ const allowedHeaders = ["content-type", "content-length"];
15972
+ Object.entries(formHeaders).forEach(([key, val]) => {
15973
+ if (allowedHeaders.includes(key.toLowerCase())) {
15974
+ headers.set(key, val);
15975
+ }
15976
+ });
15895
15977
  }
15896
15978
  }
15897
15979
  if (platform_default.hasStandardBrowserEnv) {
@@ -15971,8 +16053,11 @@ var xhr_default = isXHRAdapterSupported && function(config2) {
15971
16053
  reject(new AxiosError_default("Request aborted", AxiosError_default.ECONNABORTED, config2, request));
15972
16054
  request = null;
15973
16055
  };
15974
- request.onerror = function handleError() {
15975
- reject(new AxiosError_default("Network Error", AxiosError_default.ERR_NETWORK, config2, request));
16056
+ request.onerror = function handleError(event) {
16057
+ const msg = event && event.message ? event.message : "Network Error";
16058
+ const err = new AxiosError_default(msg, AxiosError_default.ERR_NETWORK, config2, request);
16059
+ err.event = event || null;
16060
+ reject(err);
15976
16061
  request = null;
15977
16062
  };
15978
16063
  request.ontimeout = function handleTimeout() {
@@ -16147,9 +16232,16 @@ var trackStream = (stream4, chunkSize, onProgress, onFinish) => {
16147
16232
  };
16148
16233
 
16149
16234
  // node_modules/axios/lib/adapters/fetch.js
16150
- var isFetchSupported = typeof fetch === "function" && typeof Request === "function" && typeof Response === "function";
16151
- var isReadableStreamSupported = isFetchSupported && typeof ReadableStream === "function";
16152
- var encodeText = isFetchSupported && (typeof TextEncoder === "function" ? ((encoder) => (str) => encoder.encode(str))(new TextEncoder()) : async (str) => new Uint8Array(await new Response(str).arrayBuffer()));
16235
+ var DEFAULT_CHUNK_SIZE = 64 * 1024;
16236
+ var { isFunction: isFunction2 } = utils_default;
16237
+ var globalFetchAPI = (({ Request, Response }) => ({
16238
+ Request,
16239
+ Response
16240
+ }))(utils_default.global);
16241
+ var {
16242
+ ReadableStream: ReadableStream2,
16243
+ TextEncoder: TextEncoder2
16244
+ } = utils_default.global;
16153
16245
  var test = (fn, ...args) => {
16154
16246
  try {
16155
16247
  return !!fn(...args);
@@ -16157,164 +16249,204 @@ var test = (fn, ...args) => {
16157
16249
  return false;
16158
16250
  }
16159
16251
  };
16160
- var supportsRequestStream = isReadableStreamSupported && test(() => {
16161
- let duplexAccessed = false;
16162
- const hasContentType = new Request(platform_default.origin, {
16163
- body: new ReadableStream(),
16164
- method: "POST",
16165
- get duplex() {
16166
- duplexAccessed = true;
16167
- return "half";
16168
- }
16169
- }).headers.has("Content-Type");
16170
- return duplexAccessed && !hasContentType;
16171
- });
16172
- var DEFAULT_CHUNK_SIZE = 64 * 1024;
16173
- var supportsResponseStream = isReadableStreamSupported && test(() => utils_default.isReadableStream(new Response("").body));
16174
- var resolvers = {
16175
- stream: supportsResponseStream && ((res) => res.body)
16176
- };
16177
- isFetchSupported && ((res) => {
16178
- ["text", "arrayBuffer", "blob", "formData", "stream"].forEach((type) => {
16179
- !resolvers[type] && (resolvers[type] = utils_default.isFunction(res[type]) ? (res2) => res2[type]() : (_, config2) => {
16180
- throw new AxiosError_default(`Response type '${type}' is not supported`, AxiosError_default.ERR_NOT_SUPPORT, config2);
16181
- });
16182
- });
16183
- })(new Response());
16184
- var getBodyLength = async (body) => {
16185
- if (body == null) {
16186
- return 0;
16187
- }
16188
- if (utils_default.isBlob(body)) {
16189
- return body.size;
16252
+ var factory = (env) => {
16253
+ env = utils_default.merge.call({
16254
+ skipUndefined: true
16255
+ }, globalFetchAPI, env);
16256
+ const { fetch: envFetch, Request, Response } = env;
16257
+ const isFetchSupported = envFetch ? isFunction2(envFetch) : typeof fetch === "function";
16258
+ const isRequestSupported = isFunction2(Request);
16259
+ const isResponseSupported = isFunction2(Response);
16260
+ if (!isFetchSupported) {
16261
+ return false;
16190
16262
  }
16191
- if (utils_default.isSpecCompliantForm(body)) {
16192
- const _request = new Request(platform_default.origin, {
16263
+ const isReadableStreamSupported = isFetchSupported && isFunction2(ReadableStream2);
16264
+ const encodeText = isFetchSupported && (typeof TextEncoder2 === "function" ? ((encoder) => (str) => encoder.encode(str))(new TextEncoder2()) : async (str) => new Uint8Array(await new Request(str).arrayBuffer()));
16265
+ const supportsRequestStream = isRequestSupported && isReadableStreamSupported && test(() => {
16266
+ let duplexAccessed = false;
16267
+ const hasContentType = new Request(platform_default.origin, {
16268
+ body: new ReadableStream2(),
16193
16269
  method: "POST",
16194
- body
16195
- });
16196
- return (await _request.arrayBuffer()).byteLength;
16197
- }
16198
- if (utils_default.isArrayBufferView(body) || utils_default.isArrayBuffer(body)) {
16199
- return body.byteLength;
16200
- }
16201
- if (utils_default.isURLSearchParams(body)) {
16202
- body = body + "";
16203
- }
16204
- if (utils_default.isString(body)) {
16205
- return (await encodeText(body)).byteLength;
16206
- }
16207
- };
16208
- var resolveBodyLength = async (headers, body) => {
16209
- const length = utils_default.toFiniteNumber(headers.getContentLength());
16210
- return length == null ? getBodyLength(body) : length;
16211
- };
16212
- var fetch_default = isFetchSupported && (async (config2) => {
16213
- let {
16214
- url: url2,
16215
- method,
16216
- data,
16217
- signal,
16218
- cancelToken,
16219
- timeout,
16220
- onDownloadProgress,
16221
- onUploadProgress,
16222
- responseType,
16223
- headers,
16224
- withCredentials = "same-origin",
16225
- fetchOptions
16226
- } = resolveConfig_default(config2);
16227
- responseType = responseType ? (responseType + "").toLowerCase() : "text";
16228
- let composedSignal = composeSignals_default([signal, cancelToken && cancelToken.toAbortSignal()], timeout);
16229
- let request;
16230
- const unsubscribe = composedSignal && composedSignal.unsubscribe && (() => {
16231
- composedSignal.unsubscribe();
16270
+ get duplex() {
16271
+ duplexAccessed = true;
16272
+ return "half";
16273
+ }
16274
+ }).headers.has("Content-Type");
16275
+ return duplexAccessed && !hasContentType;
16232
16276
  });
16233
- let requestContentLength;
16234
- try {
16235
- if (onUploadProgress && supportsRequestStream && method !== "get" && method !== "head" && (requestContentLength = await resolveBodyLength(headers, data)) !== 0) {
16236
- let _request = new Request(url2, {
16277
+ const supportsResponseStream = isResponseSupported && isReadableStreamSupported && test(() => utils_default.isReadableStream(new Response("").body));
16278
+ const resolvers = {
16279
+ stream: supportsResponseStream && ((res) => res.body)
16280
+ };
16281
+ isFetchSupported && (() => {
16282
+ ["text", "arrayBuffer", "blob", "formData", "stream"].forEach((type) => {
16283
+ !resolvers[type] && (resolvers[type] = (res, config2) => {
16284
+ let method = res && res[type];
16285
+ if (method) {
16286
+ return method.call(res);
16287
+ }
16288
+ throw new AxiosError_default(`Response type '${type}' is not supported`, AxiosError_default.ERR_NOT_SUPPORT, config2);
16289
+ });
16290
+ });
16291
+ })();
16292
+ const getBodyLength = async (body) => {
16293
+ if (body == null) {
16294
+ return 0;
16295
+ }
16296
+ if (utils_default.isBlob(body)) {
16297
+ return body.size;
16298
+ }
16299
+ if (utils_default.isSpecCompliantForm(body)) {
16300
+ const _request = new Request(platform_default.origin, {
16237
16301
  method: "POST",
16238
- body: data,
16239
- duplex: "half"
16302
+ body
16240
16303
  });
16241
- let contentTypeHeader;
16242
- if (utils_default.isFormData(data) && (contentTypeHeader = _request.headers.get("content-type"))) {
16243
- headers.setContentType(contentTypeHeader);
16244
- }
16245
- if (_request.body) {
16246
- const [onProgress, flush] = progressEventDecorator(
16247
- requestContentLength,
16248
- progressEventReducer(asyncDecorator(onUploadProgress))
16249
- );
16250
- data = trackStream(_request.body, DEFAULT_CHUNK_SIZE, onProgress, flush);
16251
- }
16304
+ return (await _request.arrayBuffer()).byteLength;
16252
16305
  }
16253
- if (!utils_default.isString(withCredentials)) {
16254
- withCredentials = withCredentials ? "include" : "omit";
16306
+ if (utils_default.isArrayBufferView(body) || utils_default.isArrayBuffer(body)) {
16307
+ return body.byteLength;
16255
16308
  }
16256
- const isCredentialsSupported = "credentials" in Request.prototype;
16257
- request = new Request(url2, {
16258
- ...fetchOptions,
16259
- signal: composedSignal,
16260
- method: method.toUpperCase(),
16261
- headers: headers.normalize().toJSON(),
16262
- body: data,
16263
- duplex: "half",
16264
- credentials: isCredentialsSupported ? withCredentials : void 0
16265
- });
16266
- let response = await fetch(request, fetchOptions);
16267
- const isStreamResponse = supportsResponseStream && (responseType === "stream" || responseType === "response");
16268
- if (supportsResponseStream && (onDownloadProgress || isStreamResponse && unsubscribe)) {
16269
- const options = {};
16270
- ["status", "statusText", "headers"].forEach((prop) => {
16271
- options[prop] = response[prop];
16272
- });
16273
- const responseContentLength = utils_default.toFiniteNumber(response.headers.get("content-length"));
16274
- const [onProgress, flush] = onDownloadProgress && progressEventDecorator(
16275
- responseContentLength,
16276
- progressEventReducer(asyncDecorator(onDownloadProgress), true)
16277
- ) || [];
16278
- response = new Response(
16279
- trackStream(response.body, DEFAULT_CHUNK_SIZE, onProgress, () => {
16280
- flush && flush();
16281
- unsubscribe && unsubscribe();
16282
- }),
16283
- options
16284
- );
16309
+ if (utils_default.isURLSearchParams(body)) {
16310
+ body = body + "";
16285
16311
  }
16286
- responseType = responseType || "text";
16287
- let responseData = await resolvers[utils_default.findKey(resolvers, responseType) || "text"](response, config2);
16288
- !isStreamResponse && unsubscribe && unsubscribe();
16289
- return await new Promise((resolve, reject) => {
16290
- settle(resolve, reject, {
16291
- data: responseData,
16292
- headers: AxiosHeaders_default.from(response.headers),
16293
- status: response.status,
16294
- statusText: response.statusText,
16295
- config: config2,
16296
- request
16297
- });
16312
+ if (utils_default.isString(body)) {
16313
+ return (await encodeText(body)).byteLength;
16314
+ }
16315
+ };
16316
+ const resolveBodyLength = async (headers, body) => {
16317
+ const length = utils_default.toFiniteNumber(headers.getContentLength());
16318
+ return length == null ? getBodyLength(body) : length;
16319
+ };
16320
+ return async (config2) => {
16321
+ let {
16322
+ url: url2,
16323
+ method,
16324
+ data,
16325
+ signal,
16326
+ cancelToken,
16327
+ timeout,
16328
+ onDownloadProgress,
16329
+ onUploadProgress,
16330
+ responseType,
16331
+ headers,
16332
+ withCredentials = "same-origin",
16333
+ fetchOptions
16334
+ } = resolveConfig_default(config2);
16335
+ let _fetch = envFetch || fetch;
16336
+ responseType = responseType ? (responseType + "").toLowerCase() : "text";
16337
+ let composedSignal = composeSignals_default([signal, cancelToken && cancelToken.toAbortSignal()], timeout);
16338
+ let request = null;
16339
+ const unsubscribe = composedSignal && composedSignal.unsubscribe && (() => {
16340
+ composedSignal.unsubscribe();
16298
16341
  });
16299
- } catch (err) {
16300
- unsubscribe && unsubscribe();
16301
- if (err && err.name === "TypeError" && /Load failed|fetch/i.test(err.message)) {
16302
- throw Object.assign(
16303
- new AxiosError_default("Network Error", AxiosError_default.ERR_NETWORK, config2, request),
16304
- {
16305
- cause: err.cause || err
16342
+ let requestContentLength;
16343
+ try {
16344
+ if (onUploadProgress && supportsRequestStream && method !== "get" && method !== "head" && (requestContentLength = await resolveBodyLength(headers, data)) !== 0) {
16345
+ let _request = new Request(url2, {
16346
+ method: "POST",
16347
+ body: data,
16348
+ duplex: "half"
16349
+ });
16350
+ let contentTypeHeader;
16351
+ if (utils_default.isFormData(data) && (contentTypeHeader = _request.headers.get("content-type"))) {
16352
+ headers.setContentType(contentTypeHeader);
16306
16353
  }
16307
- );
16354
+ if (_request.body) {
16355
+ const [onProgress, flush] = progressEventDecorator(
16356
+ requestContentLength,
16357
+ progressEventReducer(asyncDecorator(onUploadProgress))
16358
+ );
16359
+ data = trackStream(_request.body, DEFAULT_CHUNK_SIZE, onProgress, flush);
16360
+ }
16361
+ }
16362
+ if (!utils_default.isString(withCredentials)) {
16363
+ withCredentials = withCredentials ? "include" : "omit";
16364
+ }
16365
+ const isCredentialsSupported = isRequestSupported && "credentials" in Request.prototype;
16366
+ const resolvedOptions = {
16367
+ ...fetchOptions,
16368
+ signal: composedSignal,
16369
+ method: method.toUpperCase(),
16370
+ headers: headers.normalize().toJSON(),
16371
+ body: data,
16372
+ duplex: "half",
16373
+ credentials: isCredentialsSupported ? withCredentials : void 0
16374
+ };
16375
+ request = isRequestSupported && new Request(url2, resolvedOptions);
16376
+ let response = await (isRequestSupported ? _fetch(request, fetchOptions) : _fetch(url2, resolvedOptions));
16377
+ const isStreamResponse = supportsResponseStream && (responseType === "stream" || responseType === "response");
16378
+ if (supportsResponseStream && (onDownloadProgress || isStreamResponse && unsubscribe)) {
16379
+ const options = {};
16380
+ ["status", "statusText", "headers"].forEach((prop) => {
16381
+ options[prop] = response[prop];
16382
+ });
16383
+ const responseContentLength = utils_default.toFiniteNumber(response.headers.get("content-length"));
16384
+ const [onProgress, flush] = onDownloadProgress && progressEventDecorator(
16385
+ responseContentLength,
16386
+ progressEventReducer(asyncDecorator(onDownloadProgress), true)
16387
+ ) || [];
16388
+ response = new Response(
16389
+ trackStream(response.body, DEFAULT_CHUNK_SIZE, onProgress, () => {
16390
+ flush && flush();
16391
+ unsubscribe && unsubscribe();
16392
+ }),
16393
+ options
16394
+ );
16395
+ }
16396
+ responseType = responseType || "text";
16397
+ let responseData = await resolvers[utils_default.findKey(resolvers, responseType) || "text"](response, config2);
16398
+ !isStreamResponse && unsubscribe && unsubscribe();
16399
+ return await new Promise((resolve, reject) => {
16400
+ settle(resolve, reject, {
16401
+ data: responseData,
16402
+ headers: AxiosHeaders_default.from(response.headers),
16403
+ status: response.status,
16404
+ statusText: response.statusText,
16405
+ config: config2,
16406
+ request
16407
+ });
16408
+ });
16409
+ } catch (err) {
16410
+ unsubscribe && unsubscribe();
16411
+ if (err && err.name === "TypeError" && /Load failed|fetch/i.test(err.message)) {
16412
+ throw Object.assign(
16413
+ new AxiosError_default("Network Error", AxiosError_default.ERR_NETWORK, config2, request),
16414
+ {
16415
+ cause: err.cause || err
16416
+ }
16417
+ );
16418
+ }
16419
+ throw AxiosError_default.from(err, err && err.code, config2, request);
16308
16420
  }
16309
- throw AxiosError_default.from(err, err && err.code, config2, request);
16310
- }
16311
- });
16421
+ };
16422
+ };
16423
+ var seedCache = /* @__PURE__ */ new Map();
16424
+ var getFetch = (config2) => {
16425
+ let env = config2 ? config2.env : {};
16426
+ const { fetch: fetch2, Request, Response } = env;
16427
+ const seeds = [
16428
+ Request,
16429
+ Response,
16430
+ fetch2
16431
+ ];
16432
+ let len = seeds.length, i = len, seed, target, map = seedCache;
16433
+ while (i--) {
16434
+ seed = seeds[i];
16435
+ target = map.get(seed);
16436
+ target === void 0 && map.set(seed, target = i ? /* @__PURE__ */ new Map() : factory(env));
16437
+ map = target;
16438
+ }
16439
+ return target;
16440
+ };
16441
+ var adapter = getFetch();
16312
16442
 
16313
16443
  // node_modules/axios/lib/adapters/adapters.js
16314
16444
  var knownAdapters = {
16315
16445
  http: http_default,
16316
16446
  xhr: xhr_default,
16317
- fetch: fetch_default
16447
+ fetch: {
16448
+ get: getFetch
16449
+ }
16318
16450
  };
16319
16451
  utils_default.forEach(knownAdapters, (fn, value) => {
16320
16452
  if (fn) {
@@ -16326,30 +16458,30 @@ utils_default.forEach(knownAdapters, (fn, value) => {
16326
16458
  }
16327
16459
  });
16328
16460
  var renderReason = (reason) => `- ${reason}`;
16329
- var isResolvedHandle = (adapter) => utils_default.isFunction(adapter) || adapter === null || adapter === false;
16461
+ var isResolvedHandle = (adapter2) => utils_default.isFunction(adapter2) || adapter2 === null || adapter2 === false;
16330
16462
  var adapters_default = {
16331
- getAdapter: (adapters) => {
16463
+ getAdapter: (adapters, config2) => {
16332
16464
  adapters = utils_default.isArray(adapters) ? adapters : [adapters];
16333
16465
  const { length } = adapters;
16334
16466
  let nameOrAdapter;
16335
- let adapter;
16467
+ let adapter2;
16336
16468
  const rejectedReasons = {};
16337
16469
  for (let i = 0; i < length; i++) {
16338
16470
  nameOrAdapter = adapters[i];
16339
16471
  let id;
16340
- adapter = nameOrAdapter;
16472
+ adapter2 = nameOrAdapter;
16341
16473
  if (!isResolvedHandle(nameOrAdapter)) {
16342
- adapter = knownAdapters[(id = String(nameOrAdapter)).toLowerCase()];
16343
- if (adapter === void 0) {
16474
+ adapter2 = knownAdapters[(id = String(nameOrAdapter)).toLowerCase()];
16475
+ if (adapter2 === void 0) {
16344
16476
  throw new AxiosError_default(`Unknown adapter '${id}'`);
16345
16477
  }
16346
16478
  }
16347
- if (adapter) {
16479
+ if (adapter2 && (utils_default.isFunction(adapter2) || (adapter2 = adapter2.get(config2)))) {
16348
16480
  break;
16349
16481
  }
16350
- rejectedReasons[id || "#" + i] = adapter;
16482
+ rejectedReasons[id || "#" + i] = adapter2;
16351
16483
  }
16352
- if (!adapter) {
16484
+ if (!adapter2) {
16353
16485
  const reasons = Object.entries(rejectedReasons).map(
16354
16486
  ([id, state]) => `adapter ${id} ` + (state === false ? "is not supported by the environment" : "is not available in the build")
16355
16487
  );
@@ -16359,7 +16491,7 @@ var adapters_default = {
16359
16491
  "ERR_NOT_SUPPORT"
16360
16492
  );
16361
16493
  }
16362
- return adapter;
16494
+ return adapter2;
16363
16495
  },
16364
16496
  adapters: knownAdapters
16365
16497
  };
@@ -16383,8 +16515,8 @@ function dispatchRequest(config2) {
16383
16515
  if (["post", "put", "patch"].indexOf(config2.method) !== -1) {
16384
16516
  config2.headers.setContentType("application/x-www-form-urlencoded", false);
16385
16517
  }
16386
- const adapter = adapters_default.getAdapter(config2.adapter || defaults_default.adapter);
16387
- return adapter(config2).then(function onAdapterResolution(response) {
16518
+ const adapter2 = adapters_default.getAdapter(config2.adapter || defaults_default.adapter, config2);
16519
+ return adapter2(config2).then(function onAdapterResolution(response) {
16388
16520
  throwIfCancellationRequested(config2);
16389
16521
  response.data = transformData.call(
16390
16522
  config2,
@@ -16590,7 +16722,6 @@ var Axios = class {
16590
16722
  }
16591
16723
  len = requestInterceptorChain.length;
16592
16724
  let newConfig = config2;
16593
- i = 0;
16594
16725
  while (i < len) {
16595
16726
  const onFulfilled = requestInterceptorChain[i++];
16596
16727
  const onRejected = requestInterceptorChain[i++];
@@ -26312,11 +26443,8 @@ function useDivisionController() {
26312
26443
  return;
26313
26444
  }
26314
26445
  try {
26315
- const division = await _getById(id);
26316
- res.json({
26317
- message: "Successfully retrieved division.",
26318
- data: { division }
26319
- });
26446
+ const data = await _getById(id);
26447
+ res.json(data);
26320
26448
  return;
26321
26449
  } catch (error2) {
26322
26450
  next(error2);
@@ -26403,16 +26531,17 @@ var import_joi31 = __toESM(require("joi"));
26403
26531
  var import_mongodb37 = require("mongodb");
26404
26532
  var schemaSchool = import_joi31.default.object({
26405
26533
  _id: import_joi31.default.string().hex().optional().allow("", null),
26406
- id: import_joi31.default.string().required(),
26407
- name: import_joi31.default.string().required(),
26408
- country: import_joi31.default.string().required(),
26409
- address: import_joi31.default.string().required(),
26534
+ id: import_joi31.default.string().optional().allow("", null),
26535
+ name: import_joi31.default.string().optional().allow("", null),
26536
+ country: import_joi31.default.string().optional().allow("", null),
26537
+ address: import_joi31.default.string().optional().allow("", null),
26410
26538
  continuedAddress: import_joi31.default.string().optional().allow("", null),
26411
- city: import_joi31.default.string().required(),
26412
- province: import_joi31.default.string().required(),
26413
- postalCode: import_joi31.default.string().required(),
26414
- courses: import_joi31.default.array().items(import_joi31.default.string()).required(),
26415
- principalName: import_joi31.default.string().required(),
26539
+ city: import_joi31.default.string().required().allow("", null),
26540
+ province: import_joi31.default.string().required().allow("", null),
26541
+ district: import_joi31.default.string().optional().allow("", null),
26542
+ postalCode: import_joi31.default.string().required().allow("", null),
26543
+ courses: import_joi31.default.array().items(import_joi31.default.string()).optional(),
26544
+ principalName: import_joi31.default.string().required().allow("", null),
26416
26545
  principalEmail: import_joi31.default.string().email().optional().allow("", null),
26417
26546
  principalNumber: import_joi31.default.string().optional().allow("", null),
26418
26547
  region: import_joi31.default.string().hex().required(),
@@ -26422,7 +26551,7 @@ var schemaSchool = import_joi31.default.object({
26422
26551
  status: import_joi31.default.string().optional().allow(null, ""),
26423
26552
  createdAt: import_joi31.default.date().optional().allow("", null),
26424
26553
  updatedAt: import_joi31.default.date().optional().allow("", null),
26425
- createdBy: import_joi31.default.string().hex().required()
26554
+ createdBy: import_joi31.default.string().hex().optional().allow("", null)
26426
26555
  });
26427
26556
  function MSchool(value) {
26428
26557
  const { error } = schemaSchool.validate(value);
@@ -26461,15 +26590,15 @@ function MSchool(value) {
26461
26590
  _id: value._id ? value._id : new import_mongodb37.ObjectId(),
26462
26591
  id: value.id,
26463
26592
  name: value.name,
26464
- country: value.country,
26465
- address: value.address,
26593
+ country: value.country ?? "",
26594
+ address: value.address ?? "",
26466
26595
  continuedAddress: value.continuedAddress ?? "",
26467
- city: value.city,
26468
- province: value.province,
26469
- postalCode: value.postalCode,
26596
+ city: value.city ?? "",
26597
+ province: value.province ?? "",
26598
+ postalCode: value.postalCode ?? "",
26470
26599
  courses: value.courses || [],
26471
- principalName: value.principalName,
26472
- principalEmail: value.principalEmail,
26600
+ principalName: value.principalName ?? "",
26601
+ principalEmail: value.principalEmail ?? "",
26473
26602
  principalNumber: value.principalNumber ?? "",
26474
26603
  region: value.region,
26475
26604
  regionName: value.regionName ?? "",
@@ -26478,7 +26607,7 @@ function MSchool(value) {
26478
26607
  createdAt: value.createdAt ?? (/* @__PURE__ */ new Date()).toISOString(),
26479
26608
  updatedAt: value.updatedAt ?? "",
26480
26609
  status: value.status ?? "pending",
26481
- createdBy: value.createdBy
26610
+ createdBy: value.createdBy ?? ""
26482
26611
  };
26483
26612
  }
26484
26613
 
@@ -26746,8 +26875,16 @@ function useSchoolRepo() {
26746
26875
 
26747
26876
  // src/services/school.service.ts
26748
26877
  var import_nodejs_utils64 = require("@eeplatform/nodejs-utils");
26878
+ var XLSX = __toESM(require("xlsx"));
26879
+ var Papa = __toESM(require("papaparse"));
26880
+ var BSON = __toESM(require("bson"));
26749
26881
  function useSchoolService() {
26750
- const { add, getPendingByCreatedBy, updateStatusById, getPendingById } = useSchoolRepo();
26882
+ const {
26883
+ add: addSchool,
26884
+ getPendingByCreatedBy,
26885
+ updateStatusById,
26886
+ getPendingById
26887
+ } = useSchoolRepo();
26751
26888
  const { addRole } = useRoleRepo();
26752
26889
  const { getUserById } = useUserRepo();
26753
26890
  const { add: addMember } = useMemberRepo();
@@ -26764,7 +26901,7 @@ function useSchoolService() {
26764
26901
  }
26765
26902
  try {
26766
26903
  value.status = "pending";
26767
- await add(value);
26904
+ await addSchool(value);
26768
26905
  return "Request to register school has been sent successfully. Please wait for approval.";
26769
26906
  } catch (error2) {
26770
26907
  throw error2;
@@ -26783,7 +26920,7 @@ function useSchoolService() {
26783
26920
  session.startTransaction();
26784
26921
  school.status = "approved";
26785
26922
  await updateStatusById(id, "active", session);
26786
- const roleType = "school";
26923
+ const roleType = "basic-edu-school";
26787
26924
  const roleName = "Admin";
26788
26925
  const roleId = await addRole(
26789
26926
  {
@@ -26828,9 +26965,245 @@ function useSchoolService() {
26828
26965
  await session.endSession();
26829
26966
  }
26830
26967
  }
26968
+ async function add(value) {
26969
+ const { error } = schemaSchool.validate(value);
26970
+ if (error) {
26971
+ throw new import_nodejs_utils64.BadRequestError(error.message);
26972
+ }
26973
+ const session = import_nodejs_utils64.useAtlas.getClient()?.startSession();
26974
+ if (!session) {
26975
+ throw new Error("Unable to start session for school service.");
26976
+ }
26977
+ try {
26978
+ session.startTransaction();
26979
+ value.status = "active";
26980
+ const schoolId = await addSchool(value, session);
26981
+ const roleType = "basic-edu-school";
26982
+ const roleName = "Admin";
26983
+ const roleId = await addRole(
26984
+ {
26985
+ id: schoolId.toString(),
26986
+ type: roleType,
26987
+ name: roleName,
26988
+ permissions: ["*"],
26989
+ status: "active",
26990
+ default: true
26991
+ },
26992
+ session
26993
+ );
26994
+ if (!value.createdBy) {
26995
+ throw new import_nodejs_utils64.BadRequestError("School must have a creator.");
26996
+ }
26997
+ const user = await getUserById(value.createdBy ?? "");
26998
+ if (!user) {
26999
+ throw new import_nodejs_utils64.BadRequestError("User not found for the school creator.");
27000
+ }
27001
+ await addMember(
27002
+ {
27003
+ org: schoolId.toString(),
27004
+ orgName: value.name,
27005
+ user: value.createdBy.toString(),
27006
+ name: `${user.firstName} ${user.lastName}`,
27007
+ role: roleId.toString(),
27008
+ roleName,
27009
+ type: roleType
27010
+ },
27011
+ session
27012
+ );
27013
+ await session.commitTransaction();
27014
+ return "School has been added and activated successfully.";
27015
+ } catch (error2) {
27016
+ import_nodejs_utils64.logger.log({
27017
+ level: "error",
27018
+ message: `Error adding school: ${error2.message}`
27019
+ });
27020
+ await session.abortTransaction();
27021
+ throw error2;
27022
+ } finally {
27023
+ await session.endSession();
27024
+ }
27025
+ }
27026
+ async function addBulk(file, region, division) {
27027
+ const MAX_SIZE = 16 * 1024 * 1024;
27028
+ if (file.size > MAX_SIZE) {
27029
+ throw new import_nodejs_utils64.BadRequestError(
27030
+ "File size exceeds 16MB limit. Please use a smaller file to ensure transaction compatibility."
27031
+ );
27032
+ }
27033
+ let schools = [];
27034
+ const validatedSchools = [];
27035
+ const totalSize = validatedSchools.reduce(
27036
+ (sum, school) => sum + BSON.calculateObjectSize(school),
27037
+ 0
27038
+ );
27039
+ try {
27040
+ if (file.mimetype.includes("sheet") || file.originalname.endsWith(".xlsx") || file.originalname.endsWith(".xls")) {
27041
+ const workbook = XLSX.read(file.buffer);
27042
+ const sheetName = workbook.SheetNames[0];
27043
+ const worksheet = workbook.Sheets[sheetName];
27044
+ schools = XLSX.utils.sheet_to_json(worksheet);
27045
+ } else if (file.mimetype.includes("csv") || file.originalname.endsWith(".csv")) {
27046
+ const csvText = file.buffer.toString("utf8");
27047
+ const parseResult = Papa.parse(csvText, {
27048
+ header: true,
27049
+ skipEmptyLines: true,
27050
+ transformHeader: (header) => header.trim()
27051
+ });
27052
+ if (parseResult.errors.length > 0) {
27053
+ throw new import_nodejs_utils64.BadRequestError(
27054
+ `CSV parsing error: ${parseResult.errors[0].message}`
27055
+ );
27056
+ }
27057
+ schools = parseResult.data;
27058
+ } else {
27059
+ throw new import_nodejs_utils64.BadRequestError(
27060
+ "Unsupported file type. Please upload an Excel (.xlsx, .xls) or CSV (.csv) file."
27061
+ );
27062
+ }
27063
+ if (!schools || schools.length === 0) {
27064
+ throw new import_nodejs_utils64.BadRequestError("No data found in the uploaded file.");
27065
+ }
27066
+ const errors = [];
27067
+ for (let i = 0; i < schools.length; i++) {
27068
+ const schoolData = schools[i];
27069
+ const rowNumber = i + 1;
27070
+ try {
27071
+ const schoolName = schoolData.schoolName || schoolData.name || "";
27072
+ const schoolId = schoolData.schoolId || schoolData.id || "";
27073
+ const district = schoolData.district || "";
27074
+ if (!schoolName.trim()) {
27075
+ errors.push(`Row ${rowNumber}: School name is required`);
27076
+ continue;
27077
+ }
27078
+ if (!schoolId.trim()) {
27079
+ errors.push(`Row ${rowNumber}: School ID is required`);
27080
+ continue;
27081
+ }
27082
+ if (!district.trim()) {
27083
+ errors.push(`Row ${rowNumber}: District is required`);
27084
+ continue;
27085
+ }
27086
+ const school = {
27087
+ id: schoolId.trim(),
27088
+ name: schoolName.trim(),
27089
+ country: "Philippines",
27090
+ // Default country
27091
+ address: district.trim(),
27092
+ // Use district as address
27093
+ continuedAddress: "",
27094
+ city: district.trim(),
27095
+ // Use district as city
27096
+ province: "",
27097
+ // Will need to be set based on region/division
27098
+ postalCode: "",
27099
+ courses: [],
27100
+ // Empty array for courses
27101
+ principalName: "",
27102
+ principalEmail: "",
27103
+ principalNumber: "",
27104
+ region,
27105
+ regionName: "",
27106
+ // Will be populated from region lookup
27107
+ division,
27108
+ divisionName: "",
27109
+ // Will be populated from division lookup
27110
+ status: "active"
27111
+ };
27112
+ const { error } = schemaSchool.validate(school);
27113
+ if (error) {
27114
+ errors.push(`Row ${rowNumber}: ${error.message}`);
27115
+ continue;
27116
+ }
27117
+ validatedSchools.push(school);
27118
+ } catch (error) {
27119
+ errors.push(
27120
+ `Row ${rowNumber}: ${error.message || "Invalid data format"}`
27121
+ );
27122
+ }
27123
+ }
27124
+ if (errors.length > 0) {
27125
+ throw new import_nodejs_utils64.BadRequestError(
27126
+ `Validation errors found:
27127
+ ${errors.slice(0, 10).join("\n")}${errors.length > 10 ? `
27128
+ ... and ${errors.length - 10} more errors` : ""}`
27129
+ );
27130
+ }
27131
+ if (validatedSchools.length === 0) {
27132
+ throw new import_nodejs_utils64.BadRequestError(
27133
+ "No valid school records found after validation."
27134
+ );
27135
+ }
27136
+ if (totalSize > MAX_SIZE) {
27137
+ throw new import_nodejs_utils64.BadRequestError(
27138
+ `Data payload (${Math.round(
27139
+ totalSize / 1024 / 1024
27140
+ )}MB) exceeds MongoDB transaction limit of 16MB. Please reduce the number of records or split into smaller files.`
27141
+ );
27142
+ }
27143
+ } catch (error) {
27144
+ if (error instanceof import_nodejs_utils64.BadRequestError) {
27145
+ throw error;
27146
+ }
27147
+ throw new import_nodejs_utils64.BadRequestError(`File processing error: ${error.message}`);
27148
+ }
27149
+ const session = import_nodejs_utils64.useAtlas.getClient()?.startSession();
27150
+ if (!session) {
27151
+ throw new Error("Unable to start session for bulk school upload.");
27152
+ }
27153
+ try {
27154
+ session.startTransaction();
27155
+ const results = {
27156
+ successful: 0,
27157
+ failed: 0,
27158
+ errors: []
27159
+ };
27160
+ for (const school of validatedSchools) {
27161
+ try {
27162
+ const schoolId = await addSchool(school, session);
27163
+ await addRole(
27164
+ {
27165
+ id: schoolId.toString(),
27166
+ type: "basic-edu-school",
27167
+ name: "Admin",
27168
+ permissions: ["*"],
27169
+ status: "active",
27170
+ default: true
27171
+ },
27172
+ session
27173
+ );
27174
+ results.successful++;
27175
+ } catch (error) {
27176
+ results.failed++;
27177
+ results.errors.push(`School "${school.name}": ${error.message}`);
27178
+ }
27179
+ }
27180
+ await session.commitTransaction();
27181
+ return {
27182
+ message: `Bulk upload completed. ${results.successful} schools added successfully.`,
27183
+ details: {
27184
+ successful: results.successful,
27185
+ failed: results.failed,
27186
+ total: validatedSchools.length,
27187
+ totalSizeMB: Math.round(totalSize / 1024 / 1024 * 100) / 100,
27188
+ errors: results.errors
27189
+ }
27190
+ };
27191
+ } catch (error) {
27192
+ import_nodejs_utils64.logger.log({
27193
+ level: "error",
27194
+ message: `Error in bulk school upload: ${error.message}`
27195
+ });
27196
+ await session.abortTransaction();
27197
+ throw error;
27198
+ } finally {
27199
+ await session.endSession();
27200
+ }
27201
+ }
26831
27202
  return {
26832
27203
  register,
26833
- approve
27204
+ approve,
27205
+ add,
27206
+ addBulk
26834
27207
  };
26835
27208
  }
26836
27209
 
@@ -26839,11 +27212,16 @@ var import_nodejs_utils65 = require("@eeplatform/nodejs-utils");
26839
27212
  var import_joi32 = __toESM(require("joi"));
26840
27213
  function useSchoolController() {
26841
27214
  const {
26842
- add: _add,
26843
27215
  getAll: _getAll,
26844
27216
  getPendingByCreatedBy: _getPendingByCreatedBy,
26845
27217
  updateStatusById: _updateStatusById
26846
27218
  } = useSchoolRepo();
27219
+ const {
27220
+ add: _addSchool,
27221
+ register: _registerSchool,
27222
+ approve,
27223
+ addBulk: _addBulk
27224
+ } = useSchoolService();
26847
27225
  async function add(req, res, next) {
26848
27226
  const payload = req.body;
26849
27227
  const { error } = schemaSchool.validate(payload);
@@ -26852,8 +27230,8 @@ function useSchoolController() {
26852
27230
  return;
26853
27231
  }
26854
27232
  try {
26855
- const school = await _add(payload);
26856
- res.status(201).json(school);
27233
+ const result = await _addSchool(payload);
27234
+ res.status(201).json({ message: result });
26857
27235
  return;
26858
27236
  } catch (error2) {
26859
27237
  next(error2);
@@ -26943,7 +27321,6 @@ function useSchoolController() {
26943
27321
  next(error2);
26944
27322
  }
26945
27323
  }
26946
- const { register: _registerSchool, approve } = useSchoolService();
26947
27324
  async function registerSchool(req, res, next) {
26948
27325
  const payload = req.body;
26949
27326
  const { error } = schemaSchool.validate(payload);
@@ -26978,13 +27355,38 @@ function useSchoolController() {
26978
27355
  next(error2);
26979
27356
  }
26980
27357
  }
27358
+ async function addBulk(req, res, next) {
27359
+ if (!req.file) {
27360
+ res.status(400).send("File is required!");
27361
+ return;
27362
+ }
27363
+ const { region, division } = req.body;
27364
+ const validation = import_joi32.default.object({
27365
+ region: import_joi32.default.string().hex().required(),
27366
+ division: import_joi32.default.string().hex().required()
27367
+ });
27368
+ const { error } = validation.validate({ region, division });
27369
+ if (error) {
27370
+ next(new import_nodejs_utils65.BadRequestError(`Validation error: ${error.message}`));
27371
+ return;
27372
+ }
27373
+ try {
27374
+ const result = await _addBulk(req.file, region, division);
27375
+ res.status(201).json(result);
27376
+ return;
27377
+ } catch (error2) {
27378
+ next(error2);
27379
+ return;
27380
+ }
27381
+ }
26981
27382
  return {
26982
27383
  add,
26983
27384
  getAll,
26984
27385
  getByCreatedBy,
26985
27386
  updateStatusById,
26986
27387
  registerSchool,
26987
- approveSchool
27388
+ approveSchool,
27389
+ addBulk
26988
27390
  };
26989
27391
  }
26990
27392
 
@@ -27935,7 +28337,10 @@ function useBuildingUnitService() {
27935
28337
  try {
27936
28338
  await session.startTransaction();
27937
28339
  for (let index = 0; index < value.qty; index++) {
27938
- await _add({ ...value.building }, session);
28340
+ await _add(
28341
+ { ...value.building, name: `${value.building.name} ${index + 1}` },
28342
+ session
28343
+ );
27939
28344
  }
27940
28345
  await session.commitTransaction();
27941
28346
  return "Building unit added successfully.";
@@ -29427,12 +29832,23 @@ var import_joi41 = __toESM(require("joi"));
29427
29832
  var import_mongodb46 = require("mongodb");
29428
29833
  var schemaPlantilla = import_joi41.default.object({
29429
29834
  _id: import_joi41.default.string().hex().optional().allow(null, ""),
29835
+ org: import_joi41.default.string().hex().required(),
29836
+ orgUnitCode: import_joi41.default.string().optional().allow(null, ""),
29837
+ employmentType: import_joi41.default.string().optional().allow(null, ""),
29838
+ personnelType: import_joi41.default.string().required(),
29430
29839
  itemNumber: import_joi41.default.string().required(),
29431
29840
  positionTitle: import_joi41.default.string().required(),
29432
- officeAssignmentType: import_joi41.default.string().required(),
29433
- officeAssignment: import_joi41.default.string().required(),
29841
+ positionCategory: import_joi41.default.string().required(),
29842
+ region: import_joi41.default.string().hex().optional().allow(null, ""),
29843
+ regionName: import_joi41.default.string().optional().allow(null, ""),
29844
+ division: import_joi41.default.string().hex().optional().allow(null, ""),
29845
+ divisionName: import_joi41.default.string().optional().allow(null, ""),
29846
+ salaryGrade: import_joi41.default.number().required(),
29847
+ employeeName: import_joi41.default.string().optional().allow(null, ""),
29848
+ annualSalary: import_joi41.default.number().optional().allow(null, 0),
29849
+ monthlySalary: import_joi41.default.number().optional().allow(null, 0),
29434
29850
  status: import_joi41.default.string().required(),
29435
- employeeId: import_joi41.default.string().hex().optional().allow(null, ""),
29851
+ employee: import_joi41.default.string().hex().optional().allow(null, ""),
29436
29852
  createdAt: import_joi41.default.date().iso().optional().allow(null, ""),
29437
29853
  updatedAt: import_joi41.default.date().iso().optional().allow(null, ""),
29438
29854
  deletedAt: import_joi41.default.date().iso().optional().allow(null, "")
@@ -29449,21 +29865,25 @@ function MPlantilla(data) {
29449
29865
  throw new import_nodejs_utils82.BadRequestError("Invalid _id.");
29450
29866
  }
29451
29867
  }
29452
- if (data.employeeId && typeof data.employeeId === "string") {
29453
- try {
29454
- data.employeeId = new import_mongodb46.ObjectId(data.employeeId);
29455
- } catch (error2) {
29456
- throw new import_nodejs_utils82.BadRequestError("Invalid employeeId.");
29457
- }
29458
- }
29459
29868
  return {
29460
29869
  _id: data._id,
29461
29870
  itemNumber: data.itemNumber ?? "",
29462
29871
  positionTitle: data.positionTitle ?? "",
29463
- officeAssignmentType: data.officeAssignmentType ?? "",
29464
- officeAssignment: data.officeAssignment ?? "",
29872
+ positionCategory: data.positionCategory ?? "",
29465
29873
  status: data.status ?? "active",
29466
- employeeId: data.employeeId,
29874
+ salaryGrade: data.salaryGrade ?? 0,
29875
+ monthlySalary: data.monthlySalary ?? 0,
29876
+ annualSalary: data.annualSalary ?? 0,
29877
+ region: data.region ?? "",
29878
+ regionName: data.regionName ?? "",
29879
+ division: data.division ?? "",
29880
+ divisionName: data.divisionName ?? "",
29881
+ org: data.org ?? "",
29882
+ orgUnitCode: data.orgUnitCode ?? "",
29883
+ employmentType: data.employmentType ?? "",
29884
+ personnelType: data.personnelType ?? "",
29885
+ employee: data.employee ?? "",
29886
+ employeeName: data.employeeName ?? "",
29467
29887
  createdAt: data.createdAt ? new Date(data.createdAt) : /* @__PURE__ */ new Date(),
29468
29888
  updatedAt: data.updatedAt ? new Date(data.updatedAt) : "",
29469
29889
  deletedAt: data.deletedAt ? new Date(data.deletedAt) : ""
@@ -29492,11 +29912,14 @@ function usePlantillaRepo() {
29492
29912
  throw new Error("Failed to create index on plantillas.");
29493
29913
  }
29494
29914
  }
29495
- async function add(value, session) {
29915
+ async function add(value, session, clearCache = true) {
29916
+ console.log(value);
29496
29917
  try {
29497
29918
  value = MPlantilla(value);
29498
29919
  const res = await collection.insertOne(value, { session });
29499
- delCachedData();
29920
+ if (clearCache) {
29921
+ delCachedData();
29922
+ }
29500
29923
  return res.insertedId;
29501
29924
  } catch (error) {
29502
29925
  import_nodejs_utils83.logger.log({
@@ -29697,34 +30120,243 @@ function usePlantillaRepo() {
29697
30120
  getAll,
29698
30121
  getById,
29699
30122
  updateById,
29700
- deleteById
30123
+ deleteById,
30124
+ delCachedData
29701
30125
  };
29702
30126
  }
29703
30127
 
29704
30128
  // src/controllers/plantilla.controller.ts
29705
- var import_nodejs_utils84 = require("@eeplatform/nodejs-utils");
30129
+ var import_nodejs_utils85 = require("@eeplatform/nodejs-utils");
29706
30130
  var import_joi42 = __toESM(require("joi"));
29707
- function usePlantillaController() {
29708
- const {
29709
- add: _addPlantilla,
29710
- getAll: _getAllPlantillas,
29711
- getById: _getPlantillaById,
29712
- updateById: _updatePlantillaById,
30131
+
30132
+ // src/services/plantilla.service.ts
30133
+ var import_nodejs_utils84 = require("@eeplatform/nodejs-utils");
30134
+ var XLSX2 = __toESM(require("xlsx"));
30135
+ var Papa2 = __toESM(require("papaparse"));
30136
+ function usePlantillaService() {
30137
+ const { add: addPlantilla, delCachedData } = usePlantillaRepo();
30138
+ async function addBulk(file, region, division) {
30139
+ import_nodejs_utils84.logger.log({
30140
+ level: "info",
30141
+ message: `Starting plantilla bulk upload. File: ${file.originalname}, Size: ${file.size} bytes`
30142
+ });
30143
+ const MAX_SIZE = 16 * 1024 * 1024;
30144
+ let plantillas = [];
30145
+ let totalSize = 0;
30146
+ let validatedPlantillas = [];
30147
+ if (!file.buffer) {
30148
+ throw new import_nodejs_utils84.BadRequestError("File buffer is empty or corrupted");
30149
+ }
30150
+ try {
30151
+ const fileExtension = file.originalname.split(".").pop()?.toLowerCase();
30152
+ if (fileExtension === "csv") {
30153
+ const csvData = file.buffer.toString("utf-8");
30154
+ totalSize = Buffer.byteLength(csvData, "utf8");
30155
+ const parseResult = Papa2.parse(csvData, {
30156
+ header: true,
30157
+ skipEmptyLines: true,
30158
+ transformHeader: (header) => {
30159
+ return header.toLowerCase().replace(/\s+/g, "").replace(/[^\w]/g, "");
30160
+ }
30161
+ });
30162
+ if (parseResult.errors.length > 0) {
30163
+ throw new import_nodejs_utils84.BadRequestError(
30164
+ `CSV parsing errors: ${parseResult.errors.map((e) => e.message).join(", ")}`
30165
+ );
30166
+ }
30167
+ plantillas = parseResult.data;
30168
+ } else if (fileExtension === "xlsx" || fileExtension === "xls") {
30169
+ totalSize = file.buffer.length;
30170
+ const workbook = XLSX2.read(file.buffer, { type: "buffer" });
30171
+ const sheetName = workbook.SheetNames[0];
30172
+ const worksheet = workbook.Sheets[sheetName];
30173
+ plantillas = XLSX2.utils.sheet_to_json(worksheet, {
30174
+ header: 1,
30175
+ defval: ""
30176
+ });
30177
+ if (plantillas.length === 0) {
30178
+ throw new import_nodejs_utils84.BadRequestError("Excel file is empty.");
30179
+ }
30180
+ const headers = plantillas[0];
30181
+ const normalizedHeaders = headers.map(
30182
+ (header) => header.toLowerCase().replace(/\s+/g, "").replace(/[^\w]/g, "")
30183
+ );
30184
+ plantillas = plantillas.slice(1).map((row) => {
30185
+ const obj = {};
30186
+ normalizedHeaders.forEach((header, index) => {
30187
+ obj[header] = row[index] || "";
30188
+ });
30189
+ return obj;
30190
+ });
30191
+ } else {
30192
+ throw new import_nodejs_utils84.BadRequestError(
30193
+ "Unsupported file type. Please upload an Excel (.xlsx, .xls) or CSV (.csv) file."
30194
+ );
30195
+ }
30196
+ if (!plantillas || plantillas.length === 0) {
30197
+ throw new import_nodejs_utils84.BadRequestError("No data found in the uploaded file.");
30198
+ }
30199
+ const errors = [];
30200
+ for (let i = 0; i < plantillas.length; i++) {
30201
+ const plantillaData = plantillas[i];
30202
+ const rowNumber = i + 1;
30203
+ try {
30204
+ const itemNumber = plantillaData.itemnumber || plantillaData.item_number || "";
30205
+ const positionTitle = plantillaData.positiontitle || plantillaData.position_title || plantillaData.title || "";
30206
+ const positionCategory = plantillaData.positioncategory || plantillaData.position_category || "";
30207
+ const status = plantillaData.status || "active";
30208
+ if (!itemNumber.trim()) {
30209
+ errors.push(`Row ${rowNumber}: Item Number is required`);
30210
+ continue;
30211
+ }
30212
+ if (!positionTitle.trim()) {
30213
+ errors.push(`Row ${rowNumber}: Position Title is required`);
30214
+ continue;
30215
+ }
30216
+ if (!positionCategory.trim()) {
30217
+ errors.push(`Row ${rowNumber}: Position Category is required`);
30218
+ continue;
30219
+ }
30220
+ const plantilla = {
30221
+ itemNumber: itemNumber.trim(),
30222
+ positionTitle: positionTitle.trim(),
30223
+ positionCategory: positionCategory.trim(),
30224
+ salaryGrade: parseInt(
30225
+ plantillaData.salarygrade || plantillaData.salary_grade || "1"
30226
+ ) || 1,
30227
+ org: "",
30228
+ personnelType: "",
30229
+ status: status.trim() || "active"
30230
+ };
30231
+ if (region)
30232
+ plantilla.region = region;
30233
+ if (division)
30234
+ plantilla.division = division;
30235
+ if (plantillaData.regionname || plantillaData.region_name) {
30236
+ plantilla.regionName = plantillaData.regionname || plantillaData.region_name;
30237
+ }
30238
+ if (plantillaData.divisionname || plantillaData.division_name) {
30239
+ plantilla.divisionName = plantillaData.divisionname || plantillaData.division_name;
30240
+ }
30241
+ if (plantillaData.employee) {
30242
+ plantilla.employee = plantillaData.employee;
30243
+ }
30244
+ if (plantillaData.annualsalary || plantillaData.annual_salary) {
30245
+ plantilla.annualSalary = parseFloat(
30246
+ plantillaData.annualsalary || plantillaData.annual_salary
30247
+ ) || void 0;
30248
+ }
30249
+ if (plantillaData.monthlysalary || plantillaData.monthly_salary) {
30250
+ plantilla.monthlySalary = parseFloat(
30251
+ plantillaData.monthlysalary || plantillaData.monthly_salary
30252
+ ) || void 0;
30253
+ }
30254
+ if (!plantilla.itemNumber || !plantilla.positionTitle || !plantilla.positionCategory) {
30255
+ errors.push(`Row ${rowNumber}: Missing required fields`);
30256
+ continue;
30257
+ }
30258
+ validatedPlantillas.push(plantilla);
30259
+ } catch (error) {
30260
+ errors.push(
30261
+ `Row ${rowNumber}: ${error.message || "Invalid data format"}`
30262
+ );
30263
+ }
30264
+ }
30265
+ if (errors.length > 0) {
30266
+ throw new import_nodejs_utils84.BadRequestError(
30267
+ `Validation errors found:
30268
+ ${errors.slice(0, 10).join("\n")}${errors.length > 10 ? `
30269
+ ... and ${errors.length - 10} more errors` : ""}`
30270
+ );
30271
+ }
30272
+ if (validatedPlantillas.length === 0) {
30273
+ throw new import_nodejs_utils84.BadRequestError(
30274
+ "No valid plantilla records found after validation."
30275
+ );
30276
+ }
30277
+ if (totalSize > MAX_SIZE) {
30278
+ throw new import_nodejs_utils84.BadRequestError(
30279
+ `Data payload (${Math.round(
30280
+ totalSize / 1024 / 1024
30281
+ )}MB) exceeds MongoDB transaction limit of 16MB. Please reduce the number of records or split into smaller files.`
30282
+ );
30283
+ }
30284
+ } catch (error) {
30285
+ if (error instanceof import_nodejs_utils84.BadRequestError) {
30286
+ throw error;
30287
+ }
30288
+ throw new import_nodejs_utils84.BadRequestError(`File processing error: ${error.message}`);
30289
+ }
30290
+ const session = import_nodejs_utils84.useAtlas.getClient()?.startSession();
30291
+ if (!session) {
30292
+ throw new Error("Unable to start session for bulk plantilla upload.");
30293
+ }
30294
+ import_nodejs_utils84.logger.log({
30295
+ level: "info",
30296
+ message: `Starting bulk plantilla upload with ${validatedPlantillas.length} records`
30297
+ });
30298
+ try {
30299
+ session.startTransaction();
30300
+ const results = {
30301
+ successful: 0,
30302
+ failed: 0,
30303
+ errors: []
30304
+ };
30305
+ const promises = [];
30306
+ for (let i = 0; i < validatedPlantillas.length; i++) {
30307
+ const plantilla = validatedPlantillas[i];
30308
+ promises.push(addPlantilla(plantilla, session, false));
30309
+ }
30310
+ await Promise.all(promises);
30311
+ await delCachedData();
30312
+ await session.commitTransaction();
30313
+ return {
30314
+ message: `Bulk upload completed. ${results.successful} plantillas added successfully.`,
30315
+ details: {
30316
+ successful: results.successful,
30317
+ failed: results.failed,
30318
+ total: validatedPlantillas.length,
30319
+ totalSizeMB: Math.round(totalSize / 1024 / 1024 * 100) / 100,
30320
+ errors: results.errors
30321
+ }
30322
+ };
30323
+ } catch (error) {
30324
+ import_nodejs_utils84.logger.log({
30325
+ level: "error",
30326
+ message: `Error in bulk plantilla upload: ${error.message}`
30327
+ });
30328
+ await session.abortTransaction();
30329
+ throw error;
30330
+ } finally {
30331
+ await session.endSession();
30332
+ }
30333
+ }
30334
+ return {
30335
+ addBulk
30336
+ };
30337
+ }
30338
+
30339
+ // src/controllers/plantilla.controller.ts
30340
+ function usePlantillaController() {
30341
+ const {
30342
+ add: _addPlantilla,
30343
+ getAll: _getAllPlantillas,
30344
+ getById: _getPlantillaById,
30345
+ updateById: _updatePlantillaById,
29713
30346
  deleteById: _deletePlantillaById
29714
30347
  } = usePlantillaRepo();
30348
+ const { addBulk: _addBulk } = usePlantillaService();
29715
30349
  async function createPlantilla(req, res, next) {
29716
30350
  const value = req.body;
29717
30351
  const validation = import_joi42.default.object({
29718
30352
  itemNumber: import_joi42.default.string().required(),
29719
30353
  positionTitle: import_joi42.default.string().required(),
29720
- officeAssignmentType: import_joi42.default.string().required(),
29721
- officeAssignment: import_joi42.default.string().required(),
29722
- status: import_joi42.default.string().required(),
29723
- employeeId: import_joi42.default.string().hex().optional().allow(null, "")
30354
+ positionCategory: import_joi42.default.string().required(),
30355
+ status: import_joi42.default.string().required()
29724
30356
  });
29725
30357
  const { error } = validation.validate(value);
29726
30358
  if (error) {
29727
- next(new import_nodejs_utils84.BadRequestError(error.message));
30359
+ next(new import_nodejs_utils85.BadRequestError(error.message));
29728
30360
  return;
29729
30361
  }
29730
30362
  try {
@@ -29742,12 +30374,12 @@ function usePlantillaController() {
29742
30374
  const org = req.query.org ?? "";
29743
30375
  const isPageNumber = isFinite(page);
29744
30376
  if (!isPageNumber) {
29745
- next(new import_nodejs_utils84.BadRequestError("Invalid page number."));
30377
+ next(new import_nodejs_utils85.BadRequestError("Invalid page number."));
29746
30378
  return;
29747
30379
  }
29748
30380
  const isLimitNumber = isFinite(limit);
29749
30381
  if (!isLimitNumber) {
29750
- next(new import_nodejs_utils84.BadRequestError("Invalid limit number."));
30382
+ next(new import_nodejs_utils85.BadRequestError("Invalid limit number."));
29751
30383
  return;
29752
30384
  }
29753
30385
  const validation = import_joi42.default.object({
@@ -29758,7 +30390,7 @@ function usePlantillaController() {
29758
30390
  });
29759
30391
  const { error } = validation.validate({ page, limit, search, org });
29760
30392
  if (error) {
29761
- next(new import_nodejs_utils84.BadRequestError(error.message));
30393
+ next(new import_nodejs_utils85.BadRequestError(error.message));
29762
30394
  return;
29763
30395
  }
29764
30396
  try {
@@ -29781,13 +30413,13 @@ function usePlantillaController() {
29781
30413
  });
29782
30414
  const { error } = validation.validate({ id });
29783
30415
  if (error) {
29784
- next(new import_nodejs_utils84.BadRequestError(error.message));
30416
+ next(new import_nodejs_utils85.BadRequestError(error.message));
29785
30417
  return;
29786
30418
  }
29787
30419
  try {
29788
30420
  const plantilla = await _getPlantillaById(id);
29789
30421
  if (!plantilla) {
29790
- next(new import_nodejs_utils84.BadRequestError("Plantilla not found."));
30422
+ next(new import_nodejs_utils85.BadRequestError("Plantilla not found."));
29791
30423
  return;
29792
30424
  }
29793
30425
  res.json(plantilla);
@@ -29801,19 +30433,20 @@ function usePlantillaController() {
29801
30433
  const value = req.body;
29802
30434
  const validation = import_joi42.default.object({
29803
30435
  id: import_joi42.default.string().hex().required(),
29804
- employeeId: import_joi42.default.string().hex().optional().allow(null, ""),
30436
+ employee: import_joi42.default.string().hex().optional().allow(null, ""),
29805
30437
  status: import_joi42.default.string().optional(),
29806
- positionTitle: import_joi42.default.string().optional()
30438
+ positionTitle: import_joi42.default.string().optional(),
30439
+ positionCategory: import_joi42.default.string().optional()
29807
30440
  });
29808
30441
  const { error } = validation.validate({ id, ...value });
29809
30442
  if (error) {
29810
- next(new import_nodejs_utils84.BadRequestError(error.message));
30443
+ next(new import_nodejs_utils85.BadRequestError(error.message));
29811
30444
  return;
29812
30445
  }
29813
30446
  try {
29814
30447
  const result = await _updatePlantillaById(id, value);
29815
30448
  if (result.matchedCount === 0) {
29816
- next(new import_nodejs_utils84.BadRequestError("Plantilla not found."));
30449
+ next(new import_nodejs_utils85.BadRequestError("Plantilla not found."));
29817
30450
  return;
29818
30451
  }
29819
30452
  res.json({ message: "Plantilla updated successfully" });
@@ -29829,13 +30462,13 @@ function usePlantillaController() {
29829
30462
  });
29830
30463
  const { error } = validation.validate({ id });
29831
30464
  if (error) {
29832
- next(new import_nodejs_utils84.BadRequestError(error.message));
30465
+ next(new import_nodejs_utils85.BadRequestError(error.message));
29833
30466
  return;
29834
30467
  }
29835
30468
  try {
29836
30469
  const result = await _deletePlantillaById(id);
29837
30470
  if (result.matchedCount === 0) {
29838
- next(new import_nodejs_utils84.BadRequestError("Plantilla not found."));
30471
+ next(new import_nodejs_utils85.BadRequestError("Plantilla not found."));
29839
30472
  return;
29840
30473
  }
29841
30474
  res.json({ message: "Plantilla deleted successfully" });
@@ -29844,12 +30477,1175 @@ function usePlantillaController() {
29844
30477
  next(error2);
29845
30478
  }
29846
30479
  }
30480
+ async function bulkAddPlantillas(req, res, next) {
30481
+ if (!req.file) {
30482
+ res.status(400).send("File is required!");
30483
+ return;
30484
+ }
30485
+ const { region, division } = req.body;
30486
+ const validation = import_joi42.default.object({
30487
+ region: import_joi42.default.string().hex().optional(),
30488
+ division: import_joi42.default.string().hex().optional()
30489
+ });
30490
+ const { error } = validation.validate({ region, division });
30491
+ if (error) {
30492
+ next(new import_nodejs_utils85.BadRequestError(`Validation error: ${error.message}`));
30493
+ return;
30494
+ }
30495
+ if (!region && !division) {
30496
+ next(
30497
+ new import_nodejs_utils85.BadRequestError(
30498
+ "At least one of region or division must be provided"
30499
+ )
30500
+ );
30501
+ return;
30502
+ }
30503
+ try {
30504
+ const result = await _addBulk(req.file, region, division);
30505
+ res.status(201).json(result);
30506
+ return;
30507
+ } catch (error2) {
30508
+ next(error2);
30509
+ return;
30510
+ }
30511
+ }
29847
30512
  return {
29848
30513
  createPlantilla,
29849
30514
  getAllPlantillas,
29850
30515
  getPlantillaById,
29851
30516
  updatePlantilla,
29852
- deletePlantilla
30517
+ deletePlantilla,
30518
+ bulkAddPlantillas
30519
+ };
30520
+ }
30521
+
30522
+ // src/models/office.model.ts
30523
+ var import_nodejs_utils86 = require("@eeplatform/nodejs-utils");
30524
+ var import_joi43 = __toESM(require("joi"));
30525
+ var import_mongodb48 = require("mongodb");
30526
+ var schemaOffice = import_joi43.default.object({
30527
+ _id: import_joi43.default.string().hex().optional().allow(null, ""),
30528
+ name: import_joi43.default.string().required(),
30529
+ code: import_joi43.default.string().required(),
30530
+ type: import_joi43.default.string().required(),
30531
+ parent: import_joi43.default.string().hex().optional().allow(null, ""),
30532
+ path: import_joi43.default.string().required(),
30533
+ status: import_joi43.default.string().required(),
30534
+ createdAt: import_joi43.default.date().iso().optional().allow(null, ""),
30535
+ updatedAt: import_joi43.default.date().iso().optional().allow(null, ""),
30536
+ deletedAt: import_joi43.default.date().iso().optional().allow(null, "")
30537
+ });
30538
+ function MOffice(data) {
30539
+ const { error } = schemaOffice.validate(data);
30540
+ if (error) {
30541
+ throw new import_nodejs_utils86.BadRequestError(error.message);
30542
+ }
30543
+ if (data._id && typeof data._id === "string") {
30544
+ try {
30545
+ data._id = new import_mongodb48.ObjectId(data._id);
30546
+ } catch (error2) {
30547
+ throw new import_nodejs_utils86.BadRequestError("Invalid _id.");
30548
+ }
30549
+ }
30550
+ if (data.parent && typeof data.parent === "string") {
30551
+ try {
30552
+ data.parent = new import_mongodb48.ObjectId(data.parent);
30553
+ } catch (error2) {
30554
+ throw new import_nodejs_utils86.BadRequestError("Invalid parent.");
30555
+ }
30556
+ }
30557
+ return {
30558
+ _id: data._id,
30559
+ name: data.name ?? "",
30560
+ code: data.code ?? "",
30561
+ type: data.type ?? "",
30562
+ parent: data.parent ?? "",
30563
+ path: data.path ?? "",
30564
+ status: data.status ?? "active",
30565
+ createdAt: data.createdAt ? new Date(data.createdAt) : /* @__PURE__ */ new Date(),
30566
+ updatedAt: data.updatedAt ? new Date(data.updatedAt) : "",
30567
+ deletedAt: data.deletedAt ? new Date(data.deletedAt) : ""
30568
+ };
30569
+ }
30570
+
30571
+ // src/repositories/office.repository.ts
30572
+ var import_nodejs_utils87 = require("@eeplatform/nodejs-utils");
30573
+ var import_mongodb49 = require("mongodb");
30574
+ function useOfficeRepo() {
30575
+ const db = import_nodejs_utils87.useAtlas.getDb();
30576
+ if (!db) {
30577
+ throw new Error("Unable to connect to server.");
30578
+ }
30579
+ const namespace_collection = "offices";
30580
+ const collection = db.collection(namespace_collection);
30581
+ const { getCache, setCache, delNamespace } = (0, import_nodejs_utils87.useCache)(namespace_collection);
30582
+ async function createIndexes() {
30583
+ try {
30584
+ await collection.createIndexes([
30585
+ {
30586
+ key: { name: 1, code: 1 },
30587
+ unique: true,
30588
+ name: "unique_name_code_index"
30589
+ },
30590
+ { key: { type: 1 } },
30591
+ { key: { parent: 1 } },
30592
+ { key: { status: 1 } }
30593
+ ]);
30594
+ } catch (error) {
30595
+ throw new Error("Failed to create index on offices.");
30596
+ }
30597
+ }
30598
+ async function add(value, session, clearCache = true) {
30599
+ try {
30600
+ value = MOffice(value);
30601
+ const res = await collection.insertOne(value, { session });
30602
+ if (clearCache) {
30603
+ delCachedData();
30604
+ }
30605
+ return res.insertedId;
30606
+ } catch (error) {
30607
+ import_nodejs_utils87.logger.log({
30608
+ level: "error",
30609
+ message: error.message
30610
+ });
30611
+ if (error instanceof import_nodejs_utils87.AppError) {
30612
+ throw error;
30613
+ } else {
30614
+ const isDuplicated = error.message.includes("duplicate");
30615
+ if (isDuplicated) {
30616
+ throw new import_nodejs_utils87.BadRequestError("Office already exists.");
30617
+ }
30618
+ throw new Error("Failed to create office.");
30619
+ }
30620
+ }
30621
+ }
30622
+ async function updateById(_id, value, session) {
30623
+ try {
30624
+ _id = new import_mongodb49.ObjectId(_id);
30625
+ } catch (error) {
30626
+ throw new import_nodejs_utils87.BadRequestError("Invalid ID.");
30627
+ }
30628
+ value.updatedAt = /* @__PURE__ */ new Date();
30629
+ try {
30630
+ const res = await collection.updateOne(
30631
+ { _id },
30632
+ { $set: value },
30633
+ { session }
30634
+ );
30635
+ delCachedData();
30636
+ return res;
30637
+ } catch (error) {
30638
+ import_nodejs_utils87.logger.log({
30639
+ level: "error",
30640
+ message: error.message
30641
+ });
30642
+ if (error instanceof import_nodejs_utils87.AppError) {
30643
+ throw error;
30644
+ } else {
30645
+ throw new Error("Failed to update office.");
30646
+ }
30647
+ }
30648
+ }
30649
+ async function getAll({
30650
+ search = "",
30651
+ page = 1,
30652
+ limit = 10,
30653
+ sort = {},
30654
+ type = "",
30655
+ parent = "",
30656
+ status = "active"
30657
+ } = {}) {
30658
+ page = page > 0 ? page - 1 : 0;
30659
+ const query = {
30660
+ status
30661
+ };
30662
+ sort = Object.keys(sort).length > 0 ? sort : { _id: -1 };
30663
+ if (search) {
30664
+ query.$text = { $search: search };
30665
+ }
30666
+ if (type) {
30667
+ query.type = type;
30668
+ }
30669
+ if (parent) {
30670
+ try {
30671
+ query.parent = new import_mongodb49.ObjectId(parent);
30672
+ } catch (error) {
30673
+ throw new import_nodejs_utils87.BadRequestError("Invalid parent ID.");
30674
+ }
30675
+ }
30676
+ const cacheParams = {
30677
+ page,
30678
+ limit,
30679
+ sort: JSON.stringify(sort)
30680
+ };
30681
+ if (search)
30682
+ cacheParams.search = search;
30683
+ if (type)
30684
+ cacheParams.type = type;
30685
+ if (parent)
30686
+ cacheParams.parent = parent;
30687
+ if (status !== "active")
30688
+ cacheParams.status = status;
30689
+ const cacheKey = (0, import_nodejs_utils87.makeCacheKey)(namespace_collection, cacheParams);
30690
+ import_nodejs_utils87.logger.log({
30691
+ level: "info",
30692
+ message: `Cache key for getAll offices: ${cacheKey}`
30693
+ });
30694
+ try {
30695
+ const cached = await getCache(cacheKey);
30696
+ if (cached) {
30697
+ import_nodejs_utils87.logger.log({
30698
+ level: "info",
30699
+ message: `Cache hit for getAll offices: ${cacheKey}`
30700
+ });
30701
+ return cached;
30702
+ }
30703
+ const items = await collection.aggregate([
30704
+ { $match: query },
30705
+ { $sort: sort },
30706
+ { $skip: page * limit },
30707
+ { $limit: limit }
30708
+ ]).toArray();
30709
+ const length = await collection.countDocuments(query);
30710
+ const data = (0, import_nodejs_utils87.paginate)(items, page, limit, length);
30711
+ setCache(cacheKey, data, 600).then(() => {
30712
+ import_nodejs_utils87.logger.log({
30713
+ level: "info",
30714
+ message: `Cache set for getAll offices: ${cacheKey}`
30715
+ });
30716
+ }).catch((err) => {
30717
+ import_nodejs_utils87.logger.log({
30718
+ level: "error",
30719
+ message: `Failed to set cache for getAll offices: ${err.message}`
30720
+ });
30721
+ });
30722
+ return data;
30723
+ } catch (error) {
30724
+ import_nodejs_utils87.logger.log({ level: "error", message: `${error}` });
30725
+ throw error;
30726
+ }
30727
+ }
30728
+ async function getById(_id) {
30729
+ try {
30730
+ _id = new import_mongodb49.ObjectId(_id);
30731
+ } catch (error) {
30732
+ throw new import_nodejs_utils87.BadRequestError("Invalid ID.");
30733
+ }
30734
+ const cacheKey = (0, import_nodejs_utils87.makeCacheKey)(namespace_collection, { _id: String(_id) });
30735
+ try {
30736
+ const cached = await getCache(cacheKey);
30737
+ if (cached) {
30738
+ import_nodejs_utils87.logger.log({
30739
+ level: "info",
30740
+ message: `Cache hit for getById office: ${cacheKey}`
30741
+ });
30742
+ return cached;
30743
+ }
30744
+ const result = await collection.findOne({
30745
+ _id
30746
+ });
30747
+ setCache(cacheKey, result, 300).then(() => {
30748
+ import_nodejs_utils87.logger.log({
30749
+ level: "info",
30750
+ message: `Cache set for office by id: ${cacheKey}`
30751
+ });
30752
+ }).catch((err) => {
30753
+ import_nodejs_utils87.logger.log({
30754
+ level: "error",
30755
+ message: `Failed to set cache for office by id: ${err.message}`
30756
+ });
30757
+ });
30758
+ return result;
30759
+ } catch (error) {
30760
+ if (error instanceof import_nodejs_utils87.AppError) {
30761
+ throw error;
30762
+ } else {
30763
+ throw new import_nodejs_utils87.InternalServerError("Failed to get office.");
30764
+ }
30765
+ }
30766
+ }
30767
+ async function deleteById(_id, session) {
30768
+ try {
30769
+ _id = new import_mongodb49.ObjectId(_id);
30770
+ } catch (error) {
30771
+ throw new import_nodejs_utils87.BadRequestError("Invalid ID.");
30772
+ }
30773
+ try {
30774
+ const res = await collection.updateOne(
30775
+ { _id },
30776
+ { $set: { status: "deleted", deletedAt: /* @__PURE__ */ new Date() } }
30777
+ );
30778
+ delCachedData();
30779
+ return res;
30780
+ } catch (error) {
30781
+ import_nodejs_utils87.logger.log({
30782
+ level: "error",
30783
+ message: error.message
30784
+ });
30785
+ if (error instanceof import_nodejs_utils87.AppError) {
30786
+ throw error;
30787
+ } else {
30788
+ throw new import_nodejs_utils87.InternalServerError("Failed to delete office.");
30789
+ }
30790
+ }
30791
+ }
30792
+ function delCachedData() {
30793
+ delNamespace().then(() => {
30794
+ import_nodejs_utils87.logger.log({
30795
+ level: "info",
30796
+ message: `Cache namespace cleared for ${namespace_collection}`
30797
+ });
30798
+ }).catch((err) => {
30799
+ import_nodejs_utils87.logger.log({
30800
+ level: "error",
30801
+ message: `Failed to clear cache namespace for ${namespace_collection}: ${err.message}`
30802
+ });
30803
+ });
30804
+ }
30805
+ return {
30806
+ createIndexes,
30807
+ add,
30808
+ getAll,
30809
+ getById,
30810
+ updateById,
30811
+ deleteById,
30812
+ delCachedData
30813
+ };
30814
+ }
30815
+
30816
+ // src/services/office.service.ts
30817
+ var import_nodejs_utils88 = require("@eeplatform/nodejs-utils");
30818
+ var XLSX3 = __toESM(require("xlsx"));
30819
+ var Papa3 = __toESM(require("papaparse"));
30820
+ function useOfficeService() {
30821
+ const { add: addOffice, delCachedData } = useOfficeRepo();
30822
+ async function addBulk(file) {
30823
+ import_nodejs_utils88.logger.log({
30824
+ level: "info",
30825
+ message: `Starting office bulk upload. File: ${file.originalname}, Size: ${file.size} bytes`
30826
+ });
30827
+ const MAX_SIZE = 16 * 1024 * 1024;
30828
+ let offices = [];
30829
+ let totalSize = 0;
30830
+ let validatedOffices = [];
30831
+ if (!file.buffer) {
30832
+ throw new import_nodejs_utils88.BadRequestError("File buffer is empty or corrupted");
30833
+ }
30834
+ try {
30835
+ const fileExtension = file.originalname.split(".").pop()?.toLowerCase();
30836
+ if (fileExtension === "csv") {
30837
+ const csvData = file.buffer.toString("utf-8");
30838
+ totalSize = Buffer.byteLength(csvData, "utf8");
30839
+ if (totalSize > MAX_SIZE) {
30840
+ throw new import_nodejs_utils88.BadRequestError(
30841
+ `File size exceeds limit. Maximum allowed: ${MAX_SIZE / 1024 / 1024}MB, Received: ${(totalSize / 1024 / 1024).toFixed(2)}MB`
30842
+ );
30843
+ }
30844
+ const parseResult = Papa3.parse(csvData, {
30845
+ header: true,
30846
+ skipEmptyLines: true,
30847
+ transformHeader: (header) => {
30848
+ return header.toLowerCase().replace(/\s+/g, "").replace(/[^\w]/g, "");
30849
+ }
30850
+ });
30851
+ if (parseResult.errors.length > 0) {
30852
+ throw new import_nodejs_utils88.BadRequestError(
30853
+ `CSV parsing errors: ${parseResult.errors.map((e) => e.message).join(", ")}`
30854
+ );
30855
+ }
30856
+ offices = parseResult.data || [];
30857
+ } else if (["xlsx", "xls"].includes(fileExtension || "")) {
30858
+ totalSize = file.buffer.length;
30859
+ if (totalSize > MAX_SIZE) {
30860
+ throw new import_nodejs_utils88.BadRequestError(
30861
+ `File size exceeds limit. Maximum allowed: ${MAX_SIZE / 1024 / 1024}MB, Received: ${(totalSize / 1024 / 1024).toFixed(2)}MB`
30862
+ );
30863
+ }
30864
+ const workbook = XLSX3.read(file.buffer, { type: "buffer" });
30865
+ const sheetName = workbook.SheetNames[0];
30866
+ if (!sheetName) {
30867
+ throw new import_nodejs_utils88.BadRequestError("Excel file contains no sheets");
30868
+ }
30869
+ const worksheet = workbook.Sheets[sheetName];
30870
+ offices = XLSX3.utils.sheet_to_json(worksheet, {
30871
+ header: 1,
30872
+ defval: ""
30873
+ });
30874
+ if (offices.length > 0) {
30875
+ const headers = offices[0];
30876
+ offices = offices.slice(1).map((row) => {
30877
+ const obj = {};
30878
+ headers.forEach((header, index) => {
30879
+ obj[header.trim()] = row[index] || "";
30880
+ });
30881
+ return obj;
30882
+ });
30883
+ }
30884
+ } else {
30885
+ throw new import_nodejs_utils88.BadRequestError(
30886
+ "Unsupported file format. Please upload CSV, XLS, or XLSX files."
30887
+ );
30888
+ }
30889
+ if (!offices || offices.length === 0) {
30890
+ throw new import_nodejs_utils88.BadRequestError("File is empty or contains no valid data");
30891
+ }
30892
+ const results = {
30893
+ total: offices.length,
30894
+ successful: 0,
30895
+ failed: 0,
30896
+ errors: []
30897
+ };
30898
+ import_nodejs_utils88.logger.log({
30899
+ level: "info",
30900
+ message: `Processing ${offices.length} offices from file`
30901
+ });
30902
+ for (let i = 0; i < offices.length; i++) {
30903
+ const officeData = offices[i];
30904
+ try {
30905
+ const cleanOffice = {
30906
+ name: String(officeData.name || "").trim(),
30907
+ code: String(officeData.code || "").trim(),
30908
+ type: String(officeData.type || "").trim(),
30909
+ path: String(officeData.path || "").trim(),
30910
+ status: String(officeData.status || "active").trim()
30911
+ };
30912
+ if (officeData.parent && String(officeData.parent).trim()) {
30913
+ cleanOffice.parent = String(officeData.parent).trim();
30914
+ }
30915
+ const { error } = schemaOffice.validate(cleanOffice);
30916
+ if (error) {
30917
+ results.errors.push(`Row ${i + 1}: ${error.message}`);
30918
+ results.failed++;
30919
+ continue;
30920
+ }
30921
+ validatedOffices.push(cleanOffice);
30922
+ } catch (error) {
30923
+ results.errors.push(`Row ${i + 1}: ${error.message}`);
30924
+ results.failed++;
30925
+ }
30926
+ }
30927
+ if (validatedOffices.length === 0) {
30928
+ throw new import_nodejs_utils88.BadRequestError(
30929
+ "No valid offices found in file. Please check the format and data."
30930
+ );
30931
+ }
30932
+ const db = import_nodejs_utils88.useAtlas.getDb();
30933
+ if (!db) {
30934
+ throw new Error("Database connection not available");
30935
+ }
30936
+ const session = db.client.startSession();
30937
+ try {
30938
+ await session.withTransaction(async () => {
30939
+ const batchSize = 100;
30940
+ for (let i = 0; i < validatedOffices.length; i += batchSize) {
30941
+ const batch = validatedOffices.slice(i, i + batchSize);
30942
+ for (const office of batch) {
30943
+ try {
30944
+ await addOffice(office, session, false);
30945
+ results.successful++;
30946
+ } catch (error) {
30947
+ results.failed++;
30948
+ results.errors.push(
30949
+ `Failed to insert office "${office.name}": ${error.message}`
30950
+ );
30951
+ import_nodejs_utils88.logger.log({
30952
+ level: "error",
30953
+ message: `Failed to insert office: ${error.message}`
30954
+ });
30955
+ }
30956
+ }
30957
+ }
30958
+ });
30959
+ delCachedData();
30960
+ import_nodejs_utils88.logger.log({
30961
+ level: "info",
30962
+ message: `Bulk upload completed. Successful: ${results.successful}, Failed: ${results.failed}`
30963
+ });
30964
+ return results;
30965
+ } catch (error) {
30966
+ import_nodejs_utils88.logger.log({
30967
+ level: "error",
30968
+ message: `Transaction failed: ${error.message}`
30969
+ });
30970
+ throw new import_nodejs_utils88.BadRequestError(`Bulk upload failed: ${error.message}`);
30971
+ } finally {
30972
+ await session.endSession();
30973
+ }
30974
+ } catch (error) {
30975
+ import_nodejs_utils88.logger.log({
30976
+ level: "error",
30977
+ message: `Bulk office upload failed: ${error.message}`
30978
+ });
30979
+ if (error instanceof import_nodejs_utils88.BadRequestError) {
30980
+ throw error;
30981
+ }
30982
+ throw new import_nodejs_utils88.BadRequestError(`File processing failed: ${error.message}`);
30983
+ }
30984
+ }
30985
+ return {
30986
+ addBulk
30987
+ };
30988
+ }
30989
+
30990
+ // src/controllers/office.controller.ts
30991
+ var import_nodejs_utils89 = require("@eeplatform/nodejs-utils");
30992
+ var import_joi44 = __toESM(require("joi"));
30993
+ function useOfficeController() {
30994
+ const {
30995
+ add: _add,
30996
+ getAll: _getAll,
30997
+ getById: _getById,
30998
+ updateById: _updateByIdById,
30999
+ deleteById: _deleteByIdById
31000
+ } = useOfficeRepo();
31001
+ const { addBulk: _addBulk } = useOfficeService();
31002
+ async function add(req, res, next) {
31003
+ const value = req.body;
31004
+ const validation = import_joi44.default.object({
31005
+ name: import_joi44.default.string().required(),
31006
+ code: import_joi44.default.string().required(),
31007
+ type: import_joi44.default.string().required(),
31008
+ path: import_joi44.default.string().required(),
31009
+ parent: import_joi44.default.string().hex().optional().allow(null, ""),
31010
+ status: import_joi44.default.string().optional().allow(null, "")
31011
+ });
31012
+ const { error } = validation.validate(value);
31013
+ if (error) {
31014
+ next(new import_nodejs_utils89.BadRequestError(error.message));
31015
+ return;
31016
+ }
31017
+ try {
31018
+ const id = await _add(value);
31019
+ res.json({ message: "Office created successfully", id });
31020
+ return;
31021
+ } catch (error2) {
31022
+ next(error2);
31023
+ }
31024
+ }
31025
+ async function getAll(req, res, next) {
31026
+ const page = typeof req.query.page === "string" ? Number(req.query.page) : 1;
31027
+ const limit = typeof req.query.limit === "string" ? Number(req.query.limit) : 10;
31028
+ const search = req.query.search ?? "";
31029
+ const type = req.query.type ?? "";
31030
+ const parent = req.query.parent ?? "";
31031
+ const status = req.query.status ?? "active";
31032
+ const isPageNumber = isFinite(page);
31033
+ if (!isPageNumber) {
31034
+ next(new import_nodejs_utils89.BadRequestError("Invalid page number."));
31035
+ return;
31036
+ }
31037
+ const isLimitNumber = isFinite(limit);
31038
+ if (!isLimitNumber) {
31039
+ next(new import_nodejs_utils89.BadRequestError("Invalid limit number."));
31040
+ return;
31041
+ }
31042
+ const validation = import_joi44.default.object({
31043
+ page: import_joi44.default.number().min(1).optional().allow("", null),
31044
+ limit: import_joi44.default.number().min(1).optional().allow("", null),
31045
+ search: import_joi44.default.string().optional().allow("", null),
31046
+ type: import_joi44.default.string().optional().allow("", null),
31047
+ parent: import_joi44.default.string().optional().allow("", null),
31048
+ status: import_joi44.default.string().optional().allow("", null)
31049
+ });
31050
+ const { error } = validation.validate({
31051
+ page,
31052
+ limit,
31053
+ search,
31054
+ type,
31055
+ parent,
31056
+ status
31057
+ });
31058
+ if (error) {
31059
+ next(new import_nodejs_utils89.BadRequestError(error.message));
31060
+ return;
31061
+ }
31062
+ try {
31063
+ const offices = await _getAll({
31064
+ search,
31065
+ page,
31066
+ limit,
31067
+ type,
31068
+ parent,
31069
+ status
31070
+ });
31071
+ res.json(offices);
31072
+ return;
31073
+ } catch (error2) {
31074
+ next(error2);
31075
+ }
31076
+ }
31077
+ async function getById(req, res, next) {
31078
+ const id = req.params.id;
31079
+ const validation = import_joi44.default.object({
31080
+ id: import_joi44.default.string().hex().required()
31081
+ });
31082
+ const { error } = validation.validate({ id });
31083
+ if (error) {
31084
+ next(new import_nodejs_utils89.BadRequestError(error.message));
31085
+ return;
31086
+ }
31087
+ try {
31088
+ const office = await _getById(id);
31089
+ if (!office) {
31090
+ next(new import_nodejs_utils89.BadRequestError("Office not found."));
31091
+ return;
31092
+ }
31093
+ res.json(office);
31094
+ return;
31095
+ } catch (error2) {
31096
+ next(error2);
31097
+ }
31098
+ }
31099
+ async function updateById(req, res, next) {
31100
+ const id = req.params.id;
31101
+ const value = req.body;
31102
+ const validation = import_joi44.default.object({
31103
+ id: import_joi44.default.string().hex().required(),
31104
+ name: import_joi44.default.string().optional(),
31105
+ code: import_joi44.default.string().optional(),
31106
+ type: import_joi44.default.string().optional(),
31107
+ parent: import_joi44.default.string().hex().optional().allow(null, ""),
31108
+ path: import_joi44.default.string().optional(),
31109
+ status: import_joi44.default.string().optional()
31110
+ });
31111
+ const { error } = validation.validate({ id, ...value });
31112
+ if (error) {
31113
+ next(new import_nodejs_utils89.BadRequestError(error.message));
31114
+ return;
31115
+ }
31116
+ try {
31117
+ const result = await _updateByIdById(id, value);
31118
+ if (result.matchedCount === 0) {
31119
+ next(new import_nodejs_utils89.BadRequestError("Office not found."));
31120
+ return;
31121
+ }
31122
+ res.json({ message: "Office updated successfully" });
31123
+ return;
31124
+ } catch (error2) {
31125
+ next(error2);
31126
+ }
31127
+ }
31128
+ async function deleteById(req, res, next) {
31129
+ const id = req.params.id;
31130
+ const validation = import_joi44.default.object({
31131
+ id: import_joi44.default.string().hex().required()
31132
+ });
31133
+ const { error } = validation.validate({ id });
31134
+ if (error) {
31135
+ next(new import_nodejs_utils89.BadRequestError(error.message));
31136
+ return;
31137
+ }
31138
+ try {
31139
+ const result = await _deleteByIdById(id);
31140
+ if (result.matchedCount === 0) {
31141
+ next(new import_nodejs_utils89.BadRequestError("Office not found."));
31142
+ return;
31143
+ }
31144
+ res.json({ message: "Office deleted successfully" });
31145
+ return;
31146
+ } catch (error2) {
31147
+ next(error2);
31148
+ }
31149
+ }
31150
+ async function bulkAddOffices(req, res, next) {
31151
+ if (!req.file) {
31152
+ res.status(400).send("File is required!");
31153
+ return;
31154
+ }
31155
+ try {
31156
+ const result = await _addBulk(req.file);
31157
+ res.status(201).json(result);
31158
+ return;
31159
+ } catch (error) {
31160
+ next(error);
31161
+ return;
31162
+ }
31163
+ }
31164
+ return {
31165
+ add,
31166
+ getAll,
31167
+ getById,
31168
+ updateById,
31169
+ deleteById,
31170
+ bulkAddOffices
31171
+ };
31172
+ }
31173
+
31174
+ // src/models/curriculum.model.ts
31175
+ var import_nodejs_utils90 = require("@eeplatform/nodejs-utils");
31176
+ var import_joi45 = __toESM(require("joi"));
31177
+ var import_mongodb50 = require("mongodb");
31178
+ var schemaCurriculum = import_joi45.default.object({
31179
+ _id: import_joi45.default.string().hex().optional(),
31180
+ school: import_joi45.default.string().hex().required(),
31181
+ code: import_joi45.default.string().required(),
31182
+ educationLevel: import_joi45.default.string().required(),
31183
+ gradeLevel: import_joi45.default.string().required(),
31184
+ subjectCode: import_joi45.default.string().required(),
31185
+ subjectName: import_joi45.default.string().required(),
31186
+ subjectType: import_joi45.default.string().required(),
31187
+ sessionFrequency: import_joi45.default.number().integer().min(0).required(),
31188
+ sessionDuration: import_joi45.default.number().integer().min(0).required(),
31189
+ totalMinutesPerWeek: import_joi45.default.number().integer().min(0).required(),
31190
+ curriculumMemoRef: import_joi45.default.string().optional().allow("", null),
31191
+ status: import_joi45.default.string().optional().allow("", null),
31192
+ createdAt: import_joi45.default.date().optional().allow("", null),
31193
+ updatedAt: import_joi45.default.date().optional().allow("", null),
31194
+ deletedAt: import_joi45.default.date().optional().allow("", null),
31195
+ createdBy: import_joi45.default.string().optional().allow("", null),
31196
+ updatedBy: import_joi45.default.string().optional().allow("", null),
31197
+ deletedBy: import_joi45.default.string().optional().allow("", null)
31198
+ });
31199
+ function MCurriculum(value) {
31200
+ const { error } = schemaCurriculum.validate(value);
31201
+ if (error) {
31202
+ import_nodejs_utils90.logger.info(`Curriculum Model: ${error.message}`);
31203
+ throw new import_nodejs_utils90.BadRequestError(error.message);
31204
+ }
31205
+ if (value._id && typeof value._id === "string") {
31206
+ try {
31207
+ value._id = new import_mongodb50.ObjectId(value._id);
31208
+ } catch (error2) {
31209
+ throw new import_nodejs_utils90.BadRequestError("Invalid _id format");
31210
+ }
31211
+ }
31212
+ return {
31213
+ _id: value._id ?? void 0,
31214
+ school: value.school ?? "",
31215
+ code: value.code ?? "",
31216
+ educationLevel: value.educationLevel ?? "",
31217
+ gradeLevel: value.gradeLevel ?? "",
31218
+ subjectCode: value.subjectCode ?? "",
31219
+ subjectName: value.subjectName ?? "",
31220
+ subjectType: value.subjectType ?? "",
31221
+ sessionFrequency: value.sessionFrequency ?? 0,
31222
+ sessionDuration: value.sessionDuration ?? 0,
31223
+ totalMinutesPerWeek: value.totalMinutesPerWeek ?? 0,
31224
+ curriculumMemoRef: value.curriculumMemoRef ?? "",
31225
+ status: value.status ?? "active",
31226
+ createdAt: value.createdAt ?? /* @__PURE__ */ new Date(),
31227
+ updatedAt: value.updatedAt ?? "",
31228
+ deletedAt: value.deletedAt ?? "",
31229
+ createdBy: value.createdBy ?? "",
31230
+ updatedBy: value.updatedBy ?? "",
31231
+ deletedBy: value.deletedBy ?? ""
31232
+ };
31233
+ }
31234
+
31235
+ // src/repositories/curriculum.repository.ts
31236
+ var import_nodejs_utils91 = require("@eeplatform/nodejs-utils");
31237
+ var import_mongodb51 = require("mongodb");
31238
+ function useCurriculumRepo() {
31239
+ const db = import_nodejs_utils91.useAtlas.getDb();
31240
+ if (!db) {
31241
+ throw new Error("Unable to connect to server.");
31242
+ }
31243
+ const namespace_collection = "school.curriculums";
31244
+ const collection = db.collection(namespace_collection);
31245
+ const { getCache, setCache, delNamespace } = (0, import_nodejs_utils91.useCache)(namespace_collection);
31246
+ async function createIndexes() {
31247
+ try {
31248
+ await collection.createIndexes([
31249
+ { key: { code: 1 }, unique: true, name: "unique_code_index" },
31250
+ { key: { educationLevel: 1 } },
31251
+ { key: { gradeLevel: 1 } },
31252
+ { key: { subjectCode: 1 } },
31253
+ { key: { status: 1 } }
31254
+ ]);
31255
+ } catch (error) {
31256
+ throw new Error("Failed to create index on curriculums.");
31257
+ }
31258
+ }
31259
+ async function add(value, session) {
31260
+ try {
31261
+ value = MCurriculum(value);
31262
+ const res = await collection.insertOne(value, { session });
31263
+ delCachedData();
31264
+ return res.insertedId;
31265
+ } catch (error) {
31266
+ import_nodejs_utils91.logger.log({
31267
+ level: "error",
31268
+ message: error.message
31269
+ });
31270
+ if (error instanceof import_nodejs_utils91.AppError) {
31271
+ throw error;
31272
+ } else {
31273
+ const isDuplicated = error.message.includes("duplicate");
31274
+ if (isDuplicated) {
31275
+ throw new import_nodejs_utils91.BadRequestError("Curriculum already exists.");
31276
+ }
31277
+ throw new Error("Failed to create curriculum.");
31278
+ }
31279
+ }
31280
+ }
31281
+ async function updateById(_id, value, session) {
31282
+ try {
31283
+ _id = new import_mongodb51.ObjectId(_id);
31284
+ } catch (error) {
31285
+ throw new import_nodejs_utils91.BadRequestError("Invalid ID.");
31286
+ }
31287
+ try {
31288
+ const res = await collection.updateOne(
31289
+ { _id },
31290
+ { $set: { ...value, updatedAt: /* @__PURE__ */ new Date() } },
31291
+ { session }
31292
+ );
31293
+ delCachedData();
31294
+ return res;
31295
+ } catch (error) {
31296
+ import_nodejs_utils91.logger.log({
31297
+ level: "error",
31298
+ message: error.message
31299
+ });
31300
+ if (error instanceof import_nodejs_utils91.AppError) {
31301
+ throw error;
31302
+ } else {
31303
+ throw new Error("Failed to update curriculum.");
31304
+ }
31305
+ }
31306
+ }
31307
+ async function getAll({
31308
+ search = "",
31309
+ page = 1,
31310
+ limit = 10,
31311
+ sort = {},
31312
+ educationLevel = "",
31313
+ gradeLevel = "",
31314
+ subjectCode = "",
31315
+ status = "active"
31316
+ } = {}) {
31317
+ page = page > 0 ? page - 1 : 0;
31318
+ const query = {
31319
+ status
31320
+ };
31321
+ sort = Object.keys(sort).length > 0 ? sort : { _id: -1 };
31322
+ if (search) {
31323
+ query.$or = [
31324
+ { code: { $regex: search, $options: "i" } },
31325
+ { subjectName: { $regex: search, $options: "i" } },
31326
+ { subjectCode: { $regex: search, $options: "i" } }
31327
+ ];
31328
+ }
31329
+ if (educationLevel) {
31330
+ query.educationLevel = educationLevel;
31331
+ }
31332
+ if (gradeLevel) {
31333
+ query.gradeLevel = gradeLevel;
31334
+ }
31335
+ if (subjectCode) {
31336
+ query.subjectCode = subjectCode;
31337
+ }
31338
+ const cacheParams = {
31339
+ page,
31340
+ limit,
31341
+ sort: JSON.stringify(sort)
31342
+ };
31343
+ if (search)
31344
+ cacheParams.search = search;
31345
+ if (educationLevel)
31346
+ cacheParams.educationLevel = educationLevel;
31347
+ if (gradeLevel)
31348
+ cacheParams.gradeLevel = gradeLevel;
31349
+ if (subjectCode)
31350
+ cacheParams.subjectCode = subjectCode;
31351
+ if (status !== "active")
31352
+ cacheParams.status = status;
31353
+ const cacheKey = (0, import_nodejs_utils91.makeCacheKey)(namespace_collection, cacheParams);
31354
+ import_nodejs_utils91.logger.log({
31355
+ level: "info",
31356
+ message: `Cache key for getAll curriculums: ${cacheKey}`
31357
+ });
31358
+ try {
31359
+ const cached = await getCache(cacheKey);
31360
+ if (cached) {
31361
+ import_nodejs_utils91.logger.log({
31362
+ level: "info",
31363
+ message: `Cache hit for getAll curriculums: ${cacheKey}`
31364
+ });
31365
+ return cached;
31366
+ }
31367
+ const items = await collection.aggregate([
31368
+ { $match: query },
31369
+ { $sort: sort },
31370
+ { $skip: page * limit },
31371
+ { $limit: limit }
31372
+ ]).toArray();
31373
+ const length = await collection.countDocuments(query);
31374
+ const data = (0, import_nodejs_utils91.paginate)(items, page, limit, length);
31375
+ setCache(cacheKey, data, 600).then(() => {
31376
+ import_nodejs_utils91.logger.log({
31377
+ level: "info",
31378
+ message: `Cache set for getAll curriculums: ${cacheKey}`
31379
+ });
31380
+ }).catch((err) => {
31381
+ import_nodejs_utils91.logger.log({
31382
+ level: "error",
31383
+ message: `Failed to set cache for getAll curriculums: ${err.message}`
31384
+ });
31385
+ });
31386
+ return data;
31387
+ } catch (error) {
31388
+ import_nodejs_utils91.logger.log({ level: "error", message: `${error}` });
31389
+ throw error;
31390
+ }
31391
+ }
31392
+ async function getById(_id) {
31393
+ try {
31394
+ _id = new import_mongodb51.ObjectId(_id);
31395
+ } catch (error) {
31396
+ throw new import_nodejs_utils91.BadRequestError("Invalid ID.");
31397
+ }
31398
+ const cacheKey = (0, import_nodejs_utils91.makeCacheKey)(namespace_collection, { _id: String(_id) });
31399
+ try {
31400
+ const cached = await getCache(cacheKey);
31401
+ if (cached) {
31402
+ import_nodejs_utils91.logger.log({
31403
+ level: "info",
31404
+ message: `Cache hit for getById curriculum: ${cacheKey}`
31405
+ });
31406
+ return cached;
31407
+ }
31408
+ const result = await collection.findOne({
31409
+ _id
31410
+ });
31411
+ setCache(cacheKey, result, 300).then(() => {
31412
+ import_nodejs_utils91.logger.log({
31413
+ level: "info",
31414
+ message: `Cache set for curriculum by id: ${cacheKey}`
31415
+ });
31416
+ }).catch((err) => {
31417
+ import_nodejs_utils91.logger.log({
31418
+ level: "error",
31419
+ message: `Failed to set cache for curriculum by id: ${err.message}`
31420
+ });
31421
+ });
31422
+ return result;
31423
+ } catch (error) {
31424
+ if (error instanceof import_nodejs_utils91.AppError) {
31425
+ throw error;
31426
+ } else {
31427
+ throw new import_nodejs_utils91.InternalServerError("Failed to get curriculum.");
31428
+ }
31429
+ }
31430
+ }
31431
+ async function deleteById(_id, session) {
31432
+ try {
31433
+ _id = new import_mongodb51.ObjectId(_id);
31434
+ } catch (error) {
31435
+ throw new import_nodejs_utils91.BadRequestError("Invalid ID.");
31436
+ }
31437
+ try {
31438
+ const res = await collection.updateOne(
31439
+ { _id },
31440
+ { $set: { status: "deleted", deletedAt: /* @__PURE__ */ new Date() } }
31441
+ );
31442
+ delCachedData();
31443
+ return res;
31444
+ } catch (error) {
31445
+ import_nodejs_utils91.logger.log({
31446
+ level: "error",
31447
+ message: error.message
31448
+ });
31449
+ if (error instanceof import_nodejs_utils91.AppError) {
31450
+ throw error;
31451
+ } else {
31452
+ throw new import_nodejs_utils91.InternalServerError("Failed to delete curriculum.");
31453
+ }
31454
+ }
31455
+ }
31456
+ function delCachedData() {
31457
+ delNamespace().then(() => {
31458
+ import_nodejs_utils91.logger.log({
31459
+ level: "info",
31460
+ message: `Cache namespace cleared for ${namespace_collection}`
31461
+ });
31462
+ }).catch((err) => {
31463
+ import_nodejs_utils91.logger.log({
31464
+ level: "error",
31465
+ message: `Failed to clear cache namespace for ${namespace_collection}: ${err.message}`
31466
+ });
31467
+ });
31468
+ }
31469
+ return {
31470
+ createIndexes,
31471
+ add,
31472
+ getAll,
31473
+ getById,
31474
+ updateById,
31475
+ deleteById
31476
+ };
31477
+ }
31478
+
31479
+ // src/controllers/curriculum.controller.ts
31480
+ var import_nodejs_utils92 = require("@eeplatform/nodejs-utils");
31481
+ var import_joi46 = __toESM(require("joi"));
31482
+ function useCurriculumController() {
31483
+ const {
31484
+ getAll: _getAll,
31485
+ getById: _getById,
31486
+ add: _add,
31487
+ updateById: _updateById,
31488
+ deleteById: _deleteById
31489
+ } = useCurriculumRepo();
31490
+ async function add(req, res, next) {
31491
+ const value = req.body;
31492
+ const validation = import_joi46.default.object({
31493
+ code: import_joi46.default.string().required(),
31494
+ school: import_joi46.default.string().hex().required(),
31495
+ educationLevel: import_joi46.default.string().required(),
31496
+ gradeLevel: import_joi46.default.string().required(),
31497
+ subjectCode: import_joi46.default.string().required(),
31498
+ subjectName: import_joi46.default.string().required(),
31499
+ subjectType: import_joi46.default.string().required(),
31500
+ sessionFrequency: import_joi46.default.number().integer().min(0).required(),
31501
+ sessionDuration: import_joi46.default.number().integer().min(0).required(),
31502
+ totalMinutesPerWeek: import_joi46.default.number().integer().min(0).required(),
31503
+ curriculumMemoRef: import_joi46.default.string().optional().allow("", null),
31504
+ status: import_joi46.default.string().optional().allow("", null)
31505
+ });
31506
+ const { error } = validation.validate(value);
31507
+ if (error) {
31508
+ next(new import_nodejs_utils92.BadRequestError(error.message));
31509
+ import_nodejs_utils92.logger.info(`Controller: ${error.message}`);
31510
+ return;
31511
+ }
31512
+ try {
31513
+ const result = await _add(value);
31514
+ res.json(result);
31515
+ return;
31516
+ } catch (error2) {
31517
+ next(error2);
31518
+ }
31519
+ }
31520
+ async function updateById(req, res, next) {
31521
+ const value = req.body;
31522
+ const id = req.params.id ?? "";
31523
+ const validation = import_joi46.default.object({
31524
+ id: import_joi46.default.string().hex().required(),
31525
+ value: import_joi46.default.object({
31526
+ code: import_joi46.default.string().optional(),
31527
+ educationLevel: import_joi46.default.string().optional(),
31528
+ gradeLevel: import_joi46.default.string().optional(),
31529
+ subjectCode: import_joi46.default.string().optional(),
31530
+ subjectName: import_joi46.default.string().optional(),
31531
+ subjectType: import_joi46.default.string().optional(),
31532
+ sessionFrequency: import_joi46.default.number().integer().min(0).optional(),
31533
+ sessionDuration: import_joi46.default.number().integer().min(0).optional(),
31534
+ totalMinutesPerWeek: import_joi46.default.number().integer().min(0).optional(),
31535
+ curriculumMemoRef: import_joi46.default.string().optional().allow("", null)
31536
+ }).min(1)
31537
+ });
31538
+ const { error } = validation.validate({ id, value });
31539
+ if (error) {
31540
+ next(new import_nodejs_utils92.BadRequestError(error.message));
31541
+ import_nodejs_utils92.logger.info(`Controller: ${error.message}`);
31542
+ return;
31543
+ }
31544
+ try {
31545
+ const result = await _updateById(id, value);
31546
+ res.json(result);
31547
+ return;
31548
+ } catch (error2) {
31549
+ next(error2);
31550
+ }
31551
+ }
31552
+ async function getAll(req, res, next) {
31553
+ const query = req.query;
31554
+ const validation = import_joi46.default.object({
31555
+ page: import_joi46.default.number().min(1).optional().allow("", null),
31556
+ limit: import_joi46.default.number().min(1).optional().allow("", null),
31557
+ search: import_joi46.default.string().optional().allow("", null),
31558
+ educationLevel: import_joi46.default.string().optional().allow("", null),
31559
+ gradeLevel: import_joi46.default.string().optional().allow("", null),
31560
+ subjectCode: import_joi46.default.string().optional().allow("", null),
31561
+ status: import_joi46.default.string().optional().allow("", null)
31562
+ });
31563
+ const { error } = validation.validate(query);
31564
+ if (error) {
31565
+ next(new import_nodejs_utils92.BadRequestError(error.message));
31566
+ return;
31567
+ }
31568
+ const page = parseInt(req.query.page) ?? 1;
31569
+ let limit = parseInt(req.query.limit) ?? 20;
31570
+ limit = isNaN(limit) ? 20 : limit;
31571
+ const sort = req.query.sort ? String(req.query.sort).split(",") : "";
31572
+ const sortOrder = req.query.sortOrder ? String(req.query.sortOrder).split(",") : "";
31573
+ const sortObj = {};
31574
+ if (sort && Array.isArray(sort) && sort.length && sortOrder && Array.isArray(sortOrder) && sortOrder.length) {
31575
+ sort.forEach((field, index) => {
31576
+ sortObj[field] = sortOrder[index] === "desc" ? -1 : 1;
31577
+ });
31578
+ }
31579
+ const status = req.query.status ?? "active";
31580
+ const educationLevel = req.query.educationLevel ?? "";
31581
+ const gradeLevel = req.query.gradeLevel ?? "";
31582
+ const subjectCode = req.query.subjectCode ?? "";
31583
+ const search = req.query.search ?? "";
31584
+ try {
31585
+ const curriculums = await _getAll({
31586
+ page,
31587
+ limit,
31588
+ sort: sortObj,
31589
+ status,
31590
+ educationLevel,
31591
+ gradeLevel,
31592
+ subjectCode,
31593
+ search
31594
+ });
31595
+ res.json(curriculums);
31596
+ return;
31597
+ } catch (error2) {
31598
+ next(error2);
31599
+ }
31600
+ }
31601
+ async function getById(req, res, next) {
31602
+ const id = req.params.id;
31603
+ const validation = import_joi46.default.object({
31604
+ id: import_joi46.default.string().hex().required()
31605
+ });
31606
+ const { error } = validation.validate({ id });
31607
+ if (error) {
31608
+ next(new import_nodejs_utils92.BadRequestError(error.message));
31609
+ return;
31610
+ }
31611
+ try {
31612
+ const curriculum = await _getById(id);
31613
+ res.json({
31614
+ message: "Successfully retrieved curriculum.",
31615
+ data: { curriculum }
31616
+ });
31617
+ return;
31618
+ } catch (error2) {
31619
+ next(error2);
31620
+ }
31621
+ }
31622
+ async function deleteById(req, res, next) {
31623
+ const id = req.params.id;
31624
+ const validation = import_joi46.default.object({
31625
+ id: import_joi46.default.string().hex().required()
31626
+ });
31627
+ const { error } = validation.validate({ id });
31628
+ if (error) {
31629
+ next(new import_nodejs_utils92.BadRequestError(error.message));
31630
+ return;
31631
+ }
31632
+ try {
31633
+ const result = await _deleteById(id);
31634
+ res.json({
31635
+ message: "Successfully deleted curriculum.",
31636
+ data: result
31637
+ });
31638
+ return;
31639
+ } catch (error2) {
31640
+ next(error2);
31641
+ }
31642
+ }
31643
+ return {
31644
+ add,
31645
+ getAll,
31646
+ getById,
31647
+ updateById,
31648
+ deleteById
29853
31649
  };
29854
31650
  }
29855
31651
  // Annotate the CommonJS export names for ESM import in node:
@@ -29874,12 +31670,14 @@ function usePlantillaController() {
29874
31670
  MAsset,
29875
31671
  MBuilding,
29876
31672
  MBuildingUnit,
31673
+ MCurriculum,
29877
31674
  MDivision,
29878
31675
  MEntity,
29879
31676
  MFile,
29880
31677
  MMember,
29881
31678
  MONGO_DB,
29882
31679
  MONGO_URI,
31680
+ MOffice,
29883
31681
  MOrder,
29884
31682
  MOrg,
29885
31683
  MPaymentMethod,
@@ -29920,7 +31718,9 @@ function usePlantillaController() {
29920
31718
  schemaAssetUpdateOption,
29921
31719
  schemaBuilding,
29922
31720
  schemaBuildingUnit,
31721
+ schemaCurriculum,
29923
31722
  schemaDivision,
31723
+ schemaOffice,
29924
31724
  schemaPlantilla,
29925
31725
  schemaRegion,
29926
31726
  schemaSchool,
@@ -29938,6 +31738,8 @@ function usePlantillaController() {
29938
31738
  useBuildingUnitRepo,
29939
31739
  useCounterModel,
29940
31740
  useCounterRepo,
31741
+ useCurriculumController,
31742
+ useCurriculumRepo,
29941
31743
  useDivisionController,
29942
31744
  useDivisionRepo,
29943
31745
  useDivisionService,
@@ -29953,6 +31755,9 @@ function usePlantillaController() {
29953
31755
  useInvoiceService,
29954
31756
  useMemberController,
29955
31757
  useMemberRepo,
31758
+ useOfficeController,
31759
+ useOfficeRepo,
31760
+ useOfficeService,
29956
31761
  useOrderController,
29957
31762
  useOrderRepo,
29958
31763
  useOrgController,