From 3836e4c521f12862348b8dd85201fb9710a710a9 Mon Sep 17 00:00:00 2001 From: wayanrivan Date: Tue, 7 Jul 2026 10:52:42 +0700 Subject: [PATCH] update site points controller and route to add new endpoint for all data --- config/default.json | 12 +- package.json | 7 +- src/controllers/administrativu.ts | 428 ------ src/controllers/application.ts | 519 -------- src/controllers/card_key_sets.ts | 164 --- src/controllers/card_print_queue.ts | 214 --- src/controllers/card_type.ts | 369 ------ src/controllers/currency.ts | 282 ---- src/controllers/department.ts | 255 ---- src/controllers/diagnosis.ts | 494 ------- src/controllers/diagnostic_procedure.ts | 391 ------ src/controllers/district.ts | 391 ------ src/controllers/doctor_item.ts | 405 ------ src/controllers/doctor_item_package.ts | 345 ----- src/controllers/doctor_schedule.ts | 279 ---- src/controllers/examination_detail.ts | 301 ----- src/controllers/examination_type.ts | 276 ---- src/controllers/faretype.ts | 395 ------ src/controllers/file/file.ts | 226 ---- src/controllers/fostercarehistory.ts | 557 -------- src/controllers/hospital_information.ts | 309 ----- src/controllers/inpatient_room.ts | 371 ------ src/controllers/laboratory.ts | 88 -- src/controllers/main_disease.ts | 267 ---- src/controllers/measurement_unit.ts | 255 ---- src/controllers/medical_form.ts | 267 ---- src/controllers/menu.ts | 465 ------- src/controllers/munisipo.ts | 391 ------ src/controllers/nationality.ts | 392 ------ src/controllers/patient_group.ts | 363 ------ src/controllers/patient_guarantor.ts | 438 ------- src/controllers/payment-method.ts | 369 ------ src/controllers/pharmacy.ts | 88 -- src/controllers/pharmacy/factory.ts | 355 ----- .../pharmacy/factory_to_supplier.ts | 409 ------ src/controllers/pharmacy/generic_name.ts | 339 ----- src/controllers/pharmacy/initial_stock.ts | 151 --- src/controllers/pharmacy/item_category.ts | 339 ----- src/controllers/pharmacy/item_class.ts | 339 ----- src/controllers/pharmacy/item_class_detail.ts | 339 ----- src/controllers/pharmacy/item_group.ts | 339 ----- src/controllers/pharmacy/item_master.ts | 424 ------ src/controllers/pharmacy/item_origin.ts | 377 ------ src/controllers/pharmacy/item_price.ts | 386 ------ src/controllers/pharmacy/item_status.ts | 339 ----- src/controllers/pharmacy/item_type.ts | 343 ----- src/controllers/pharmacy/item_type_detail.ts | 343 ----- src/controllers/pharmacy/pharmacy_info.ts | 692 ---------- .../pharmacy/planning_verificator.ts | 282 ---- .../pharmacy/selling_price_percentage.ts | 347 ----- src/controllers/pharmacy/supplier.ts | 376 ------ src/controllers/pharmacy/unit.ts | 347 ----- .../pharmacy/usage_instructions.ts | 343 ----- src/controllers/pharmacy/usage_time.ts | 343 ----- src/controllers/queue_monitoring.ts | 467 ------- src/controllers/reference_range.ts | 297 ----- src/controllers/refferal_hospital.ts | 375 ------ src/controllers/region.ts | 164 --- src/controllers/registrationfee.ts | 201 --- src/controllers/responsiblepartyconsent.ts | 147 --- src/controllers/room.ts | 578 -------- src/controllers/room_number.ts | 237 ---- src/controllers/room_services.ts | 406 ------ src/controllers/room_to_pharmacy.ts | 507 ------- src/controllers/schedule.ts | 407 ------ src/controllers/service.ts | 348 ----- src/controllers/service_class.ts | 251 ---- src/controllers/service_examination.ts | 216 --- src/controllers/service_fare.ts | 424 ------ src/controllers/service_package.ts | 287 ---- src/controllers/service_type.ts | 255 ---- src/controllers/{aldeia.ts => sitepoints.ts} | 201 +-- src/controllers/suco.ts | 428 ------ src/controllers/surgery_room.ts | 290 ---- src/controllers/surgery_type.ts | 197 --- src/controllers/user_to_room.ts | 573 -------- src/helpers/express/return.ts | 2 +- src/helpers/express/upload.ts | 12 - src/helpers/orm.ts | 233 +--- src/model/card_key_sets.ts | 23 - src/model/card_print_queue.ts | 37 - src/model/card_type.ts | 37 - src/model/currencies.ts | 27 - src/model/department.ts | 23 - src/model/diagnosis.ts | 23 - src/model/diagnostic_procedure.ts | 24 - src/model/doctor_item.ts | 27 - src/model/doctor_item_package.ts | 38 - src/model/doctor_schedule.ts | 26 - src/model/examination_detail.ts | 23 - src/model/examination_type.ts | 23 - src/model/factory.ts | 23 - src/model/factory_to_supplier.ts | 25 - src/model/faretype.ts | 23 - src/model/fostercarehistory.ts | 37 - src/model/generic_name.ts | 23 - src/model/initial_stock.ts | 23 - src/model/inpatient_room.ts | 28 - src/model/item_category.ts | 23 - src/model/item_class.ts | 23 - src/model/item_class_detail.ts | 23 - src/model/item_group.ts | 23 - src/model/item_master.ts | 32 - src/model/item_origin.ts | 23 - src/model/item_price.ts | 23 - src/model/item_status.ts | 23 - src/model/item_type.ts | 23 - src/model/item_type_detail.ts | 23 - src/model/main_disease.ts | 23 - src/model/measurement_unit.ts | 23 - src/model/medical_form.ts | 23 - src/model/patient_group.ts | 23 - src/model/patient_guarantor.ts | 43 - src/model/payment_method.ts | 37 - src/model/pharmacy_info.ts | 32 - src/model/planning_verificator.ts | 23 - src/model/queue_monitoring.ts | 23 - src/model/reference_range.ts | 27 - src/model/refferal_hospital.ts | 23 - src/model/room.ts | 25 - src/model/room_number.ts | 24 - src/model/room_services.ts | 316 ----- src/model/room_to_pharmacy.ts | 24 - src/model/schedule.ts | 569 -------- src/model/selling_price_percentage.ts | 25 - src/model/service.ts | 39 - src/model/service_class.ts | 23 - src/model/service_fare.ts | 23 - src/model/service_package.ts | 23 - src/model/service_type.ts | 23 - src/model/supplier.ts | 23 - src/model/surgery_room.ts | 27 - src/model/surgery_type.ts | 36 - src/model/unit.ts | 23 - src/model/usage_instructions.ts | 23 - src/model/usage_time.ts | 23 - src/model/user_to_room.ts | 25 - src/routes/private.ts | 575 +------- src/scripts/seed-diagnoses-data.ts | 155 --- src/scripts/seed-site-points.ts | 43 + src/server.ts | 2 - src/sitePointsData.ts | 1161 +++++++++++++++++ src/swagger/builder.js | 698 +--------- 143 files changed, 1384 insertions(+), 29024 deletions(-) delete mode 100644 src/controllers/administrativu.ts delete mode 100644 src/controllers/application.ts delete mode 100644 src/controllers/card_key_sets.ts delete mode 100644 src/controllers/card_print_queue.ts delete mode 100644 src/controllers/card_type.ts delete mode 100644 src/controllers/currency.ts delete mode 100644 src/controllers/department.ts delete mode 100644 src/controllers/diagnosis.ts delete mode 100644 src/controllers/diagnostic_procedure.ts delete mode 100644 src/controllers/district.ts delete mode 100644 src/controllers/doctor_item.ts delete mode 100644 src/controllers/doctor_item_package.ts delete mode 100644 src/controllers/doctor_schedule.ts delete mode 100644 src/controllers/examination_detail.ts delete mode 100644 src/controllers/examination_type.ts delete mode 100644 src/controllers/faretype.ts delete mode 100644 src/controllers/file/file.ts delete mode 100644 src/controllers/fostercarehistory.ts delete mode 100644 src/controllers/hospital_information.ts delete mode 100644 src/controllers/inpatient_room.ts delete mode 100644 src/controllers/laboratory.ts delete mode 100644 src/controllers/main_disease.ts delete mode 100644 src/controllers/measurement_unit.ts delete mode 100644 src/controllers/medical_form.ts delete mode 100644 src/controllers/menu.ts delete mode 100644 src/controllers/munisipo.ts delete mode 100644 src/controllers/nationality.ts delete mode 100644 src/controllers/patient_group.ts delete mode 100644 src/controllers/patient_guarantor.ts delete mode 100644 src/controllers/payment-method.ts delete mode 100644 src/controllers/pharmacy.ts delete mode 100644 src/controllers/pharmacy/factory.ts delete mode 100644 src/controllers/pharmacy/factory_to_supplier.ts delete mode 100644 src/controllers/pharmacy/generic_name.ts delete mode 100644 src/controllers/pharmacy/initial_stock.ts delete mode 100644 src/controllers/pharmacy/item_category.ts delete mode 100644 src/controllers/pharmacy/item_class.ts delete mode 100644 src/controllers/pharmacy/item_class_detail.ts delete mode 100644 src/controllers/pharmacy/item_group.ts delete mode 100644 src/controllers/pharmacy/item_master.ts delete mode 100644 src/controllers/pharmacy/item_origin.ts delete mode 100644 src/controllers/pharmacy/item_price.ts delete mode 100644 src/controllers/pharmacy/item_status.ts delete mode 100644 src/controllers/pharmacy/item_type.ts delete mode 100644 src/controllers/pharmacy/item_type_detail.ts delete mode 100644 src/controllers/pharmacy/pharmacy_info.ts delete mode 100644 src/controllers/pharmacy/planning_verificator.ts delete mode 100644 src/controllers/pharmacy/selling_price_percentage.ts delete mode 100644 src/controllers/pharmacy/supplier.ts delete mode 100644 src/controllers/pharmacy/unit.ts delete mode 100644 src/controllers/pharmacy/usage_instructions.ts delete mode 100644 src/controllers/pharmacy/usage_time.ts delete mode 100644 src/controllers/queue_monitoring.ts delete mode 100644 src/controllers/reference_range.ts delete mode 100644 src/controllers/refferal_hospital.ts delete mode 100644 src/controllers/region.ts delete mode 100644 src/controllers/registrationfee.ts delete mode 100644 src/controllers/responsiblepartyconsent.ts delete mode 100644 src/controllers/room.ts delete mode 100644 src/controllers/room_number.ts delete mode 100644 src/controllers/room_services.ts delete mode 100644 src/controllers/room_to_pharmacy.ts delete mode 100644 src/controllers/schedule.ts delete mode 100644 src/controllers/service.ts delete mode 100644 src/controllers/service_class.ts delete mode 100644 src/controllers/service_examination.ts delete mode 100644 src/controllers/service_fare.ts delete mode 100644 src/controllers/service_package.ts delete mode 100644 src/controllers/service_type.ts rename src/controllers/{aldeia.ts => sitepoints.ts} (66%) delete mode 100644 src/controllers/suco.ts delete mode 100644 src/controllers/surgery_room.ts delete mode 100644 src/controllers/surgery_type.ts delete mode 100644 src/controllers/user_to_room.ts delete mode 100644 src/helpers/express/upload.ts delete mode 100644 src/model/card_key_sets.ts delete mode 100644 src/model/card_print_queue.ts delete mode 100644 src/model/card_type.ts delete mode 100644 src/model/currencies.ts delete mode 100644 src/model/department.ts delete mode 100644 src/model/diagnosis.ts delete mode 100644 src/model/diagnostic_procedure.ts delete mode 100644 src/model/doctor_item.ts delete mode 100644 src/model/doctor_item_package.ts delete mode 100644 src/model/doctor_schedule.ts delete mode 100644 src/model/examination_detail.ts delete mode 100644 src/model/examination_type.ts delete mode 100644 src/model/factory.ts delete mode 100644 src/model/factory_to_supplier.ts delete mode 100644 src/model/faretype.ts delete mode 100644 src/model/fostercarehistory.ts delete mode 100644 src/model/generic_name.ts delete mode 100644 src/model/initial_stock.ts delete mode 100644 src/model/inpatient_room.ts delete mode 100644 src/model/item_category.ts delete mode 100644 src/model/item_class.ts delete mode 100644 src/model/item_class_detail.ts delete mode 100644 src/model/item_group.ts delete mode 100644 src/model/item_master.ts delete mode 100644 src/model/item_origin.ts delete mode 100644 src/model/item_price.ts delete mode 100644 src/model/item_status.ts delete mode 100644 src/model/item_type.ts delete mode 100644 src/model/item_type_detail.ts delete mode 100644 src/model/main_disease.ts delete mode 100644 src/model/measurement_unit.ts delete mode 100644 src/model/medical_form.ts delete mode 100644 src/model/patient_group.ts delete mode 100644 src/model/patient_guarantor.ts delete mode 100644 src/model/payment_method.ts delete mode 100644 src/model/pharmacy_info.ts delete mode 100644 src/model/planning_verificator.ts delete mode 100644 src/model/queue_monitoring.ts delete mode 100644 src/model/reference_range.ts delete mode 100644 src/model/refferal_hospital.ts delete mode 100644 src/model/room.ts delete mode 100644 src/model/room_number.ts delete mode 100644 src/model/room_services.ts delete mode 100644 src/model/room_to_pharmacy.ts delete mode 100644 src/model/schedule.ts delete mode 100644 src/model/selling_price_percentage.ts delete mode 100644 src/model/service.ts delete mode 100644 src/model/service_class.ts delete mode 100644 src/model/service_fare.ts delete mode 100644 src/model/service_package.ts delete mode 100644 src/model/service_type.ts delete mode 100644 src/model/supplier.ts delete mode 100644 src/model/surgery_room.ts delete mode 100644 src/model/surgery_type.ts delete mode 100644 src/model/unit.ts delete mode 100644 src/model/usage_instructions.ts delete mode 100644 src/model/usage_time.ts delete mode 100644 src/model/user_to_room.ts delete mode 100644 src/scripts/seed-diagnoses-data.ts create mode 100644 src/scripts/seed-site-points.ts create mode 100644 src/sitePointsData.ts diff --git a/config/default.json b/config/default.json index 89272b0..bc28222 100644 --- a/config/default.json +++ b/config/default.json @@ -21,11 +21,11 @@ }, "database": { "engine": "postgres", - "host": "147.139.175.69", - "port": "4137", - "username": "saude_stag", - "password": "gM*#o>3W4&5X", - "database": "saude_stag", + "host": "127.0.0.1", + "port": "5432", + "username": "rivanwayan", + "password": "", + "database": "revenue", "synchronize": true, "logging": true }, @@ -41,4 +41,4 @@ "tcel": "http://127.0.0.1:4028/", "kartaun": "http://127.0.0.1:7017/service-kartaun-edc/api/" } -} +} \ No newline at end of file diff --git a/package.json b/package.json index 63fc7f9..c74cd9d 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,6 @@ "cors": "^2.8.5", "entity": "file:../entity", "express": "^4.21.1", - "express-fileupload": "^1.5.2", "express-jwt": "^8.4.1", "fast-csv": "^5.0.2", "helmet": "^8.0.0", @@ -37,6 +36,7 @@ "joi": "^17.13.3", "moment": "^2.30.1", "morgan": "^1.10.0", + "multer": "^2.2.0", "npm": "^10.9.1", "pg": "^8.13.1", "reflect-metadata": "^0.2.2", @@ -44,7 +44,8 @@ "swagger-jsdoc": "^6.2.8", "swagger-ui-express": "^5.0.1", "tslog": "^4.9.3", - "typeorm": "^0.3.20" + "typeorm": "^0.3.20", + "xlsx": "^0.18.5" }, "devDependencies": { "@types/bcryptjs": "^2.4.6", @@ -52,8 +53,8 @@ "@types/config": "^3.3.5", "@types/cors": "^2.8.17", "@types/express": "^4.17.21", - "@types/express-fileupload": "^1.5.1", "@types/morgan": "^1.9.9", + "@types/multer": "^2.2.0", "@types/swagger-ui-express": "^4.1.7", "@types/uuid": "^10.0.0", "ts-node": "^10.9.2", diff --git a/src/controllers/administrativu.ts b/src/controllers/administrativu.ts deleted file mode 100644 index 63e2bed..0000000 --- a/src/controllers/administrativu.ts +++ /dev/null @@ -1,428 +0,0 @@ -import { Response, NextFunction, Application } from "express"; -import { Request } from "express-jwt"; -import { ReturnHelper } from "../helpers/express/return"; -import { OrmHelper } from "../helpers/orm"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import { Language } from "../langs/lang"; -import { Paging } from "entity"; -import CommonHelper from "../helpers/common"; -import * as fastcsv from 'fast-csv'; -import dayjs from "dayjs"; -import { Administrativu, Munisipo } from "entity"; - -const log: Logger = new Logger({ name: '[AdministrativuController]', type: 'pretty' }); - -export class AdministrativuController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Administrativu'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['filter'] = { - description: 'Filter with 2 format :
  • Simple format use text plaint will filter eq:code or like %name%
  • Advance format using field existing {status:\'Y\', any:\'SAME AS PLAINT LOGIC\', etc...}
', - in: 'query', - type: 'string' - } - #swagger.parameters['limit'] = { - in: 'query', - required: true, - type: 'number' - } - #swagger.parameters['page'] = { - in: 'query', - required: true, - type: 'number' - } - #swagger.parameters['with_deleted'] = { - in: 'query', - required: true, - type: 'boolean' - } - #swagger.parameters['order_field'] = { - in: 'query', - required: true, - type: 'string' - } - #swagger.parameters['order_direction'] = { - in: 'query', - required: true, - schema: { - '@enum': ['ASC', 'DESC'] - } - } - */ - - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow('').optional().label('Filter'), - page: Joi.number().required().min(1).label('Page'), - limit: Joi.number().required().min(1).label('Limit'), - with_deleted: Joi.bool().required().label('With Deleted'), - order_field: Joi.string().required().label('Order Field'), - order_direction: Joi.string().allow('asc', 'desc').required().label('Order Direction'), - }); - - const param: Paging = await schema.validateAsync(req.query); - - const repo = OrmHelper.DB.getRepository(Administrativu); - - const offset = (param.page - 1) * param.limit - - const filterObj = param.filter ? JSON.parse(param.filter) : {}; - // Remove foreign key from filter for CommonHelper.handleFilter - const filterWithoutFK = { ...filterObj }; - delete filterWithoutFK.munisipo_id; - const filterStrWithoutFK = JSON.stringify(filterWithoutFK); - - const { whereAttr, whereVal } = CommonHelper.handleFilter({ - filter: filterStrWithoutFK, - col_any_eq: ['code'], - col_any_like: ['name'] - }); - - const res_count = repo.createQueryBuilder("Administrativu") - .leftJoin("Administrativu.munisipo", "munisipo") - .where(whereAttr || "1=1", whereVal); - - // Handle foreign key filter with relation - if (filterObj.munisipo_id) { - res_count.andWhere("munisipo.id = :munisipoId", { munisipoId: filterObj.munisipo_id }); - } - - const res_list = repo.createQueryBuilder("Administrativu") - .leftJoin("Administrativu.munisipo", "munisipo") - .where(whereAttr || "1=1", whereVal) - .orderBy("Administrativu." + param.order_field, param.order_direction) - .offset(offset) - .limit(param.limit); - - // Handle foreign key filter with relation - if (filterObj.munisipo_id) { - res_list.andWhere("munisipo.id = :munisipoId", { munisipoId: filterObj.munisipo_id }); - } - - if (param.with_deleted) { - res_count.withDeleted(); - res_list.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async export(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Administrativu'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['filter'] = { - description: 'Filter with 2 format :
  • Simple format use text plaint will filter eq:code or like %name%
  • Advance format using field existing {status:\'Y\', any:\'SAME AS PLAINT LOGIC\', etc...}
', - in: 'query', - type: 'string' - } - #swagger.parameters['filter'] = { - in: 'query', - type: 'string' - } - #swagger.parameters['order_field'] = { - in: 'query', - required: true, - type: 'string' - } - #swagger.parameters['order_direction'] = { - in: 'query', - required: true, - schema: { - '@enum': ['ASC', 'DESC'] - } - } - */ - - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow('').optional().label('Filter'), - order_field: Joi.string().required().label('Order Field'), - order_direction: Joi.string().allow('asc', 'desc').required().label('Order Direction'), - }); - - const param: Paging = await schema.validateAsync(req.query); - - const repo = OrmHelper.DB.getRepository(Administrativu); - - const filterObj = param.filter ? JSON.parse(param.filter) : {}; - // Remove foreign key from filter for CommonHelper.handleFilter - const filterWithoutFK = { ...filterObj }; - delete filterWithoutFK.munisipo_id; - const filterStrWithoutFK = JSON.stringify(filterWithoutFK); - - const { whereAttr, whereVal } = CommonHelper.handleFilter({ - filter: filterStrWithoutFK, - col_any_eq: ['code'], - col_any_like: ['name'] - }); - - const filename = "administrativu.csv"; - - res.setHeader('Content-Type', 'text/csv'); - res.setHeader('Content-Disposition', 'attachment; filename=' + filename); - - const csvStream = fastcsv.format({ - headers: true, - writeHeaders: true, - transform: (row: Administrativu): any => ({ - ...row, - created_at: dayjs(row.created_at).format('DD-MM-YYYY HH:MM:ss'), - }) - }); - csvStream.pipe(res); - - const limit = 50; - - const fetchAndWrite = async (page: any) => { - const offset = (page - 1) * limit - - let query = repo.createQueryBuilder("Administrativu") - .leftJoin("Administrativu.munisipo", "munisipo") - .where(whereAttr || "1=1", whereVal); - - // Handle foreign key filter with relation - if (filterObj.munisipo_id) { - query = query.andWhere("munisipo.id = :munisipoId", { munisipoId: filterObj.munisipo_id }); - } - - const data = await query - .select([ - 'Administrativu.id', - 'Administrativu.code', - 'Administrativu.name', - 'Administrativu.status', - 'Administrativu.created_at']) - .orderBy("Administrativu." + param.order_field, param.order_direction) - .offset(offset) - .limit(limit).getRawMany(); - - if (CommonHelper.countObject(data) === 0) { - csvStream.end(); - } else { - data.forEach((item: any) => csvStream.write(item)); - - if (CommonHelper.countObject(data) == limit) { - fetchAndWrite(page + 1); - } else { - csvStream.end(); - } - } - }; - - fetchAndWrite(1); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Administrativu'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/administrativu" - } - } - } - } - */ - - try { - const schema = Joi.object().keys({ - code: Joi.string().max(128).required().label('Code'), - name: Joi.string().max(256).required().label('Name'), - status: Joi.string().required().label('Status'), - munisipo_id: Joi.string().uuid().required().label('Munisipo'), - }); - - const param: any = await schema.validateAsync(req.body); - - const data = new Administrativu() - data.code = param.code - data.name = param.name - data.status = param.status - data.munisipo = await OrmHelper.DB.getRepository(Munisipo).findOneByOrFail({ id: param.munisipo_id }); - - await OrmHelper.DB.manager.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 401, Language.lang.failed_insert, err.message); - } - } - - static async update(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Administrativu'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'Administrativu ID.', - required: true, - type: 'string' - } - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/administrativu" - } - } - } - } - */ - - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID'), - code: Joi.string().max(128).required().label('Code'), - name: Joi.string().max(256).required().label('Name'), - status: Joi.string().required().label('Status'), - munisipo_id: Joi.string().uuid().required().label('Munisipo'), - }); - - req.body.id = req.params['id']; - - const param: any = await schema.validateAsync(req.body); - - const repo = OrmHelper.DB.getRepository(Administrativu); - - const data = await repo.findOneBy({ id: param.id }); - - if (data != null) { - data.code = param.code - data.name = param.name - data.status = param.status - data.munisipo = await OrmHelper.DB.getRepository(Munisipo).findOneByOrFail({ id: param.munisipo_id }); - - await repo.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_update, data); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_update, err.message); - } - } - - static async delete(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Administrativu'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'Administrativu ID.', - required: true, - type: 'string' - } - #swagger.parameters['hard'] = { - in: 'path', - description: 'Is Hard Delete', - required: false, - type: 'boolean' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID'), - hard: Joi.bool().optional().allow('').label('Is hard delete?') - }); - - const param: { id: string, hard: boolean } = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(Administrativu); - - const affected = (!param.hard ? await repo.softDelete({ id: param.id }) : await repo.delete({ id: param.id })).affected; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_delete, err.message); - } - } - - static async restore(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Administrativu'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.parameters['id'] = { - in: 'path', - description: 'Administrativu ID.', - required: true, - type: 'string' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID') - }); - - const param: Administrativu = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(Administrativu); - - const affected = (await repo.restore({ id: param.id })).affected; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_restore, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_restore, err.message); - } - } -} \ No newline at end of file diff --git a/src/controllers/application.ts b/src/controllers/application.ts deleted file mode 100644 index 72c1f97..0000000 --- a/src/controllers/application.ts +++ /dev/null @@ -1,519 +0,0 @@ -import { Response, NextFunction } from "express"; -import { Request } from "express-jwt"; -import { ReturnHelper } from "../helpers/express/return"; -import { OrmHelper } from "../helpers/orm"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import { Language } from "../langs/lang"; -import { Paging } from "entity"; -import CommonHelper from "../helpers/common"; -import * as fastcsv from "fast-csv"; -import dayjs from "dayjs"; -import { Application } from "entity"; - -const log: Logger = new Logger({ - name: "[ApplicationController]", - type: "pretty", -}); - -export class ApplicationController { - static async list( - req: Request, - res: Response, - next: NextFunction - ): Promise { - /* - #swagger.tags = ['Application'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['filter'] = { - description: 'Filter with 2 format :
  • Simple format use text plaint will filter eq:code or like %name%
  • Advance format using field existing {status:\'Y\', any:\'SAME AS PLAINT LOGIC\', etc...}
', - in: 'query', - type: 'string' - } - #swagger.parameters['limit'] = { - in: 'query', - required: true, - type: 'number' - } - #swagger.parameters['page'] = { - in: 'query', - required: true, - type: 'number' - } - #swagger.parameters['with_deleted'] = { - in: 'query', - required: true, - type: 'boolean' - } - #swagger.parameters['order_field'] = { - in: 'query', - required: true, - type: 'string' - } - #swagger.parameters['order_direction'] = { - in: 'query', - required: true, - schema: { - '@enum': ['ASC', 'DESC'] - } - } - */ - - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().required().label("With Deleted"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string() - .allow("asc", "desc") - .required() - .label("Order Direction"), - }); - - const param: Paging = await schema.validateAsync(req.query); - - const repo = OrmHelper.DB.getRepository(Application); - - const offset = (param.page - 1) * param.limit; - - const { whereAttr, whereVal } = CommonHelper.handleFilter({ - filter: param.filter, - col_any_eq: ["code"], - col_any_like: ["name"], - }); - - const res_count = repo.createQueryBuilder().where(whereAttr, whereVal); - const res_list = repo - .createQueryBuilder() - .where(whereAttr, whereVal) - .orderBy(param.order_field, param.order_direction) - .offset(offset) - .limit(param.limit); - - if (param.with_deleted) { - res_count.withDeleted(); - res_list.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist( - res, - 200, - Language.lang.success_view, - count_data, - current_page, - total_count_data, - list_data - ); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse( - res, - 400, - 401, - Language.lang.failed_view, - err.message - ); - } - } - - static async export( - req: Request, - res: Response, - next: NextFunction - ): Promise { - /* - #swagger.tags = ['Application'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['filter'] = { - description: 'Filter with 2 format :
  • Simple format use text plaint will filter eq:code or like %name%
  • Advance format using field existing {status:\'Y\', any:\'SAME AS PLAINT LOGIC\', etc...}
', - in: 'query', - type: 'string' - } - #swagger.parameters['filter'] = { - in: 'query', - type: 'string' - } - #swagger.parameters['order_field'] = { - in: 'query', - required: true, - type: 'string' - } - #swagger.parameters['order_direction'] = { - in: 'query', - required: true, - schema: { - '@enum': ['ASC', 'DESC'] - } - } - */ - - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string() - .allow("asc", "desc") - .required() - .label("Order Direction"), - }); - - const param: Paging = await schema.validateAsync(req.query); - - const repo = OrmHelper.DB.getRepository(Application); - - const { whereAttr, whereVal } = CommonHelper.handleFilter({ - filter: param.filter, - col_any_eq: ["code"], - col_any_like: ["name"], - }); - - const filename = "application.csv"; - - res.setHeader("Content-Type", "text/csv"); - res.setHeader("Content-Disposition", "attachment; filename=" + filename); - - const csvStream = fastcsv.format({ - headers: true, - writeHeaders: true, - transform: (row: Application): any => ({ - ...row, - created_at: dayjs(row.created_at).format("DD-MM-YYYY HH:MM:ss"), - }), - }); - csvStream.pipe(res); - - const limit = 50; - - const fetchAndWrite = async (page: any) => { - const offset = (page - 1) * limit; - - const data = await repo - .createQueryBuilder() - .where(whereAttr, whereVal) - .select(["id", "code", "name", "status", "created_at"]) - .orderBy(param.order_field, param.order_direction) - .offset(offset) - .limit(limit) - .getRawMany(); - - if (CommonHelper.countObject(data) === 0) { - csvStream.end(); - } else { - data.forEach((item: any) => csvStream.write(item)); - - if (CommonHelper.countObject(data) == limit) { - fetchAndWrite(page + 1); - } else { - csvStream.end(); - } - } - }; - - fetchAndWrite(1); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse( - res, - 400, - 401, - Language.lang.failed_view, - err.message - ); - } - } - - static async create( - req: Request, - res: Response, - next: NextFunction - ): Promise { - /* - #swagger.tags = ['Application'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/application" - } - } - } - } - */ - - try { - const schema = Joi.object().keys({ - id: Joi.string().max(32).required().label("ID"), - name: Joi.string().max(256).required().label("Name"), - reset_password_url: Joi.string() - .max(512) - .optional() - .allow("") - .label("Url reset password"), - status: Joi.string().required().label("Status"), - }); - - const param: Application = await schema.validateAsync(req.body); - - const data = new Application(); - data.id = param.id; - data.name = param.name; - data.reset_password_url = param.reset_password_url; - data.status = param.status; - - await OrmHelper.DB.manager.save(data); - - return ReturnHelper.successResponseAny( - res, - 200, - Language.lang.success_insert, - data - ); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse( - res, - 500, - 401, - Language.lang.failed_insert, - err.message - ); - } - } - - static async update( - req: Request, - res: Response, - next: NextFunction - ): Promise { - /* - #swagger.tags = ['Application'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'Application ID.', - required: true, - type: 'string' - } - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/application" - } - } - } - } - */ - - try { - const schema = Joi.object().keys({ - id: Joi.string().required().label("ID"), - name: Joi.string().max(256).required().label("Name"), - reset_password_url: Joi.string() - .max(512) - .optional() - .allow("") - .label("Url reset password"), - status: Joi.string().required().label("Status"), - }); - - req.body.id = req.params["id"]; - - const param: Application = await schema.validateAsync(req.body); - - const repo = OrmHelper.DB.getRepository(Application); - - const data = await repo.findOneBy({ id: param.id }); - - if (data != null) { - data.name = param.name; - data.reset_password_url = param.reset_password_url; - data.status = param.status; - - await repo.save(data); - - return ReturnHelper.successResponseAny( - res, - 200, - Language.lang.success_update, - data - ); - } else { - return ReturnHelper.errorResponse( - res, - 404, - 401, - Language.lang.failed_not_found, - "" - ); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse( - res, - 500, - 402, - Language.lang.failed_update, - err.message - ); - } - } - - static async delete( - req: Request, - res: Response, - next: NextFunction - ): Promise { - /* - #swagger.tags = ['Application'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'Application ID.', - required: true, - type: 'string' - } - #swagger.parameters['hard'] = { - in: 'path', - description: 'Is Hard Delete', - required: false, - type: 'boolean' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("ID"), - hard: Joi.bool().optional().allow("").label("Is hard delete?"), - }); - - const param: { id: string; hard: boolean } = await schema.validateAsync( - req.params - ); - - const repo = OrmHelper.DB.getRepository(Application); - - const affected = ( - !param.hard - ? await repo.softDelete({ id: param.id }) - : await repo.delete({ id: param.id }) - ).affected; - - if (affected > 0) { - return ReturnHelper.successResponseAny( - res, - 200, - Language.lang.success_delete, - {} - ); - } else { - return ReturnHelper.errorResponse( - res, - 404, - 401, - Language.lang.failed_not_found, - "" - ); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse( - res, - 500, - 402, - Language.lang.failed_delete, - err.message - ); - } - } - - static async restore( - req: Request, - res: Response, - next: NextFunction - ): Promise { - /* - #swagger.tags = ['Application'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.parameters['id'] = { - in: 'path', - description: 'Application ID.', - required: true, - type: 'string' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("ID"), - }); - - const param: Application = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(Application); - - const affected = (await repo.restore({ id: param.id })).affected; - - if (affected > 0) { - return ReturnHelper.successResponseAny( - res, - 200, - Language.lang.success_restore, - {} - ); - } else { - return ReturnHelper.errorResponse( - res, - 404, - 401, - Language.lang.failed_not_found, - "" - ); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse( - res, - 500, - 402, - Language.lang.failed_restore, - err.message - ); - } - } -} diff --git a/src/controllers/card_key_sets.ts b/src/controllers/card_key_sets.ts deleted file mode 100644 index 5c6b75a..0000000 --- a/src/controllers/card_key_sets.ts +++ /dev/null @@ -1,164 +0,0 @@ -import { CardKeySet, Paging } from "entity"; -import { NextFunction, Response } from "express"; -import { Request } from "express-jwt"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import CommonHelper from "../helpers/common"; -import { ReturnHelper } from "../helpers/express/return"; -import { Language } from "../langs/lang"; -import { CardKeySetModel } from "../model/card_key_sets"; -import { OrmHelper } from "../helpers/orm"; - -const log: Logger = new Logger({ - name: "[CardKeySetsController]", - type: "pretty", -}); - -export class CardKeySetsController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Card Key Set'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['filter'] = { description: '', in: 'query', type: 'string' } - #swagger.parameters['limit'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['page'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['order_field'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['order_direction'] = { in: 'query', required: true, schema: { '@enum': ['ASC', 'DESC'] } } - */ - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().optional().label("With Deleted"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").required().label("Order Direction"), - }); - - let param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await CardKeySetModel.list(filter); - - const offset = (param.page - 1) * param.limit; - let limit = param.limit; - - const res_count = query; - const res_list = query - .orderBy("CardKeySet." + param.order_field, param.order_direction) - .offset(offset) - .limit(limit); - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async active(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Card Key Set'] - #swagger.security = [{ "bearerAuth": [] }] - */ - try { - const repo = OrmHelper.DB.getRepository(CardKeySet); - let entity = await repo.createQueryBuilder("CardKeySet") - .where("CardKeySet.is_active = :is_active", { is_active: true }) - .orderBy("CardKeySet.created_at", "DESC") - .getOne(); - - if (!entity) throw { message: "Active Card Key Set Not Found" }; - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_view, entity); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Card Key Set'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.requestBody = { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/card_key_set" } } } } - */ - const queryRunner = OrmHelper.DB.createQueryRunner(); - await queryRunner.startTransaction(); - try { - const schema = Joi.object().keys({ - key_set_id: Joi.string().max(256).required().label("Key Set ID"), - app_master_key: Joi.string().allow(null, "").optional().label("App Master Key"), - read_basic_key: Joi.string().allow(null, "").optional().label("Read Basic Key"), - write_update_key: Joi.string().allow(null, "").optional().label("Write Update Key"), - read_sensitive_key: Joi.string().allow(null, "").optional().label("Read Sensitive Key"), - }); - - let param: any = await schema.validateAsync(req.body); - - let filter = { key_set_id: param.key_set_id }; - let exist = await CardKeySetModel.list(filter).then((q) => q.getOne()); - if (exist) throw { message: "Card Key Set " + Language.lang.failed_duplicate }; - - let entity = new CardKeySet(); - entity.key_set_id = param.key_set_id; - entity.app_master_key = param.app_master_key; - entity.read_basic_key = param.read_basic_key; - entity.write_update_key = param.write_update_key; - entity.read_sensitive_key = param.read_sensitive_key; - entity.is_active = true; - await queryRunner.manager.save(entity); - - // Set the previous data (all other records) to is_active = false - await queryRunner.manager.createQueryBuilder() - .update(CardKeySet) - .set({ is_active: false }) - .where("id != :id", { id: entity.id }) - .execute(); - - await queryRunner.commitTransaction(); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, entity); - } catch (e: unknown) { - await queryRunner.rollbackTransaction(); - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } finally { - await queryRunner.release(); - } - } - - static async detail(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Card Key Set'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['key_set_id'] = { description: '', in: 'path', type: 'string' } - */ - try { - const schema = Joi.object().keys({ - key_set_id: Joi.string().required().label("Card Key Set ID"), - }); - - let param: any = await schema.validateAsync(req.params); - - let entity = await CardKeySetModel.list({ "CardKeySet.key_set_id": param.key_set_id }).then((q) => q.getOne()); - - if (!entity) throw { message: "Card Key Set Not Found" }; - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_view, entity); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_not_found, err.message); - } - } -} diff --git a/src/controllers/card_print_queue.ts b/src/controllers/card_print_queue.ts deleted file mode 100644 index 4884f46..0000000 --- a/src/controllers/card_print_queue.ts +++ /dev/null @@ -1,214 +0,0 @@ -import { Response, NextFunction } from "express"; -import { Request } from "express-jwt"; -import { ReturnHelper } from "../helpers/express/return"; -import { OrmHelper } from "../helpers/orm"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import { Language } from "../langs/lang"; -import { Paging, CardPrintQueue, CardPrintQueueStatus, CardPrintQueueType } from "entity"; -import CommonHelper from "../helpers/common"; -import { CardPrintQueueModel } from "../model/card_print_queue"; - -const log: Logger = new Logger({ name: '[CardPrintQueueController]', type: 'pretty' }); - -export class CardPrintQueueController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['CardPrintQueue'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['filter'] = { description: '', in: 'query', type: 'string' } - #swagger.parameters['limit'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['page'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['with_deleted'] = { in: 'query', required: true, type: 'boolean' } - #swagger.parameters['order_field'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['order_direction'] = { in: 'query', required: true, schema: { '@enum': ['ASC', 'DESC'] } } - */ - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().required().label("With Deleted"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").required().label("Order Direction"), - }); - - let param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - let filterAny = filter.any && filter.any !== "" ? filter.any : ""; - - let filterObj = { ...filter } as any; - delete filterObj.any; - filterObj = { ...filterObj }; - - var query = await CardPrintQueueModel.list(filterObj, filterAny); - - const offset = (param.page - 1) * param.limit; - let limit = param.limit; - - const res_count = query; - const res_list = query - .orderBy("card_print_queue." + param.order_field, param.order_direction) - .offset(offset) - .limit(limit); - - if (param.with_deleted) { - res_count.withDeleted(); - res_list.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - private static async handleCreate(req: Request, res: Response, type: CardPrintQueueType): Promise { - try { - const schema = Joi.object().keys({ - mrn: Joi.string().max(256).allow("").optional().label("MRN"), - municipiu_code: Joi.string().max(256).allow("").optional().label("Municipiu Code"), - posto_adm_code: Joi.string().max(256).allow("").optional().label("Posto Adm Code"), - name: Joi.string().max(256).allow("").optional().label("Name"), - address: Joi.string().allow("").optional().label("Address"), - municipiu: Joi.string().max(256).allow("").optional().label("Municipiu"), - posto_adm: Joi.string().max(256).allow("").optional().label("Posto Adm"), - suco: Joi.string().max(256).allow("").optional().label("Suco"), - aldeia: Joi.string().max(256).allow("").optional().label("Aldeia"), - sexo: Joi.string().max(64).allow("").optional().label("Sexo"), - birthdate: Joi.string().max(64).allow("").optional().label("Birthdate"), - patient_id: Joi.string().uuid().allow("").optional().label("Patient ID"), - facility_code: Joi.string().max(256).allow("").optional().label("Facility Code"), - status: Joi.string().valid("pending", "in_progress", "completed", "failed", "blocked").optional().label("Status"), - }); - - const param: any = await schema.validateAsync(req.body); - - const data = new CardPrintQueue(); - data.mrn = param.mrn || null; - data.municipiu_code = param.municipiu_code || null; - data.posto_adm_code = param.posto_adm_code || null; - data.name = param.name || null; - data.address = param.address || null; - data.municipiu = param.municipiu || null; - data.posto_adm = param.posto_adm || null; - data.suco = param.suco || null; - data.aldeia = param.aldeia || null; - data.sexo = param.sexo || null; - data.birthdate = param.birthdate || null; - data.patient_id = param.patient_id || null; - data.facility_code = param.facility_code || null; - data.status = param.status || CardPrintQueueStatus.PENDING; - data.type = type; - - const authHeader = req.headers.authorization; - let rawToken = ""; - if (authHeader) { - const parts = authHeader.split(" "); - rawToken = parts.length > 1 ? parts[1] : parts[0]; - } - data.token = rawToken ? Buffer.from(rawToken).toString("base64") : null; - - data.created_by = req.auth?.data?.name || null; - data.updated_by = req.auth?.data?.name || null; - - await OrmHelper.DB.manager.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 500, 401, Language.lang.failed_insert, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['CardPrintQueue'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/card_print_queue" - } - } - } - } - */ - return CardPrintQueueController.handleCreate(req, res, CardPrintQueueType.PRINT_PROVISION); - } - - static async createProvision(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['CardPrintQueue'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/card_print_queue" - } - } - } - } - */ - return CardPrintQueueController.handleCreate(req, res, CardPrintQueueType.PROVISION); - } - - static async createPrint(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['CardPrintQueue'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/card_print_queue" - } - } - } - } - */ - return CardPrintQueueController.handleCreate(req, res, CardPrintQueueType.PRINT); - } - - - static async detail(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['CardPrintQueue'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { in: 'path', type: 'number' } - */ - try { - const schema = Joi.object().keys({ - id: Joi.number().integer().required().label("ID"), - }); - let param: any = await schema.validateAsync(req.params); - let cardPrintQueue = await CardPrintQueueModel.list({ "card_print_queue.id": param.id }).then((q) => q.getOne()); - if (!cardPrintQueue) throw { message: "Card Print Queue Not Found" }; - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_view, cardPrintQueue); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_not_found, err.message); - } - } -} diff --git a/src/controllers/card_type.ts b/src/controllers/card_type.ts deleted file mode 100644 index 3a2f0ef..0000000 --- a/src/controllers/card_type.ts +++ /dev/null @@ -1,369 +0,0 @@ -import { Response, NextFunction, Application } from "express"; -import { Request } from "express-jwt"; -import { ReturnHelper } from "../helpers/express/return"; -import { OrmHelper } from "../helpers/orm"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import { Language } from "../langs/lang"; -import { Paging, CardType } from "entity"; -import CommonHelper from "../helpers/common"; -import * as fastcsv from 'fast-csv'; -import dayjs from "dayjs"; -import { CardTypeModel } from "../model/card_type"; - -const log: Logger = new Logger({ name: '[CardTypeController]', type: 'pretty' }); - -export class CardTypeController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['CardType'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['filter'] = { description: '', in: 'query', type: 'string' } - #swagger.parameters['limit'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['page'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['with_deleted'] = { in: 'query', required: true, type: 'boolean' } - #swagger.parameters['order_field'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['order_direction'] = { in: 'query', required: true, schema: { '@enum': ['ASC', 'DESC'] } } - */ - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().required().label("With Deleted"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").required().label("Order Direction"), - }); - - let param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - let filterAny = filter.any && filter.any !== "" ? filter.any : ""; - - let filterObj = { ...filter } as any; - delete filterObj.any; - filterObj = { ...filterObj }; - - var query = await CardTypeModel.list(filterObj, filterAny); - - const offset = (param.page - 1) * param.limit; - let limit = param.limit; - - const res_count = query; - const res_list = query - .orderBy("card_type." + param.order_field, param.order_direction) - .offset(offset) - .limit(limit); - - if (param.with_deleted) { - res_count.withDeleted(); - res_list.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async export(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['CardType'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['filter'] = { - description: 'Filter with 2 format :
  • Simple format use text plaint will filter eq:code or like %name%
  • Advance format using field existing {status:\'Y\', any:\'SAME AS PLAINT LOGIC\', etc...}
', - in: 'query', - type: 'string' - } - #swagger.parameters['filter'] = { - in: 'query', - type: 'string' - } - #swagger.parameters['order_field'] = { - in: 'query', - required: true, - type: 'string' - } - #swagger.parameters['order_direction'] = { - in: 'query', - required: true, - schema: { - '@enum': ['ASC', 'DESC'] - } - } - */ - - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow('').optional().label('Filter'), - order_field: Joi.string().required().label('Order Field'), - order_direction: Joi.string().allow('asc', 'desc').required().label('Order Direction'), - }); - - const param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await CardTypeModel.list(filter); - const data = await query.getMany(); - - const filename = "card_type.csv"; - - res.setHeader('Content-Type', 'text/csv'); - res.setHeader('Content-Disposition', 'attachment; filename=' + filename); - - const csvStream = fastcsv.format({ - headers: true, - writeHeaders: true, - transform: (row: CardType): any => ({ - ...row, - created_at: dayjs(row.created_at).format('DD-MM-YYYY HH:MM:ss'), - }) - }); - csvStream.pipe(res); - - const limit = 50; - - const fetchAndWrite = async (page: any) => { - - if (CommonHelper.countObject(data) === 0) { - csvStream.end(); - } else { - data.forEach((item: any) => csvStream.write(item)); - - if (CommonHelper.countObject(data) == limit) { - fetchAndWrite(page + 1); - } else { - csvStream.end(); - } - } - }; - - fetchAndWrite(1); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['CardType'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/card_type" - } - } - } - } - */ - try { - const schema = Joi.object().keys({ - name: Joi.string().max(256).required().label('Name'), - }); - - const param: any = await schema.validateAsync(req.body); - - const data = new CardType() - data.name = param.name; - data.created_by = req.auth.data.name; - data.updated_by = req.auth.data.name; - - await OrmHelper.DB.manager.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 401, Language.lang.failed_insert, err.message); - } - } - - static async update(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['CardType'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'CardType ID.', - required: true, - type: 'string' - } - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/card_type" - } - } - } - } - */ - - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID'), - name: Joi.string().max(256).required().label('Name'), - }); - - req.body.id = req.params['id']; - - const param: any = await schema.validateAsync(req.body); - - const repo = OrmHelper.DB.getRepository(CardType); - - const data = await repo.findOneBy({ id: param.id }); - - if (data != null) { - data.name = param.name; - data.updated_by = req.auth.data.name; - - await repo.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_update, data); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_update, err.message); - } - } - - static async delete(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['CardType'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'CardType ID.', - required: true, - type: 'string' - } - #swagger.parameters['hard'] = { - in: 'path', - description: 'Is Hard Delete', - required: false, - type: 'boolean' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID'), - hard: Joi.bool().optional().allow('').label('Is hard delete?') - }); - - const param: { id: string, hard: boolean } = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(CardType); - - const existData = await repo.findOne({ where: { id: param.id } }); - if (existData && !param.hard) { - existData.deleted_by = req.auth.data.name; - await OrmHelper.DB.manager.save(existData); - } - - const affected = (!param.hard ? await repo.softDelete({ id: param.id }) : await repo.delete({ id: param.id })).affected; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_delete, err.message); - } - } - - static async restore(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['CardType'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.parameters['id'] = { - in: 'path', - description: 'CardType ID.', - required: true, - type: 'string' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID') - }); - - const param: any = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(CardType); - - const affected = (await repo.restore({ id: param.id })).affected; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_restore, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_restore, err.message); - } - } - - static async detail(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['CardType'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { description: '', in: 'path', type: 'string' } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("CardType Id"), - }); - - let param: any = await schema.validateAsync(req.params); - - let data = await CardTypeModel.list({ "id": param.id }).then((q) => q.getOne()); - if (!data) throw { message: "CardType Not Found" }; - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_view, data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_not_found, err.message); - } - } -} \ No newline at end of file diff --git a/src/controllers/currency.ts b/src/controllers/currency.ts deleted file mode 100644 index 620a5e7..0000000 --- a/src/controllers/currency.ts +++ /dev/null @@ -1,282 +0,0 @@ -import config from "config"; -import { Paging, Status, Currency } from "entity"; -import { NextFunction, Response } from "express"; -import { Request } from "express-jwt"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import CommonHelper from "../helpers/common"; -import { ReturnHelper } from "../helpers/express/return"; -import { OrmHelper } from "../helpers/orm"; -import { Language } from "../langs/lang"; -import fs from "fs"; -import { CurrencyModel } from "../model/currencies"; - -const log: Logger = new Logger({ - name: "[CurrencyController]", - type: "pretty", -}); - -export class CurrencyController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Currency'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['filter'] = { - descriptionk:'', - in: 'query', - type: 'string' - } - #swagger.parameters['limit'] = { - in: 'query', - required: true, - type: 'number' - } - #swagger.parameters['page'] = { - in: 'query', - required: true, - type: 'number' - } - #swagger.parameters['with_deleted'] = { - in: 'query', - required: true, - type: 'boolean' - } - #swagger.parameters['order_field'] = { - in: 'query', - required: true, - type: 'string' - } - #swagger.parameters['order_direction'] = { - in: 'query', - required: true, - schema: { - '@enum': ['ASC', 'DESC'] - } - } - */ - - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().required().label("With Deleted"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").required().label("Order Direction"), - }); - - const param: Paging = await schema.validateAsync(req.query); - const offset = (param.page - 1) * param.limit; - const filter = JSON.parse(param.filter); - const query = await CurrencyModel.list(filter); - const limit = param.limit; - - const res_count = query; - const res_list = query - .orderBy("Currency." + param.order_field, param.order_direction) - .offset(offset) - .limit(limit); - - if (param.with_deleted) { - res_count.withDeleted(); - res_list.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Currency'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/currency" - } - } - } - } - */ - - try { - const schema = Joi.object().keys({ - name: Joi.string().required().label("Name"), - symbol: Joi.string().required().label("Symbol"), - status: Joi.string().uuid().required().valid("Y", "N").label("Status"), - }); - - const param = await schema.validateAsync(req.body); - - const data = new Currency(); - data.name = param.name; - data.symbol = param.symbol; - data.status = param.status; - data.created_by = req.auth.data.name; - - await OrmHelper.DB.manager.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_insert, err.message); - } - } - - static async detail(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Currency'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'Currency ID.', - required: true, - type: 'string' - } - */ - - try { - const schema = Joi.object().keys({ - id: Joi.string().required().label("ID"), - }); - - let param: any = await schema.validateAsync(req.params); - - let data = await CurrencyModel.list({ id: param.id }).then((q) => q.getOne()); - - if (!data) throw { message: "Currency " + Language.lang.failed_not_found }; - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_view, data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_view, err.message); - } - } - - static async update(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Currency'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - description:'', - in: 'path', - type: 'string' - } - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/currency" - } - } - } - } - */ - - const queryRunner = OrmHelper.DB.createQueryRunner(); - await queryRunner.startTransaction(); - - try { - req.body.id = req.params["id"]; - - const schema = Joi.object().keys({ - id: Joi.string().required().label("Bank ID"), - name: Joi.string().required().label("Name"), - symbol: Joi.string().required().label("Symbol"), - status: Joi.string().uuid().required().valid("Y", "N").label("Status"), - }); - - let param: any = await schema.validateAsync(req.body); - - let currency: Currency = await CurrencyModel.list({ id: param.id }).then((q) => q.getOne()); - if (!currency) throw { message: "Currnecy " + Language.lang.failed_not_found }; - - currency.name = param.name; - currency.symbol = param.symbol; - currency.status = param.status; - - await queryRunner.manager.save(currency); - - await queryRunner.commitTransaction(); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_update, currency); - } catch (e: unknown) { - await queryRunner.rollbackTransaction(); - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } finally { - await queryRunner.release(); - } - } - - static async delete(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Currency'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'Bank ID.', - required: true, - type: 'string' - } - #swagger.parameters['hard'] = { - in: 'path', - description: 'Is Hard Delete', - required: false, - type: 'boolean' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("ID"), - hard: Joi.bool().optional().allow("").label("Is hard delete?"), - }); - - const param: { id: string; hard: boolean } = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(Currency); - - const affected = (!param.hard ? await repo.softDelete({ id: param.id }) : await repo.delete({ id: param.id })).affected; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_delete, err.message); - } - } -} diff --git a/src/controllers/department.ts b/src/controllers/department.ts deleted file mode 100644 index 86011dc..0000000 --- a/src/controllers/department.ts +++ /dev/null @@ -1,255 +0,0 @@ -import { Department, Paging } from "entity"; -import { NextFunction, Response } from "express"; -import { Request } from "express-jwt"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import CommonHelper from "../helpers/common"; -import { ReturnHelper } from "../helpers/express/return"; -import { Language } from "../langs/lang"; -import { DepartmentModel } from "../model/department"; -import { OrmHelper } from "../helpers/orm"; -import moment from "moment"; - -const log: Logger = new Logger({ - name: "[DepartmentController]", - type: "pretty", -}); - -export class DepartmentController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Department'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['filter'] = { description: '', in: 'query', type: 'string' } - #swagger.parameters['limit'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['page'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['with_deleted'] = { in: 'query', required: true, type: 'boolean' } - #swagger.parameters['order_field'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['order_direction'] = { in: 'query', required: true, schema: { '@enum': ['ASC', 'DESC'] } } - */ - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().required().label("With Deleted"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").required().label("Order Direction"), - }); - - let param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await DepartmentModel.list(filter); - - const offset = (param.page - 1) * param.limit; - let limit = param.limit; - - const res_count = query; - const res_list = query - .orderBy("Department." + param.order_field, param.order_direction) - .offset(offset) - .limit(limit); - - if (param.with_deleted) { - res_count.withDeleted(); - res_list.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Department'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.requestBody = { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/department" } } } } - */ - const queryRunner = OrmHelper.DB.createQueryRunner(); - await queryRunner.startTransaction(); - try { - const schema = Joi.object().keys({ - name: Joi.string().max(128).required().label("Name"), - status: Joi.string().required().label("Status"), - }); - - let param: any = await schema.validateAsync(req.body); - - let filter = { name: param.name }; - let exist = await DepartmentModel.list(filter).then((q) => q.getOne()); - if (exist) throw { message: "Department " + Language.lang.failed_duplicate }; - - let department = new Department(); - department.name = param.name; - department.status = param.status; - department.created_by = req.auth.data.name; - department.updated_by = req.auth.data.name; - await queryRunner.manager.save(department); - - await queryRunner.commitTransaction(); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, department); - } catch (e: unknown) { - await queryRunner.rollbackTransaction(); - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } finally { - await queryRunner.release(); - } - } - - static async detail(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Department'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { description: '', in: 'path', type: 'string' } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("Department Id"), - }); - - let param: any = await schema.validateAsync(req.params); - - let department = await DepartmentModel.list({ "Department.id": param.id }).then((q) => q.getOne()); - - if (!department) throw { message: "Department Not Found" }; - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_view, department); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_not_found, err.message); - } - } - - static async update(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Department'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { description: '', in: 'path', type: 'string' } - #swagger.requestBody = { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/department" } } } } - */ - const queryRunner = OrmHelper.DB.createQueryRunner(); - await queryRunner.startTransaction(); - - try { - req.body.id = req.params["id"]; - - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("Department ID"), - name: Joi.string().max(128).required().label("Name"), - status: Joi.string().required().label("Status"), - }); - - let param: any = await schema.validateAsync(req.body); - - let filter = { name: param.name }; - let exist = await DepartmentModel.list(filter).then((q) => q.getOne()); - if (exist && exist.id != param.id) throw { message: "Department " + Language.lang.failed_duplicate }; - - let department = await DepartmentModel.list({ "Department.id": param.id }).then((q) => q.getOne()); - - if (!department) throw { message: "Department " + Language.lang.failed_not_found }; - - department.name = param.name; - department.status = param.status; - department.updated_by = req.auth.data.name; - await queryRunner.manager.save(department); - - await queryRunner.commitTransaction(); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_update, department); - } catch (e: unknown) { - await queryRunner.rollbackTransaction(); - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } finally { - await queryRunner.release(); - } - } - - static async delete(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Department'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { in: 'path', required: true, type: 'string' } - #swagger.parameters['hard'] = { in: 'path', description: 'Is Hard Delete', required: false, type: 'boolean' } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("ID"), - hard: Joi.bool().optional().allow("").label("Is hard delete?"), - }); - - const param: { id: string; hard: boolean } = await schema.validateAsync(req.params); - - let affected = 0; - if (!param.hard) { - let department: Department = await DepartmentModel.list({ "Department.id": param.id }).then((q) => q.getOne()); - - if (!department) throw { message: "Department " + Language.lang.failed_not_found }; - - department.deleted_by = req.auth.data.name; - department.deleted_at = moment().toDate(); - await OrmHelper.DB.manager.save(department); - affected = 1; - } else { - const repo = OrmHelper.DB.getRepository(Department); - affected = (await repo.delete({ id: param.id })).affected ?? 0; - } - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_delete, err.message); - } - } - - static async restore(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Department'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { in: 'path', required: true, type: 'string' } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("ID"), - }); - - const param: any = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(Department); - - const affected = (await repo.restore({ id: param.id })).affected ?? 0; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_restore, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_restore, err.message); - } - } -} diff --git a/src/controllers/diagnosis.ts b/src/controllers/diagnosis.ts deleted file mode 100644 index 1f74242..0000000 --- a/src/controllers/diagnosis.ts +++ /dev/null @@ -1,494 +0,0 @@ -import { Diagnosis, Paging } from "entity"; -import { NextFunction, Response } from "express"; -import { Request } from "express-jwt"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import { Brackets } from "typeorm"; -import { validate as validateUuid } from "uuid"; -import CommonHelper from "../helpers/common"; -import { ReturnHelper } from "../helpers/express/return"; -import { Language } from "../langs/lang"; -import { DiagnosisModel } from "../model/diagnosis"; -import { OrmHelper } from "../helpers/orm"; -import moment from "moment"; - -const log: Logger = new Logger({ - name: "[DiagnosisController]", - type: "pretty", -}); - -const DIAGNOSIS_NAME_COLUMNS = [ - "Diagnosis.diagnosis", - "Diagnosis.diagnosis_ind", - "Diagnosis.diagnosis_pt", - "Diagnosis.diagnosis_tet", -] as const; - -const MIN_DIAGNOSIS_SEARCH_TOKEN_LENGTH = 2; - -function stripLikeWildcards(value: string): string { - return value.replace(/^%+|%+$/g, "").trim(); -} - -function parseDiagnosisSearchTokens(raw: unknown): string[] { - const text = stripLikeWildcards(String(raw ?? "")); - if (!text) { - return []; - } - return text - .split(/\s+/) - .map((t) => t.trim()) - .filter((t) => t.length >= MIN_DIAGNOSIS_SEARCH_TOKEN_LENGTH); -} - -function applyLocalizedDiagnosisFields( - diagnosis: Diagnosis, - param: { diagnosis: string; diagnosis_ind?: string; diagnosis_pt?: string; diagnosis_tet?: string }, -) { - diagnosis.diagnosis = param.diagnosis; - diagnosis.diagnosis_ind = param.diagnosis_ind?.trim() || param.diagnosis; - diagnosis.diagnosis_pt = param.diagnosis_pt?.trim() || param.diagnosis; - diagnosis.diagnosis_tet = param.diagnosis_tet?.trim() || param.diagnosis; -} - -type DiagnosisQueryBuilder = { - where: (sql: string, params?: Record) => unknown; - orWhere: (sql: string, params?: Record) => unknown; - andWhere: (sql: string, params?: Record) => unknown; -}; - -function addDiagnosisNameTokenSearch( - qb: DiagnosisQueryBuilder, - raw: unknown, - op: "where" | "orWhere", - paramPrefix: string, -): void { - const tokens = parseDiagnosisSearchTokens(raw); - if (tokens.length === 0) { - const phrase = `%${stripLikeWildcards(String(raw ?? ""))}%`; - (qb as any)[op]( - new Brackets((inner) => { - DIAGNOSIS_NAME_COLUMNS.forEach((col, idx) => { - const key = `${paramPrefix}_phrase_${idx}`; - const method = idx === 0 ? "where" : "orWhere"; - (inner as any)[method](`${col} ILIKE :${key}`, { [key]: phrase }); - }); - }), - ); - return; - } - - (qb as any)[op]( - new Brackets((tokenGroup) => { - tokens.forEach((token, tokenIdx) => { - const tokenKey = `${paramPrefix}_tok_${tokenIdx}`; - const tokenMethod = tokenIdx === 0 ? "andWhere" : "andWhere"; - (tokenGroup as any)[tokenMethod]( - new Brackets((colGroup) => { - DIAGNOSIS_NAME_COLUMNS.forEach((col, colIdx) => { - const colKey = `${tokenKey}_col_${colIdx}`; - const colMethod = colIdx === 0 ? "where" : "orWhere"; - (colGroup as any)[colMethod](`${col} ILIKE :${colKey}`, { - [colKey]: `%${token}%`, - }); - }); - }), - ); - }); - }), - ); -} - -export class DiagnosisController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Diagnosis (ICD-11)'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['filter'] = { - description: 'Filter JSON. Diagnosis.code, Diagnosis.diagnosis (multi-word token AND on diagnosis, diagnosis_ind, diagnosis_pt, diagnosis_tet), and Diagnosis.type are OR-combined; other fields use AND.', - in: 'query', - type: 'string', - } - #swagger.parameters['limit'] = { - in: 'query', - required: true, - type: 'number' - } - #swagger.parameters['page'] = { - in: 'query', - required: true, - type: 'number' - } - #swagger.parameters['with_deleted'] = { - in: 'query', - required: true, - type: 'boolean' - } - #swagger.parameters['order_field'] = { - in: 'query', - required: true, - type: 'string' - } - #swagger.parameters['order_direction'] = { - in: 'query', - required: true, - schema: { - '@enum': ['ASC', 'DESC'] - } - } - */ - - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().required().label("With Deleted"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").required().label("Order Direction"), - }); - - let param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - const codeKey = "Diagnosis.code"; - const diagnosisKey = "Diagnosis.diagnosis"; - const typeKey = "Diagnosis.type"; - const orCode = filter[codeKey]; - const orDiagnosis = filter[diagnosisKey]; - const orType = filter[typeKey]; - const restFilter = { ...filter }; - delete restFilter[codeKey]; - delete restFilter[diagnosisKey]; - delete restFilter[typeKey]; - - var query = await DiagnosisModel.list(restFilter); - - if (orCode !== undefined || orDiagnosis !== undefined || orType !== undefined) { - query.andWhere( - new Brackets((qb) => { - let isFirst = true; - const addOr = (column: string, paramKey: string, raw: any, castText = false) => { - const op = isFirst ? "where" : "orWhere"; - isFirst = false; - const colExpr = castText ? `CAST(${column} AS TEXT)` : column; - if (Array.isArray(raw)) { - (qb as any)[op](`${colExpr} IN (:...${paramKey})`, { [paramKey]: raw }); - return; - } - const f = String(raw); - if (validateUuid(f)) { - (qb as any)[op](`${colExpr} = :${paramKey}`, { [paramKey]: f }); - return; - } - if (f === "null") { - (qb as any)[op](`${column} IS NULL`); - return; - } - if (f.includes("%")) { - (qb as any)[op](`${colExpr} ILIKE :${paramKey}`, { [paramKey]: f }); - return; - } - (qb as any)[op](`${colExpr} = :${paramKey}`, { [paramKey]: f }); - }; - if (orCode !== undefined) addOr("Diagnosis.code", "diag_or_code", orCode); - if (orDiagnosis !== undefined) { - const op = isFirst ? "where" : "orWhere"; - isFirst = false; - addDiagnosisNameTokenSearch(qb as DiagnosisQueryBuilder, orDiagnosis, op, "diag_or_diagnosis"); - } - if (orType !== undefined) addOr("Diagnosis.type", "diag_or_type", orType, true); - }), - ); - } - - const offset = (param.page - 1) * param.limit; - let limit = param.limit; - - const res_count = query; - const res_list = query - .orderBy("Diagnosis." + param.order_field, param.order_direction) - .offset(offset) - .limit(limit); - - if (param.with_deleted) { - res_count.withDeleted(); - res_list.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Diagnosis (ICD-11)'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/diagnosis" - } - } - } - } - */ - const queryRunner = OrmHelper.DB.createQueryRunner(); - await queryRunner.startTransaction(); - try { - const schema = Joi.object().keys({ - diagnosis: Joi.string().max(256).required().label("Diagnosis"), - diagnosis_ind: Joi.string().max(256).allow("", null).optional().label("Diagnosis (Indonesian)"), - diagnosis_pt: Joi.string().max(256).allow("", null).optional().label("Diagnosis (Portuguese)"), - diagnosis_tet: Joi.string().max(256).allow("", null).optional().label("Diagnosis (Tetum)"), - code: Joi.string().max(128).required().label("Code"), - status: Joi.string().required().label("Status"), - }); - - let param: any = await schema.validateAsync(req.body); - - let filter = { - code: param.code, - }; - let exist = await DiagnosisModel.list(filter).then((q) => q.getOne()); - if (exist) throw { message: "Diagnosis " + Language.lang.failed_duplicate }; - - let diagnosis = new Diagnosis(); - applyLocalizedDiagnosisFields(diagnosis, param); - diagnosis.code = param.code; - diagnosis.status = param.status; - diagnosis.created_by = req.auth?.data.name; - diagnosis.updated_by = req.auth?.data.name; - await queryRunner.manager.save(diagnosis); - - await queryRunner.commitTransaction(); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, diagnosis); - } catch (e: unknown) { - await queryRunner.rollbackTransaction(); - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } finally { - await queryRunner.release(); - } - } - - static async detail(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Diagnosis (ICD-11)'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - description:'', - in: 'path', - type: 'string' - } - */ - - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("Diagnosis Id"), - }); - - let param: any = await schema.validateAsync(req.params); - - let diagnosis = await DiagnosisModel.list({ - "Diagnosis.id": param.id, - }).then((q) => q.getOne()); - - if (!diagnosis) throw { message: "Diagnosis Not Found" }; - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_view, diagnosis); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_not_found, err.message); - } - } - - static async update(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Diagnosis (ICD-11)'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - description:'', - in: 'path', - type: 'string' - } - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/diagnosis" - } - } - } - } - */ - - const queryRunner = OrmHelper.DB.createQueryRunner(); - await queryRunner.startTransaction(); - - try { - req.body.id = req.params["id"]; - - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("Diagnosis ID"), - diagnosis: Joi.string().max(256).required().label("Diagnosis"), - diagnosis_ind: Joi.string().max(256).allow("", null).optional().label("Diagnosis (Indonesian)"), - diagnosis_pt: Joi.string().max(256).allow("", null).optional().label("Diagnosis (Portuguese)"), - diagnosis_tet: Joi.string().max(256).allow("", null).optional().label("Diagnosis (Tetum)"), - code: Joi.string().max(128).required().label("Code"), - status: Joi.string().required().label("Status"), - }); - - let param: any = await schema.validateAsync(req.body); - - let filter = { - code: param.code, - }; - let exist = await DiagnosisModel.list(filter).then((q) => q.getOne()); - if (exist && exist.id != param.id) throw { message: "Diagnosis " + Language.lang.failed_duplicate }; - - let diagnosis = await DiagnosisModel.list({ - "Diagnosis.id": param.id, - }).then((q) => q.getOne()); - - if (!diagnosis) throw { message: "Diagnosis " + Language.lang.failed_not_found }; - - applyLocalizedDiagnosisFields(diagnosis, param); - diagnosis.code = param.code; - diagnosis.status = param.status; - diagnosis.updated_by = req.auth?.data.name; - await queryRunner.manager.save(diagnosis); - - await queryRunner.commitTransaction(); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_update, diagnosis); - } catch (e: unknown) { - await queryRunner.rollbackTransaction(); - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } finally { - await queryRunner.release(); - } - } - - static async delete(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Diagnosis (ICD-11)'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'Diagnosis ID.', - required: true, - type: 'string' - } - #swagger.parameters['hard'] = { - in: 'path', - description: 'Is Hard Delete', - required: false, - type: 'boolean' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("ID"), - hard: Joi.bool().optional().allow("").label("Is hard delete?"), - }); - - const param: { id: string; hard: boolean } = await schema.validateAsync(req.params); - - let affected = 0; - if (!param.hard) { - let diagnosis: Diagnosis = await DiagnosisModel.list({ - "Diagnosis.id": param.id, - }).then((q) => q.getOne()); - - if (!diagnosis) throw { message: "Diagnosis " + Language.lang.failed_not_found }; - - diagnosis.deleted_by = req.auth?.data.name; - diagnosis.deleted_at = moment().toDate(); - await OrmHelper.DB.manager.save(diagnosis); - affected = 1; - } else { - const repo = OrmHelper.DB.getRepository(Diagnosis); - affected = (await repo.delete({ id: param.id })).affected ?? 0; - } - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_delete, err.message); - } - } - - static async restore(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Diagnosis (ICD-11)'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'Diagnosis ID.', - required: true, - type: 'string' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("ID"), - }); - - const param: any = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(Diagnosis); - - const affected = (await repo.restore({ id: param.id })).affected ?? 0; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_restore, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_restore, err.message); - } - } -} diff --git a/src/controllers/diagnostic_procedure.ts b/src/controllers/diagnostic_procedure.ts deleted file mode 100644 index 62881f5..0000000 --- a/src/controllers/diagnostic_procedure.ts +++ /dev/null @@ -1,391 +0,0 @@ -import { DiagnosticProcedure, Paging } from "entity"; -import { NextFunction, Response } from "express"; -import { Request } from "express-jwt"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import { Brackets } from "typeorm"; -import { validate as validateUuid } from "uuid"; -import CommonHelper from "../helpers/common"; -import { ReturnHelper } from "../helpers/express/return"; -import { Language } from "../langs/lang"; -import { DiagnosticProcedureModel } from "../model/diagnostic_procedure"; -import { OrmHelper } from "../helpers/orm"; -import moment from "moment"; - -const log: Logger = new Logger({ - name: "[DiagnosticProcedureController]", - type: "pretty", -}); - -export class DiagnosticProcedureController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Diagnostic Procedure (ICD-9)'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['filter'] = { - description: 'Filter: JSON object; DiagnosticProcedure.code and DiagnosticProcedure.diagnosticProcedure are combined with OR; other fields use AND.', - in: 'query', - type: 'string', - } - #swagger.parameters['limit'] = { - in: 'query', - required: true, - type: 'number' - } - #swagger.parameters['page'] = { - in: 'query', - required: true, - type: 'number' - } - #swagger.parameters['with_deleted'] = { - in: 'query', - required: true, - type: 'boolean' - } - #swagger.parameters['order_field'] = { - in: 'query', - required: true, - type: 'string' - } - #swagger.parameters['order_direction'] = { - in: 'query', - required: true, - schema: { - '@enum': ['ASC', 'DESC'] - } - } - */ - - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().required().label("With Deleted"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").required().label("Order Direction"), - }); - - let param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - const codeKey = "DiagnosticProcedure.code"; - const procedureKey = "DiagnosticProcedure.diagnosticProcedure"; - const orCode = filter[codeKey]; - const orProcedure = filter[procedureKey]; - const restFilter = { ...filter }; - delete restFilter[codeKey]; - delete restFilter[procedureKey]; - - var query = await DiagnosticProcedureModel.list(restFilter); - - if (orCode !== undefined || orProcedure !== undefined) { - query.andWhere( - new Brackets((qb) => { - let isFirst = true; - const addOr = (column: string, paramKey: string, raw: any) => { - const op = isFirst ? "where" : "orWhere"; - isFirst = false; - if (Array.isArray(raw)) { - (qb as any)[op](`${column} IN (:...${paramKey})`, { [paramKey]: raw }); - return; - } - const f = String(raw); - if (validateUuid(f)) { - (qb as any)[op](`${column} = :${paramKey}`, { [paramKey]: f }); - return; - } - if (f === "null") { - (qb as any)[op](`${column} IS NULL`); - return; - } - if (f.includes("%")) { - (qb as any)[op](`${column} ILIKE :${paramKey}`, { [paramKey]: f }); - return; - } - (qb as any)[op](`${column} = :${paramKey}`, { [paramKey]: f }); - }; - if (orCode !== undefined) addOr("DiagnosticProcedure.code", "dp_or_code", orCode); - if (orProcedure !== undefined) addOr("DiagnosticProcedure.diagnosticProcedure", "dp_or_procedure", orProcedure); - }), - ); - } - - const offset = (param.page - 1) * param.limit; - let limit = param.limit; - - const res_count = query; - const res_list = query - .orderBy("DiagnosticProcedure." + param.order_field, param.order_direction) - .offset(offset) - .limit(limit); - - if (param.with_deleted) { - res_count.withDeleted(); - res_list.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Diagnostic Procedure (ICD-9)'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/diagnostic_procedure" - } - } - } - } - */ - const queryRunner = OrmHelper.DB.createQueryRunner(); - await queryRunner.startTransaction(); - try { - const schema = Joi.object().keys({ - diagnosticProcedure: Joi.string().max(256).required().label("Diagnostic Procedure"), - code: Joi.string().max(128).required().label("Code"), - status: Joi.string().required().label("Status"), - }); - - let param: any = await schema.validateAsync(req.body); - - let filter = { - code: param.code, - }; - let exist = await DiagnosticProcedureModel.list(filter).then((q) => q.getOne()); - if (exist) throw { message: "Diagnostic Procedure " + Language.lang.failed_duplicate }; - - let diagnosticProcedure = new DiagnosticProcedure(); - diagnosticProcedure.diagnosticProcedure = param.diagnosticProcedure; - diagnosticProcedure.code = param.code; - diagnosticProcedure.status = param.status; - diagnosticProcedure.created_by = req.auth.data.name; - diagnosticProcedure.updated_by = req.auth.data.name; - await queryRunner.manager.save(diagnosticProcedure); - - await queryRunner.commitTransaction(); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, diagnosticProcedure); - } catch (e: unknown) { - await queryRunner.rollbackTransaction(); - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } finally { - await queryRunner.release(); - } - } - - static async detail(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Diagnostic Procedure (ICD-9)'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - description:'', - in: 'path', - type: 'string' - } - */ - - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("Diagnostic Procedure Id"), - }); - - let param: any = await schema.validateAsync(req.params); - - let diagnosticProcedure = await DiagnosticProcedureModel.list({ "DiagnosticProcedure.id": param.id }).then((q) => q.getOne()); - - if (!diagnosticProcedure) throw { message: "Diagnostic Procedure Not Found" }; - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_view, diagnosticProcedure); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_not_found, err.message); - } - } - - static async update(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Diagnostic Procedure (ICD-9)'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - description:'', - in: 'path', - type: 'string' - } - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/diagnostic_procedure" - } - } - } - } - */ - - const queryRunner = OrmHelper.DB.createQueryRunner(); - await queryRunner.startTransaction(); - - try { - req.body.id = req.params["id"]; - - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("Diagnostic Procedure ID"), - diagnosticProcedure: Joi.string().max(256).required().label("Diagnostic Procedure"), - code: Joi.string().max(128).required().label("Code"), - status: Joi.string().required().label("Status"), - }); - - let param: any = await schema.validateAsync(req.body); - - let filter = { - code: param.code, - }; - let exist = await DiagnosticProcedureModel.list(filter).then((q) => q.getOne()); - if (exist && exist.id != param.id) throw { message: "Diagnostic Procedure " + Language.lang.failed_duplicate }; - - let diagnosticProcedure = await DiagnosticProcedureModel.list({ "DiagnosticProcedure.id": param.id }).then((q) => q.getOne()); - - if (!diagnosticProcedure) throw { message: "Diagnostic Procedure " + Language.lang.failed_not_found }; - - diagnosticProcedure.diagnosticProcedure = param.diagnosticProcedure; - diagnosticProcedure.code = param.code; - diagnosticProcedure.status = param.status; - diagnosticProcedure.updated_by = req.auth.data.name; - await queryRunner.manager.save(diagnosticProcedure); - - await queryRunner.commitTransaction(); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_update, diagnosticProcedure); - } catch (e: unknown) { - await queryRunner.rollbackTransaction(); - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } finally { - await queryRunner.release(); - } - } - - static async delete(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Diagnostic Procedure (ICD-9)'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'Diagnostic Procedure ID.', - required: true, - type: 'string' - } - #swagger.parameters['hard'] = { - in: 'path', - description: 'Is Hard Delete', - required: false, - type: 'boolean' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("ID"), - hard: Joi.bool().optional().allow("").label("Is hard delete?"), - }); - - const param: { id: string; hard: boolean } = await schema.validateAsync(req.params); - - let affected = 0; - if (!param.hard) { - let diagnosticProcedure: DiagnosticProcedure = await DiagnosticProcedureModel.list({ "DiagnosticProcedure.id": param.id }).then((q) => q.getOne()); - - if (!diagnosticProcedure) throw { message: "Diagnostic Procedure " + Language.lang.failed_not_found }; - - diagnosticProcedure.deleted_by = req.auth.data.name; - diagnosticProcedure.deleted_at = moment().toDate(); - await OrmHelper.DB.manager.save(diagnosticProcedure); - affected = 1; - } else { - const repo = OrmHelper.DB.getRepository(DiagnosticProcedure); - affected = (await repo.delete({ id: param.id })).affected; - } - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_delete, err.message); - } - } - - static async restore(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Diagnostic Procedure (ICD-9)'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'Diagnostic Procedure ID.', - required: true, - type: 'string' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("ID"), - }); - - const param: any = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(DiagnosticProcedure); - - const affected = (await repo.restore({ id: param.id })).affected; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_restore, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_restore, err.message); - } - } -} diff --git a/src/controllers/district.ts b/src/controllers/district.ts deleted file mode 100644 index cf82d49..0000000 --- a/src/controllers/district.ts +++ /dev/null @@ -1,391 +0,0 @@ -import { Response, NextFunction, Application } from "express"; -import { Request } from "express-jwt"; -import { ReturnHelper } from "../helpers/express/return"; -import { OrmHelper } from "../helpers/orm"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import { Language } from "../langs/lang"; -import { Paging } from "entity"; -import CommonHelper from "../helpers/common"; -import * as fastcsv from 'fast-csv'; -import dayjs from "dayjs"; -import { District } from "entity"; - -const log: Logger = new Logger({ name: '[DistrictController]', type: 'pretty' }); - -export class DistrictController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['District'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['filter'] = { - description: 'Filter with 2 format :
  • Simple format use text plaint will filter eq:code or like %name%
  • Advance format using field existing {status:\'Y\', any:\'SAME AS PLAINT LOGIC\', etc...}
', - in: 'query', - type: 'string' - } - #swagger.parameters['limit'] = { - in: 'query', - required: true, - type: 'number' - } - #swagger.parameters['page'] = { - in: 'query', - required: true, - type: 'number' - } - #swagger.parameters['with_deleted'] = { - in: 'query', - required: true, - type: 'boolean' - } - #swagger.parameters['order_field'] = { - in: 'query', - required: true, - type: 'string' - } - #swagger.parameters['order_direction'] = { - in: 'query', - required: true, - schema: { - '@enum': ['ASC', 'DESC'] - } - } - */ - - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow('').optional().label('Filter'), - page: Joi.number().required().min(1).label('Page'), - limit: Joi.number().required().min(1).label('Limit'), - with_deleted: Joi.bool().required().label('With Deleted'), - order_field: Joi.string().required().label('Order Field'), - order_direction: Joi.string().allow('asc', 'desc').required().label('Order Direction'), - }); - - const param: Paging = await schema.validateAsync(req.query); - - const repo = OrmHelper.DB.getRepository(District); - - const offset = (param.page - 1) * param.limit - - const { whereAttr, whereVal } = CommonHelper.handleFilter({ - filter: param.filter, - col_any_eq: ['code'], - col_any_like: ['name'] - }); - - const res_count = repo.createQueryBuilder() - .where(whereAttr, whereVal); - const res_list = repo.createQueryBuilder() - .where(whereAttr, whereVal) - .orderBy(param.order_field, param.order_direction) - .offset(offset) - .limit(param.limit); - - if (param.with_deleted) { - res_count.withDeleted(); - res_list.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async export(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['District'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['filter'] = { - description: 'Filter with 2 format :
  • Simple format use text plaint will filter eq:code or like %name%
  • Advance format using field existing {status:\'Y\', any:\'SAME AS PLAINT LOGIC\', etc...}
', - in: 'query', - type: 'string' - } - #swagger.parameters['filter'] = { - in: 'query', - type: 'string' - } - #swagger.parameters['order_field'] = { - in: 'query', - required: true, - type: 'string' - } - #swagger.parameters['order_direction'] = { - in: 'query', - required: true, - schema: { - '@enum': ['ASC', 'DESC'] - } - } - */ - - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow('').optional().label('Filter'), - order_field: Joi.string().required().label('Order Field'), - order_direction: Joi.string().allow('asc', 'desc').required().label('Order Direction'), - }); - - const param: Paging = await schema.validateAsync(req.query); - - const repo = OrmHelper.DB.getRepository(District); - - const { whereAttr, whereVal } = CommonHelper.handleFilter({ - filter: param.filter, - col_any_eq: ['code'], - col_any_like: ['name'] - }); - - const filename = "district.csv"; - - res.setHeader('Content-Type', 'text/csv'); - res.setHeader('Content-Disposition', 'attachment; filename=' + filename); - - const csvStream = fastcsv.format({ - headers: true, - writeHeaders: true, - transform: (row: District): any => ({ - ...row, - created_at: dayjs(row.created_at).format('DD-MM-YYYY HH:MM:ss'), - }) - }); - csvStream.pipe(res); - - const limit = 50; - - const fetchAndWrite = async (page: any) => { - const offset = (page - 1) * limit - - const data = await repo.createQueryBuilder() - .where(whereAttr, whereVal) - .select([ - 'id', - 'code', - 'name', - 'status', - 'created_at']) - .orderBy(param.order_field, param.order_direction) - .offset(offset) - .limit(limit).getRawMany(); - - if (CommonHelper.countObject(data) === 0) { - csvStream.end(); - } else { - data.forEach((item: any) => csvStream.write(item)); - - if (CommonHelper.countObject(data) == limit) { - fetchAndWrite(page + 1); - } else { - csvStream.end(); - } - } - }; - - fetchAndWrite(1); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['District'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/district" - } - } - } - } - */ - - try { - const schema = Joi.object().keys({ - code: Joi.string().max(128).required().label('Code'), - name: Joi.string().max(256).required().label('Name'), - status: Joi.string().required().label('Status'), - }); - - const param: District = await schema.validateAsync(req.body); - - const data = new District() - data.code = param.code - data.name = param.name - data.status = param.status - - await OrmHelper.DB.manager.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 401, Language.lang.failed_insert, err.message); - } - } - - static async update(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['District'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'District ID.', - required: true, - type: 'string' - } - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/district" - } - } - } - } - */ - - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID'), - code: Joi.string().max(128).required().label('Code'), - name: Joi.string().max(256).required().label('Name'), - status: Joi.string().required().label('Status'), - }); - - req.body.id = req.params['id']; - - const param: District = await schema.validateAsync(req.body); - - const repo = OrmHelper.DB.getRepository(District); - - const data = await repo.findOneBy({ id: param.id }); - - if (data != null) { - data.code = param.code - data.name = param.name - data.status = param.status - - await repo.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_update, data); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_update, err.message); - } - } - - static async delete(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['District'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'District ID.', - required: true, - type: 'string' - } - #swagger.parameters['hard'] = { - in: 'path', - description: 'Is Hard Delete', - required: false, - type: 'boolean' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID'), - hard: Joi.bool().optional().allow('').label('Is hard delete?') - }); - - const param: { id: string, hard: boolean } = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(District); - - const affected = (!param.hard ? await repo.softDelete({ id: param.id }) : await repo.delete({ id: param.id })).affected; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_delete, err.message); - } - } - - static async restore(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['District'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.parameters['id'] = { - in: 'path', - description: 'District ID.', - required: true, - type: 'string' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID') - }); - - const param: District = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(District); - - const affected = (await repo.restore({ id: param.id })).affected; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_restore, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_restore, err.message); - } - } -} \ No newline at end of file diff --git a/src/controllers/doctor_item.ts b/src/controllers/doctor_item.ts deleted file mode 100644 index 585e5ff..0000000 --- a/src/controllers/doctor_item.ts +++ /dev/null @@ -1,405 +0,0 @@ -import { DoctorItem, GenericName, ItemMaster, ItemPrice, ItemTypeDetail, User, SellingPricePercentage, PharmacyInfo, RoomToPharmacy } from "entity"; -import { NextFunction, Response } from "express"; -import { Request } from "express-jwt"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import { ReturnHelper } from "../helpers/express/return"; -import { Language } from "../langs/lang"; -import { DoctorItemModel } from "../model/doctor_item"; -import { OrmHelper } from "../helpers/orm"; -import CommonHelper from "../helpers/common"; - -const log: Logger = new Logger({ - name: "[DoctorItemController]", - type: "pretty", -}); - -export class DoctorItemController { - static async listAll(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Doctor Item'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['doctor_id'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['room_id'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['filter'] = { description: '', in: 'query', type: 'string' } - #swagger.parameters['page'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['limit'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['order_field'] = { in: 'query', required: false, type: 'string' } - #swagger.parameters['order_direction'] = { in: 'query', required: false, schema: { '@enum': ['ASC', 'DESC'] } } - */ - try { - const schema = Joi.object().keys({ - doctor_id: Joi.string().uuid().required().label("Doctor ID"), - room_id: Joi.string().uuid().required().label("Room ID"), - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - order_field: Joi.string().optional().label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").optional().label("Order Direction"), - }); - - let param: any = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - let filterAny = filter.any && filter.any !== "" ? filter.any : ""; - - let filterObj = { ...filter } as any; - delete filterObj.any; - // filterObj = { ...filterObj}; - - const repo = OrmHelper.DB.getRepository(ItemMaster); - - let whereAttr: string[] = []; - let whereVal: any = {}; - - if (filterObj && Object.keys(filterObj).length > 0) { - const filterResult = CommonHelper.handleQueryFilter(filterObj, "item_master"); - whereAttr = [...whereAttr, ...filterResult.whereAttr]; - whereVal = { ...whereVal, ...filterResult.whereVal }; - } - - if (filterAny && filterAny !== "" && filterAny !== null && filterAny !== undefined) { - const filterResult = CommonHelper.handleFilter({ - filter: JSON.stringify({ any: filterAny.toLowerCase() }), - col_any_eq: [], - col_any_like: ["item_name", "generic_name"], - }); - - if (filterResult.whereAttr && filterResult.whereAttr !== "") { - whereAttr = [...whereAttr, filterResult.whereAttr]; - whereVal = { ...whereVal, ...filterResult.whereVal }; - } - } - - const orderField = param.order_field || "id"; - const orderDirection = param.order_direction || "asc"; - - const offset = (param.page - 1) * param.limit; - - const pharmacyInfoRow = await OrmHelper.DB - .getRepository(PharmacyInfo) - .createQueryBuilder("pharmacy_info") - .select("pharmacy_info.default_room_id", "default_room_id") - .where("pharmacy_info.deleted_at IS NULL") - .orderBy("pharmacy_info.created_at", "DESC") - .limit(1) - .getRawOne<{ default_room_id: string | null }>(); - - const defaultRoomId = pharmacyInfoRow?.default_room_id ?? null; - - const roomToPharmacyRow = await OrmHelper.DB - .getRepository(RoomToPharmacy) - .createQueryBuilder("room_to_pharmacy") - .select("room_to_pharmacy.pharmacy_room_id", "pharmacy_room_id") - .where("room_to_pharmacy.deleted_at IS NULL") - .andWhere("room_to_pharmacy.room_id = :roomId", { roomId: param.room_id }) - .orderBy("room_to_pharmacy.created_at", "DESC") - .limit(1) - .getRawOne<{ pharmacy_room_id: string | null }>(); - - const pharmacyRoomId = roomToPharmacyRow?.pharmacy_room_id ?? null; - - let res_count = repo.createQueryBuilder("item_master") - .leftJoin("item_master.generic_name", "generic_name") - .leftJoin("item_master.type_detail", "item_type_detail") - .leftJoin(ItemPrice, "item_price", "item_price.item_master_id = item_master.id") - .leftJoin(SellingPricePercentage, "selling_price_percentage", "selling_price_percentage.item_master_id = item_master.id") - .leftJoin( - DoctorItem, - "doctor_item", - "doctor_item.item_master_id = item_master.id AND doctor_item.doctor_id = :doctorId", - { doctorId: param.doctor_id } - ); - - if (whereAttr.length !== 0) { - res_count = res_count.where(whereAttr.join(" and "), whereVal); - } - - let res_list = repo.createQueryBuilder("item_master") - .leftJoin("item_master.generic_name", "generic_name") - .leftJoin("item_master.type_detail", "item_type_detail") - .leftJoin(ItemPrice, "item_price", "item_price.item_master_id = item_master.id") - .leftJoin(SellingPricePercentage, "selling_price_percentage", "selling_price_percentage.item_master_id = item_master.id") - .leftJoin( - DoctorItem, - "doctor_item", - "doctor_item.item_master_id = item_master.id AND doctor_item.doctor_id = :doctorId", - { doctorId: param.doctor_id } - ); - - if (whereAttr.length !== 0) { - res_list = res_list.where(whereAttr.join(" and "), whereVal); - } - - res_list = res_list - .select([ - "item_master.active_ingredient as active_ingredient", - "item_master.id as item_id", - "item_master.item_name as item_name", - "generic_name.generic_name as item_generic_name", - "item_type_detail.type_detail_name as item_type", - (pharmacyRoomId - ? `COALESCE((SELECT SUM(rs.total_stock)::text FROM pharmacy_logistic.room_stock rs WHERE rs."roomId" = :pharmacyRoomId AND rs."itemmasterId" = item_master.id AND rs.deleted_at IS NULL), '0') as pharmacy_stock` - : "'0' as pharmacy_stock"), - (defaultRoomId - ? `COALESCE((SELECT SUM(rs.total_stock)::text FROM pharmacy_logistic.room_stock rs WHERE rs."roomId" = :defaultRoomId AND rs."itemmasterId" = item_master.id AND rs.deleted_at IS NULL), '0') as storage_stock` - : "'0' as storage_stock"), - "ROUND(CASE WHEN selling_price_percentage.percentage IS NULL " + - "THEN COALESCE(item_price.selling_price, 0) " + - "ELSE COALESCE(item_price.selling_price, 0) + (COALESCE(item_price.selling_price, 0) * COALESCE(selling_price_percentage.percentage, 0) / 100) END, 2) as price", - "doctor_item.id as fav_id", - ]) - .orderBy("item_master." + orderField, orderDirection) - .offset(offset) - .limit(param.limit) - - if (defaultRoomId) { - res_list = res_list.setParameter("defaultRoomId", defaultRoomId); - } - if (pharmacyRoomId) { - res_list = res_list.setParameter("pharmacyRoomId", pharmacyRoomId); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getRawMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async listFav(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Doctor Item'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['doctor_id'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['room_id'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['filter'] = { description: '', in: 'query', type: 'string' } - #swagger.parameters['page'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['limit'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['order_field'] = { in: 'query', required: false, type: 'string' } - #swagger.parameters['order_direction'] = { in: 'query', required: false, schema: { '@enum': ['ASC', 'DESC'] } } - */ - try { - const schema = Joi.object().keys({ - doctor_id: Joi.string().uuid().required().label("Doctor ID"), - room_id: Joi.string().uuid().required().label("Room ID"), - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - order_field: Joi.string().optional().label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").optional().label("Order Direction"), - }); - - let param: any = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - let filterAny = filter.any && filter.any !== "" ? filter.any : ""; - - let filterObj = { ...filter } as any; - delete filterObj.any; - // filterObj = { ...filterObj}; - - const repo = OrmHelper.DB.getRepository(ItemMaster); - - let whereAttr: string[] = []; - let whereVal: any = {}; - - if (filterObj && Object.keys(filterObj).length > 0) { - const filterResult = CommonHelper.handleQueryFilter(filter, "item_master"); - whereAttr = [...whereAttr, ...filterResult.whereAttr]; - whereVal = { ...whereVal, ...filterResult.whereVal }; - } - - if (filterAny && filterAny !== "" && filterAny !== null && filterAny !== undefined) { - const filterResult = CommonHelper.handleFilter({ - filter: JSON.stringify({ any: filterAny.toLowerCase() }), - col_any_eq: [], - col_any_like: ["item_name", "generic_name"], - }); - - if (filterResult.whereAttr && filterResult.whereAttr !== "") { - whereAttr = [...whereAttr, filterResult.whereAttr]; - whereVal = { ...whereVal, ...filterResult.whereVal }; - } - } - - const orderField = param.order_field || "id"; - const orderDirection = param.order_direction || "asc"; - - const offset = (param.page - 1) * param.limit; - - const pharmacyInfoRow = await OrmHelper.DB - .getRepository(PharmacyInfo) - .createQueryBuilder("pharmacy_info") - .select("pharmacy_info.default_room_id", "default_room_id") - .where("pharmacy_info.deleted_at IS NULL") - .orderBy("pharmacy_info.created_at", "DESC") - .limit(1) - .getRawOne<{ default_room_id: string | null }>(); - - const defaultRoomId = pharmacyInfoRow?.default_room_id ?? null; - - const roomToPharmacyRow = await OrmHelper.DB - .getRepository(RoomToPharmacy) - .createQueryBuilder("room_to_pharmacy") - .select("room_to_pharmacy.pharmacy_room_id", "pharmacy_room_id") - .where("room_to_pharmacy.deleted_at IS NULL") - .andWhere("room_to_pharmacy.room_id = :roomId", { roomId: param.room_id }) - .orderBy("room_to_pharmacy.created_at", "DESC") - .limit(1) - .getRawOne<{ pharmacy_room_id: string | null }>(); - - const pharmacyRoomId = roomToPharmacyRow?.pharmacy_room_id ?? null; - - let res_count = repo.createQueryBuilder("item_master") - .innerJoin( - DoctorItem, - "doctor_item", - "doctor_item.item_master_id = item_master.id AND doctor_item.doctor_id = :doctorId", - { doctorId: param.doctor_id } - ) - .leftJoin("item_master.generic_name", "generic_name") - .leftJoin("item_master.type_detail", "item_type_detail") - .leftJoin(ItemPrice, "item_price", "item_price.item_master_id = item_master.id") - .leftJoin(SellingPricePercentage, "selling_price_percentage", "selling_price_percentage.item_master_id = item_master.id"); - - if (whereAttr.length !== 0) { - res_count = res_count.where(whereAttr.join(" and "), whereVal); - } - - let res_list = repo.createQueryBuilder("item_master") - .innerJoin( - DoctorItem, - "doctor_item", - "doctor_item.item_master_id = item_master.id AND doctor_item.doctor_id = :doctorId", - { doctorId: param.doctor_id } - ) - .leftJoin("item_master.generic_name", "generic_name") - .leftJoin("item_master.type_detail", "item_type_detail") - .leftJoin(ItemPrice, "item_price", "item_price.item_master_id = item_master.id") - .leftJoin(SellingPricePercentage, "selling_price_percentage", "selling_price_percentage.item_master_id = item_master.id"); - - if (whereAttr.length !== 0) { - res_list = res_list.where(whereAttr.join(" and "), whereVal); - } - - res_list = res_list - .select([ - "item_master.id as item_id", - "item_master.item_name as item_name", - "generic_name.generic_name as item_generic_name", - "item_type_detail.type_detail_name as item_type", - (pharmacyRoomId - ? `COALESCE((SELECT SUM(rs.total_stock)::text FROM pharmacy_logistic.room_stock rs WHERE rs."roomId" = :pharmacyRoomId AND rs."itemmasterId" = item_master.id AND rs.deleted_at IS NULL), '0') as pharmacy_stock` - : "'0' as pharmacy_stock"), - (defaultRoomId - ? `COALESCE((SELECT SUM(rs.total_stock)::text FROM pharmacy_logistic.room_stock rs WHERE rs."roomId" = :defaultRoomId AND rs."itemmasterId" = item_master.id AND rs.deleted_at IS NULL), '0') as storage_stock` - : "'0' as storage_stock"), - "ROUND(CASE WHEN selling_price_percentage.percentage IS NULL " + - "THEN COALESCE(item_price.selling_price, 0) " + - "ELSE COALESCE(item_price.selling_price, 0) + (COALESCE(item_price.selling_price, 0) * COALESCE(selling_price_percentage.percentage, 0) / 100) END, 2) as price", - "doctor_item.id as fav_id", - ]) - .orderBy("item_master." + orderField, orderDirection) - .offset(offset) - .limit(param.limit); - - if (defaultRoomId) { - res_list = res_list.setParameter("defaultRoomId", defaultRoomId); - } - if (pharmacyRoomId) { - res_list = res_list.setParameter("pharmacyRoomId", pharmacyRoomId); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getRawMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async selectFav(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Doctor Item'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.requestBody = { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/doctorItem" } } } } - */ - const queryRunner = OrmHelper.DB.createQueryRunner(); - await queryRunner.startTransaction(); - try { - const schema = Joi.object().keys({ - doctor_id: Joi.string().uuid().required().label("Doctor ID"), - item_master_id: Joi.string().uuid().required().label("Item Master ID"), - }); - - let param: any = await schema.validateAsync(req.body); - - const doctor = await OrmHelper.DB.getRepository(User).findOne({ where: { id: param.doctor_id } }); - if (!doctor) throw { message: "Doctor (User) " + Language.lang.failed_not_found }; - - const itemMaster = await OrmHelper.DB.getRepository(ItemMaster).findOne({ where: { id: param.item_master_id } }); - if (!itemMaster) throw { message: "Item Master " + Language.lang.failed_not_found }; - - const exist = await DoctorItemModel.list({ doctor_id: param.doctor_id, item_master_id: param.item_master_id }).then((q) => q.getOne()); - if (exist) throw { message: "Doctor Item " + Language.lang.failed_duplicate }; - - let doctorItem = new DoctorItem(); - doctorItem.doctor = doctor; - doctorItem.item_master = itemMaster; - doctorItem.created_by = req.auth.data.name; - doctorItem.updated_by = req.auth.data.name; - await queryRunner.manager.save(doctorItem); - - await queryRunner.commitTransaction(); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, doctorItem); - } catch (e: unknown) { - await queryRunner.rollbackTransaction(); - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_insert, err.message); - } finally { - await queryRunner.release(); - } - } - - static async removeFav(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Doctor Item'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['fav_id'] = { in: 'path', required: true, type: 'string' } - */ - try { - const schema = Joi.object().keys({ - fav_id: Joi.string().uuid().required().label("Favorite ID"), - }); - - const param: { fav_id: string } = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(DoctorItem); - const affected = (await repo.delete({ id: param.fav_id })).affected ?? 0; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_delete, err.message); - } - } -} diff --git a/src/controllers/doctor_item_package.ts b/src/controllers/doctor_item_package.ts deleted file mode 100644 index 085914e..0000000 --- a/src/controllers/doctor_item_package.ts +++ /dev/null @@ -1,345 +0,0 @@ -import { DoctorItemPackage, ItemMaster, ItemPrice, SellingPricePercentage, User, PharmacyInfo, RoomToPharmacy } from "entity"; -import { NextFunction, Response } from "express"; -import { Request } from "express-jwt"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import { ReturnHelper } from "../helpers/express/return"; -import { Language } from "../langs/lang"; -import { DoctorItemPackageModel } from "../model/doctor_item_package"; -import { OrmHelper } from "../helpers/orm"; -import CommonHelper from "../helpers/common"; - -const log: Logger = new Logger({ - name: "[DoctorItemPackageController]", - type: "pretty", -}); - -export class DoctorItemPackageController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Doctor Item Package'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['doctor_id'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['room_id'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['filter'] = { description: '', in: 'query', type: 'string' } - #swagger.parameters['page'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['limit'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['order_field'] = { in: 'query', required: false, type: 'string' } - #swagger.parameters['order_direction'] = { in: 'query', required: false, schema: { '@enum': ['ASC', 'DESC'] } } - */ - try { - const schema = Joi.object().keys({ - doctor_id: Joi.string().uuid().required().label("Doctor ID"), - room_id: Joi.string().uuid().required().label("Room ID"), - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - order_field: Joi.string().optional().label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").optional().label("Order Direction"), - }); - - let param: any = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - let filterAny = filter.any && filter.any !== "" ? filter.any : ""; - - let filterObj = { ...filter } as any; - delete filterObj.any; - filterObj = { ...filterObj, "DoctorItemPackage.doctor": param.doctor_id }; - - const query = await DoctorItemPackageModel.list(filterObj, filterAny); - - const orderField = param.order_field || "id"; - const orderDirection = param.order_direction || "asc"; - - const offset = (param.page - 1) * param.limit; - - const pharmacyInfoRow = await OrmHelper.DB - .getRepository(PharmacyInfo) - .createQueryBuilder("pharmacy_info") - .select("pharmacy_info.default_room_id", "default_room_id") - .where("pharmacy_info.deleted_at IS NULL") - .orderBy("pharmacy_info.created_at", "DESC") - .limit(1) - .getRawOne<{ default_room_id: string | null }>(); - - const defaultRoomId = pharmacyInfoRow?.default_room_id ?? null; - - const roomToPharmacyRow = await OrmHelper.DB - .getRepository(RoomToPharmacy) - .createQueryBuilder("room_to_pharmacy") - .select("room_to_pharmacy.pharmacy_room_id", "pharmacy_room_id") - .where("room_to_pharmacy.deleted_at IS NULL") - .andWhere("room_to_pharmacy.room_id = :roomId", { roomId: param.room_id }) - .orderBy("room_to_pharmacy.created_at", "DESC") - .limit(1) - .getRawOne<{ pharmacy_room_id: string | null }>(); - - const pharmacyRoomId = roomToPharmacyRow?.pharmacy_room_id ?? null; - - const current_page = param.page; - const total_count_data = await query.getCount(); - - // Query 1: packages only (pagination is correct) - const packages = await query - .select([ - "DoctorItemPackage.id", - "DoctorItemPackage.name", - "DoctorItemPackage.description", - "DoctorItemPackage.active", - ]) - .orderBy("DoctorItemPackage." + orderField, orderDirection) - .offset(offset) - .limit(param.limit) - .getMany(); - - if (!packages || packages.length === 0) { - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, 0, current_page, total_count_data, []); - } - - const packageIds = packages.map((p: any) => p.id); - - // Query 2: all items for these packages (build items[] per package) - let itemsQuery = OrmHelper.DB.getRepository(DoctorItemPackage) - .createQueryBuilder("DoctorItemPackage") - .select([ - "DoctorItemPackage.id as package_id", - "ItemMaster.id as item_id", - "ItemMaster.item_name as item_name", - "GenericName.generic_name as item_generic_name", - "item_type.type_detail_name as item_type", - (pharmacyRoomId - ? `COALESCE((SELECT SUM(rs.total_stock)::text FROM pharmacy_logistic.room_stock rs WHERE rs."roomId" = :pharmacyRoomId AND rs."itemmasterId" = ItemMaster.id AND rs.deleted_at IS NULL), '0') as pharmacy_stock` - : "'0' as pharmacy_stock"), - (defaultRoomId - ? `COALESCE((SELECT SUM(rs.total_stock)::text FROM pharmacy_logistic.room_stock rs WHERE rs."roomId" = :defaultRoomId AND rs."itemmasterId" = ItemMaster.id AND rs.deleted_at IS NULL), '0') as storage_stock` - : "'0' as storage_stock"), - "ROUND(CASE WHEN selling_price_percentage.percentage IS NULL " + - "THEN COALESCE(item_price.selling_price, 0) " + - "ELSE COALESCE(item_price.selling_price, 0) + (COALESCE(item_price.selling_price, 0) * COALESCE(selling_price_percentage.percentage, 0) / 100) END, 2) as price", - ]) - .leftJoin("DoctorItemPackage.items", "ItemMaster") - .leftJoin("ItemMaster.generic_name", "GenericName") - .leftJoin("ItemMaster.type_detail", "item_type") - .leftJoin(ItemPrice, "item_price", "item_price.item_master_id = ItemMaster.id") - .leftJoin(SellingPricePercentage, "selling_price_percentage", "selling_price_percentage.item_master_id = ItemMaster.id") - .where("DoctorItemPackage.id IN (:...ids)", { ids: packageIds }); - - if (defaultRoomId) { - itemsQuery = itemsQuery.setParameter("defaultRoomId", defaultRoomId); - } - if (pharmacyRoomId) { - itemsQuery = itemsQuery.setParameter("pharmacyRoomId", pharmacyRoomId); - } - - const itemsRaw = await itemsQuery.getRawMany(); - - const itemsByPackageId = new Map(); - for (const row of itemsRaw) { - const pkgId = row["package_id"]; - if (!pkgId || !row["item_id"]) continue; - if (!itemsByPackageId.has(pkgId)) itemsByPackageId.set(pkgId, []); - itemsByPackageId.get(pkgId)!.push({ - item_id: row["item_id"], - item_name: row["item_name"], - item_generic_name: row["item_generic_name"], - item_type: row["item_type"], - pharmacy_stock: row["pharmacy_stock"], - storage_stock: row["storage_stock"], - price: row["price"], - }); - } - - const list_data = packages.map((p: any) => ({ - id: p.id, - name: p.name, - description: p.description ?? null, - active: p.active, - items: itemsByPackageId.get(p.id) ?? [], - })); - - const count_data = list_data.length; - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Doctor Item Package'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.requestBody = { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/doctorItemPackage" } } } } - */ - const queryRunner = OrmHelper.DB.createQueryRunner(); - await queryRunner.startTransaction(); - try { - const schema = Joi.object().keys({ - doctor_id: Joi.string().uuid().required().label("Doctor ID"), - name: Joi.string().required().max(256).label("Name"), - description: Joi.string().allow("", null).optional().label("Description"), - item_master_ids: Joi.array().items(Joi.string().uuid()).optional().label("Item Master IDs"), - active: Joi.bool().optional().label("Active"), - }); - - let param: any = await schema.validateAsync(req.body); - - const doctor = await OrmHelper.DB.getRepository(User).findOne({ where: { id: param.doctor_id } }); - if (!doctor) throw { message: "Doctor (User) " + Language.lang.failed_not_found }; - - // const exist = await DoctorItemPackageModel.list({ "Doctor.id": param.doctor_id, "DoctorItemPackage.name": param.name }).then((q) => q.getOne()); - // if (exist) throw { message: "Doctor Item Package " + Language.lang.failed_duplicate }; - - let items: ItemMaster[] = []; - if (param.item_master_ids && param.item_master_ids.length > 0) { - for (const itemMasterId of param.item_master_ids) { - const itemMaster = await OrmHelper.DB.getRepository(ItemMaster).findOne({ where: { id: itemMasterId } }); - if (!itemMaster) throw { message: "Item Master " + Language.lang.failed_not_found }; - items.push(itemMaster); - } - } - - let doctorItemPackage = new DoctorItemPackage(); - doctorItemPackage.doctor = doctor; - doctorItemPackage.name = param.name; - doctorItemPackage.description = param.description || null; - doctorItemPackage.items = items; - doctorItemPackage.active = typeof param.active === "boolean" ? param.active : true; - doctorItemPackage.created_by = req.auth.data.name; - doctorItemPackage.updated_by = req.auth.data.name; - await queryRunner.manager.save(doctorItemPackage); - - await queryRunner.commitTransaction(); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, doctorItemPackage); - } catch (e: unknown) { - await queryRunner.rollbackTransaction(); - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_insert, err.message); - } finally { - await queryRunner.release(); - } - } - - static async detail(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Doctor Item Package'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { description: '', in: 'path', type: 'string' } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("Doctor Item Package Id"), - }); - - let param: any = await schema.validateAsync(req.params); - - let doctorItemPackage = await DoctorItemPackageModel.list({ "DoctorItemPackage.id": param.id }).then((q) => q.getOne()); - - if (!doctorItemPackage) throw { message: "Doctor Item Package " + Language.lang.failed_not_found }; - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_view, doctorItemPackage); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_not_found, err.message); - } - } - - static async update(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Doctor Item Package'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { description: '', in: 'path', type: 'string' } - #swagger.requestBody = { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/doctorItemPackage" } } } } - */ - const queryRunner = OrmHelper.DB.createQueryRunner(); - await queryRunner.startTransaction(); - - try { - req.body.id = req.params["id"]; - - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("Doctor Item Package ID"), - doctor_id: Joi.string().uuid().required().label("Doctor ID"), - name: Joi.string().required().max(256).label("Name"), - description: Joi.string().allow("", null).optional().label("Description"), - item_master_ids: Joi.array().items(Joi.string().uuid()).optional().label("Item Master IDs"), - active: Joi.bool().optional().label("Active"), - }); - - let param: any = await schema.validateAsync(req.body); - - const doctor = await OrmHelper.DB.getRepository(User).findOne({ where: { id: param.doctor_id } }); - if (!doctor) throw { message: "Doctor (User) " + Language.lang.failed_not_found }; - - let doctorItemPackage = await DoctorItemPackageModel.list({ "DoctorItemPackage.id": param.id }).then((q) => q.getOne()); - if (!doctorItemPackage) throw { message: "Doctor Item Package " + Language.lang.failed_not_found }; - - const exist = await DoctorItemPackageModel.list({ "Doctor.id": param.doctor_id, "DoctorItemPackage.name": param.name }).then((q) => q.getOne()); - if (exist && exist.id != param.id) throw { message: "Doctor Item Package " + Language.lang.failed_duplicate }; - - let items: ItemMaster[] = []; - if (param.item_master_ids && param.item_master_ids.length > 0) { - for (const itemMasterId of param.item_master_ids) { - const itemMaster = await OrmHelper.DB.getRepository(ItemMaster).findOne({ where: { id: itemMasterId } }); - if (!itemMaster) throw { message: "Item Master " + Language.lang.failed_not_found }; - items.push(itemMaster); - } - } - - doctorItemPackage.doctor = doctor; - doctorItemPackage.name = param.name; - doctorItemPackage.description = param.description || null; - doctorItemPackage.items = items; - if (typeof param.active === "boolean") { - doctorItemPackage.active = param.active; - } - doctorItemPackage.updated_by = req.auth.data.name; - await queryRunner.manager.save(doctorItemPackage); - - await queryRunner.commitTransaction(); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_update, doctorItemPackage); - } catch (e: unknown) { - await queryRunner.rollbackTransaction(); - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_update, err.message); - } finally { - await queryRunner.release(); - } - } - - static async delete(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Doctor Item Package'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { in: 'path', required: true, type: 'string' } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("ID"), - }); - - const param: { id: string } = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(DoctorItemPackage); - const affected = (await repo.delete({ id: param.id })).affected ?? 0; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_delete, err.message); - } - } -} diff --git a/src/controllers/doctor_schedule.ts b/src/controllers/doctor_schedule.ts deleted file mode 100644 index 866337a..0000000 --- a/src/controllers/doctor_schedule.ts +++ /dev/null @@ -1,279 +0,0 @@ -import { DoctorSchedule, Room, User, Paging } from "entity"; -import { NextFunction, Response } from "express"; -import { Request } from "express-jwt"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import CommonHelper from "../helpers/common"; -import { ReturnHelper } from "../helpers/express/return"; -import { Language } from "../langs/lang"; -import { DoctorScheduleModel } from "../model/doctor_schedule"; -import { OrmHelper } from "../helpers/orm"; -import moment from "moment"; - -const log: Logger = new Logger({ - name: "[DoctorScheduleController]", - type: "pretty", -}); - -export class DoctorScheduleController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Doctor Schedule'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['filter'] = { description: '', in: 'query', type: 'string' } - #swagger.parameters['limit'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['page'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['with_deleted'] = { in: 'query', required: true, type: 'boolean' } - #swagger.parameters['order_field'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['order_direction'] = { in: 'query', required: true, schema: { '@enum': ['ASC', 'DESC'] } } - */ - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().required().label("With Deleted"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").required().label("Order Direction"), - }); - - let param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await DoctorScheduleModel.list(filter); - - const offset = (param.page - 1) * param.limit; - let limit = param.limit; - - const res_count = query; - const res_list = query - .orderBy("DoctorSchedule." + param.order_field, param.order_direction) - .offset(offset) - .limit(limit); - - if (param.with_deleted) { - res_count.withDeleted(); - res_list.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Doctor Schedule'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.requestBody = { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/doctorSchedule" } } } } - */ - const queryRunner = OrmHelper.DB.createQueryRunner(); - await queryRunner.startTransaction(); - try { - const schema = Joi.object().keys({ - day: Joi.string().max(32).required().label("Day"), - start_time: Joi.string().max(16).required().label("Start Time"), - end_time: Joi.string().max(16).required().label("End Time"), - doctor_id: Joi.string().uuid().required().label("Doctor ID"), - room_id: Joi.string().uuid().required().label("Room ID"), - quota: Joi.string().max(32).allow("", null).optional().label("Quota"), - status: Joi.string().required().label("Status"), - }); - - let param: any = await schema.validateAsync(req.body); - - let room = await OrmHelper.DB.getRepository(Room).findOne({ where: { id: param.room_id } }); - if (!room) throw { message: "Room " + Language.lang.failed_not_found }; - - let doctor = await OrmHelper.DB.getRepository(User).findOne({ where: { id: param.doctor_id } }); - if (!doctor) throw { message: "Doctor (User) " + Language.lang.failed_not_found }; - - let doctorSchedule = new DoctorSchedule(); - doctorSchedule.day = param.day; - doctorSchedule.start_time = param.start_time; - doctorSchedule.end_time = param.end_time; - doctorSchedule.doctor = doctor; - doctorSchedule.room = room; - doctorSchedule.quota = param.quota || null; - doctorSchedule.status = param.status; - doctorSchedule.created_by = req.auth.data.name; - doctorSchedule.updated_by = req.auth.data.name; - await queryRunner.manager.save(doctorSchedule); - - await queryRunner.commitTransaction(); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, doctorSchedule); - } catch (e: unknown) { - await queryRunner.rollbackTransaction(); - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } finally { - await queryRunner.release(); - } - } - - static async detail(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Doctor Schedule'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { description: '', in: 'path', type: 'string' } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("Doctor Schedule Id"), - }); - - let param: any = await schema.validateAsync(req.params); - - let doctorSchedule = await DoctorScheduleModel.list({ "DoctorSchedule.id": param.id }).then((q) => q.getOne()); - - if (!doctorSchedule) throw { message: "Doctor Schedule Not Found" }; - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_view, doctorSchedule); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_not_found, err.message); - } - } - - static async update(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Doctor Schedule'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { description: '', in: 'path', type: 'string' } - #swagger.requestBody = { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/doctorSchedule" } } } } - */ - const queryRunner = OrmHelper.DB.createQueryRunner(); - await queryRunner.startTransaction(); - - try { - req.body.id = req.params["id"]; - - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("Doctor Schedule ID"), - day: Joi.string().max(32).required().label("Day"), - start_time: Joi.string().max(16).required().label("Start Time"), - end_time: Joi.string().max(16).required().label("End Time"), - doctor_id: Joi.string().uuid().required().label("Doctor ID"), - room_id: Joi.string().uuid().required().label("Room ID"), - quota: Joi.string().max(32).allow("", null).optional().label("Quota"), - status: Joi.string().required().label("Status"), - }); - - let param: any = await schema.validateAsync(req.body); - - let room = await OrmHelper.DB.getRepository(Room).findOne({ where: { id: param.room_id } }); - if (!room) throw { message: "Room " + Language.lang.failed_not_found }; - - let doctor = await OrmHelper.DB.getRepository(User).findOne({ where: { id: param.doctor_id } }); - if (!doctor) throw { message: "Doctor (User) " + Language.lang.failed_not_found }; - - let doctorSchedule = await DoctorScheduleModel.list({ "DoctorSchedule.id": param.id }).then((q) => q.getOne()); - - if (!doctorSchedule) throw { message: "Doctor Schedule " + Language.lang.failed_not_found }; - - doctorSchedule.day = param.day; - doctorSchedule.start_time = param.start_time; - doctorSchedule.end_time = param.end_time; - doctorSchedule.doctor = doctor; - doctorSchedule.room = room; - doctorSchedule.quota = param.quota || null; - doctorSchedule.status = param.status; - doctorSchedule.updated_by = req.auth.data.name; - await queryRunner.manager.save(doctorSchedule); - - await queryRunner.commitTransaction(); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_update, doctorSchedule); - } catch (e: unknown) { - await queryRunner.rollbackTransaction(); - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } finally { - await queryRunner.release(); - } - } - - static async delete(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Doctor Schedule'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { in: 'path', required: true, type: 'string' } - #swagger.parameters['hard'] = { in: 'path', description: 'Is Hard Delete', required: false, type: 'boolean' } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("ID"), - hard: Joi.bool().optional().allow("").label("Is hard delete?"), - }); - - const param: { id: string; hard: boolean } = await schema.validateAsync(req.params); - - let affected = 0; - if (!param.hard) { - let doctorSchedule: DoctorSchedule = await DoctorScheduleModel.list({ "DoctorSchedule.id": param.id }).then((q) => q.getOne()); - - if (!doctorSchedule) throw { message: "Doctor Schedule " + Language.lang.failed_not_found }; - - doctorSchedule.deleted_by = req.auth.data.name; - doctorSchedule.deleted_at = moment().toDate(); - await OrmHelper.DB.manager.save(doctorSchedule); - affected = 1; - } else { - const repo = OrmHelper.DB.getRepository(DoctorSchedule); - affected = (await repo.delete({ id: param.id })).affected ?? 0; - } - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_delete, err.message); - } - } - - static async restore(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Doctor Schedule'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { in: 'path', required: true, type: 'string' } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("ID"), - }); - - const param: any = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(DoctorSchedule); - - const affected = (await repo.restore({ id: param.id })).affected ?? 0; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_restore, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_restore, err.message); - } - } -} diff --git a/src/controllers/examination_detail.ts b/src/controllers/examination_detail.ts deleted file mode 100644 index 0b8fa19..0000000 --- a/src/controllers/examination_detail.ts +++ /dev/null @@ -1,301 +0,0 @@ -import { ExaminationDetail, Paging } from "entity"; -import { NextFunction, Response } from "express"; -import { Request } from "express-jwt"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import CommonHelper from "../helpers/common"; -import { ReturnHelper } from "../helpers/express/return"; -import { Language } from "../langs/lang"; -import { ExaminationDetailModel } from "../model/examination_detail"; -import { MeasurementUnitModel } from "../model/measurement_unit"; -import { ReferenceRangeModel } from "../model/reference_range"; -import { OrmHelper } from "../helpers/orm"; -import moment from "moment"; - -const log: Logger = new Logger({ - name: "[ExaminationDetailController]", - type: "pretty", -}); - -export class ExaminationDetailController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Examination Detail'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['filter'] = { description: 'Filter: plain text or JSON object (name, order_no, etc.)', in: 'query', type: 'string' } - #swagger.parameters['limit'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['page'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['with_deleted'] = { in: 'query', required: true, type: 'boolean' } - #swagger.parameters['order_field'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['order_direction'] = { in: 'query', required: true, schema: { '@enum': ['ASC', 'DESC'] } } - */ - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().required().label("With Deleted"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").required().label("Order Direction"), - }); - - let param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await ExaminationDetailModel.list(filter); - - const offset = (param.page - 1) * param.limit; - let limit = param.limit; - - const res_count = query.clone(); - const res_ids = query - .clone() - .select("ExaminationDetail.id", "id") - .orderBy("ExaminationDetail." + param.order_field, param.order_direction) - .offset(offset) - .limit(limit); - - if (param.with_deleted) { - res_count.withDeleted(); - res_ids.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const ids = (await res_ids.getRawMany()).map((r: any) => r.id).filter(Boolean); - - let list_data: any[] = []; - if (ids.length > 0) { - const res_list = OrmHelper.DB.getRepository(ExaminationDetail) - .createQueryBuilder("ExaminationDetail") - .leftJoinAndSelect("ExaminationDetail.measurement_unit", "measurementUnit") - .leftJoinAndSelect("ExaminationDetail.reference_range", "referenceRange") - .where("ExaminationDetail.id IN (:...ids)", { ids }) - .orderBy("ExaminationDetail." + param.order_field, param.order_direction); - - if (param.with_deleted) { - res_list.withDeleted(); - } - - list_data = await res_list.getMany(); - } - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Examination Detail'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.requestBody = { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/examinationDetail" } } } } - */ - const queryRunner = OrmHelper.DB.createQueryRunner(); - await queryRunner.startTransaction(); - try { - const schema = Joi.object().keys({ - name: Joi.string().max(256).required().label("Name"), - order_no: Joi.string().max(256).required().label("Order No."), - measurement_unit_id: Joi.string().uuid().required().label("Measurement Unit ID"), - reference_range_ids: Joi.array().items(Joi.string().uuid()).min(1).required().label("Reference Range IDs"), - status: Joi.string().required().label("Status"), - }); - - let param: any = await schema.validateAsync(req.body); - - let measurementUnit = await MeasurementUnitModel.list({ "MeasurementUnit.id": param.measurement_unit_id }).then((q) => q.getOne()); - if (!measurementUnit) throw { message: "Measurement Unit not found" }; - - const referenceRanges = await Promise.all( - param.reference_range_ids.map(async (id: string) => { - const rr = await ReferenceRangeModel.list({ "ReferenceRange.id": id }).then((q) => q.getOne()); - if (!rr) throw { message: `Reference Range ${id} not found` }; - return rr; - }) - ); - - let examinationDetail = new ExaminationDetail(); - examinationDetail.name = param.name; - examinationDetail.order_no = param.order_no; - examinationDetail.measurement_unit = measurementUnit; - examinationDetail.reference_range = referenceRanges; - examinationDetail.status = param.status; - examinationDetail.created_by = req.auth?.data.name; - examinationDetail.updated_by = req.auth?.data.name; - await queryRunner.manager.save(examinationDetail); - - await queryRunner.commitTransaction(); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, examinationDetail); - } catch (e: unknown) { - await queryRunner.rollbackTransaction(); - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } finally { - await queryRunner.release(); - } - } - - static async detail(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Examination Detail'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { in: 'path', type: 'string' } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("Examination Detail Id"), - }); - - let param: any = await schema.validateAsync(req.params); - - let examinationDetail = await ExaminationDetailModel.list({ "ExaminationDetail.id": param.id }).then((q) => q.leftJoinAndSelect("ExaminationDetail.measurement_unit", "measurementUnit").leftJoinAndSelect("ExaminationDetail.reference_range", "referenceRange").getOne()); - - if (!examinationDetail) throw { message: "Examination Detail Not Found" }; - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_view, examinationDetail); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_not_found, err.message); - } - } - - static async update(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Examination Detail'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { in: 'path', type: 'string' } - #swagger.requestBody = { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/examinationDetail" } } } } - */ - const queryRunner = OrmHelper.DB.createQueryRunner(); - await queryRunner.startTransaction(); - - try { - req.body.id = req.params["id"]; - - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("Examination Detail ID"), - name: Joi.string().max(256).required().label("Name"), - order_no: Joi.string().max(256).required().label("Order No."), - measurement_unit_id: Joi.string().uuid().required().label("Measurement Unit ID"), - reference_range_ids: Joi.array().items(Joi.string().uuid()).min(1).required().label("Reference Range IDs"), - status: Joi.string().required().label("Status"), - }); - - let param: any = await schema.validateAsync(req.body); - - let examinationDetail = await ExaminationDetailModel.list({ "ExaminationDetail.id": param.id }).then((q) => q.getOne()); - - if (!examinationDetail) throw { message: "Examination Detail " + Language.lang.failed_not_found }; - - let measurementUnit = await MeasurementUnitModel.list({ "MeasurementUnit.id": param.measurement_unit_id }).then((q) => q.getOne()); - if (!measurementUnit) throw { message: "Measurement Unit not found" }; - - const referenceRanges = await Promise.all( - param.reference_range_ids.map(async (id: string) => { - const rr = await ReferenceRangeModel.list({ "ReferenceRange.id": id }).then((q) => q.getOne()); - if (!rr) throw { message: `Reference Range ${id} not found` }; - return rr; - }) - ); - - examinationDetail.name = param.name; - examinationDetail.order_no = param.order_no; - examinationDetail.measurement_unit = measurementUnit; - examinationDetail.reference_range = referenceRanges; - examinationDetail.status = param.status; - examinationDetail.updated_by = req.auth?.data.name; - await queryRunner.manager.save(examinationDetail); - - await queryRunner.commitTransaction(); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_update, examinationDetail); - } catch (e: unknown) { - await queryRunner.rollbackTransaction(); - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } finally { - await queryRunner.release(); - } - } - - static async delete(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Examination Detail'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { in: 'path', required: true, type: 'string' } - #swagger.parameters['hard'] = { in: 'path', description: 'Is Hard Delete', required: false, type: 'boolean' } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("ID"), - hard: Joi.bool().optional().allow("").label("Is hard delete?"), - }); - - const param: { id: string; hard: boolean } = await schema.validateAsync(req.params); - - let affected = 0; - if (!param.hard) { - let examinationDetail: ExaminationDetail = await ExaminationDetailModel.list({ "ExaminationDetail.id": param.id }).then((q) => q.getOne()); - - if (!examinationDetail) throw { message: "Examination Detail " + Language.lang.failed_not_found }; - - examinationDetail.deleted_by = req.auth?.data.name; - examinationDetail.deleted_at = moment().toDate(); - await OrmHelper.DB.manager.save(examinationDetail); - affected = 1; - } else { - const repo = OrmHelper.DB.getRepository(ExaminationDetail); - affected = (await repo.delete({ id: param.id })).affected ?? 0; - } - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_delete, err.message); - } - } - - static async restore(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Examination Detail'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { in: 'path', required: true, type: 'string' } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("ID"), - }); - - const param: any = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(ExaminationDetail); - - const affected = (await repo.restore({ id: param.id })).affected ?? 0; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_restore, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_restore, err.message); - } - } -} \ No newline at end of file diff --git a/src/controllers/examination_type.ts b/src/controllers/examination_type.ts deleted file mode 100644 index 01635fd..0000000 --- a/src/controllers/examination_type.ts +++ /dev/null @@ -1,276 +0,0 @@ -import { ExaminationType, Paging, Service } from "entity"; -import { NextFunction, Response } from "express"; -import { Request } from "express-jwt"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import CommonHelper from "../helpers/common"; -import { ReturnHelper } from "../helpers/express/return"; -import { Language } from "../langs/lang"; -import { ExaminationTypeModel } from "../model/examination_type"; -import { ServiceModel } from "../model/service"; -import { OrmHelper } from "../helpers/orm"; -import moment from "moment"; -import { In } from "typeorm"; - -const log: Logger = new Logger({ - name: "[ExaminationTypeController]", - type: "pretty", -}); - -export class ExaminationTypeController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Examination Type'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['filter'] = { description: 'Filter: plain text or JSON object (name, status, etc.)', in: 'query', type: 'string' } - #swagger.parameters['limit'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['page'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['with_deleted'] = { in: 'query', required: true, type: 'boolean' } - #swagger.parameters['order_field'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['order_direction'] = { in: 'query', required: true, schema: { '@enum': ['ASC', 'DESC'] } } - */ - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().required().label("With Deleted"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").required().label("Order Direction"), - }); - - let param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await ExaminationTypeModel.list(filter); - - const offset = (param.page - 1) * param.limit; - let limit = param.limit; - - const res_count = query; - const res_list = query - .leftJoinAndSelect("ExaminationType.services", "services") - .orderBy("ExaminationType." + param.order_field, param.order_direction) - .offset(offset) - .limit(limit) - - if (param.with_deleted) { - res_count.withDeleted(); - res_list.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Examination Type'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.requestBody = { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/examinationType" } } } } - */ - const queryRunner = OrmHelper.DB.createQueryRunner(); - await queryRunner.startTransaction(); - try { - const schema = Joi.object().keys({ - name: Joi.string().max(256).required().label("Name"), - status: Joi.string().required().label("Status"), - service_ids: Joi.array().items(Joi.string().uuid()).optional().label("Service IDs"), - }); - - let param: any = await schema.validateAsync(req.body); - - let filter = { name: param.name }; - let exist = await ExaminationTypeModel.list(filter).then((q) => q.getOne()); - if (exist) throw { message: "Examination Type " + Language.lang.failed_duplicate }; - - let services: Service[] = []; - if (param.service_ids && param.service_ids.length > 0) { - services = await queryRunner.manager.getRepository(Service).find({ where: { id: In(param.service_ids) } }); - if (services.length != param.service_ids.length) throw { message: "Service not found" }; - } - - let examinationType = new ExaminationType(); - examinationType.name = param.name; - examinationType.status = param.status; - examinationType.services = services; - examinationType.created_by = req.auth.data.name; - examinationType.updated_by = req.auth.data.name; - await queryRunner.manager.save(examinationType); - - await queryRunner.commitTransaction(); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, examinationType); - } catch (e: unknown) { - await queryRunner.rollbackTransaction(); - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } finally { - await queryRunner.release(); - } - } - - static async detail(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Examination Type'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { in: 'path', type: 'string' } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("Examination Type Id"), - }); - - let param: any = await schema.validateAsync(req.params); - - let examinationType = await ExaminationTypeModel.list({ "ExaminationType.id": param.id }) - .then((q) => q.leftJoinAndSelect("ExaminationType.services", "services").getOne()); - - if (!examinationType) throw { message: "Examination Type Not Found" }; - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_view, examinationType); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_not_found, err.message); - } - } - - static async update(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Examination Type'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { in: 'path', type: 'string' } - #swagger.requestBody = { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/examinationType" } } } } - */ - const queryRunner = OrmHelper.DB.createQueryRunner(); - await queryRunner.startTransaction(); - - try { - req.body.id = req.params["id"]; - - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("Examination Type ID"), - name: Joi.string().max(256).required().label("Name"), - status: Joi.string().required().label("Status"), - service_ids: Joi.array().items(Joi.string().uuid()).optional().label("Service IDs"), - }); - - let param: any = await schema.validateAsync(req.body); - - let filter = { name: param.name }; - let exist = await ExaminationTypeModel.list(filter).then((q) => q.getOne()); - if (exist && exist.id != param.id) throw { message: "Examination Type " + Language.lang.failed_duplicate }; - - let examinationType = await ExaminationTypeModel.list({ "ExaminationType.id": param.id }) - .then((q) => q.leftJoinAndSelect("ExaminationType.services", "services").getOne()); - - if (!examinationType) throw { message: "Examination Type " + Language.lang.failed_not_found }; - - let services: Service[] = []; - if (param.service_ids && param.service_ids.length > 0) { - services = await queryRunner.manager.getRepository(Service).find({ where: { id: In(param.service_ids) } }); - if (services.length != param.service_ids.length) throw { message: "Service not found" }; - } - - examinationType.name = param.name; - examinationType.status = param.status; - examinationType.services = services; - examinationType.updated_by = req.auth.data.name; - await queryRunner.manager.save(examinationType); - - await queryRunner.commitTransaction(); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_update, examinationType); - } catch (e: unknown) { - await queryRunner.rollbackTransaction(); - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } finally { - await queryRunner.release(); - } - } - - static async delete(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Examination Type'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { in: 'path', required: true, type: 'string' } - #swagger.parameters['hard'] = { in: 'path', description: 'Is Hard Delete', required: false, type: 'boolean' } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("ID"), - hard: Joi.bool().optional().allow("").label("Is hard delete?"), - }); - - const param: { id: string; hard: boolean } = await schema.validateAsync(req.params); - - let affected = 0; - if (!param.hard) { - let examinationType: ExaminationType = await ExaminationTypeModel.list({ "ExaminationType.id": param.id }).then((q) => q.getOne()); - - if (!examinationType) throw { message: "Examination Type " + Language.lang.failed_not_found }; - - examinationType.deleted_by = req.auth.data.name; - examinationType.deleted_at = moment().toDate(); - await OrmHelper.DB.manager.save(examinationType); - affected = 1; - } else { - const repo = OrmHelper.DB.getRepository(ExaminationType); - affected = (await repo.delete({ id: param.id })).affected ?? 0; - } - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_delete, err.message); - } - } - - static async restore(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Examination Type'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { in: 'path', required: true, type: 'string' } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("ID"), - }); - - const param: any = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(ExaminationType); - - const affected = (await repo.restore({ id: param.id })).affected ?? 0; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_restore, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_restore, err.message); - } - } -} diff --git a/src/controllers/faretype.ts b/src/controllers/faretype.ts deleted file mode 100644 index 6cb5237..0000000 --- a/src/controllers/faretype.ts +++ /dev/null @@ -1,395 +0,0 @@ -import { Response, NextFunction, Application } from "express"; -import { Request } from "express-jwt"; -import { ReturnHelper } from "../helpers/express/return"; -import { OrmHelper } from "../helpers/orm"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import { Language } from "../langs/lang"; -import { Paging } from "entity"; -import CommonHelper from "../helpers/common"; -import * as fastcsv from 'fast-csv'; -import dayjs from "dayjs"; -import { FareType } from "entity"; - -const log: Logger = new Logger({ name: '[FareTypeController]', type: 'pretty' }); - -export class FareTypeController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Fare Type'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['filter'] = { - description: '', - in: 'query', - type: 'string' - } - #swagger.parameters['limit'] = { - in: 'query', - required: true, - type: 'number' - } - #swagger.parameters['page'] = { - in: 'query', - required: true, - type: 'number' - } - #swagger.parameters['with_deleted'] = { - in: 'query', - required: true, - type: 'boolean' - } - #swagger.parameters['order_field'] = { - in: 'query', - required: true, - type: 'string' - } - #swagger.parameters['order_direction'] = { - in: 'query', - required: true, - schema: { - '@enum': ['ASC', 'DESC'] - } - } - */ - - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow('').optional().label('Filter'), - page: Joi.number().required().min(1).label('Page'), - limit: Joi.number().required().min(1).label('Limit'), - with_deleted: Joi.bool().required().label('With Deleted'), - order_field: Joi.string().required().label('Order Field'), - order_direction: Joi.string().allow('asc', 'desc').required().label('Order Direction'), - }); - - const param: Paging = await schema.validateAsync(req.query); - - const repo = OrmHelper.DB.getRepository(FareType); - - const offset = (param.page - 1) * param.limit - - const filterObj = param.filter ? JSON.parse(param.filter) : {}; - const filterAny = filterObj.any && filterObj.any !== "" ? String(filterObj.any) : ""; - // Remove foreign key from filter for CommonHelper.handleFilter - const filterWithoutFK = { ...filterObj }; - delete filterWithoutFK.any; - delete filterWithoutFK.munisipo_id; - const filterStrWithoutFK = JSON.stringify(filterWithoutFK); - - // const { whereAttr, whereVal } = CommonHelper.handleFilter({ - // filter: filterStrWithoutFK, - // col_any_eq: ['code'], - // col_any_like: ['name'] - // }); - - const res_count = repo.createQueryBuilder("FareType") - // .leftJoin("Administrativu.munisipo", "munisipo") - // .where(whereAttr || "1=1", whereVal); - - // Handle foreign key filter with relation - // if (filterObj.munisipo_id) { - // res_count.andWhere("munisipo.id = :munisipoId", { munisipoId: filterObj.munisipo_id }); - // } - - if (filterAny !== "") { - res_count.andWhere("FareType.name ILIKE :any", { - any: filterAny.includes("%") ? filterAny : `%${filterAny}%` - }); - } - - const res_list = repo.createQueryBuilder("FareType") - // .leftJoin("Administrativu.munisipo", "munisipo") - // .where(whereAttr || "1=1", whereVal) - .orderBy("FareType." + param.order_field, param.order_direction) - .offset(offset) - .limit(param.limit); - - // Handle foreign key filter with relation - // if (filterObj.munisipo_id) { - // res_list.andWhere("munisipo.id = :munisipoId", { munisipoId: filterObj.munisipo_id }); - // } - - if (filterAny !== "") { - res_list.andWhere("FareType.name ILIKE :any", { - any: filterAny.includes("%") ? filterAny : `%${filterAny}%` - }); - } - - if (param.with_deleted) { - res_count.withDeleted(); - res_list.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async option(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Fare Type'] - #swagger.security = [{ - "bearerAuth": [] - }] - */ - - try { - const repo = OrmHelper.DB.getRepository(FareType); - const res_count = repo.createQueryBuilder("FareType") - // .leftJoin("Administrativu.munisipo", "munisipo") - // .where(whereAttr || "1=1", whereVal); - - // Handle foreign key filter with relation - // if (filterObj.munisipo_id) { - // res_count.andWhere("munisipo.id = :munisipoId", { munisipoId: filterObj.munisipo_id }); - // } - - const res_list = repo.createQueryBuilder("FareType").orderBy("FareType.name", "ASC"); - - // Handle foreign key filter with relation - // if (filterObj.munisipo_id) { - // res_list.andWhere("munisipo.id = :munisipoId", { munisipoId: filterObj.munisipo_id }); - // } - - const current_page = 1; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Fare Type'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/faretype" - } - } - } - } - */ - - try { - const schema = Joi.object().keys({ - name: Joi.string().required().label('Name'), - }); - - const param: any = await schema.validateAsync(req.body); - - const data = new FareType() - data.name = param.name - await OrmHelper.DB.manager.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 401, Language.lang.failed_insert, err.message); - } - } - - static async detail(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Fare Type'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'Fare Type ID.', - required: true, - type: 'string' - } - - */ - - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID'), - }); - - req.body.id = req.params['id']; - - const param: any = await schema.validateAsync(req.body); - - const repo = OrmHelper.DB.getRepository(FareType); - - const data = await repo.findOneBy({ id: param.id }); - - if (data != null) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_view, { name: data.name }); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_view, err.message); - } - } - - static async update(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Fare Type'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'Fare Type ID.', - required: true, - type: 'string' - } - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/faretype" - } - } - } - } - */ - - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID'), - name: Joi.string().required().label('Name'), - }); - - req.body.id = req.params['id']; - - const param: any = await schema.validateAsync(req.body); - - const repo = OrmHelper.DB.getRepository(FareType); - - const data = await repo.findOneBy({ id: param.id }); - - if (data != null) { - data.name = param.name - await repo.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_update, data); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_update, err.message); - } - } - - static async delete(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Fare Type'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'Fare Type ID.', - required: true, - type: 'string' - } - #swagger.parameters['hard'] = { - in: 'path', - description: 'Is Hard Delete', - required: false, - type: 'boolean' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID'), - hard: Joi.bool().optional().allow('').label('Is hard delete?') - }); - - const param: { id: string, hard: boolean } = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(FareType); - - const affected = (!param.hard ? await repo.softDelete({ id: param.id }) : await repo.delete({ id: param.id })).affected; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_delete, err.message); - } - } - - static async restore(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Fare Type'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.parameters['id'] = { - in: 'path', - description: 'Fare Type ID.', - required: true, - type: 'string' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID') - }); - - const param: FareType = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(FareType); - - const affected = (await repo.restore({ id: param.id })).affected; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_restore, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_restore, err.message); - } - } -} \ No newline at end of file diff --git a/src/controllers/file/file.ts b/src/controllers/file/file.ts deleted file mode 100644 index 18862b5..0000000 --- a/src/controllers/file/file.ts +++ /dev/null @@ -1,226 +0,0 @@ -import { NextFunction, Response } from "express"; -import { Request } from "express-jwt"; -import { UploadedFile } from "express-fileupload"; -import fs from "fs"; // Import fs module to check if directory exists -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import CommonHelper from "../../helpers/common"; -import { ReturnHelper } from "../../helpers/express/return"; -import { Language } from "../../langs/lang"; -import config from "config"; -import Thirdparty from "../../helpers/thirdparty"; -import JwtHelper from "../../helpers/jwt"; - -const log: Logger = new Logger({ - name: "[FileController]", - type: "pretty", -}); - -export class FileController { - static async upload(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['File'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.requestBody = { - required: true, - content: { - "multipart/form-data": { - schema: { - type: "object", - properties: { - file: { - type: "string", - format: "binary" - } - } - } - } - } - } - } - */ - try { - const uploadedFile: UploadedFile | any = req.files.file; - - const schema = Joi.object({ - file: Joi.object({ - name: Joi.string().label("File Name"), - mimetype: Joi.string() - .valid( - "image/jpeg", - "image/png", - "image/webp", - "application/pdf", - "application/vnd.ms-excel", // ✅ .xls - "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", // ✅ .xlsx - "application/vnd.openxmlformats-officedocument.wordprocessingml.document", - "text/csv", // csv - ) - .optional() - .label("File Type"), - size: Joi.number() - .max(10 * 1024 * 1024) - .optional() - .label("File Size"), - }) - .optional() - .label("File"), - }); - - const fileData = { - name: uploadedFile.name, - mimetype: uploadedFile.mimetype, - size: uploadedFile.size, - }; - - let body = await schema.validateAsync({ file: fileData }); - - const field = { - file: uploadedFile, - application: "saude", - }; - - let url = config.get("service.file") + "upload"; - let result = await Thirdparty.UploadFile(url, field, JwtHelper.token(req.auth.data)); - console.log("result :", result); - - let data = { file: result.data.file }; - return ReturnHelper.successResponseAny(res, 200, Language.lang.success, data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async delete(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['File'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - type: "object", - properties: { - file: { - type: "string", - description: "File name returned from upload" - } - }, - required: ["file"] - } - } - } - } - } - */ - try { - const schema = Joi.object({ - file: Joi.string().required().label("File"), - }); - - const param = await schema.validateAsync(req.body); - - if (param.file.includes("..") || param.file.includes("/") || param.file.includes("\\")) { - return ReturnHelper.errorResponse(res, 400, 400, Language.lang.failed_delete, "Invalid file name"); - } - - const field = { - file: param.file, - application: "saude", - }; - - let url = config.get("service.file") + "delete"; - await Thirdparty.DeleteFile(url, field, JwtHelper.token(req.auth.data)); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_delete, err.message); - } - } - - static async download(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['File'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['name'] = { - in: 'query', - type: 'string' - } - #swagger.parameters['token'] = { - in: 'query', - required: true, - type: 'string' - } - */ - try { - // 1️⃣ Validasi parameter - const schema = Joi.object({ - name: Joi.string().required().label("File Name"), - token: Joi.string().required().label("Token"), - }); - - const param = await schema.validateAsync(req.query); - - // 2️⃣ Ambil file dari service-file via SFTP (bukan static URL /file/ yang diarahkan ke frontend) - const url = config.get("service.file") + "download"; - const buffer = await Thirdparty.DownloadFile(url, { file: param.name, application: "saude" }, param.token); - - // 3️⃣ Deteksi ekstensi & MIME type - const fileName = param.name; - const ext = fileName.split(".").pop()?.toLowerCase(); - - const mimeMap: Record = { - xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", - xls: "application/vnd.ms-excel", - csv: "text/csv", - pdf: "application/pdf", - jpg: "image/jpeg", - jpeg: "image/jpeg", - png: "image/png", - webp: "image/webp", - gif: "image/gif", - doc: "application/msword", - docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document", - zip: "application/zip", - txt: "text/plain", - }; - - const contentType = mimeMap[ext ?? ""] ?? "application/octet-stream"; - - // 4️⃣ Set header tipe file - res.setHeader("Content-Type", contentType); - res.setHeader("Content-Length", buffer.length); - - // 5️⃣ Tentukan apakah file perlu auto download - const isInline = contentType.startsWith("image/") || contentType === "application/pdf"; - - // 🟢 Kalau image/pdf → tampil di browser - // 🔵 Kalau file lain → download otomatis - if (isInline) { - res.setHeader("Content-Disposition", `inline; filename="${encodeURIComponent(fileName)}"`); - } else { - res.setHeader("Content-Disposition", `attachment; filename="${encodeURIComponent(fileName)}"`); - } - - // 6️⃣ Kirim file ke browser - return res.end(buffer); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_not_found, err.message); - } - } -} diff --git a/src/controllers/fostercarehistory.ts b/src/controllers/fostercarehistory.ts deleted file mode 100644 index 0e227e2..0000000 --- a/src/controllers/fostercarehistory.ts +++ /dev/null @@ -1,557 +0,0 @@ -import { Diagnosis, FosterCareHistory, Paging } from "entity"; -import { NextFunction, Response } from "express"; -import { Request } from "express-jwt"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import { Brackets } from "typeorm"; -import { validate as validateUuid } from "uuid"; -import CommonHelper from "../helpers/common"; -import { ReturnHelper } from "../helpers/express/return"; -import { Language } from "../langs/lang"; -import { FosterCareHistoryModel } from "../model/fostercarehistory"; -import { OrmHelper } from "../helpers/orm"; -import moment from "moment"; - -const log: Logger = new Logger({ - name: "[FosterCareHistoryController]", - type: "pretty", -}); - -export class FosterCareHistoryController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Foster Care History'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['filter'] = { - description: 'Filter: JSON object; FosterCareHistory.code and FosterCareHistory.diagnosis are combined with OR; other fields use AND.', - in: 'query', - type: 'string', - } - #swagger.parameters['limit'] = { - in: 'query', - required: true, - type: 'number' - } - #swagger.parameters['page'] = { - in: 'query', - required: true, - type: 'number' - } - #swagger.parameters['with_deleted'] = { - in: 'query', - required: true, - type: 'boolean' - } - #swagger.parameters['order_field'] = { - in: 'query', - required: true, - type: 'string' - } - #swagger.parameters['order_direction'] = { - in: 'query', - required: true, - schema: { - '@enum': ['ASC', 'DESC'] - } - } - */ - - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().required().label("With Deleted"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").required().label("Order Direction"), - }); - - let param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - const codeKey = "FosterCareHistory.code"; - const diagnosisKey = "FosterCareHistory.diagnosis"; - const orCode = filter[codeKey]; - const orDiagnosis = filter[diagnosisKey]; - const restFilter = { ...filter }; - delete restFilter[codeKey]; - delete restFilter[diagnosisKey]; - - var query = await FosterCareHistoryModel.list(restFilter); - - if (orCode !== undefined || orDiagnosis !== undefined) { - query.andWhere( - new Brackets((qb) => { - let isFirst = true; - const addOr = (column: string, paramKey: string, raw: any) => { - const op = isFirst ? "where" : "orWhere"; - isFirst = false; - if (Array.isArray(raw)) { - (qb as any)[op](`${column} IN (:...${paramKey})`, { [paramKey]: raw }); - return; - } - const f = String(raw); - if (validateUuid(f)) { - (qb as any)[op](`${column} = :${paramKey}`, { [paramKey]: f }); - return; - } - if (f === "null") { - (qb as any)[op](`${column} IS NULL`); - return; - } - if (f.includes("%")) { - (qb as any)[op](`${column} ILIKE :${paramKey}`, { [paramKey]: f }); - return; - } - (qb as any)[op](`${column} = :${paramKey}`, { [paramKey]: f }); - }; - if (orCode !== undefined) addOr("FosterCareHistory.code", "diag_or_code", orCode); - if (orDiagnosis !== undefined) addOr("FosterCareHistory.diagnosis", "diag_or_diagnosis", orDiagnosis); - }), - ); - } - - const offset = (param.page - 1) * param.limit; - let limit = param.limit; - - const res_count = query; - const res_list = query - .orderBy("FosterCareHistory." + param.order_field, param.order_direction) - .offset(offset) - .limit(limit); - - if (param.with_deleted) { - res_count.withDeleted(); - res_list.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Foster Care History'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/fostercarehistory" - } - } - } - } - */ - const queryRunner = OrmHelper.DB.createQueryRunner(); - await queryRunner.startTransaction(); - try { - const schema = Joi.object().keys({ - diagnosis: Joi.string().max(256).required().label("Diagnosis"), - code: Joi.string().max(128).required().label("Code"), - status: Joi.string().required().label("Status"), - category: Joi.string().max(128).allow(null, "").label("Category"), - subcategory: Joi.string().max(128).allow(null, "").label("Subcategory"), - definition: Joi.string().max(128).allow(null, "").label("Definition"), - objective: Joi.string().max(128).allow(null, "").label("Objective"), - result_criteria: Joi.array().items( - Joi.object({ - group: Joi.number().allow(null), - name: Joi.string().allow(null, ""), - }) - ).allow(null).label("Result Criteria"), - causes: Joi.array().items( - Joi.object({ - group: Joi.string().allow(null, ""), - name: Joi.string().allow(null, ""), - }) - ).allow(null).label("Causes"), - related_clinical_condition: Joi.array().items( - Joi.object({ - name: Joi.string().allow(null, ""), - }) - ).allow(null).label("Related Clinical Condition"), - subjective_major: Joi.array().items( - Joi.object({ - group: Joi.string().allow(null, ""), - name: Joi.string().allow(null, ""), - }) - ).allow(null).label("Subjective Major"), - objectitve_major: Joi.array().items( - Joi.object({ - group: Joi.string().allow(null, ""), - name: Joi.string().allow(null, ""), - }) - ).allow(null).label("Objective Major"), - subjective_minor: Joi.array().items( - Joi.object({ - group: Joi.string().allow(null, ""), - name: Joi.string().allow(null, ""), - }) - ).allow(null).label("Subjective Minor"), - objective_minor: Joi.array().items( - Joi.object({ - group: Joi.string().allow(null, ""), - name: Joi.string().allow(null, ""), - }) - ).allow(null).label("Objective Minor"), - observation: Joi.array().items( - Joi.object({ - name: Joi.string().allow(null, ""), - }) - ).allow(null).label("Observation"), - therapeutic: Joi.array().items( - Joi.object({ - name: Joi.string().allow(null, ""), - }) - ).allow(null).label("Therapeutic"), - education: Joi.array().items( - Joi.object({ - name: Joi.string().allow(null, ""), - }) - ).allow(null).label("Education"), - colaboration: Joi.array().items( - Joi.object({ - name: Joi.string().allow(null, ""), - }) - ).allow(null).label("Colaboration"), - }); - - let param: any = await schema.validateAsync(req.body); - - let filter = { - code: param.code, - }; - let exist = await FosterCareHistoryModel.list(filter).then((q) => q.getOne()); - if (exist) throw { message: "Diagnosis " + Language.lang.failed_duplicate }; - - let fostercarehistory = new FosterCareHistory(); - fostercarehistory.diagnosis = param.diagnosis; - fostercarehistory.code = param.code; - fostercarehistory.status = param.status; - fostercarehistory.category = param.category; - fostercarehistory.subcategory = param.subcategory; - fostercarehistory.definition = param.definition; - fostercarehistory.objective = param.objective; - fostercarehistory.result_criteria = param.result_criteria ?? []; - fostercarehistory.causes = param.causes ?? []; - fostercarehistory.related_clinical_condition = param.related_clinical_condition ?? []; - fostercarehistory.subjective_major = param.subjective_major ?? []; - fostercarehistory.objectitve_major = param.objectitve_major ?? []; - fostercarehistory.subjective_minor = param.subjective_minor ?? []; - fostercarehistory.objective_minor = param.objective_minor ?? []; - fostercarehistory.observation = param.observation ?? []; - fostercarehistory.therapeutic = param.therapeutic ?? []; - fostercarehistory.education = param.education ?? []; - fostercarehistory.colaboration = param.colaboration ?? []; - fostercarehistory.created_by = req.auth?.data.name; - fostercarehistory.updated_by = req.auth?.data.name; - await queryRunner.manager.save(fostercarehistory); - - await queryRunner.commitTransaction(); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, fostercarehistory); - } catch (e: unknown) { - await queryRunner.rollbackTransaction(); - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } finally { - await queryRunner.release(); - } - } - - static async detail(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Foster Care History'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - description:'', - in: 'path', - type: 'string' - } - */ - - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("Foster Care History Id"), - }); - - let param: any = await schema.validateAsync(req.params); - - let fostercarehistory = await FosterCareHistoryModel.list({ - "FosterCareHistory.id": param.id, - }).then((q) => q.getOne()); - - if (!fostercarehistory) throw { message: "Foster Care History Not Found" }; - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_view, fostercarehistory); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_not_found, err.message); - } - } - - static async update(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Foster Care History'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - description:'', - in: 'path', - type: 'string' - } - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/fostercarehistory" - } - } - } - } - */ - - const queryRunner = OrmHelper.DB.createQueryRunner(); - await queryRunner.startTransaction(); - - try { - req.body.id = req.params["id"]; - - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("Diagnosis ID"), - diagnosis: Joi.string().max(256).required().label("Diagnosis"), - code: Joi.string().max(128).required().label("Code"), - status: Joi.string().required().label("Status"), - category: Joi.string().max(128).allow(null, "").label("Category"), - subcategory: Joi.string().max(128).allow(null, "").label("Subcategory"), - definition: Joi.string().max(128).allow(null, "").label("Definition"), - objective: Joi.string().max(128).allow(null, "").label("Objective"), - result_criteria: Joi.array().items( - Joi.object({ - group: Joi.number().allow(null), - name: Joi.string().allow(null, ""), - }) - ).allow(null).label("Result Criteria"), - causes: Joi.array().items( - Joi.object({ - group: Joi.string().allow(null, ""), - name: Joi.string().allow(null, ""), - }) - ).allow(null).label("Causes"), - related_clinical_condition: Joi.array().items( - Joi.object({ - name: Joi.string().allow(null, ""), - }) - ).allow(null).label("Related Clinical Condition"), - subjective_major: Joi.array().items( - Joi.object({ - group: Joi.string().allow(null, ""), - name: Joi.string().allow(null, ""), - }) - ).allow(null).label("Subjective Major"), - objectitve_major: Joi.array().items( - Joi.object({ - group: Joi.string().allow(null, ""), - name: Joi.string().allow(null, ""), - }) - ).allow(null).label("Objective Major"), - subjective_minor: Joi.array().items( - Joi.object({ - group: Joi.string().allow(null, ""), - name: Joi.string().allow(null, ""), - }) - ).allow(null).label("Subjective Minor"), - objective_minor: Joi.array().items( - Joi.object({ - group: Joi.string().allow(null, ""), - name: Joi.string().allow(null, ""), - }) - ).allow(null).label("Objective Minor"), - observation: Joi.array().items( - Joi.object({ - name: Joi.string().allow(null, ""), - }) - ).allow(null).label("Observation"), - therapeutic: Joi.array().items( - Joi.object({ - name: Joi.string().allow(null, ""), - }) - ).allow(null).label("Therapeutic"), - education: Joi.array().items( - Joi.object({ - name: Joi.string().allow(null, ""), - }) - ).allow(null).label("Education"), - colaboration: Joi.array().items( - Joi.object({ - name: Joi.string().allow(null, ""), - }) - ).allow(null).label("Colaboration"), - }); - - let param: any = await schema.validateAsync(req.body); - - let filter = { - code: param.code, - }; - let exist = await FosterCareHistoryModel.list(filter).then((q) => q.getOne()); - if (exist && exist.id != param.id) throw { message: "Foster Care History " + Language.lang.failed_duplicate }; - - let fostercarehistory = await FosterCareHistoryModel.list({ - "FosterCareHistory.id": param.id, - }).then((q) => q.getOne()); - - if (!fostercarehistory) throw { message: "FosterCareHistory " + Language.lang.failed_not_found }; - - fostercarehistory.diagnosis = param.diagnosis; - fostercarehistory.code = param.code; - fostercarehistory.status = param.status; - fostercarehistory.category = param.category; - fostercarehistory.subcategory = param.subcategory; - fostercarehistory.definition = param.definition; - fostercarehistory.objective = param.objective; - fostercarehistory.result_criteria = param.result_criteria ?? fostercarehistory.result_criteria; - fostercarehistory.causes = param.causes ?? fostercarehistory.causes; - fostercarehistory.related_clinical_condition = param.related_clinical_condition ?? fostercarehistory.related_clinical_condition; - fostercarehistory.subjective_major = param.subjective_major ?? fostercarehistory.subjective_major; - fostercarehistory.objectitve_major = param.objectitve_major ?? fostercarehistory.objectitve_major; - fostercarehistory.subjective_minor = param.subjective_minor ?? fostercarehistory.subjective_minor; - fostercarehistory.objective_minor = param.objective_minor ?? fostercarehistory.objective_minor; - fostercarehistory.observation = param.observation ?? fostercarehistory.observation; - fostercarehistory.therapeutic = param.therapeutic ?? fostercarehistory.therapeutic; - fostercarehistory.education = param.education ?? fostercarehistory.education; - fostercarehistory.colaboration = param.colaboration ?? fostercarehistory.colaboration; - fostercarehistory.updated_by = req.auth?.data.name; - await queryRunner.manager.save(fostercarehistory); - - await queryRunner.commitTransaction(); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_update, fostercarehistory); - } catch (e: unknown) { - await queryRunner.rollbackTransaction(); - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } finally { - await queryRunner.release(); - } - } - - static async delete(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Foster Care History'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'Foster Care History ID.', - required: true, - type: 'string' - } - #swagger.parameters['hard'] = { - in: 'path', - description: 'Is Hard Delete', - required: false, - type: 'boolean' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("ID"), - hard: Joi.bool().optional().allow("").label("Is hard delete?"), - }); - - const param: { id: string; hard: boolean } = await schema.validateAsync(req.params); - - let affected = 0; - if (!param.hard) { - let fostercarehistory: FosterCareHistory = await FosterCareHistoryModel.list({ - "FosterCareHistory.id": param.id, - }).then((q) => q.getOne()); - - if (!fostercarehistory) throw { message: "Foster Care History " + Language.lang.failed_not_found }; - - fostercarehistory.deleted_by = req.auth?.data.name; - fostercarehistory.deleted_at = moment().toDate(); - await OrmHelper.DB.manager.save(fostercarehistory); - affected = 1; - } else { - const repo = OrmHelper.DB.getRepository(FosterCareHistory); - affected = (await repo.delete({ id: param.id })).affected ?? 0; - } - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_delete, err.message); - } - } - - static async restore(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Foster Care History'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'Foster Care History ID.', - required: true, - type: 'string' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("ID"), - }); - - const param: any = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(FosterCareHistory); - - const affected = (await repo.restore({ id: param.id })).affected ?? 0; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_restore, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_restore, err.message); - } - } -} diff --git a/src/controllers/hospital_information.ts b/src/controllers/hospital_information.ts deleted file mode 100644 index c25e933..0000000 --- a/src/controllers/hospital_information.ts +++ /dev/null @@ -1,309 +0,0 @@ -import { HospitalInformation } from "entity"; -import { NextFunction, Response } from "express"; -import { Request } from "express-jwt"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import CommonHelper from "../helpers/common"; -import { ReturnHelper } from "../helpers/express/return"; -import { Language } from "../langs/lang"; -import { OrmHelper } from "../helpers/orm"; -import moment from "moment"; -import dayjs from 'dayjs'; -import fileUpload from "express-fileupload"; -import { v4 as uuidv4 } from 'uuid'; -import fs from "fs"; -import path from "path"; -import config from '../../config/stag.json'; - -const log: Logger = new Logger({ - name: "[HospitalInformationController]", - type: "pretty", -}); - -const hospitalCreateUpdateSchema = { - name: Joi.string().required().label("Hospital Name"), - address: Joi.string().required().label("Hospital Address"), - phone: Joi.string().required().label("Hospital Phone"), - logo: Joi.string().allow(null, "").label("Hospital Logo"), - // province: Joi.string().allow("").optional().label("Province Code"), - // city: Joi.string().allow("").optional().label("City Code"), - // subdistrict: Joi.string().allow("").optional().label("Subdistrict Code"), - // ward: Joi.string().allow("").optional().label("Ward Code"), - munisipo: Joi.string().allow(null, "").label("Munisipo ID"), - administrativu: Joi.string().allow(null, "").label("Administrativu ID"), - aldeia: Joi.string().allow(null, "").label("Aldeia ID"), - suco: Joi.string().allow(null, "").label("Suco ID"), -}; - -interface FileUploadRequest extends Request { - files?: fileUpload.FileArray | null; - body: any; -} - -export class HospitalInformationController { - - static async view(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Hospital Information'] - #swagger.security = [{ "bearerAuth": [] }] - */ - try { - const hospital = await OrmHelper.DB.getRepository(HospitalInformation) - .createQueryBuilder("HospitalInformation") - .leftJoinAndSelect("HospitalInformation.munisipo", "munisipo") - .leftJoinAndSelect("HospitalInformation.administrativu", "administrativu") - .leftJoinAndSelect("HospitalInformation.aldeia", "aldeia") - .leftJoinAndSelect("HospitalInformation.suco", "suco") - // .leftJoinAndSelect("HospitalInformation.province", "province") - // .leftJoinAndSelect("HospitalInformation.city", "city") - // .leftJoinAndSelect("HospitalInformation.subdistrict", "subdistrict") - // .leftJoinAndSelect("HospitalInformation.ward", "ward") - .getOne(); - - if (!hospital) return ReturnHelper.errorResponse(res, 404, 404, Language.lang.failed_view, "Hospital not found"); - - let hospitallogo = ''; - if (hospital.logo != null && hospital.logo != undefined && hospital.logo != '') { - hospitallogo = `${config.server.host_swagger}uploads/hospital-logo/${hospital.logo}`; - } - - const result = { - id: hospital.id, - name: hospital.name, - address: hospital.address, - phone: hospital.phone, - logo: hospitallogo, - file: hospital.logo, - munisipo: hospital.munisipo, - administrativu: hospital.administrativu, - aldeia: hospital.aldeia, - suco: hospital.suco - }; - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_view, result); - - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Hospital Information'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.requestBody = { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/hospitalinformation" } } } } - */ - const queryRunner = OrmHelper.DB.createQueryRunner(); - await queryRunner.connect(); - await queryRunner.startTransaction(); - try { - const schema = Joi.object().keys({ ...hospitalCreateUpdateSchema }); - let param: any = await schema.validateAsync(req.body); - - const existing = await OrmHelper.DB.getRepository(HospitalInformation).findOne({ where: {} }); - - let hospitalinformation: HospitalInformation; - - if (existing) { - // ── UPDATE ───────────────────────────────────────────── - hospitalinformation = existing; - hospitalinformation.name = param.name; - hospitalinformation.address = param.address; - hospitalinformation.phone = param.phone; - hospitalinformation.logo = param.logo || existing.logo; // ✅ pertahankan logo lama kalau kosong - // hospitalinformation.province = param.province; - // hospitalinformation.city = param.city; - // hospitalinformation.subdistrict = param.subdistrict; - // hospitalinformation.ward = param.ward; - hospitalinformation.suco = param.suco; - hospitalinformation.administrativu = param.administrativu; - hospitalinformation.aldeia = param.aldeia; - hospitalinformation.munisipo = param.munisipo; - hospitalinformation.updated_at = dayjs().toDate(); - hospitalinformation.updated_by = req.auth?.data.name; - } else { - // ── INSERT ───────────────────────────────────────────── - hospitalinformation = new HospitalInformation(); - hospitalinformation.name = param.name; - hospitalinformation.address = param.address; - hospitalinformation.phone = param.phone; - hospitalinformation.logo = param.logo; - // hospitalinformation.province = param.province; - // hospitalinformation.city = param.city; - // hospitalinformation.subdistrict = param.subdistrict; - // hospitalinformation.ward = param.ward; - hospitalinformation.suco = param.suco; - hospitalinformation.administrativu = param.administrativu; - hospitalinformation.aldeia = param.aldeia; - hospitalinformation.munisipo = param.munisipo; - hospitalinformation.created_at = dayjs().toDate(); - hospitalinformation.updated_at = dayjs().toDate(); - hospitalinformation.created_by = req.auth?.data.name; - hospitalinformation.updated_by = req.auth?.data.name; - } - - await queryRunner.manager.save(hospitalinformation); - await queryRunner.commitTransaction(); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, hospitalinformation); - - } catch (e: unknown) { - await queryRunner.rollbackTransaction(); - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } finally { - await queryRunner.release(); - } - } - - static async uploadlogo(req: FileUploadRequest, res: Response, next: NextFunction): Promise { - /* #swagger.tags = ['Hospital Information'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.consumes = ['multipart/form-data'] - #swagger.requestBody = { - required: true, - content: { - "multipart/form-data": { - schema: { - type: "object", - properties: { - file: { - type: "string", - format: "binary", - description: "Image file (max 1MB, jpg/png/webp)" - }, - }, - required: ["file"] - } - } - } - } - */ - try { - // Validation schema - // const schema = Joi.object().keys({ - // path: Joi.string().label('File Path'), - // application: Joi.string().label('Application'), - // }); - - log.info("body", req.body); - - // const param: { path: string, application: string } = await schema.validateAsync(req.body); - - // Check if file exists - if (!req.files || !req.files.file) { - return ReturnHelper.errorResponse(res, 400, 404, Language.lang.failed_insert, "File not found"); - } - - const file = req.files.file as fileUpload.UploadedFile; - - // Validate file size (max 1MB) - const maxSize = 10 * 1024 * 1024; // 10MB - if (file.size > maxSize) { - return ReturnHelper.errorResponse( - res, - 400, - 400, - Language.lang.failed_insert, - "File size exceeds 10MB limit" - ); - } - - // Validate file type - const allowedMimes = ['image/jpeg', 'image/jpg', 'image/png', 'image/webp']; - if (!allowedMimes.includes(file.mimetype)) { - return ReturnHelper.errorResponse(res, 400, 400, Language.lang.failed_insert, "Invalid file type. Only JPG, PNG, and WEBP are allowed"); - } - - // Normalize path - // param.path = param.path[param.path.length - 1] !== '/' ? param.path + '/' : param.path; - - // if (param.path == undefined || param.path == null) param.path = 'uploads/hospital-logo/'; - - // Generate unique filename - const ext = file.name.split('.'); - const name = uuidv4() + '.' + ext[ext.length - 1]; - - const result: { file: string } = { - // url: "", - // path: "", - file: "", - // mime: file.mimetype, - // size: file.size, - // md5: file.md5 - }; - - const folder_path = 'uploads/hospital-logo/'; - const file_path = path.join(folder_path, name); - - // Create directory if it doesn't exist - if (!fs.existsSync(folder_path)) { - fs.mkdirSync(folder_path, { recursive: true }); - } - - // Move file to destination - await file.mv(file_path); - - // result.path = param.path[param.path.length - 1] === '/' ? param.path.substring(0, param.path.length - 1) : param.path; - result.file = name; - // result.url = `${result.path}/${name}`; // Generate URL - - log.info(`File uploaded successfully: ${file_path}`); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, result); - - } catch (e: unknown) { - // Proper error logging to avoid tslog serialization issues - if (e instanceof Error) { - log.error("File upload failed:", { - message: e.message, - stack: e.stack, - name: e.name - }); - return ReturnHelper.errorResponse(res, 500, 500, Language.lang.failed_insert, e.message); - } else { - log.error("File upload failed with unknown error:", String(e)); - return ReturnHelper.errorResponse(res, 500, 500, Language.lang.failed_insert, "Unknown error occurred"); - } - } - } - - static async deletelogo(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Hospital Information'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.requestBody = { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/files" } } } } - */ - - try { - const schema = Joi.object().keys({ - file_name: Joi.string().required().label('File Name'), - }); - - const param: { file_name: string } = await schema.validateAsync(req.body); - - // const env = process.env.NODE_ENV + '/' - const fixedPath = 'uploads/hospital-logo/'; - const file_path = fixedPath + param.file_name; - - // Check if file exists - if (!fs.existsSync(file_path)) { - return ReturnHelper.errorResponse(res, 404, 404, Language.lang.failed_not_found, "File not found"); - } - - // Delete file - fs.unlinkSync(file_path); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_delete, err.message); - } - } - -} diff --git a/src/controllers/inpatient_room.ts b/src/controllers/inpatient_room.ts deleted file mode 100644 index e0fc36b..0000000 --- a/src/controllers/inpatient_room.ts +++ /dev/null @@ -1,371 +0,0 @@ -import { Paging, InpatientRoom, Room, InpatientRoomBed, InpatientRoomBedStatus } from "entity"; -import { NextFunction, Response } from "express"; -import { Request } from "express-jwt"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import CommonHelper from "../helpers/common"; -import { ReturnHelper } from "../helpers/express/return"; -import { OrmHelper } from "../helpers/orm"; -import { Language } from "../langs/lang"; -import { InpatientRoomModel } from "../model/inpatient_room"; -import { RoomModel } from "../model/room"; - -const log: Logger = new Logger({ - name: "[InpatientRoomController]", - type: "pretty", -}); - -export class InpatientRoomController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Inpatient Room'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['filter'] = { - descriptionk:'', - in: 'query', - type: 'string' - } - #swagger.parameters['limit'] = { - in: 'query', - required: true, - type: 'number' - } - #swagger.parameters['page'] = { - in: 'query', - required: true, - type: 'number' - } - #swagger.parameters['with_deleted'] = { - in: 'query', - required: true, - type: 'boolean' - } - #swagger.parameters['order_field'] = { - in: 'query', - required: true, - type: 'string' - } - #swagger.parameters['order_direction'] = { - in: 'query', - required: true, - schema: { - '@enum': ['ASC', 'DESC'] - } - } - */ - - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().required().label("With Deleted"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").required().label("Order Direction"), - }); - - const param: Paging = await schema.validateAsync(req.query); - const offset = (param.page - 1) * param.limit; - const filter = JSON.parse(param.filter); - const query = await InpatientRoomModel.list(filter); - const limit = param.limit; - - const res_count = query; - const res_list = query - .leftJoinAndSelect("InpatientRoom.room", "room") - .leftJoinAndSelect("room.serviceclass", "service_class") - .orderBy("InpatientRoom." + param.order_field, param.order_direction) - .offset(offset) - .limit(limit); - - if (param.with_deleted) { - res_count.withDeleted(); - res_list.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Inpatient Room'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/inpatient_room" - } - } - } - } - */ - - const queryRunner = OrmHelper.DB.createQueryRunner(); - await queryRunner.startTransaction(); - - try { - const schema = Joi.object().keys({ - room_id: Joi.string().uuid().required().label("Room ID"), - name: Joi.string().required().label("Name"), - number_of_bed: Joi.number().required().min(0).label("Number of Bed"), - }); - - const param = await schema.validateAsync(req.body); - - let room: Room = await RoomModel.list({ id: param.room_id }).then((q) => q.getOne()); - if (!room) throw { message: "Room " + Language.lang.failed_not_found }; - - const data = new InpatientRoom(); - data.room = room; - data.name = param.name; - data.number_of_bed = param.number_of_bed; - data.created_by = req.auth?.data.name; - - await queryRunner.manager.save(data); - - for (let i = 1; i <= param.number_of_bed; i++) { - const bed = new InpatientRoomBed(); - bed.inpatient_room = data; - bed.number = i; - bed.status = InpatientRoomBedStatus.Empty; - bed.created_by = req.auth?.data.name; - await queryRunner.manager.save(bed); - } - - await queryRunner.commitTransaction(); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, data); - } catch (e: unknown) { - await queryRunner.rollbackTransaction(); - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_insert, err.message); - } finally { - await queryRunner.release(); - } - } - - static async detail(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Inpatient Room'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'Inpatient Room ID.', - required: true, - type: 'string' - } - */ - - try { - const schema = Joi.object().keys({ - id: Joi.string().required().label("ID"), - }); - - let param: any = await schema.validateAsync(req.params); - - let data = await InpatientRoomModel.list({ "InpatientRoom.id": param.id }).then((q) => - q // - .leftJoinAndSelect("InpatientRoom.room", "room") - .getOne(), - ); - - if (!data) throw { message: "Inpatient Room " + Language.lang.failed_not_found }; - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_view, data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_view, err.message); - } - } - - static async update(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Inpatient Room'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - description:'', - in: 'path', - type: 'string' - } - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/inpatient_room" - } - } - } - } - */ - - const queryRunner = OrmHelper.DB.createQueryRunner(); - await queryRunner.startTransaction(); - - try { - req.body.id = req.params["id"]; - - const schema = Joi.object().keys({ - id: Joi.string().required().label("Inpatient Room ID"), - room_id: Joi.string().uuid().required().label("Room ID"), - name: Joi.string().required().label("Name"), - number_of_bed: Joi.number().required().min(0).label("Number of Bed"), - }); - - let param: any = await schema.validateAsync(req.body); - - let inpatientRoom: InpatientRoom = await InpatientRoomModel.list({ id: param.id }).then((q) => q.getOne()); - if (!inpatientRoom) throw { message: "Inpatient Room " + Language.lang.failed_not_found }; - - let room: Room = await RoomModel.list({ id: param.room_id }).then((q) => q.getOne()); - if (!room) throw { message: "Room " + Language.lang.failed_not_found }; - - const newNumberOfBed: number = param.number_of_bed; - const authName = req.auth?.data?.name; - - const existingBeds = await queryRunner.manager - .getRepository(InpatientRoomBed) - .createQueryBuilder("bed") - .leftJoinAndSelect("bed.boarding_room", "boarding_room") - .leftJoin("bed.inpatient_room", "inpatient_room") - .where("inpatient_room.id = :roomId", { roomId: param.id }) - .andWhere("bed.deleted_at IS NULL") - .orderBy("bed.number", "DESC") - .getMany(); - - const occupiedCount = existingBeds.filter((bed) => bed.boarding_room != null).length; - if (occupiedCount > newNumberOfBed) { - throw { message: "Update gagal, masih ada bed yang sedang digunakan" }; - } - - if (existingBeds.length > newNumberOfBed) { - let remainingToDelete = existingBeds.length - newNumberOfBed; - - for (const bed of existingBeds) { - if (remainingToDelete <= 0) break; - if (bed.boarding_room != null) continue; - - await queryRunner.manager.update(InpatientRoomBed, { id: bed.id }, { deleted_by: authName }); - await queryRunner.manager.softDelete(InpatientRoomBed, { id: bed.id }); - remainingToDelete--; - } - - if (remainingToDelete > 0) { - throw { message: "Update gagal, masih ada bed yang sedang digunakan" }; - } - } - - const activeBeds = await queryRunner.manager - .getRepository(InpatientRoomBed) - .createQueryBuilder("bed") - .leftJoin("bed.inpatient_room", "inpatient_room") - .where("inpatient_room.id = :roomId", { roomId: param.id }) - .andWhere("bed.deleted_at IS NULL") - .getMany(); - - if (activeBeds.length < newNumberOfBed) { - const usedNumbers = activeBeds.map((bed) => bed.number); - let added = 0; - const toAdd = newNumberOfBed - activeBeds.length; - - for (let i = 1; i <= newNumberOfBed && added < toAdd; i++) { - if (usedNumbers.includes(i)) continue; - - const bed = new InpatientRoomBed(); - bed.inpatient_room = inpatientRoom; - bed.number = i; - bed.status = InpatientRoomBedStatus.Empty; - bed.created_by = authName; - await queryRunner.manager.save(bed); - added++; - } - } - - inpatientRoom.room = room; - inpatientRoom.name = param.name; - inpatientRoom.number_of_bed = newNumberOfBed; - inpatientRoom.updated_by = authName; - - await queryRunner.manager.save(inpatientRoom); - - await queryRunner.commitTransaction(); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_update, inpatientRoom); - } catch (e: unknown) { - await queryRunner.rollbackTransaction(); - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } finally { - await queryRunner.release(); - } - } - - static async delete(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Inpatient Room'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'Inpatient Room ID.', - required: true, - type: 'string' - } - #swagger.parameters['hard'] = { - in: 'path', - description: 'Is Hard Delete', - required: false, - type: 'boolean' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("ID"), - hard: Joi.bool().optional().allow("").label("Is hard delete?"), - }); - - const param: { id: string; hard: boolean } = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(InpatientRoom); - - const affected = (!param.hard ? await repo.softDelete({ id: param.id }) : await repo.delete({ id: param.id })).affected ?? 0; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_delete, err.message); - } - } -} diff --git a/src/controllers/laboratory.ts b/src/controllers/laboratory.ts deleted file mode 100644 index ec232ed..0000000 --- a/src/controllers/laboratory.ts +++ /dev/null @@ -1,88 +0,0 @@ -import { Room, Paging } from "entity"; -import { NextFunction, Response } from "express"; -import { Request } from "express-jwt"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import CommonHelper from "../helpers/common"; -import { ReturnHelper } from "../helpers/express/return"; -import { Language } from "../langs/lang"; -import { OrmHelper } from "../helpers/orm"; - -const log: Logger = new Logger({ - name: "[LaboratoryController]", - type: "pretty", -}); - -const LABORATORY_DEPARTMENT_ID = "7ebc5d8a-63f0-40f6-962b-59953ebd4ba0"; - -export class LaboratoryController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Laboratory'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['filter'] = { description: 'Filter: plain text or JSON object (status, code, etc.)', in: 'query', type: 'string' } - #swagger.parameters['limit'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['page'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['with_deleted'] = { in: 'query', required: true, type: 'boolean' } - #swagger.parameters['order_field'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['order_direction'] = { in: 'query', required: true, schema: { '@enum': ['ASC', 'DESC'] } } - */ - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().required().label("With Deleted"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").required().label("Order Direction"), - }); - - let param: Paging = await schema.validateAsync(req.query); - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - // Build query with department join - const repo = OrmHelper.DB.getRepository(Room); - let whereAttr: string[] = []; - let whereVal: any = {}; - - // Always filter by laboratory department ID - whereAttr.push("department.id = :_departmentId"); - whereVal["_departmentId"] = LABORATORY_DEPARTMENT_ID; - - // Apply additional filters if provided - if (filter && Object.keys(filter).length > 0) { - const filterResult = CommonHelper.handleQueryFilter(filter, "Room"); - whereAttr = [...whereAttr, ...filterResult.whereAttr]; - whereVal = { ...whereVal, ...filterResult.whereVal }; - } - - const offset = (param.page - 1) * param.limit; - const res_count = repo.createQueryBuilder("Room") - .leftJoin("Room.department", "department") - .where(whereAttr.join(" and "), whereVal); - - const res_list = repo.createQueryBuilder("Room") - .leftJoinAndSelect("Room.department", "department") - .where(whereAttr.join(" and "), whereVal) - .orderBy("Room." + param.order_field, param.order_direction) - .offset(offset) - .limit(param.limit); - - if (param.with_deleted) { - res_count.withDeleted(); - res_list.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } -} diff --git a/src/controllers/main_disease.ts b/src/controllers/main_disease.ts deleted file mode 100644 index c023c8a..0000000 --- a/src/controllers/main_disease.ts +++ /dev/null @@ -1,267 +0,0 @@ -import { DiseaseCategory, MainDisease, Paging } from "entity"; -import { NextFunction, Response } from "express"; -import { Request } from "express-jwt"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import CommonHelper from "../helpers/common"; -import { ReturnHelper } from "../helpers/express/return"; -import { Language } from "../langs/lang"; -import { MainDiseaseModel } from "../model/main_disease"; -import { OrmHelper } from "../helpers/orm"; -import moment from "moment"; - -const log: Logger = new Logger({ - name: "[MainDiseaseController]", - type: "pretty", -}); - -const diseaseCategoryValues = Object.values(DiseaseCategory); - -export class MainDiseaseController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Main Disease'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['filter'] = { description: '', in: 'query', type: 'string' } - #swagger.parameters['limit'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['page'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['with_deleted'] = { in: 'query', required: true, type: 'boolean' } - #swagger.parameters['order_field'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['order_direction'] = { in: 'query', required: true, schema: { '@enum': ['ASC', 'DESC'] } } - */ - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().required().label("With Deleted"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").required().label("Order Direction"), - }); - - let param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await MainDiseaseModel.list(filter); - - const offset = (param.page - 1) * param.limit; - let limit = param.limit; - - const res_count = query; - const res_list = query - .orderBy("MainDisease." + param.order_field, param.order_direction) - .offset(offset) - .limit(limit); - - if (param.with_deleted) { - res_count.withDeleted(); - res_list.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Main Disease'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.requestBody = { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/main_disease" } } } } - */ - const queryRunner = OrmHelper.DB.createQueryRunner(); - await queryRunner.startTransaction(); - try { - const schema = Joi.object().keys({ - name: Joi.string().max(128).required().label("Name"), - status: Joi.string().required().label("Status"), - category: Joi.string() - .valid(...diseaseCategoryValues) - .required() - .label("Category"), - }); - - let param: any = await schema.validateAsync(req.body); - - let filter = { name: param.name }; - let exist = await MainDiseaseModel.list(filter).then((q) => q.getOne()); - if (exist) throw { message: "Main Disease " + Language.lang.failed_duplicate }; - - let entity = new MainDisease(); - entity.name = param.name; - entity.status = param.status; - entity.category = param.category; - entity.created_by = req.auth.data.name; - entity.updated_by = req.auth.data.name; - await queryRunner.manager.save(entity); - - await queryRunner.commitTransaction(); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, entity); - } catch (e: unknown) { - await queryRunner.rollbackTransaction(); - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } finally { - await queryRunner.release(); - } - } - - static async detail(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Main Disease'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { description: '', in: 'path', type: 'string' } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("Main Disease Id"), - }); - - let param: any = await schema.validateAsync(req.params); - - let entity = await MainDiseaseModel.list({ "MainDisease.id": param.id }).then((q) => q.getOne()); - - if (!entity) throw { message: "Main Disease Not Found" }; - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_view, entity); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_not_found, err.message); - } - } - - static async update(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Main Disease'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { description: '', in: 'path', type: 'string' } - #swagger.requestBody = { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/main_disease" } } } } - */ - const queryRunner = OrmHelper.DB.createQueryRunner(); - await queryRunner.startTransaction(); - - try { - req.body.id = req.params["id"]; - - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("Main Disease ID"), - name: Joi.string().max(128).required().label("Name"), - status: Joi.string().required().label("Status"), - category: Joi.string() - .valid(...diseaseCategoryValues) - .required() - .label("Category"), - }); - - let param: any = await schema.validateAsync(req.body); - - let filter = { name: param.name }; - let exist = await MainDiseaseModel.list(filter).then((q) => q.getOne()); - if (exist && exist.id != param.id) throw { message: "Main Disease " + Language.lang.failed_duplicate }; - - let entity = await MainDiseaseModel.list({ "MainDisease.id": param.id }).then((q) => q.getOne()); - - if (!entity) throw { message: "Main Disease " + Language.lang.failed_not_found }; - - entity.name = param.name; - entity.status = param.status; - entity.category = param.category; - entity.updated_by = req.auth.data.name; - await queryRunner.manager.save(entity); - - await queryRunner.commitTransaction(); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_update, entity); - } catch (e: unknown) { - await queryRunner.rollbackTransaction(); - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } finally { - await queryRunner.release(); - } - } - - static async delete(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Main Disease'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { in: 'path', required: true, type: 'string' } - #swagger.parameters['hard'] = { in: 'path', description: 'Is Hard Delete', required: false, type: 'boolean' } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("ID"), - hard: Joi.bool().optional().allow("").label("Is hard delete?"), - }); - - const param: { id: string; hard: boolean } = await schema.validateAsync(req.params); - - let affected = 0; - if (!param.hard) { - let entity: MainDisease = await MainDiseaseModel.list({ "MainDisease.id": param.id }).then((q) => q.getOne()); - - if (!entity) throw { message: "Main Disease " + Language.lang.failed_not_found }; - - entity.deleted_by = req.auth.data.name; - entity.deleted_at = moment().toDate(); - await OrmHelper.DB.manager.save(entity); - affected = 1; - } else { - const repo = OrmHelper.DB.getRepository(MainDisease); - affected = (await repo.delete({ id: param.id })).affected ?? 0; - } - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_delete, err.message); - } - } - - static async restore(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Main Disease'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { in: 'path', required: true, type: 'string' } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("ID"), - }); - - const param: any = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(MainDisease); - - const affected = (await repo.restore({ id: param.id })).affected ?? 0; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_restore, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_restore, err.message); - } - } -} diff --git a/src/controllers/measurement_unit.ts b/src/controllers/measurement_unit.ts deleted file mode 100644 index 8305b7c..0000000 --- a/src/controllers/measurement_unit.ts +++ /dev/null @@ -1,255 +0,0 @@ -import { MeasurementUnit, Paging } from "entity"; -import { NextFunction, Response } from "express"; -import { Request } from "express-jwt"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import CommonHelper from "../helpers/common"; -import { ReturnHelper } from "../helpers/express/return"; -import { Language } from "../langs/lang"; -import { MeasurementUnitModel } from "../model/measurement_unit"; -import { OrmHelper } from "../helpers/orm"; -import moment from "moment"; - -const log: Logger = new Logger({ - name: "[MeasurementUnitController]", - type: "pretty", -}); - -export class MeasurementUnitController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Measurement Unit'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['filter'] = { description: 'Filter: plain text or JSON object (status, unit, etc.)', in: 'query', type: 'string' } - #swagger.parameters['limit'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['page'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['with_deleted'] = { in: 'query', required: true, type: 'boolean' } - #swagger.parameters['order_field'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['order_direction'] = { in: 'query', required: true, schema: { '@enum': ['ASC', 'DESC'] } } - */ - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().required().label("With Deleted"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").required().label("Order Direction"), - }); - - let param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await MeasurementUnitModel.list(filter); - - const offset = (param.page - 1) * param.limit; - let limit = param.limit; - - const res_count = query; - const res_list = query - .orderBy("MeasurementUnit." + param.order_field, param.order_direction) - .offset(offset) - .limit(limit); - - if (param.with_deleted) { - res_count.withDeleted(); - res_list.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Measurement Unit'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.requestBody = { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/measurementUnit" } } } } - */ - const queryRunner = OrmHelper.DB.createQueryRunner(); - await queryRunner.startTransaction(); - try { - const schema = Joi.object().keys({ - unit: Joi.string().max(256).required().label("Unit"), - status: Joi.string().required().label("Status"), - }); - - let param: any = await schema.validateAsync(req.body); - - let filter = { unit: param.unit }; - let exist = await MeasurementUnitModel.list(filter).then((q) => q.getOne()); - if (exist) throw { message: "Measurement Unit " + Language.lang.failed_duplicate }; - - let measurementUnit = new MeasurementUnit(); - measurementUnit.unit = param.unit; - measurementUnit.status = param.status; - measurementUnit.created_by = req.auth.data.name; - measurementUnit.updated_by = req.auth.data.name; - await queryRunner.manager.save(measurementUnit); - - await queryRunner.commitTransaction(); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, measurementUnit); - } catch (e: unknown) { - await queryRunner.rollbackTransaction(); - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } finally { - await queryRunner.release(); - } - } - - static async detail(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Measurement Unit'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { in: 'path', type: 'string' } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("Measurement Unit Id"), - }); - - let param: any = await schema.validateAsync(req.params); - - let measurementUnit = await MeasurementUnitModel.list({ "MeasurementUnit.id": param.id }).then((q) => q.getOne()); - - if (!measurementUnit) throw { message: "Measurement Unit Not Found" }; - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_view, measurementUnit); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_not_found, err.message); - } - } - - static async update(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Measurement Unit'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { in: 'path', type: 'string' } - #swagger.requestBody = { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/measurementUnit" } } } } - */ - const queryRunner = OrmHelper.DB.createQueryRunner(); - await queryRunner.startTransaction(); - - try { - req.body.id = req.params["id"]; - - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("Measurement Unit ID"), - unit: Joi.string().max(256).required().label("Unit"), - status: Joi.string().required().label("Status"), - }); - - let param: any = await schema.validateAsync(req.body); - - let filter = { unit: param.unit }; - let exist = await MeasurementUnitModel.list(filter).then((q) => q.getOne()); - if (exist && exist.id != param.id) throw { message: "Measurement Unit " + Language.lang.failed_duplicate }; - - let measurementUnit = await MeasurementUnitModel.list({ "MeasurementUnit.id": param.id }).then((q) => q.getOne()); - - if (!measurementUnit) throw { message: "Measurement Unit " + Language.lang.failed_not_found }; - - measurementUnit.unit = param.unit; - measurementUnit.status = param.status; - measurementUnit.updated_by = req.auth.data.name; - await queryRunner.manager.save(measurementUnit); - - await queryRunner.commitTransaction(); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_update, measurementUnit); - } catch (e: unknown) { - await queryRunner.rollbackTransaction(); - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } finally { - await queryRunner.release(); - } - } - - static async delete(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Measurement Unit'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { in: 'path', required: true, type: 'string' } - #swagger.parameters['hard'] = { in: 'path', description: 'Is Hard Delete', required: false, type: 'boolean' } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("ID"), - hard: Joi.bool().optional().allow("").label("Is hard delete?"), - }); - - const param: { id: string; hard: boolean } = await schema.validateAsync(req.params); - - let affected = 0; - if (!param.hard) { - let measurementUnit: MeasurementUnit = await MeasurementUnitModel.list({ "MeasurementUnit.id": param.id }).then((q) => q.getOne()); - - if (!measurementUnit) throw { message: "Measurement Unit " + Language.lang.failed_not_found }; - - measurementUnit.deleted_by = req.auth.data.name; - measurementUnit.deleted_at = moment().toDate(); - await OrmHelper.DB.manager.save(measurementUnit); - affected = 1; - } else { - const repo = OrmHelper.DB.getRepository(MeasurementUnit); - affected = (await repo.delete({ id: param.id })).affected ?? 0; - } - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_delete, err.message); - } - } - - static async restore(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Measurement Unit'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { in: 'path', required: true, type: 'string' } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("ID"), - }); - - const param: any = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(MeasurementUnit); - - const affected = (await repo.restore({ id: param.id })).affected ?? 0; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_restore, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_restore, err.message); - } - } -} diff --git a/src/controllers/medical_form.ts b/src/controllers/medical_form.ts deleted file mode 100644 index fdca118..0000000 --- a/src/controllers/medical_form.ts +++ /dev/null @@ -1,267 +0,0 @@ -import { MedicalForm, Paging } from "entity"; -import { NextFunction, Response } from "express"; -import { Request } from "express-jwt"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import CommonHelper from "../helpers/common"; -import { ReturnHelper } from "../helpers/express/return"; -import { Language } from "../langs/lang"; -import { MedicalFormModel } from "../model/medical_form"; -import { OrmHelper } from "../helpers/orm"; -import moment from "moment"; - -const log: Logger = new Logger({ - name: "[MedicalFormController]", - type: "pretty", -}); - -export class MedicalFormController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Medical Form'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['filter'] = { description: 'Filter: plain text or JSON object', in: 'query', type: 'string' } - #swagger.parameters['limit'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['page'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['with_deleted'] = { in: 'query', required: true, type: 'boolean' } - #swagger.parameters['order_field'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['order_direction'] = { in: 'query', required: true, schema: { '@enum': ['ASC', 'DESC'] } } - */ - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().required().label("With Deleted"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").required().label("Order Direction"), - }); - - let param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await MedicalFormModel.list(filter); - - const offset = (param.page - 1) * param.limit; - let limit = param.limit; - - const res_count = query; - const res_list = query - .orderBy("MedicalForm." + param.order_field, param.order_direction) - .offset(offset) - .limit(limit); - - if (param.with_deleted) { - res_count.withDeleted(); - res_list.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Medical Form'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.requestBody = { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/medical_form" } } } } - */ - const queryRunner = OrmHelper.DB.createQueryRunner(); - await queryRunner.startTransaction(); - try { - const schema = Joi.object().keys({ - title: Joi.string().max(256).required().label("Title"), - name: Joi.string().max(256).required().label("Name"), - description: Joi.string().max(512).required().label("Description"), - picture: Joi.string().max(512).allow("").optional().label("Picture"), - status: Joi.string().max(64).required().label("Status"), - }); - - let param: any = await schema.validateAsync(req.body); - - let filter = { name: param.name }; - let exist = await MedicalFormModel.list(filter).then((q) => q.getOne()); - if (exist) throw { message: "Medical Form " + Language.lang.failed_duplicate }; - - let medicalForm = new MedicalForm(); - medicalForm.title = param.title; - medicalForm.name = param.name; - medicalForm.description = param.description; - medicalForm.picture = param.picture || null; - medicalForm.status = param.status; - medicalForm.created_by = req.auth.data.name; - medicalForm.updated_by = req.auth.data.name; - await queryRunner.manager.save(medicalForm); - - await queryRunner.commitTransaction(); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, medicalForm); - } catch (e: unknown) { - await queryRunner.rollbackTransaction(); - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } finally { - await queryRunner.release(); - } - } - - static async detail(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Medical Form'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { description: '', in: 'path', type: 'string' } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("Medical Form Id"), - }); - - let param: any = await schema.validateAsync(req.params); - - let medicalForm = await MedicalFormModel.list({ "MedicalForm.id": param.id }).then((q) => q.getOne()); - - if (!medicalForm) throw { message: "Medical Form Not Found" }; - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_view, medicalForm); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_not_found, err.message); - } - } - - static async update(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Medical Form'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { description: '', in: 'path', type: 'string' } - #swagger.requestBody = { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/medical_form" } } } } - */ - const queryRunner = OrmHelper.DB.createQueryRunner(); - await queryRunner.startTransaction(); - - try { - req.body.id = req.params["id"]; - - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("Medical Form ID"), - title: Joi.string().max(256).required().label("Title"), - name: Joi.string().max(256).required().label("Name"), - description: Joi.string().max(512).required().label("Description"), - picture: Joi.string().max(512).allow("").optional().label("Picture"), - status: Joi.string().max(64).required().label("Status"), - }); - - let param: any = await schema.validateAsync(req.body); - - let filter = { name: param.name }; - let exist = await MedicalFormModel.list(filter).then((q) => q.getOne()); - if (exist && exist.id != param.id) throw { message: "Medical Form " + Language.lang.failed_duplicate }; - - let medicalForm = await MedicalFormModel.list({ "MedicalForm.id": param.id }).then((q) => q.getOne()); - - if (!medicalForm) throw { message: "Medical Form " + Language.lang.failed_not_found }; - - medicalForm.title = param.title; - medicalForm.name = param.name; - medicalForm.description = param.description; - medicalForm.picture = param.picture || null; - medicalForm.status = param.status; - medicalForm.updated_by = req.auth.data.name; - await queryRunner.manager.save(medicalForm); - - await queryRunner.commitTransaction(); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_update, medicalForm); - } catch (e: unknown) { - await queryRunner.rollbackTransaction(); - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } finally { - await queryRunner.release(); - } - } - - static async delete(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Medical Form'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { in: 'path', required: true, type: 'string' } - #swagger.parameters['hard'] = { in: 'path', description: 'Is Hard Delete', required: false, type: 'boolean' } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("ID"), - hard: Joi.bool().optional().allow("").label("Is hard delete?"), - }); - - const param: { id: string; hard: boolean } = await schema.validateAsync(req.params); - - let affected = 0; - if (!param.hard) { - let medicalForm: MedicalForm = await MedicalFormModel.list({ "MedicalForm.id": param.id }).then((q) => q.getOne()); - - if (!medicalForm) throw { message: "Medical Form " + Language.lang.failed_not_found }; - - medicalForm.deleted_by = req.auth.data.name; - medicalForm.deleted_at = moment().toDate(); - await OrmHelper.DB.manager.save(medicalForm); - affected = 1; - } else { - const repo = OrmHelper.DB.getRepository(MedicalForm); - affected = (await repo.delete({ id: param.id })).affected ?? 0; - } - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_delete, err.message); - } - } - - static async restore(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Medical Form'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { in: 'path', required: true, type: 'string' } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("ID"), - }); - - const param: any = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(MedicalForm); - - const affected = (await repo.restore({ id: param.id })).affected ?? 0; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_restore, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_restore, err.message); - } - } -} diff --git a/src/controllers/menu.ts b/src/controllers/menu.ts deleted file mode 100644 index 2c734a9..0000000 --- a/src/controllers/menu.ts +++ /dev/null @@ -1,465 +0,0 @@ -import { Response, NextFunction, Application } from "express"; -import { Request } from "express-jwt"; -import { ReturnHelper } from "../helpers/express/return"; -import { OrmHelper } from "../helpers/orm"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import { Language } from "../langs/lang"; -import { Paging } from "entity"; -import CommonHelper from "../helpers/common"; -import * as fastcsv from 'fast-csv'; -import dayjs from "dayjs"; -import { Menu } from "entity"; - -const log: Logger = new Logger({ name: '[MenuController]', type: 'pretty' }); - -export class MenuController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Menu'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['filter'] = { - description: 'Filter with 2 format :
  • Simple format use text plaint will filter like %name%
  • Advance format using field existing {status:\'Y\', any:\'SAME AS PLAINT LOGIC\', etc...}
', - in: 'query', - type: 'string' - } - #swagger.parameters['limit'] = { - in: 'query', - required: true, - type: 'number' - } - #swagger.parameters['page'] = { - in: 'query', - required: true, - type: 'number' - } - #swagger.parameters['with_deleted'] = { - in: 'query', - required: true, - type: 'boolean' - } - #swagger.parameters['order_field'] = { - in: 'query', - required: true, - type: 'string' - } - #swagger.parameters['order_direction'] = { - in: 'query', - required: true, - schema: { - '@enum': ['ASC', 'DESC'] - } - } - */ - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow('').optional().label('Filter'), - page: Joi.number().required().min(1).label('Page'), - limit: Joi.number().required().min(1).label('Limit'), - with_deleted: Joi.bool().required().label('With Deleted'), - order_field: Joi.string().required().label('Order Field'), - order_direction: Joi.string().allow('asc', 'desc').required().label('Order Direction'), - }); - - const param: Paging = await schema.validateAsync(req.query); - - const repo = OrmHelper.DB.getRepository(Menu); - - const offset = (param.page - 1) * param.limit - - const { whereAttr, whereVal } = CommonHelper.handleFilter({ - filter: param.filter, - col_any_eq: [], - col_any_like: ['name'] - }); - - const res_count = repo.createQueryBuilder() - .where(whereAttr, whereVal); - const res_list = repo.createQueryBuilder() - .where(whereAttr, whereVal) - .andWhere('id_parent is null') - .orderBy(param.order_field, param.order_direction) - .offset(offset) - .limit(param.limit); - - if (param.with_deleted) { - res_count.withDeleted(); - res_list.withDeleted(); - } - - const res_list_all = await repo.createQueryBuilder().andWhere('id_parent is not null').getMany(); - let list_data_final = await res_list.getMany(); - - let list_child: any = {}; - for (let p of res_list_all) { - if (!list_child[p.id_parent]) { - list_child[p.id_parent] = []; - } - - list_child[p.id_parent].push(p); - } - - for (let f of list_data_final) { - if (list_child[f.id]) { - f.children = list_child[f.id]; - - for (let g of f.children) { - if (list_child[g.id]) { - g.children = list_child[g.id]; - - for (let h of g.children) { - if (list_child[h.id]) { - h.children = list_child[h.id]; - - for (let i of h.children) { - if (list_child[i.id]) { - i.children = list_child[i.id]; - - for (let j of i.children) { - if (list_child[j.id]) { - j.children = list_child[j.id]; - - for (let k of j.children) { - if (list_child[k.id]) { - k.children = list_child[k.id]; - } - } - } - } - } - } - } - } - } - } - } - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = list_data_final; - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async export(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Menu'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['filter'] = { - description: 'Filter with 2 format :
  • Simple format use text plaint will filter like %name%
  • Advance format using field existing {status:\'Y\', any:\'SAME AS PLAINT LOGIC\', etc...}
', - in: 'query', - type: 'string' - } - #swagger.parameters['filter'] = { - in: 'query', - type: 'string' - } - #swagger.parameters['order_field'] = { - in: 'query', - required: true, - type: 'string' - } - #swagger.parameters['order_direction'] = { - in: 'query', - required: true, - schema: { - '@enum': ['ASC', 'DESC'] - } - } - */ - - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow('').optional().label('Filter'), - order_field: Joi.string().required().label('Order Field'), - order_direction: Joi.string().allow('asc', 'desc').required().label('Order Direction'), - }); - - const param: Paging = await schema.validateAsync(req.query); - - const repo = OrmHelper.DB.getRepository(Menu); - - const { whereAttr, whereVal } = CommonHelper.handleFilter({ - filter: param.filter, - col_any_eq: [], - col_any_like: ['name'] - }); - - const filename = "menu.csv"; - - res.setHeader('Content-Type', 'text/csv'); - res.setHeader('Content-Disposition', 'attachment; filename=' + filename); - - const csvStream = fastcsv.format({ - headers: true, - writeHeaders: true, - transform: (row: Menu): any => ({ - ...row, - created_at: dayjs(row.created_at).format('DD-MM-YYYY HH:MM:ss'), - }) - }); - csvStream.pipe(res); - - const limit = 50; - - const fetchAndWrite = async (page: any) => { - const offset = (page - 1) * limit - - const data = await repo.createQueryBuilder() - .where(whereAttr, whereVal) - .select([ - 'id', - 'code', - 'name', - 'status', - 'created_at']) - .orderBy(param.order_field, param.order_direction) - .offset(offset) - .limit(limit).getRawMany(); - - if (CommonHelper.countObject(data) === 0) { - csvStream.end(); - } else { - data.forEach((item: any) => csvStream.write(item)); - - if (CommonHelper.countObject(data) == limit) { - fetchAndWrite(page + 1); - } else { - csvStream.end(); - } - } - }; - - fetchAndWrite(1); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Menu'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/menu" - } - } - } - } - */ - - try { - const schema = Joi.object().keys({ - module: Joi.string().max(128).required().label('Module'), - name: Joi.string().max(128).required().label('Name'), - link: Joi.string().max(256).required().label('Link'), - id_parent: Joi.string().uuid().optional().allow('').label('ID Parent'), - order_number: Joi.number().min(1).required().label('Order'), - icon: Joi.string().max(128).optional().allow('').label('Icon'), - application: Joi.string().max(32).required().label('Application'), - status: Joi.string().required().label('Status'), - }); - - const param: Menu = await schema.validateAsync(req.body); - - const data = new Menu() - data.module = param.module - data.name = param.name - data.link = param.link - data.order_number = param.order_number - data.icon = param.icon - data.application = param.application - data.status = param.status - - if (param.id_parent) { - data.id_parent = param.id_parent - } - - await OrmHelper.DB.manager.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 401, Language.lang.failed_insert, err.message); - } - } - - static async update(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Menu'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'Menu ID.', - required: true, - type: 'string' - } - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/menu" - } - } - } - } - */ - - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID'), - module: Joi.string().max(128).required().label('Module'), - name: Joi.string().max(128).required().label('Name'), - link: Joi.string().max(256).required().label('Link'), - id_parent: Joi.string().uuid().optional().allow('').label('ID Parent'), - order_number: Joi.number().min(1).required().label('Order'), - icon: Joi.string().max(128).optional().allow('').label('Icon'), - application: Joi.string().max(32).required().label('Application'), - status: Joi.string().required().label('Status'), - }); - - req.body.id = req.params['id']; - - const param: Menu = await schema.validateAsync(req.body); - - const repo = OrmHelper.DB.getRepository(Menu); - - const data = await repo.findOneBy({ id: param.id }); - - if (data != null) { - data.module = param.module - data.name = param.name - data.link = param.link - data.order_number = param.order_number - data.icon = param.icon - data.application = param.application - data.status = param.status - - if (param.id_parent) { - data.id_parent = param.id_parent - } - - await repo.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_update, data); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_update, err.message); - } - } - - static async delete(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Menu'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'Menu ID.', - required: true, - type: 'string' - } - #swagger.parameters['hard'] = { - in: 'path', - description: 'Is Hard Delete', - required: false, - type: 'boolean' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID'), - hard: Joi.bool().optional().allow('').label('Is hard delete?') - }); - - const param: { id: string, hard: boolean } = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(Menu); - - const affected = (!param.hard ? await repo.softDelete({ id: param.id }) : await repo.delete({ id: param.id })).affected; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_delete, err.message); - } - } - - static async restore(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Menu'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.parameters['id'] = { - in: 'path', - description: 'Menu ID.', - required: true, - type: 'string' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID') - }); - - const param: Menu = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(Menu); - - const affected = (await repo.restore({ id: param.id })).affected; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_restore, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_restore, err.message); - } - } -} \ No newline at end of file diff --git a/src/controllers/munisipo.ts b/src/controllers/munisipo.ts deleted file mode 100644 index e1b0229..0000000 --- a/src/controllers/munisipo.ts +++ /dev/null @@ -1,391 +0,0 @@ -import { Response, NextFunction, Application } from "express"; -import { Request } from "express-jwt"; -import { ReturnHelper } from "../helpers/express/return"; -import { OrmHelper } from "../helpers/orm"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import { Language } from "../langs/lang"; -import { Paging } from "entity"; -import CommonHelper from "../helpers/common"; -import * as fastcsv from 'fast-csv'; -import dayjs from "dayjs"; -import { Munisipo } from "entity"; - -const log: Logger = new Logger({ name: '[MunisipoController]', type: 'pretty' }); - -export class MunisipoController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Munisipo'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['filter'] = { - description: 'Filter with 2 format :
  • Simple format use text plaint will filter eq:code or like %name%
  • Advance format using field existing {status:\'Y\', any:\'SAME AS PLAINT LOGIC\', etc...}
', - in: 'query', - type: 'string' - } - #swagger.parameters['limit'] = { - in: 'query', - required: true, - type: 'number' - } - #swagger.parameters['page'] = { - in: 'query', - required: true, - type: 'number' - } - #swagger.parameters['with_deleted'] = { - in: 'query', - required: true, - type: 'boolean' - } - #swagger.parameters['order_field'] = { - in: 'query', - required: true, - type: 'string' - } - #swagger.parameters['order_direction'] = { - in: 'query', - required: true, - schema: { - '@enum': ['ASC', 'DESC'] - } - } - */ - - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow('').optional().label('Filter'), - page: Joi.number().required().min(1).label('Page'), - limit: Joi.number().required().min(1).label('Limit'), - with_deleted: Joi.bool().required().label('With Deleted'), - order_field: Joi.string().required().label('Order Field'), - order_direction: Joi.string().allow('asc', 'desc').required().label('Order Direction'), - }); - - const param: Paging = await schema.validateAsync(req.query); - - const repo = OrmHelper.DB.getRepository(Munisipo); - - const offset = (param.page - 1) * param.limit - - const { whereAttr, whereVal } = CommonHelper.handleFilter({ - filter: param.filter, - col_any_eq: ['code'], - col_any_like: ['name'] - }); - - const res_count = repo.createQueryBuilder() - .where(whereAttr, whereVal); - const res_list = repo.createQueryBuilder() - .where(whereAttr, whereVal) - .orderBy(param.order_field, param.order_direction) - .offset(offset) - .limit(param.limit); - - if (param.with_deleted) { - res_count.withDeleted(); - res_list.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async export(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Munisipo'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['filter'] = { - description: 'Filter with 2 format :
  • Simple format use text plaint will filter eq:code or like %name%
  • Advance format using field existing {status:\'Y\', any:\'SAME AS PLAINT LOGIC\', etc...}
', - in: 'query', - type: 'string' - } - #swagger.parameters['filter'] = { - in: 'query', - type: 'string' - } - #swagger.parameters['order_field'] = { - in: 'query', - required: true, - type: 'string' - } - #swagger.parameters['order_direction'] = { - in: 'query', - required: true, - schema: { - '@enum': ['ASC', 'DESC'] - } - } - */ - - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow('').optional().label('Filter'), - order_field: Joi.string().required().label('Order Field'), - order_direction: Joi.string().allow('asc', 'desc').required().label('Order Direction'), - }); - - const param: Paging = await schema.validateAsync(req.query); - - const repo = OrmHelper.DB.getRepository(Munisipo); - - const { whereAttr, whereVal } = CommonHelper.handleFilter({ - filter: param.filter, - col_any_eq: ['code'], - col_any_like: ['name'] - }); - - const filename = "munisipo.csv"; - - res.setHeader('Content-Type', 'text/csv'); - res.setHeader('Content-Disposition', 'attachment; filename=' + filename); - - const csvStream = fastcsv.format({ - headers: true, - writeHeaders: true, - transform: (row: Munisipo): any => ({ - ...row, - created_at: dayjs(row.created_at).format('DD-MM-YYYY HH:MM:ss'), - }) - }); - csvStream.pipe(res); - - const limit = 50; - - const fetchAndWrite = async (page: any) => { - const offset = (page - 1) * limit - - const data = await repo.createQueryBuilder() - .where(whereAttr, whereVal) - .select([ - 'id', - 'code', - 'name', - 'status', - 'created_at']) - .orderBy(param.order_field, param.order_direction) - .offset(offset) - .limit(limit).getRawMany(); - - if (CommonHelper.countObject(data) === 0) { - csvStream.end(); - } else { - data.forEach((item: any) => csvStream.write(item)); - - if (CommonHelper.countObject(data) == limit) { - fetchAndWrite(page + 1); - } else { - csvStream.end(); - } - } - }; - - fetchAndWrite(1); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Munisipo'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/munisipo" - } - } - } - } - */ - - try { - const schema = Joi.object().keys({ - code: Joi.string().max(128).required().label('Code'), - name: Joi.string().max(256).required().label('Name'), - status: Joi.string().required().label('Status'), - }); - - const param: Munisipo = await schema.validateAsync(req.body); - - const data = new Munisipo() - data.code = param.code - data.name = param.name - data.status = param.status - - await OrmHelper.DB.manager.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 401, Language.lang.failed_insert, err.message); - } - } - - static async update(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Munisipo'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'Munisipo ID.', - required: true, - type: 'string' - } - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/munisipo" - } - } - } - } - */ - - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID'), - code: Joi.string().max(128).required().label('Code'), - name: Joi.string().max(256).required().label('Name'), - status: Joi.string().required().label('Status'), - }); - - req.body.id = req.params['id']; - - const param: Munisipo = await schema.validateAsync(req.body); - - const repo = OrmHelper.DB.getRepository(Munisipo); - - const data = await repo.findOneBy({ id: param.id }); - - if (data != null) { - data.code = param.code - data.name = param.name - data.status = param.status - - await repo.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_update, data); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_update, err.message); - } - } - - static async delete(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Munisipo'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'Munisipo ID.', - required: true, - type: 'string' - } - #swagger.parameters['hard'] = { - in: 'path', - description: 'Is Hard Delete', - required: false, - type: 'boolean' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID'), - hard: Joi.bool().optional().allow('').label('Is hard delete?') - }); - - const param: { id: string, hard: boolean } = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(Munisipo); - - const affected = (!param.hard ? await repo.softDelete({ id: param.id }) : await repo.delete({ id: param.id })).affected; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_delete, err.message); - } - } - - static async restore(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Munisipo'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.parameters['id'] = { - in: 'path', - description: 'Munisipo ID.', - required: true, - type: 'string' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID') - }); - - const param: Munisipo = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(Munisipo); - - const affected = (await repo.restore({ id: param.id })).affected; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_restore, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_restore, err.message); - } - } -} \ No newline at end of file diff --git a/src/controllers/nationality.ts b/src/controllers/nationality.ts deleted file mode 100644 index 0fd1601..0000000 --- a/src/controllers/nationality.ts +++ /dev/null @@ -1,392 +0,0 @@ -import { Response, NextFunction, Application } from "express"; -import { Request } from "express-jwt"; -import { ReturnHelper } from "../helpers/express/return"; -import { OrmHelper } from "../helpers/orm"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import { Language } from "../langs/lang"; -import { Paging } from "entity"; -import CommonHelper from "../helpers/common"; -import * as fastcsv from 'fast-csv'; -import dayjs from "dayjs"; -import { Nationality } from "entity"; - -const log: Logger = new Logger({ name: '[NationalityController]', type: 'pretty' }); - -export class NationalityController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Nationality'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['filter'] = { - description: 'Filter with 2 format :
  • Simple format use text plaint will filter eq:code or like %name%
  • Advance format using field existing {status:\'Y\', any:\'SAME AS PLAINT LOGIC\', etc...}
', - in: 'query', - type: 'string' - } - #swagger.parameters['limit'] = { - in: 'query', - required: true, - type: 'number' - } - #swagger.parameters['page'] = { - in: 'query', - required: true, - type: 'number' - } - #swagger.parameters['with_deleted'] = { - in: 'query', - required: true, - type: 'boolean' - } - #swagger.parameters['order_field'] = { - in: 'query', - required: true, - type: 'string' - } - #swagger.parameters['order_direction'] = { - in: 'query', - required: true, - schema: { - '@enum': ['ASC', 'DESC'] - } - } - */ - - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow('').optional().label('Filter'), - page: Joi.number().required().min(1).label('Page'), - limit: Joi.number().required().min(1).label('Limit'), - with_deleted: Joi.bool().required().label('With Deleted'), - order_field: Joi.string().required().label('Order Field'), - order_direction: Joi.string().allow('asc', 'desc').required().label('Order Direction'), - }); - - const param: Paging = await schema.validateAsync(req.query); - - const repo = OrmHelper.DB.getRepository(Nationality); - - const offset = (param.page - 1) * param.limit - - const { whereAttr, whereVal } = CommonHelper.handleFilter({ - filter: param.filter, - col_any_eq: ['code'], - col_any_like: ['name'] - }); - - const res_count = repo.createQueryBuilder() - .where(whereAttr, whereVal); - const res_list = repo.createQueryBuilder() - .where(whereAttr, whereVal) - .orderBy(param.order_field, param.order_direction) - .offset(offset) - .limit(param.limit); - - if (param.with_deleted) { - res_count.withDeleted(); - res_list.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async export(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Nationality'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['filter'] = { - description: 'Filter with 2 format :
  • Simple format use text plaint will filter eq:code or like %name%
  • Advance format using field existing {status:\'Y\', any:\'SAME AS PLAINT LOGIC\', etc...}
', - in: 'query', - type: 'string' - } - #swagger.parameters['filter'] = { - in: 'query', - type: 'string' - } - #swagger.parameters['order_field'] = { - in: 'query', - required: true, - type: 'string' - } - #swagger.parameters['order_direction'] = { - in: 'query', - required: true, - schema: { - '@enum': ['ASC', 'DESC'] - } - } - */ - - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow('').optional().label('Filter'), - order_field: Joi.string().required().label('Order Field'), - order_direction: Joi.string().allow('asc', 'desc').required().label('Order Direction'), - }); - - const param: Paging = await schema.validateAsync(req.query); - - const repo = OrmHelper.DB.getRepository(Nationality); - - const { whereAttr, whereVal } = CommonHelper.handleFilter({ - filter: param.filter, - col_any_eq: ['code'], - col_any_like: ['name'] - }); - - const filename = "nationality.csv"; - - res.setHeader('Content-Type', 'text/csv'); - res.setHeader('Content-Disposition', 'attachment; filename=' + filename); - - const csvStream = fastcsv.format({ - headers: true, - writeHeaders: true, - transform: (row: Nationality): any => ({ - ...row, - created_at: dayjs(row.created_at).format('DD-MM-YYYY HH:MM:ss'), - }) - }); - csvStream.pipe(res); - - const limit = 50; - - const fetchAndWrite = async (page: any) => { - const offset = (page - 1) * limit - - const data = await repo.createQueryBuilder() - .where(whereAttr, whereVal) - .select([ - 'id', - 'code', - 'name', - 'status', - 'created_at']) - .orderBy(param.order_field, param.order_direction) - .offset(offset) - .limit(limit).getRawMany(); - - if (CommonHelper.countObject(data) === 0) { - csvStream.end(); - } else { - data.forEach((item: any) => csvStream.write(item)); - - if (CommonHelper.countObject(data) == limit) { - fetchAndWrite(page + 1); - } else { - csvStream.end(); - } - } - }; - - fetchAndWrite(1); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Nationality'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/nationality" - } - } - } - } - */ - - try { - const schema = Joi.object().keys({ - code: Joi.string().max(128).required().label('Code'), - name: Joi.string().max(256).required().label('Name'), - status: Joi.string().required().label('Status'), - }); - - const param: Nationality = await schema.validateAsync(req.body); - - const data = new Nationality() - data.code = param.code - data.name = param.name - data.status = param.status - - await OrmHelper.DB.manager.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 401, Language.lang.failed_insert, err.message); - } - } - - static async update(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Nationality'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'Nationality ID.', - required: true, - type: 'string' - } - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/nationality" - } - } - } - } - */ - - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID'), - code: Joi.string().max(128).required().label('Code'), - name: Joi.string().max(256).required().label('Name'), - status: Joi.string().required().label('Status'), - }); - - req.body.id = req.params['id']; - - const param: Nationality = await schema.validateAsync(req.body); - - const repo = OrmHelper.DB.getRepository(Nationality); - - const data = await repo.findOneBy({ id: param.id }); - - if (data != null) { - data.code = param.code - data.name = param.name - data.status = param.status - - await repo.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_update, data); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_update, err.message); - } - } - - static async delete(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Nationality'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'Nationality ID.', - required: true, - type: 'string' - } - #swagger.parameters['hard'] = { - in: 'path', - description: 'Is Hard Delete', - required: false, - type: 'boolean' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID'), - hard: Joi.bool().optional().allow('').label('Is hard delete?') - }); - - const param: { id: string, hard: boolean } = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(Nationality); - - const affected = (!param.hard ? await repo.softDelete({ id: param.id }) : await repo.delete({ id: param.id })).affected; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_delete, err.message); - } - } - - static async restore(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Nationality'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.parameters['id'] = { - in: 'path', - description: 'Nationality ID.', - required: true, - type: 'string' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID') - }); - - const param: Nationality = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(Nationality); - - const affected = (await repo.restore({ id: param.id })).affected; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_restore, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_restore, err.message); - } - } -} - diff --git a/src/controllers/patient_group.ts b/src/controllers/patient_group.ts deleted file mode 100644 index 8929a3e..0000000 --- a/src/controllers/patient_group.ts +++ /dev/null @@ -1,363 +0,0 @@ -import { Response, NextFunction, Application } from "express"; -import { Request } from "express-jwt"; -import { ReturnHelper } from "../helpers/express/return"; -import { OrmHelper } from "../helpers/orm"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import { Language } from "../langs/lang"; -import { PatientGroup, Paging } from "entity"; -import CommonHelper from "../helpers/common"; -import * as fastcsv from 'fast-csv'; -import dayjs from "dayjs"; -import { PatientGroupModel } from "../model/patient_group"; - -const log: Logger = new Logger({ name: '[PatientGroupController]', type: 'pretty' }); - -export class PatientGroupController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['PatientGroup'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['filter'] = { description: '', in: 'query', type: 'string' } - #swagger.parameters['limit'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['page'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['with_deleted'] = { in: 'query', required: true, type: 'boolean' } - #swagger.parameters['order_field'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['order_direction'] = { in: 'query', required: true, schema: { '@enum': ['ASC', 'DESC'] } } - */ - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().required().label("With Deleted"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").required().label("Order Direction"), - }); - - let param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await PatientGroupModel.list(filter); - - const offset = (param.page - 1) * param.limit; - let limit = param.limit; - - const res_count = query; - const res_list = query - .orderBy("patient_group." + param.order_field, param.order_direction) - .offset(offset) - .limit(limit); - - if (param.with_deleted) { - res_count.withDeleted(); - res_list.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async export(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['PatientGroup'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['filter'] = { - description: 'Filter with 2 format :
  • Simple format use text plaint will filter eq:code or like %name%
  • Advance format using field existing {status:\'Y\', any:\'SAME AS PLAINT LOGIC\', etc...}
', - in: 'query', - type: 'string' - } - #swagger.parameters['filter'] = { - in: 'query', - type: 'string' - } - #swagger.parameters['order_field'] = { - in: 'query', - required: true, - type: 'string' - } - #swagger.parameters['order_direction'] = { - in: 'query', - required: true, - schema: { - '@enum': ['ASC', 'DESC'] - } - } - */ - - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow('').optional().label('Filter'), - order_field: Joi.string().required().label('Order Field'), - order_direction: Joi.string().allow('asc', 'desc').required().label('Order Direction'), - }); - - const param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await PatientGroupModel.list(filter); - const data = await query.getMany(); - - const filename = "patient_group.csv"; - - res.setHeader('Content-Type', 'text/csv'); - res.setHeader('Content-Disposition', 'attachment; filename=' + filename); - - const csvStream = fastcsv.format({ - headers: true, - writeHeaders: true, - transform: (row: PatientGroup): any => ({ - ...row, - created_at: dayjs(row.created_at).format('DD-MM-YYYY HH:MM:ss'), - }) - }); - csvStream.pipe(res); - - const limit = 50; - - const fetchAndWrite = async (page: any) => { - - if (CommonHelper.countObject(data) === 0) { - csvStream.end(); - } else { - data.forEach((item: any) => csvStream.write(item)); - - if (CommonHelper.countObject(data) == limit) { - fetchAndWrite(page + 1); - } else { - csvStream.end(); - } - } - }; - - fetchAndWrite(1); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['PatientGroup'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/patient_group" - } - } - } - } - */ - try { - const schema = Joi.object().keys({ - patient_group_name: Joi.string().max(256).required().label('Name'), - }); - - const param: any = await schema.validateAsync(req.body); - - const data = new PatientGroup() - data.patient_group_name = param.patient_group_name - data.created_by = req.auth.data.name; - - await OrmHelper.DB.manager.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 401, Language.lang.failed_insert, err.message); - } - } - - static async update(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['PatientGroup'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'PatientGroup ID.', - required: true, - type: 'string' - } - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/patient_group" - } - } - } - } - */ - - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID'), - patient_group_name: Joi.string().max(256).required().label('Name'), - }); - - req.body.id = req.params['id']; - - const param: any = await schema.validateAsync(req.body); - - const repo = OrmHelper.DB.getRepository(PatientGroup); - - const data = await repo.findOneBy({ id: param.id }); - - if (data != null) { - data.patient_group_name = param.patient_group_name - data.updated_by = req.auth.data.name; - - await repo.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_update, data); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_update, err.message); - } - } - - static async delete(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['PatientGroup'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'Patient Group ID.', - required: true, - type: 'string' - } - #swagger.parameters['hard'] = { - in: 'path', - description: 'Is Hard Delete', - required: false, - type: 'boolean' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID'), - hard: Joi.bool().optional().allow('').label('Is hard delete?') - }); - - const param: { id: string, hard: boolean } = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(PatientGroup); - - const existData = await repo.findOne({ where: { id: param.id } }); - if (existData && !param.hard) { - existData.deleted_by = req.auth.data.name; - await OrmHelper.DB.manager.save(existData); - } - - const affected = (!param.hard ? await repo.softDelete({ id: param.id }) : await repo.delete({ id: param.id })).affected; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_delete, err.message); - } - } - - static async restore(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['PatientGroup'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.parameters['id'] = { - in: 'path', - description: 'PatientGroup ID.', - required: true, - type: 'string' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID') - }); - - const param: PatientGroup = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(PatientGroup); - - const affected = (await repo.restore({ id: param.id })).affected; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_restore, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_restore, err.message); - } - } - - static async detail(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['PatientGroup'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { description: '', in: 'path', type: 'string' } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("Patient Group Id"), - }); - - let param: any = await schema.validateAsync(req.params); - - let data = await PatientGroupModel.list({ "id": param.id }).then((q) => q.getOne()); - if (!data) throw { message: "Patient Group Not Found" }; - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_view, data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_not_found, err.message); - } - } -} \ No newline at end of file diff --git a/src/controllers/patient_guarantor.ts b/src/controllers/patient_guarantor.ts deleted file mode 100644 index 238845a..0000000 --- a/src/controllers/patient_guarantor.ts +++ /dev/null @@ -1,438 +0,0 @@ -import { Response, NextFunction, Application } from "express"; -import { Request } from "express-jwt"; -import { ReturnHelper } from "../helpers/express/return"; -import { OrmHelper } from "../helpers/orm"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import { Language } from "../langs/lang"; -import { PatientGuarantor, Paging } from "entity"; -import CommonHelper from "../helpers/common"; -import * as fastcsv from 'fast-csv'; -import dayjs from "dayjs"; -import { PatientGuarantorModel } from "../model/patient_guarantor"; - -const log: Logger = new Logger({ name: '[PatientGuarantorController]', type: 'pretty' }); - -export class PatientGuarantorController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['PatientGuarantor'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['filter'] = { description: '', in: 'query', type: 'string' } - #swagger.parameters['limit'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['page'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['with_deleted'] = { in: 'query', required: true, type: 'boolean' } - #swagger.parameters['order_field'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['order_direction'] = { in: 'query', required: true, schema: { '@enum': ['ASC', 'DESC'] } } - */ - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().required().label("With Deleted"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").required().label("Order Direction"), - }); - - let param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - let filterAny = filter.any && filter.any !== "" ? filter.any : ""; - - let filterObj = { ...filter } as any; - delete filterObj.any; - filterObj = { ...filterObj }; - - var query = await PatientGuarantorModel.list(filterObj, filterAny); - - const offset = (param.page - 1) * param.limit; - let limit = param.limit; - - const res_count = query; - const res_list = query - .orderBy("patient_guarantor." + param.order_field, param.order_direction) - .offset(offset) - .limit(limit); - - if (param.with_deleted) { - res_count.withDeleted(); - res_list.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async export(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['PatientGuarantor'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['filter'] = { - description: 'Filter with 2 format :
  • Simple format use text plaint will filter eq:code or like %name%
  • Advance format using field existing {status:\'Y\', any:\'SAME AS PLAINT LOGIC\', etc...}
', - in: 'query', - type: 'string' - } - #swagger.parameters['filter'] = { - in: 'query', - type: 'string' - } - #swagger.parameters['order_field'] = { - in: 'query', - required: true, - type: 'string' - } - #swagger.parameters['order_direction'] = { - in: 'query', - required: true, - schema: { - '@enum': ['ASC', 'DESC'] - } - } - */ - - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow('').optional().label('Filter'), - order_field: Joi.string().required().label('Order Field'), - order_direction: Joi.string().allow('asc', 'desc').required().label('Order Direction'), - }); - - const param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await PatientGuarantorModel.list(filter); - const data = await query.getMany(); - - const filename = "patient_guarantor.csv"; - - res.setHeader('Content-Type', 'text/csv'); - res.setHeader('Content-Disposition', 'attachment; filename=' + filename); - - const csvStream = fastcsv.format({ - headers: true, - writeHeaders: true, - transform: (row: PatientGuarantor): any => ({ - ...row, - created_at: dayjs(row.created_at).format('DD-MM-YYYY HH:MM:ss'), - }) - }); - csvStream.pipe(res); - - const limit = 50; - - const fetchAndWrite = async (page: any) => { - - if (CommonHelper.countObject(data) === 0) { - csvStream.end(); - } else { - data.forEach((item: any) => csvStream.write(item)); - - if (CommonHelper.countObject(data) == limit) { - fetchAndWrite(page + 1); - } else { - csvStream.end(); - } - } - }; - - fetchAndWrite(1); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['PatientGuarantor'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/patient_guarantor" - } - } - } - } - */ - try { - const schema = Joi.object().keys({ - guarantor_name: Joi.string().max(256).required().label('Guarantor Name'), - phone: Joi.string().max(15).required().label('Phone'), - // province: Joi.string().max(128).required().label('Province'), - // city: Joi.string().max(128).required().label('City'), - munisipo: Joi.string().allow(null, "").label("Munisipo ID"), - administrativu: Joi.string().allow(null, "").label("Administrativu ID"), - aldeia: Joi.string().allow(null, "").label("Aldeia ID"), - suco: Joi.string().allow(null, "").label("Suco ID"), - // zip_code: Joi.string().max(10).required().label('Zip Code'), - agreement_no: Joi.string().max(50).required().label('Agreement No.'), - agreement_desc: Joi.string().max(512).optional().label('Agreement Description'), - patient_group_id: Joi.string().guid({ version: 'uuidv4' }).required().label('Patient Group'), - faretype: Joi.string().guid({ version: 'uuidv4' }).required().label('Fare Type'), - maximalliability: Joi.number().optional().label('Maximal Liability'), - is_default: Joi.bool().optional().default(false).label('Is Default'), - is_full_paid: Joi.bool().optional().default(false).label('Is Full Paid'), - }); - - const param: any = await schema.validateAsync(req.body); - - if (param.is_default === true) { - await OrmHelper.DB.getRepository(PatientGuarantor) - .update({ is_default: true }, { is_default: false, updated_by: req.auth?.data.name }); - } - - const data = new PatientGuarantor() - data.guarantor_name = param.guarantor_name; - data.phone = param.phone; - // data.province = param.province; - // data.city = param.city; - data.administrativu = param.administrativu; - data.suco = param.suco; - data.aldeia = param.aldeia; - data.munisipo = param.munisipo; - // data.zip_code = param.zip_code; - data.agreement_no = param.agreement_no; - data.agreement_desc = param.agreement_desc; - data.patient_group = param.patient_group_id; - data.faretype = param.faretype; - data.is_default = param.is_default; - data.is_full_paid = param.is_full_paid; - data.maximal_liability = param.maximalliability; - data.created_by = req.auth?.data.name; - data.updated_by = req.auth?.data.name; - - await OrmHelper.DB.manager.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 401, Language.lang.failed_insert, err.message); - } - } - - static async update(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['PatientGuarantor'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'PatientGuarantor ID.', - required: true, - type: 'string' - } - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/patient_guarantor" - } - } - } - } - */ - - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID'), - guarantor_name: Joi.string().max(256).required().label('Guarantor Name'), - phone: Joi.string().max(15).required().label('Phone'), - // province: Joi.string().max(128).required().label('Province'), - // city: Joi.string().max(128).required().label('City'), - munisipo: Joi.string().allow(null, "").label("Munisipo ID"), - administrativu: Joi.string().allow(null, "").label("Administrativu ID"), - aldeia: Joi.string().allow(null, "").label("Aldeia ID"), - suco: Joi.string().allow(null, "").label("Suco ID"), - // zip_code: Joi.string().max(10).required().label('Zip Code'), - agreement_no: Joi.string().max(50).required().label('Agreement No.'), - agreement_desc: Joi.string().max(512).optional().label('Agreement Description'), - patient_group_id: Joi.string().guid({ version: 'uuidv4' }).required().label('Patient Group'), - faretype: Joi.string().guid({ version: 'uuidv4' }).required().label('Fare Type'), - maximalliability: Joi.number().optional().label('Maximal Liability'), - is_default: Joi.bool().optional().default(false).label('Is Default'), - is_full_paid: Joi.bool().optional().default(false).label('Is Full Paid'), - }); - - req.body.id = req.params['id']; - - const param: any = await schema.validateAsync(req.body); - - const repo = OrmHelper.DB.getRepository(PatientGuarantor); - - const data = await repo.findOneBy({ id: param.id }); - - if (!data) return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - - if (param.is_default === true) { - await OrmHelper.DB.getRepository(PatientGuarantor) - .update({ is_default: true }, { is_default: false, updated_by: req.auth?.data.name }); - } - - data.guarantor_name = param.guarantor_name; - data.phone = param.phone; - // data.province = param.province; - // data.city = param.city; - data.administrativu = param.administrativu; - data.suco = param.suco; - data.aldeia = param.aldeia; - data.munisipo = param.munisipo; - // data.zip_code = param.zip_code; - data.agreement_no = param.agreement_no; - data.agreement_desc = param.agreement_desc; - data.patient_group = param.patient_group_id; - data.faretype = param.faretype; - data.maximal_liability = param.maximalliability; - data.is_default = param.is_default; - data.is_full_paid = param.is_full_paid; - data.created_by = req.auth?.data.name; - data.updated_by = req.auth?.data.name; - - await repo.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_update, data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_update, err.message); - } - } - - static async delete(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['PatientGuarantor'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'Item Group ID.', - required: true, - type: 'string' - } - #swagger.parameters['hard'] = { - in: 'path', - description: 'Is Hard Delete', - required: false, - type: 'boolean' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID'), - hard: Joi.bool().optional().allow('').label('Is hard delete?') - }); - - const param: { id: string, hard: boolean } = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(PatientGuarantor); - - const existData = await repo.findOne({ where: { id: param.id } }); - if (existData && !param.hard) { - existData.deleted_by = req.auth?.data.name; - await OrmHelper.DB.manager.save(existData); - } - - const affected = (!param.hard ? await repo.softDelete({ id: param.id }) : await repo.delete({ id: param.id })).affected ?? 0; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_delete, err.message); - } - } - - static async restore(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['PatientGuarantor'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.parameters['id'] = { - in: 'path', - description: 'PatientGuarantor ID.', - required: true, - type: 'string' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID') - }); - - const param: PatientGuarantor = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(PatientGuarantor); - - const affected = (await repo.restore({ id: param.id })).affected ?? 0; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_restore, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_restore, err.message); - } - } - - static async detail(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['PatientGuarantor'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { description: '', in: 'path', type: 'string' } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("Patient Guarantor Id"), - }); - - let param: any = await schema.validateAsync(req.params); - - let data = await PatientGuarantorModel.list({ "patient_guarantor.id": param.id }).then((q) => q.getOne()); - if (!data) throw { message: "Patient Guarantor Not Found" }; - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_view, data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_not_found, err.message); - } - } -} \ No newline at end of file diff --git a/src/controllers/payment-method.ts b/src/controllers/payment-method.ts deleted file mode 100644 index 5d38e54..0000000 --- a/src/controllers/payment-method.ts +++ /dev/null @@ -1,369 +0,0 @@ -import { Response, NextFunction, Application } from "express"; -import { Request } from "express-jwt"; -import { ReturnHelper } from "../helpers/express/return"; -import { OrmHelper } from "../helpers/orm"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import { Language } from "../langs/lang"; -import { Paging, PaymentMethod } from "entity"; -import CommonHelper from "../helpers/common"; -import * as fastcsv from 'fast-csv'; -import dayjs from "dayjs"; -import { PaymentMethodModel } from "../model/payment_method"; - -const log: Logger = new Logger({ name: '[PaymentMethodController]', type: 'pretty' }); - -export class PaymentMethodController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['PaymentMethod'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['filter'] = { description: '', in: 'query', type: 'string' } - #swagger.parameters['limit'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['page'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['with_deleted'] = { in: 'query', required: true, type: 'boolean' } - #swagger.parameters['order_field'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['order_direction'] = { in: 'query', required: true, schema: { '@enum': ['ASC', 'DESC'] } } - */ - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().required().label("With Deleted"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").required().label("Order Direction"), - }); - - let param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - let filterAny = filter.any && filter.any !== "" ? filter.any : ""; - - let filterObj = { ...filter } as any; - delete filterObj.any; - filterObj = { ...filterObj }; - - var query = await PaymentMethodModel.list(filterObj, filterAny); - - const offset = (param.page - 1) * param.limit; - let limit = param.limit; - - const res_count = query; - const res_list = query - .orderBy("payment_method." + param.order_field, param.order_direction) - .offset(offset) - .limit(limit); - - if (param.with_deleted) { - res_count.withDeleted(); - res_list.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async export(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['PaymentMethod'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['filter'] = { - description: 'Filter with 2 format :
  • Simple format use text plaint will filter eq:code or like %name%
  • Advance format using field existing {status:\'Y\', any:\'SAME AS PLAINT LOGIC\', etc...}
', - in: 'query', - type: 'string' - } - #swagger.parameters['filter'] = { - in: 'query', - type: 'string' - } - #swagger.parameters['order_field'] = { - in: 'query', - required: true, - type: 'string' - } - #swagger.parameters['order_direction'] = { - in: 'query', - required: true, - schema: { - '@enum': ['ASC', 'DESC'] - } - } - */ - - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow('').optional().label('Filter'), - order_field: Joi.string().required().label('Order Field'), - order_direction: Joi.string().allow('asc', 'desc').required().label('Order Direction'), - }); - - const param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await PaymentMethodModel.list(filter); - const data = await query.getMany(); - - const filename = "payment_method.csv"; - - res.setHeader('Content-Type', 'text/csv'); - res.setHeader('Content-Disposition', 'attachment; filename=' + filename); - - const csvStream = fastcsv.format({ - headers: true, - writeHeaders: true, - transform: (row: PaymentMethod): any => ({ - ...row, - created_at: dayjs(row.created_at).format('DD-MM-YYYY HH:MM:ss'), - }) - }); - csvStream.pipe(res); - - const limit = 50; - - const fetchAndWrite = async (page: any) => { - - if (CommonHelper.countObject(data) === 0) { - csvStream.end(); - } else { - data.forEach((item: any) => csvStream.write(item)); - - if (CommonHelper.countObject(data) == limit) { - fetchAndWrite(page + 1); - } else { - csvStream.end(); - } - } - }; - - fetchAndWrite(1); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['PaymentMethod'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/payment_method" - } - } - } - } - */ - try { - const schema = Joi.object().keys({ - name: Joi.string().max(256).required().label('Name'), - }); - - const param: any = await schema.validateAsync(req.body); - - const data = new PaymentMethod() - data.name = param.name; - data.created_by = req.auth.data.name; - data.updated_by = req.auth.data.name; - - await OrmHelper.DB.manager.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 401, Language.lang.failed_insert, err.message); - } - } - - static async update(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['PaymentMethod'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'PaymentMethod ID.', - required: true, - type: 'string' - } - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/payment_method" - } - } - } - } - */ - - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID'), - name: Joi.string().max(256).required().label('Name'), - }); - - req.body.id = req.params['id']; - - const param: any = await schema.validateAsync(req.body); - - const repo = OrmHelper.DB.getRepository(PaymentMethod); - - const data = await repo.findOneBy({ id: param.id }); - - if (data != null) { - data.name = param.name; - data.updated_by = req.auth.data.name; - - await repo.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_update, data); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_update, err.message); - } - } - - static async delete(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['PaymentMethod'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'PaymentMethod ID.', - required: true, - type: 'string' - } - #swagger.parameters['hard'] = { - in: 'path', - description: 'Is Hard Delete', - required: false, - type: 'boolean' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID'), - hard: Joi.bool().optional().allow('').label('Is hard delete?') - }); - - const param: { id: string, hard: boolean } = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(PaymentMethod); - - const existData = await repo.findOne({ where: { id: param.id } }); - if (existData && !param.hard) { - existData.deleted_by = req.auth.data.name; - await OrmHelper.DB.manager.save(existData); - } - - const affected = (!param.hard ? await repo.softDelete({ id: param.id }) : await repo.delete({ id: param.id })).affected; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_delete, err.message); - } - } - - static async restore(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['PaymentMethod'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.parameters['id'] = { - in: 'path', - description: 'PaymentMethod ID.', - required: true, - type: 'string' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID') - }); - - const param: any = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(PaymentMethod); - - const affected = (await repo.restore({ id: param.id })).affected; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_restore, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_restore, err.message); - } - } - - static async detail(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['PaymentMethod'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { description: '', in: 'path', type: 'string' } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("PaymentMethod Id"), - }); - - let param: any = await schema.validateAsync(req.params); - - let data = await PaymentMethodModel.list({ "id": param.id }).then((q) => q.getOne()); - if (!data) throw { message: "PaymentMethod Not Found" }; - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_view, data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_not_found, err.message); - } - } -} \ No newline at end of file diff --git a/src/controllers/pharmacy.ts b/src/controllers/pharmacy.ts deleted file mode 100644 index 5378be4..0000000 --- a/src/controllers/pharmacy.ts +++ /dev/null @@ -1,88 +0,0 @@ -import { Room, Paging } from "entity"; -import { NextFunction, Response } from "express"; -import { Request } from "express-jwt"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import CommonHelper from "../helpers/common"; -import { ReturnHelper } from "../helpers/express/return"; -import { Language } from "../langs/lang"; -import { OrmHelper } from "../helpers/orm"; - -const log: Logger = new Logger({ - name: "[PharmacyController]", - type: "pretty", -}); - -const PHARMACY_DEPARTMENT_ID = "81b710d9-6fe3-4dd0-9900-fae31ecadb6f"; - -export class PharmacyController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['filter'] = { description: 'Filter: plain text or JSON object (status, code, etc.)', in: 'query', type: 'string' } - #swagger.parameters['limit'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['page'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['with_deleted'] = { in: 'query', required: true, type: 'boolean' } - #swagger.parameters['order_field'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['order_direction'] = { in: 'query', required: true, schema: { '@enum': ['ASC', 'DESC'] } } - */ - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().required().label("With Deleted"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").required().label("Order Direction"), - }); - - let param: Paging = await schema.validateAsync(req.query); - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - // Build query with department join - const repo = OrmHelper.DB.getRepository(Room); - let whereAttr: string[] = []; - let whereVal: any = {}; - - // Always filter by pharmacy department ID - whereAttr.push("department.id = :_departmentId"); - whereVal["_departmentId"] = PHARMACY_DEPARTMENT_ID; - - // Apply additional filters if provided - if (filter && Object.keys(filter).length > 0) { - const filterResult = CommonHelper.handleQueryFilter(filter, "Room"); - whereAttr = [...whereAttr, ...filterResult.whereAttr]; - whereVal = { ...whereVal, ...filterResult.whereVal }; - } - - const offset = (param.page - 1) * param.limit; - const res_count = repo.createQueryBuilder("Room") - .leftJoin("Room.department", "department") - .where(whereAttr.join(" and "), whereVal); - - const res_list = repo.createQueryBuilder("Room") - .leftJoinAndSelect("Room.department", "department") - .where(whereAttr.join(" and "), whereVal) - .orderBy("Room." + param.order_field, param.order_direction) - .offset(offset) - .limit(param.limit); - - if (param.with_deleted) { - res_count.withDeleted(); - res_list.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } -} diff --git a/src/controllers/pharmacy/factory.ts b/src/controllers/pharmacy/factory.ts deleted file mode 100644 index f3a01f9..0000000 --- a/src/controllers/pharmacy/factory.ts +++ /dev/null @@ -1,355 +0,0 @@ -import { Response, NextFunction, Application } from "express"; -import { Request } from "express-jwt"; -import { ReturnHelper } from "../../helpers/express/return"; -import { OrmHelper } from "../../helpers/orm"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import { Language } from "../../langs/lang"; -import { Factory, Paging } from "entity"; -import CommonHelper from "../../helpers/common"; -import * as fastcsv from 'fast-csv'; -import dayjs from "dayjs"; -import { FactoryModel } from "../../model/factory"; - -const log: Logger = new Logger({ name: '[FactoryController]', type: 'pretty' }); - -export class FactoryController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - Factory'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['filter'] = { description: '', in: 'query', type: 'string' } - #swagger.parameters['limit'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['page'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['with_deleted'] = { in: 'query', required: true, type: 'boolean' } - #swagger.parameters['order_field'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['order_direction'] = { in: 'query', required: true, schema: { '@enum': ['ASC', 'DESC'] } } - */ - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().required().label("With Deleted"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").required().label("Order Direction"), - }); - - let param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await FactoryModel.list(filter); - - const offset = (param.page - 1) * param.limit; - let limit = param.limit; - - const res_count = query; - const res_list = query - .orderBy("factory." + param.order_field, param.order_direction) - .offset(offset) - .limit(limit); - - if (param.with_deleted) { - res_count.withDeleted(); - res_list.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async export(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - Factory'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['filter'] = { - description: 'Filter with 2 format :
  • Simple format use text plaint will filter eq:code or like %name%
  • Advance format using field existing {status:\'Y\', any:\'SAME AS PLAINT LOGIC\', etc...}
', - in: 'query', - type: 'string' - } - #swagger.parameters['filter'] = { - in: 'query', - type: 'string' - } - #swagger.parameters['order_field'] = { - in: 'query', - required: true, - type: 'string' - } - #swagger.parameters['order_direction'] = { - in: 'query', - required: true, - schema: { - '@enum': ['ASC', 'DESC'] - } - } - */ - - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow('').optional().label('Filter'), - order_field: Joi.string().required().label('Order Field'), - order_direction: Joi.string().allow('asc', 'desc').required().label('Order Direction'), - }); - - const param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await FactoryModel.list(filter); - const data = await query.getMany(); - - const filename = "factory.csv"; - - res.setHeader('Content-Type', 'text/csv'); - res.setHeader('Content-Disposition', 'attachment; filename=' + filename); - - const csvStream = fastcsv.format({ - headers: true, - writeHeaders: true, - transform: (row: Factory): any => ({ - ...row, - created_at: dayjs(row.created_at).format('DD-MM-YYYY HH:MM:ss'), - }) - }); - csvStream.pipe(res); - - const limit = 50; - - const fetchAndWrite = async (page: any) => { - - if (CommonHelper.countObject(data) === 0) { - csvStream.end(); - } else { - data.forEach((item: any) => csvStream.write(item)); - - if (CommonHelper.countObject(data) == limit) { - fetchAndWrite(page + 1); - } else { - csvStream.end(); - } - } - }; - - fetchAndWrite(1); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - Factory'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/factory" - } - } - } - } - */ - try { - const schema = Joi.object().keys({ - factory_name: Joi.string().max(256).required().label('Name'), - address: Joi.string().max(512).allow('', null).label('Address'), - web: Joi.string().uri().max(256).allow('', null).label('Web'), - phone: Joi.string().max(50).allow('', null).label('Phone'), - email: Joi.string().email().max(256).allow('', null).label('Email') - }); - - const param: any = await schema.validateAsync(req.body); - - const data = new Factory() - data.factory_name = param.factory_name - data.address = param.address - data.web = param.web - data.phone = param.phone - data.email = param.email - data.created_by = req.auth.data.name; - - await OrmHelper.DB.manager.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 401, Language.lang.failed_insert, err.message); - } - } - - static async update(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - Factory'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'Factory ID.', - required: true, - type: 'string' - } - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/factory" - } - } - } - } - */ - - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID'), - factory_name: Joi.string().max(256).required().label('Name'), - address: Joi.string().max(512).allow('', null).label('Address'), - web: Joi.string().uri().max(256).allow('', null).label('Web'), - phone: Joi.string().max(50).allow('', null).label('Phone'), - email: Joi.string().email().max(256).allow('', null).label('Email') - }); - - req.body.id = req.params['id']; - - const param: any = await schema.validateAsync(req.body); - - const repo = OrmHelper.DB.getRepository(Factory); - - const data = await repo.findOneBy({ id: param.id }); - - if (data != null) { - data.factory_name = param.factory_name - data.address = param.address - data.web = param.web - data.phone = param.phone - data.email = param.email - data.updated_by = req.auth.data.name; - - await repo.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_update, data); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_update, err.message); - } - } - - static async delete(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - Factory'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'Factory ID.', - required: true, - type: 'string' - } - #swagger.parameters['hard'] = { - in: 'path', - description: 'Is Hard Delete', - required: false, - type: 'boolean' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID'), - hard: Joi.bool().optional().allow('').label('Is hard delete?') - }); - - const param: { id: string, hard: boolean } = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(Factory); - - const existData = await repo.findOne({ where: { id: param.id } }); - if (existData && !param.hard) { - existData.deleted_by = req.auth.data.name; - await OrmHelper.DB.manager.save(existData); - } - - const affected = (!param.hard ? await repo.softDelete({ id: param.id }) : await repo.delete({ id: param.id })).affected; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_delete, err.message); - } - } - - static async restore(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - Factory'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.parameters['id'] = { - in: 'path', - description: 'Factory ID.', - required: true, - type: 'string' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID') - }); - - const param: Factory = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(Factory); - - const affected = (await repo.restore({ id: param.id })).affected; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_restore, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_restore, err.message); - } - } -} \ No newline at end of file diff --git a/src/controllers/pharmacy/factory_to_supplier.ts b/src/controllers/pharmacy/factory_to_supplier.ts deleted file mode 100644 index 9560426..0000000 --- a/src/controllers/pharmacy/factory_to_supplier.ts +++ /dev/null @@ -1,409 +0,0 @@ -import { Response, NextFunction, Application } from "express"; -import { Request } from "express-jwt"; -import { ReturnHelper } from "../../helpers/express/return"; -import { OrmHelper } from "../../helpers/orm"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import { Language } from "../../langs/lang"; -import { Factory, FactoryToSupplier, Paging, Supplier } from "entity"; -import CommonHelper from "../../helpers/common"; -import * as fastcsv from 'fast-csv'; -import dayjs from "dayjs"; -import { FactoryToSupplierModel } from "../../model/factory_to_supplier"; - -const log: Logger = new Logger({ name: '[FactorytoSupplierController]', type: 'pretty' }); - -export class FactorytoSupplierController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - FactoryToSupplier'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['filter'] = { description: '', in: 'query', type: 'string' } - #swagger.parameters['limit'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['page'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['with_deleted'] = { in: 'query', required: true, type: 'boolean' } - #swagger.parameters['order_field'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['order_direction'] = { in: 'query', required: true, schema: { '@enum': ['ASC', 'DESC'] } } - */ - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().required().label("With Deleted"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").required().label("Order Direction"), - }); - - let param: any = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await FactoryToSupplierModel.list(filter); - - const offset = (param.page - 1) * param.limit; - let limit = param.limit; - - const res_count = query; - const res_list = query - .orderBy("factory_to_supplier." + param.order_field, param.order_direction) - .offset(offset) - .limit(limit); - - if (param.with_deleted) { - res_count.withDeleted(); - res_list.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async export(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - FactoryToSupplier'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['filter'] = { - description: 'Filter with 2 format :
  • Simple format use text plaint will filter eq:code or like %name%
  • Advance format using field existing {status:\'Y\', any:\'SAME AS PLAINT LOGIC\', etc...}
', - in: 'query', - type: 'string' - } - #swagger.parameters['filter'] = { - in: 'query', - type: 'string' - } - #swagger.parameters['order_field'] = { - in: 'query', - required: true, - type: 'string' - } - #swagger.parameters['order_direction'] = { - in: 'query', - required: true, - schema: { - '@enum': ['ASC', 'DESC'] - } - } - */ - - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow('').optional().label('Filter'), - order_field: Joi.string().required().label('Order Field'), - order_direction: Joi.string().allow('asc', 'desc').required().label('Order Direction'), - }); - - const param: any = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await FactoryToSupplierModel.list(filter); - const data = await query.getMany(); - - const filename = "factory_to_supplier.csv"; - - res.setHeader('Content-Type', 'text/csv'); - res.setHeader('Content-Disposition', 'attachment; filename=' + filename); - - const csvStream = fastcsv.format({ - headers: true, - writeHeaders: true, - transform: (row: FactoryToSupplier): any => ({ - ...row, - created_at: dayjs(row.created_at).format('DD-MM-YYYY HH:MM:ss'), - }) - }); - csvStream.pipe(res); - - const limit = 50; - - const fetchAndWrite = async (page: any) => { - - if (CommonHelper.countObject(data) === 0) { - csvStream.end(); - } else { - data.forEach((item: any) => csvStream.write(item)); - - if (CommonHelper.countObject(data) == limit) { - fetchAndWrite(page + 1); - } else { - csvStream.end(); - } - } - }; - - fetchAndWrite(1); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - FactoryToSupplier'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/factory_to_supplier" - } - } - } - } - */ - try { - const schema = Joi.object().keys({ - supplier_id: Joi.string() - .uuid() - .required() - .label("Supplier ID"), - - factory_ids: Joi.array() - .items(Joi.string().uuid().required()) - .min(1) - .required() - .label("Factory IDs") - }); - - const param: any = await schema.validateAsync(req.body); - - const factoryToSupplierRepo = OrmHelper.DB.getRepository(FactoryToSupplier); - const factoryRepo = OrmHelper.DB.getRepository(Factory); - const supplierRepo = OrmHelper.DB.getRepository(Supplier); - - await factoryToSupplierRepo - .createQueryBuilder() - .delete() - .from(FactoryToSupplier) - .where("supplier_id = :supplierId", { supplierId: param.supplier_id }) - .execute(); - - let relation : FactoryToSupplier; - for (const factoryId of param.factory_ids) { - relation = new FactoryToSupplier(); - relation.factory = await factoryRepo.findOneBy({ id: factoryId }); - relation.supplier = await supplierRepo.findOneBy({ id: param.supplier_id }); - relation.created_by = req.auth.data.name; - - await factoryToSupplierRepo.save(relation); - } - - const data = await factoryToSupplierRepo.createQueryBuilder("factory_to_supplier") - .leftJoinAndSelect("factory_to_supplier.factory", "factory") - .leftJoinAndSelect("factory_to_supplier.supplier", "supplier") - .where("factory_to_supplier.supplier_id = :supplierId", { supplierId: param.supplier_id }).getMany(); - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 401, Language.lang.failed_insert, err.message); - } - } - - static async update(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - FactoryToSupplier'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['supplier_id'] = { - in: 'path', - description: 'Supplier ID.', - required: true, - type: 'string' - } - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/factory_to_supplier" - } - } - } - } - */ - - try { - const schema = Joi.object().keys({ - supplier_id: Joi.string() - .uuid() - .required() - .label("Supplier ID"), - - factory_ids: Joi.array() - .items(Joi.string().uuid().optional()) - .required() - .label("Factory IDs") - }); - - req.body.supplier_id = req.params['supplier_id']; - - const param: any = await schema.validateAsync(req.body); - - const factoryToSupplierRepo = OrmHelper.DB.getRepository(FactoryToSupplier); - const factoryRepo = OrmHelper.DB.getRepository(Factory); - const supplierRepo = OrmHelper.DB.getRepository(Supplier); - - const supplier = await supplierRepo.findOneBy({ id: param.supplier_id }); - if(supplier == null) { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - - await factoryToSupplierRepo - .createQueryBuilder() - .delete() - .from(FactoryToSupplier) - .where("supplier_id = :supplierId", { supplierId: param.supplier_id }) - .execute(); - - if(param.factory_ids.length > 0) { - let relation : FactoryToSupplier; - for (const factoryId of param.factory_ids) { - relation = new FactoryToSupplier(); - relation.factory = await factoryRepo.findOneBy({ id: factoryId }); - relation.supplier = await supplierRepo.findOneBy({ id: param.supplier_id }); - relation.created_by = req.auth.data.name; - - await factoryToSupplierRepo.save(relation); - } - } - - const data = await factoryToSupplierRepo.createQueryBuilder("factory_to_supplier") - .leftJoinAndSelect("factory_to_supplier.factory", "factory") - .leftJoinAndSelect("factory_to_supplier.supplier", "supplier") - .where("factory_to_supplier.supplier_id = :supplierId", { supplierId: param.supplier_id }).getMany(); - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_update, data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_update, err.message); - } - } - - static async delete(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - FactoryToSupplier'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.parameters['supplier_id'] = { - in: 'path', - description: 'Supplier ID.', - required: true, - type: 'string' - } - #swagger.parameters['hard'] = { - in: 'path', - description: 'Is Hard Delete', - required: true, - type: 'boolean' - } - - */ - try { - const schema = Joi.object().keys({ - supplier_id: Joi.string().uuid().required().label('Supplier ID'), - hard: Joi.bool().optional().allow('').label('Is hard delete?') - }); - - const param: { id: string, supplier_id: string, hard: boolean } = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(FactoryToSupplier); - - let baseQuery = repo.createQueryBuilder().where("supplier_id = :supplierId", { supplierId: param.supplier_id }); - - const count = await baseQuery.getCount(); - if (count === 0) return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - - if (!param.hard) { - let updateQuery = repo.createQueryBuilder().update(FactoryToSupplier) - .set({ deleted_by: req.auth.data.name }) - .where("supplier_id = :supplierId", {supplierId: param.supplier_id}); - - await updateQuery.execute(); - - let softDeleteQuery = repo.createQueryBuilder().softDelete() - .where("supplier_id = :supplierId", {supplierId: param.supplier_id}); - - await softDeleteQuery.execute(); - } else { - let deleteQuery = repo.createQueryBuilder().delete() - .where("supplier_id = :supplierId", {supplierId: param.supplier_id}); - - await deleteQuery.execute(); - } - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_delete, err.message); - } - } - - static async restore(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - FactoryToSupplier'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.parameters['supplier_id'] = { - in: 'path', - description: 'Supplier ID.', - required: false, - type: 'string' - } - */ - try { - const schema = Joi.object().keys({ - supplier_id: Joi.string().uuid().required().label('Supplier ID'), - }); - - const param: any = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(FactoryToSupplier); - - let restoreQuery = repo.createQueryBuilder().restore() - .where("supplier_id = :supplierId", {supplierId: param.supplier_id}); - - const affected = (await restoreQuery.execute()).affected; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_restore, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_restore, err.message); - } - } -} \ No newline at end of file diff --git a/src/controllers/pharmacy/generic_name.ts b/src/controllers/pharmacy/generic_name.ts deleted file mode 100644 index d6c14b7..0000000 --- a/src/controllers/pharmacy/generic_name.ts +++ /dev/null @@ -1,339 +0,0 @@ -import { Response, NextFunction, Application } from "express"; -import { Request } from "express-jwt"; -import { ReturnHelper } from "../../helpers/express/return"; -import { OrmHelper } from "../../helpers/orm"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import { Language } from "../../langs/lang"; -import { GenericName, Paging } from "entity"; -import CommonHelper from "../../helpers/common"; -import * as fastcsv from 'fast-csv'; -import dayjs from "dayjs"; -import { GenericNameModel } from "../../model/generic_name"; - -const log: Logger = new Logger({ name: '[GenericNameController]', type: 'pretty' }); - -export class GenericNameController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - GenericName'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['filter'] = { description: '', in: 'query', type: 'string' } - #swagger.parameters['limit'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['page'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['with_deleted'] = { in: 'query', required: true, type: 'boolean' } - #swagger.parameters['order_field'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['order_direction'] = { in: 'query', required: true, schema: { '@enum': ['ASC', 'DESC'] } } - */ - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().required().label("With Deleted"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").required().label("Order Direction"), - }); - - let param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await GenericNameModel.list(filter); - - const offset = (param.page - 1) * param.limit; - let limit = param.limit; - - const res_count = query; - const res_list = query - .orderBy("generic_name." + param.order_field, param.order_direction) - .offset(offset) - .limit(limit); - - if (param.with_deleted) { - res_count.withDeleted(); - res_list.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async export(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - GenericName'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['filter'] = { - description: 'Filter with 2 format :
  • Simple format use text plaint will filter eq:code or like %name%
  • Advance format using field existing {status:\'Y\', any:\'SAME AS PLAINT LOGIC\', etc...}
', - in: 'query', - type: 'string' - } - #swagger.parameters['filter'] = { - in: 'query', - type: 'string' - } - #swagger.parameters['order_field'] = { - in: 'query', - required: true, - type: 'string' - } - #swagger.parameters['order_direction'] = { - in: 'query', - required: true, - schema: { - '@enum': ['ASC', 'DESC'] - } - } - */ - - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow('').optional().label('Filter'), - order_field: Joi.string().required().label('Order Field'), - order_direction: Joi.string().allow('asc', 'desc').required().label('Order Direction'), - }); - - const param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await GenericNameModel.list(filter); - const data = await query.getMany(); - - const filename = "generic_name.csv"; - - res.setHeader('Content-Type', 'text/csv'); - res.setHeader('Content-Disposition', 'attachment; filename=' + filename); - - const csvStream = fastcsv.format({ - headers: true, - writeHeaders: true, - transform: (row: GenericName): any => ({ - ...row, - created_at: dayjs(row.created_at).format('DD-MM-YYYY HH:MM:ss'), - }) - }); - csvStream.pipe(res); - - const limit = 50; - - const fetchAndWrite = async (page: any) => { - - if (CommonHelper.countObject(data) === 0) { - csvStream.end(); - } else { - data.forEach((item: any) => csvStream.write(item)); - - if (CommonHelper.countObject(data) == limit) { - fetchAndWrite(page + 1); - } else { - csvStream.end(); - } - } - }; - - fetchAndWrite(1); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - GenericName'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/generic_name" - } - } - } - } - */ - try { - const schema = Joi.object().keys({ - generic_name: Joi.string().max(256).required().label('Name'), - }); - - const param: any = await schema.validateAsync(req.body); - - const data = new GenericName() - data.generic_name = param.generic_name - data.created_by = req.auth.data.name; - - await OrmHelper.DB.manager.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 401, Language.lang.failed_insert, err.message); - } - } - - static async update(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - GenericName'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'GenericName ID.', - required: true, - type: 'string' - } - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/generic_name" - } - } - } - } - */ - - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID'), - generic_name: Joi.string().max(256).required().label('Name'), - }); - - req.body.id = req.params['id']; - - const param: any = await schema.validateAsync(req.body); - - const repo = OrmHelper.DB.getRepository(GenericName); - - const data = await repo.findOneBy({ id: param.id }); - - if (data != null) { - data.generic_name = param.generic_name - data.updated_by = req.auth.data.name; - - await repo.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_update, data); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_update, err.message); - } - } - - static async delete(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - GenericName'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'Generic Name ID.', - required: true, - type: 'string' - } - #swagger.parameters['hard'] = { - in: 'path', - description: 'Is Hard Delete', - required: false, - type: 'boolean' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID'), - hard: Joi.bool().optional().allow('').label('Is hard delete?') - }); - - const param: { id: string, hard: boolean } = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(GenericName); - - const existData = await repo.findOne({ where: { id: param.id } }); - if (existData && !param.hard) { - existData.deleted_by = req.auth.data.name; - await OrmHelper.DB.manager.save(existData); - } - - const affected = (!param.hard ? await repo.softDelete({ id: param.id }) : await repo.delete({ id: param.id })).affected; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_delete, err.message); - } - } - - static async restore(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - GenericName'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.parameters['id'] = { - in: 'path', - description: 'GenericName ID.', - required: true, - type: 'string' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID') - }); - - const param: GenericName = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(GenericName); - - const affected = (await repo.restore({ id: param.id })).affected; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_restore, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_restore, err.message); - } - } -} \ No newline at end of file diff --git a/src/controllers/pharmacy/initial_stock.ts b/src/controllers/pharmacy/initial_stock.ts deleted file mode 100644 index 515df92..0000000 --- a/src/controllers/pharmacy/initial_stock.ts +++ /dev/null @@ -1,151 +0,0 @@ -import { Response, NextFunction, Application } from "express"; -import { Request } from "express-jwt"; -import { ReturnHelper } from "../../helpers/express/return"; -import { OrmHelper } from "../../helpers/orm"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import { Language } from "../../langs/lang"; -import { InitialStock, ItemMaster, Room, ItemOrigin, RoomStock, Paging } from "entity"; -import CommonHelper from "../../helpers/common"; -import * as fastcsv from 'fast-csv'; -import dayjs from "dayjs"; -import { InitialStockModel } from "../../model/initial_stock"; - -const log: Logger = new Logger({ name: '[InitialStockController]', type: 'pretty' }); - -export class InitialStockController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - InitialStock'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['filter'] = { description: '', in: 'query', type: 'string' } - #swagger.parameters['limit'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['page'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['with_deleted'] = { in: 'query', required: true, type: 'boolean' } - #swagger.parameters['order_field'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['order_direction'] = { in: 'query', required: true, schema: { '@enum': ['ASC', 'DESC'] } } - */ - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().required().label("With Deleted"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").required().label("Order Direction"), - }); - - let param: any = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await InitialStockModel.list(filter); - - const offset = (param.page - 1) * param.limit; - let limit = param.limit; - - const res_count = query; - const res_list = query.select([ - 'InitialStock.id', - 'InitialStock.exp_date', - 'InitialStock.stock', - 'InitialStock.batch', - 'ItemMaster.item_name', - 'Room.room', - 'ItemOrigin.origin_name', - ]) - .leftJoin("InitialStock.itemmaster", "ItemMaster") - .leftJoin("InitialStock.room", "Room") - .leftJoin("InitialStock.itemorigin", "ItemOrigin") - .orderBy("InitialStock." + param.order_field, param.order_direction) - .offset(offset) - .limit(limit); - - if (param.with_deleted) { - res_count.withDeleted(); - res_list.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - InitialStock'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/initial_stock" - } - } - } - } - */ - const queryRunner = OrmHelper.DB.createQueryRunner(); - await queryRunner.startTransaction(); - try { - const schema = Joi.object().keys({ - itemmaster: Joi.string().uuid().required().label("Item Master ID"), - room: Joi.string().uuid().required().label("Room ID"), - itemorigin: Joi.string().uuid().required().label("Item Origin ID"), - batch: Joi.string().label("Batch"), - exp_date: Joi.date().required().label("Exp Date"), - stock: Joi.number().required().label("Stock"), - }); - - const param: any = await schema.validateAsync(req.body); - - const itemmaster = OrmHelper.DB.getRepository(ItemMaster).findOneBy({ id: param.itemmaster }); - const room = OrmHelper.DB.getRepository(Room).findOneBy({ id: param.room }) - const itemorigin = OrmHelper.DB.getRepository(ItemOrigin).findOneBy({ id: param.itemorigin }); - - if (!itemmaster) throw { message: "Item Master not found" }; - if (!room) throw { message: "Room not found" }; - if (!itemorigin) throw { message: "Item Origin not found" }; - - const initial_stock = new InitialStock(); - initial_stock.itemmaster = param.itemmaster; - initial_stock.room = param.room; - initial_stock.itemorigin = param.itemorigin; - initial_stock.batch = param.batch; - initial_stock.exp_date = param.exp_date; - initial_stock.stock = param.stock; - await queryRunner.manager.save(initial_stock); - - const room_stock = new RoomStock(); - room_stock.itemmaster = param.itemmaster; - room_stock.room = param.room; - room_stock.batch = param.batch; - room_stock.exp_date = new Date(param.exp_date); - room_stock.total_stock = param.stock; - room_stock.itemorigin = param.itemorigin; - await queryRunner.manager.save(room_stock); - - await queryRunner.commitTransaction(); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, initial_stock); - - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 401, Language.lang.failed_insert, err.message); - } - } -} \ No newline at end of file diff --git a/src/controllers/pharmacy/item_category.ts b/src/controllers/pharmacy/item_category.ts deleted file mode 100644 index 4dec970..0000000 --- a/src/controllers/pharmacy/item_category.ts +++ /dev/null @@ -1,339 +0,0 @@ -import { Response, NextFunction, Application } from "express"; -import { Request } from "express-jwt"; -import { ReturnHelper } from "../../helpers/express/return"; -import { OrmHelper } from "../../helpers/orm"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import { Language } from "../../langs/lang"; -import { ItemCategory, Paging } from "entity"; -import CommonHelper from "../../helpers/common"; -import * as fastcsv from 'fast-csv'; -import dayjs from "dayjs"; -import { ItemCategoryModel } from "../../model/item_category"; - -const log: Logger = new Logger({ name: '[ItemCategoryController]', type: 'pretty' }); - -export class ItemCategoryController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - ItemCategory'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['filter'] = { description: '', in: 'query', type: 'string' } - #swagger.parameters['limit'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['page'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['with_deleted'] = { in: 'query', required: true, type: 'boolean' } - #swagger.parameters['order_field'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['order_direction'] = { in: 'query', required: true, schema: { '@enum': ['ASC', 'DESC'] } } - */ - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().required().label("With Deleted"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").required().label("Order Direction"), - }); - - let param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await ItemCategoryModel.list(filter); - - const offset = (param.page - 1) * param.limit; - let limit = param.limit; - - const res_count = query; - const res_list = query - .orderBy("item_category." + param.order_field, param.order_direction) - .offset(offset) - .limit(limit); - - if (param.with_deleted) { - res_count.withDeleted(); - res_list.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async export(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - ItemCategory'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['filter'] = { - description: 'Filter with 2 format :
  • Simple format use text plaint will filter eq:code or like %name%
  • Advance format using field existing {status:\'Y\', any:\'SAME AS PLAINT LOGIC\', etc...}
', - in: 'query', - type: 'string' - } - #swagger.parameters['filter'] = { - in: 'query', - type: 'string' - } - #swagger.parameters['order_field'] = { - in: 'query', - required: true, - type: 'string' - } - #swagger.parameters['order_direction'] = { - in: 'query', - required: true, - schema: { - '@enum': ['ASC', 'DESC'] - } - } - */ - - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow('').optional().label('Filter'), - order_field: Joi.string().required().label('Order Field'), - order_direction: Joi.string().allow('asc', 'desc').required().label('Order Direction'), - }); - - const param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await ItemCategoryModel.list(filter); - const data = await query.getMany(); - - const filename = "item_category.csv"; - - res.setHeader('Content-Type', 'text/csv'); - res.setHeader('Content-Disposition', 'attachment; filename=' + filename); - - const csvStream = fastcsv.format({ - headers: true, - writeHeaders: true, - transform: (row: ItemCategory): any => ({ - ...row, - created_at: dayjs(row.created_at).format('DD-MM-YYYY HH:MM:ss'), - }) - }); - csvStream.pipe(res); - - const limit = 50; - - const fetchAndWrite = async (page: any) => { - - if (CommonHelper.countObject(data) === 0) { - csvStream.end(); - } else { - data.forEach((item: any) => csvStream.write(item)); - - if (CommonHelper.countObject(data) == limit) { - fetchAndWrite(page + 1); - } else { - csvStream.end(); - } - } - }; - - fetchAndWrite(1); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - ItemCategory'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/item_category" - } - } - } - } - */ - try { - const schema = Joi.object().keys({ - category_name: Joi.string().max(256).required().label('Name'), - }); - - const param: any = await schema.validateAsync(req.body); - - const data = new ItemCategory() - data.category_name = param.category_name - data.created_by = req.auth.data.name - - await OrmHelper.DB.manager.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 401, Language.lang.failed_insert, err.message); - } - } - - static async update(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - ItemCategory'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'ItemCategory ID.', - required: true, - type: 'string' - } - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/item_category" - } - } - } - } - */ - - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID'), - category_name: Joi.string().max(256).required().label('Name'), - }); - - req.body.id = req.params['id']; - - const param: any = await schema.validateAsync(req.body); - - const repo = OrmHelper.DB.getRepository(ItemCategory); - - const data = await repo.findOneBy({ id: param.id }); - - if (data != null) { - data.category_name = param.category_name - data.updated_by = req.auth.data.name - - await repo.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_update, data); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_update, err.message); - } - } - - static async delete(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - ItemCategory'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'ItemCategory ID.', - required: true, - type: 'string' - } - #swagger.parameters['hard'] = { - in: 'path', - description: 'Is Hard Delete', - required: false, - type: 'boolean' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID'), - hard: Joi.bool().optional().allow('').label('Is hard delete?') - }); - - const param: { id: string, hard: boolean } = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(ItemCategory); - - const existData = await repo.findOne({ where: { id: param.id } }); - if (existData && !param.hard) { - existData.deleted_by = req.auth.data.name; - await OrmHelper.DB.manager.save(existData); - } - - const affected = (!param.hard ? await repo.softDelete({ id: param.id }) : await repo.delete({ id: param.id })).affected; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_delete, err.message); - } - } - - static async restore(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - ItemCategory'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.parameters['id'] = { - in: 'path', - description: 'ItemCategory ID.', - required: true, - type: 'string' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID') - }); - - const param: ItemCategory = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(ItemCategory); - - const affected = (await repo.restore({ id: param.id })).affected; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_restore, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_restore, err.message); - } - } -} \ No newline at end of file diff --git a/src/controllers/pharmacy/item_class.ts b/src/controllers/pharmacy/item_class.ts deleted file mode 100644 index 229896e..0000000 --- a/src/controllers/pharmacy/item_class.ts +++ /dev/null @@ -1,339 +0,0 @@ -import { Response, NextFunction, Application } from "express"; -import { Request } from "express-jwt"; -import { ReturnHelper } from "../../helpers/express/return"; -import { OrmHelper } from "../../helpers/orm"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import { Language } from "../../langs/lang"; -import { ItemClass, Paging } from "entity"; -import CommonHelper from "../../helpers/common"; -import * as fastcsv from 'fast-csv'; -import dayjs from "dayjs"; -import { ItemClassModel } from "../../model/item_class"; - -const log: Logger = new Logger({ name: '[ItemClassController]', type: 'pretty' }); - -export class ItemClassController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - ItemClass'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['filter'] = { description: '', in: 'query', type: 'string' } - #swagger.parameters['limit'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['page'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['with_deleted'] = { in: 'query', required: true, type: 'boolean' } - #swagger.parameters['order_field'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['order_direction'] = { in: 'query', required: true, schema: { '@enum': ['ASC', 'DESC'] } } - */ - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().required().label("With Deleted"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").required().label("Order Direction"), - }); - - let param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await ItemClassModel.list(filter); - - const offset = (param.page - 1) * param.limit; - let limit = param.limit; - - const res_count = query; - const res_list = query - .orderBy("item_class." + param.order_field, param.order_direction) - .offset(offset) - .limit(limit); - - if (param.with_deleted) { - res_count.withDeleted(); - res_list.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async export(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - ItemClass'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['filter'] = { - description: 'Filter with 2 format :
  • Simple format use text plaint will filter eq:code or like %name%
  • Advance format using field existing {status:\'Y\', any:\'SAME AS PLAINT LOGIC\', etc...}
', - in: 'query', - type: 'string' - } - #swagger.parameters['filter'] = { - in: 'query', - type: 'string' - } - #swagger.parameters['order_field'] = { - in: 'query', - required: true, - type: 'string' - } - #swagger.parameters['order_direction'] = { - in: 'query', - required: true, - schema: { - '@enum': ['ASC', 'DESC'] - } - } - */ - - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow('').optional().label('Filter'), - order_field: Joi.string().required().label('Order Field'), - order_direction: Joi.string().allow('asc', 'desc').required().label('Order Direction'), - }); - - const param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await ItemClassModel.list(filter); - const data = await query.getMany(); - - const filename = "item_class.csv"; - - res.setHeader('Content-Type', 'text/csv'); - res.setHeader('Content-Disposition', 'attachment; filename=' + filename); - - const csvStream = fastcsv.format({ - headers: true, - writeHeaders: true, - transform: (row: ItemClass): any => ({ - ...row, - created_at: dayjs(row.created_at).format('DD-MM-YYYY HH:MM:ss'), - }) - }); - csvStream.pipe(res); - - const limit = 50; - - const fetchAndWrite = async (page: any) => { - - if (CommonHelper.countObject(data) === 0) { - csvStream.end(); - } else { - data.forEach((item: any) => csvStream.write(item)); - - if (CommonHelper.countObject(data) == limit) { - fetchAndWrite(page + 1); - } else { - csvStream.end(); - } - } - }; - - fetchAndWrite(1); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - ItemClass'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/item_class" - } - } - } - } - */ - try { - const schema = Joi.object().keys({ - item_class_name: Joi.string().max(256).required().label('Name'), - }); - - const param: any = await schema.validateAsync(req.body); - - const data = new ItemClass() - data.item_class_name = param.item_class_name - data.created_by = req.auth.data.name; - - await OrmHelper.DB.manager.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 401, Language.lang.failed_insert, err.message); - } - } - - static async update(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - ItemClass'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'ItemClass ID.', - required: true, - type: 'string' - } - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/item_class" - } - } - } - } - */ - - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID'), - item_class_name: Joi.string().max(256).required().label('Name'), - }); - - req.body.id = req.params['id']; - - const param: any = await schema.validateAsync(req.body); - - const repo = OrmHelper.DB.getRepository(ItemClass); - - const data = await repo.findOneBy({ id: param.id }); - - if (data != null) { - data.item_class_name = param.item_class_name - data.updated_by = req.auth.data.name; - - await repo.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_update, data); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_update, err.message); - } - } - - static async delete(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - ItemClass'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'Item Class ID.', - required: true, - type: 'string' - } - #swagger.parameters['hard'] = { - in: 'path', - description: 'Is Hard Delete', - required: false, - type: 'boolean' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID'), - hard: Joi.bool().optional().allow('').label('Is hard delete?') - }); - - const param: { id: string, hard: boolean } = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(ItemClass); - - const existData = await repo.findOne({ where: { id: param.id } }); - if (existData && !param.hard) { - existData.deleted_by = req.auth.data.name; - await OrmHelper.DB.manager.save(existData); - } - - const affected = (!param.hard ? await repo.softDelete({ id: param.id }) : await repo.delete({ id: param.id })).affected; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_delete, err.message); - } - } - - static async restore(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - ItemClass'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.parameters['id'] = { - in: 'path', - description: 'ItemClass ID.', - required: true, - type: 'string' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID') - }); - - const param: ItemClass = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(ItemClass); - - const affected = (await repo.restore({ id: param.id })).affected; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_restore, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_restore, err.message); - } - } -} \ No newline at end of file diff --git a/src/controllers/pharmacy/item_class_detail.ts b/src/controllers/pharmacy/item_class_detail.ts deleted file mode 100644 index 09f959c..0000000 --- a/src/controllers/pharmacy/item_class_detail.ts +++ /dev/null @@ -1,339 +0,0 @@ -import { Response, NextFunction, Application } from "express"; -import { Request } from "express-jwt"; -import { ReturnHelper } from "../../helpers/express/return"; -import { OrmHelper } from "../../helpers/orm"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import { Language } from "../../langs/lang"; -import { ItemClassDetail, Paging } from "entity"; -import CommonHelper from "../../helpers/common"; -import * as fastcsv from 'fast-csv'; -import dayjs from "dayjs"; -import { ItemClassDetailModel } from "../../model/item_class_detail"; - -const log: Logger = new Logger({ name: '[ItemClassDetailController]', type: 'pretty' }); - -export class ItemClassDetailController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - ItemClassDetail'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['filter'] = { description: '', in: 'query', type: 'string' } - #swagger.parameters['limit'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['page'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['with_deleted'] = { in: 'query', required: true, type: 'boolean' } - #swagger.parameters['order_field'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['order_direction'] = { in: 'query', required: true, schema: { '@enum': ['ASC', 'DESC'] } } - */ - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().required().label("With Deleted"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").required().label("Order Direction"), - }); - - let param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await ItemClassDetailModel.list(filter); - - const offset = (param.page - 1) * param.limit; - let limit = param.limit; - - const res_count = query; - const res_list = query - .orderBy("item_class_detail." + param.order_field, param.order_direction) - .offset(offset) - .limit(limit); - - if (param.with_deleted) { - res_count.withDeleted(); - res_list.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async export(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - ItemClassDetail'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['filter'] = { - description: 'Filter with 2 format :
  • Simple format use text plaint will filter eq:code or like %name%
  • Advance format using field existing {status:\'Y\', any:\'SAME AS PLAINT LOGIC\', etc...}
', - in: 'query', - type: 'string' - } - #swagger.parameters['filter'] = { - in: 'query', - type: 'string' - } - #swagger.parameters['order_field'] = { - in: 'query', - required: true, - type: 'string' - } - #swagger.parameters['order_direction'] = { - in: 'query', - required: true, - schema: { - '@enum': ['ASC', 'DESC'] - } - } - */ - - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow('').optional().label('Filter'), - order_field: Joi.string().required().label('Order Field'), - order_direction: Joi.string().allow('asc', 'desc').required().label('Order Direction'), - }); - - const param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await ItemClassDetailModel.list(filter); - const data = await query.getMany(); - - const filename = "item_class_detail.csv"; - - res.setHeader('Content-Type', 'text/csv'); - res.setHeader('Content-Disposition', 'attachment; filename=' + filename); - - const csvStream = fastcsv.format({ - headers: true, - writeHeaders: true, - transform: (row: ItemClassDetail): any => ({ - ...row, - created_at: dayjs(row.created_at).format('DD-MM-YYYY HH:MM:ss'), - }) - }); - csvStream.pipe(res); - - const limit = 50; - - const fetchAndWrite = async (page: any) => { - - if (CommonHelper.countObject(data) === 0) { - csvStream.end(); - } else { - data.forEach((item: any) => csvStream.write(item)); - - if (CommonHelper.countObject(data) == limit) { - fetchAndWrite(page + 1); - } else { - csvStream.end(); - } - } - }; - - fetchAndWrite(1); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - ItemClassDetail'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/item_class_detail" - } - } - } - } - */ - try { - const schema = Joi.object().keys({ - class_detail_name: Joi.string().max(256).required().label('Name'), - }); - - const param: any = await schema.validateAsync(req.body); - - const data = new ItemClassDetail() - data.class_detail_name = param.class_detail_name - data.created_by = req.auth.data.name; - - await OrmHelper.DB.manager.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 401, Language.lang.failed_insert, err.message); - } - } - - static async update(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - ItemClassDetail'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'ItemClassDetail ID.', - required: true, - type: 'string' - } - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/item_class_detail" - } - } - } - } - */ - - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID'), - class_detail_name: Joi.string().max(256).required().label('Name'), - }); - - req.body.id = req.params['id']; - - const param: any = await schema.validateAsync(req.body); - - const repo = OrmHelper.DB.getRepository(ItemClassDetail); - - const data = await repo.findOneBy({ id: param.id }); - - if (data != null) { - data.class_detail_name = param.class_detail_name - data.updated_by = req.auth.data.name; - - await repo.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_update, data); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_update, err.message); - } - } - - static async delete(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - ItemClassDetail'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'Item Group ID.', - required: true, - type: 'string' - } - #swagger.parameters['hard'] = { - in: 'path', - description: 'Is Hard Delete', - required: false, - type: 'boolean' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID'), - hard: Joi.bool().optional().allow('').label('Is hard delete?') - }); - - const param: { id: string, hard: boolean } = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(ItemClassDetail); - - const existData = await repo.findOne({ where: { id: param.id } }); - if (existData && !param.hard) { - existData.deleted_by = req.auth.data.name; - await OrmHelper.DB.manager.save(existData); - } - - const affected = (!param.hard ? await repo.softDelete({ id: param.id }) : await repo.delete({ id: param.id })).affected; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_delete, err.message); - } - } - - static async restore(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - ItemClassDetail'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.parameters['id'] = { - in: 'path', - description: 'ItemClassDetail ID.', - required: true, - type: 'string' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID') - }); - - const param: ItemClassDetail = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(ItemClassDetail); - - const affected = (await repo.restore({ id: param.id })).affected; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_restore, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_restore, err.message); - } - } -} \ No newline at end of file diff --git a/src/controllers/pharmacy/item_group.ts b/src/controllers/pharmacy/item_group.ts deleted file mode 100644 index d2a9c8e..0000000 --- a/src/controllers/pharmacy/item_group.ts +++ /dev/null @@ -1,339 +0,0 @@ -import { Response, NextFunction, Application } from "express"; -import { Request } from "express-jwt"; -import { ReturnHelper } from "../../helpers/express/return"; -import { OrmHelper } from "../../helpers/orm"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import { Language } from "../../langs/lang"; -import { ItemGroup, Paging } from "entity"; -import CommonHelper from "../../helpers/common"; -import * as fastcsv from 'fast-csv'; -import dayjs from "dayjs"; -import { ItemGroupModel } from "../../model/item_group"; - -const log: Logger = new Logger({ name: '[ItemGroupController]', type: 'pretty' }); - -export class ItemGroupController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - ItemGroup'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['filter'] = { description: '', in: 'query', type: 'string' } - #swagger.parameters['limit'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['page'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['with_deleted'] = { in: 'query', required: true, type: 'boolean' } - #swagger.parameters['order_field'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['order_direction'] = { in: 'query', required: true, schema: { '@enum': ['ASC', 'DESC'] } } - */ - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().required().label("With Deleted"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").required().label("Order Direction"), - }); - - let param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await ItemGroupModel.list(filter); - - const offset = (param.page - 1) * param.limit; - let limit = param.limit; - - const res_count = query; - const res_list = query - .orderBy("item_group." + param.order_field, param.order_direction) - .offset(offset) - .limit(limit); - - if (param.with_deleted) { - res_count.withDeleted(); - res_list.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async export(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - ItemGroup'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['filter'] = { - description: 'Filter with 2 format :
  • Simple format use text plaint will filter eq:code or like %name%
  • Advance format using field existing {status:\'Y\', any:\'SAME AS PLAINT LOGIC\', etc...}
', - in: 'query', - type: 'string' - } - #swagger.parameters['filter'] = { - in: 'query', - type: 'string' - } - #swagger.parameters['order_field'] = { - in: 'query', - required: true, - type: 'string' - } - #swagger.parameters['order_direction'] = { - in: 'query', - required: true, - schema: { - '@enum': ['ASC', 'DESC'] - } - } - */ - - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow('').optional().label('Filter'), - order_field: Joi.string().required().label('Order Field'), - order_direction: Joi.string().allow('asc', 'desc').required().label('Order Direction'), - }); - - const param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await ItemGroupModel.list(filter); - const data = await query.getMany(); - - const filename = "item_group.csv"; - - res.setHeader('Content-Type', 'text/csv'); - res.setHeader('Content-Disposition', 'attachment; filename=' + filename); - - const csvStream = fastcsv.format({ - headers: true, - writeHeaders: true, - transform: (row: ItemGroup): any => ({ - ...row, - created_at: dayjs(row.created_at).format('DD-MM-YYYY HH:MM:ss'), - }) - }); - csvStream.pipe(res); - - const limit = 50; - - const fetchAndWrite = async (page: any) => { - - if (CommonHelper.countObject(data) === 0) { - csvStream.end(); - } else { - data.forEach((item: any) => csvStream.write(item)); - - if (CommonHelper.countObject(data) == limit) { - fetchAndWrite(page + 1); - } else { - csvStream.end(); - } - } - }; - - fetchAndWrite(1); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - ItemGroup'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/item_group" - } - } - } - } - */ - try { - const schema = Joi.object().keys({ - group_name: Joi.string().max(256).required().label('Name'), - }); - - const param: any = await schema.validateAsync(req.body); - - const data = new ItemGroup() - data.group_name = param.group_name - data.created_by = req.auth.data.name; - - await OrmHelper.DB.manager.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 401, Language.lang.failed_insert, err.message); - } - } - - static async update(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - ItemGroup'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'ItemGroup ID.', - required: true, - type: 'string' - } - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/item_group" - } - } - } - } - */ - - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID'), - group_name: Joi.string().max(256).required().label('Name'), - }); - - req.body.id = req.params['id']; - - const param: any = await schema.validateAsync(req.body); - - const repo = OrmHelper.DB.getRepository(ItemGroup); - - const data = await repo.findOneBy({ id: param.id }); - - if (data != null) { - data.group_name = param.group_name - data.updated_by = req.auth.data.name; - - await repo.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_update, data); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_update, err.message); - } - } - - static async delete(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - ItemGroup'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'Item Group ID.', - required: true, - type: 'string' - } - #swagger.parameters['hard'] = { - in: 'path', - description: 'Is Hard Delete', - required: false, - type: 'boolean' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID'), - hard: Joi.bool().optional().allow('').label('Is hard delete?') - }); - - const param: { id: string, hard: boolean } = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(ItemGroup); - - const existData = await repo.findOne({ where: { id: param.id } }); - if (existData && !param.hard) { - existData.deleted_by = req.auth.data.name; - await OrmHelper.DB.manager.save(existData); - } - - const affected = (!param.hard ? await repo.softDelete({ id: param.id }) : await repo.delete({ id: param.id })).affected; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_delete, err.message); - } - } - - static async restore(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - ItemGroup'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.parameters['id'] = { - in: 'path', - description: 'ItemGroup ID.', - required: true, - type: 'string' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID') - }); - - const param: ItemGroup = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(ItemGroup); - - const affected = (await repo.restore({ id: param.id })).affected; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_restore, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_restore, err.message); - } - } -} \ No newline at end of file diff --git a/src/controllers/pharmacy/item_master.ts b/src/controllers/pharmacy/item_master.ts deleted file mode 100644 index db9139a..0000000 --- a/src/controllers/pharmacy/item_master.ts +++ /dev/null @@ -1,424 +0,0 @@ -import { Response, NextFunction, Application } from "express"; -import { Request } from "express-jwt"; -import { ReturnHelper } from "../../helpers/express/return"; -import { OrmHelper } from "../../helpers/orm"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import { Language } from "../../langs/lang"; -import { ItemMaster, Paging } from "entity"; -import CommonHelper from "../../helpers/common"; -import * as fastcsv from 'fast-csv'; -import dayjs from "dayjs"; -import { ItemMasterModel } from "../../model/item_master"; - -const log: Logger = new Logger({ name: '[ItemMasterController]', type: 'pretty' }); - -export class ItemMasterController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - ItemMaster'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['filter'] = { description: '', in: 'query', type: 'string' } - #swagger.parameters['limit'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['page'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['with_deleted'] = { in: 'query', required: true, type: 'boolean' } - #swagger.parameters['order_field'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['order_direction'] = { in: 'query', required: true, schema: { '@enum': ['ASC', 'DESC'] } } - */ - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().required().label("With Deleted"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").required().label("Order Direction"), - }); - - let param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await ItemMasterModel.list(filter); - - const offset = (param.page - 1) * param.limit; - let limit = param.limit; - - const res_count = query; - const res_list = query - .orderBy("item_master." + param.order_field, param.order_direction) - .offset(offset) - .limit(limit); - - if (param.with_deleted) { - res_count.withDeleted(); - res_list.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - - static async option(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - ItemMaster'] - #swagger.security = [{ "bearerAuth": [] }] - */ - try { - const query = await ItemMasterModel.list(); - - query.select([ - "item_master.id", - "item_master.item_name", - "item_master.largeunit", - "item_master.smallunit", - "item_master.pack_size", - ]).orderBy("item_master.item_name", "ASC"); - - const total_count_data = await query.getCount(); - const list_data = await query.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, 1, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async export(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - ItemMaster'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['filter'] = { - description: 'Filter with 2 format :
  • Simple format use text plaint will filter eq:code or like %name%
  • Advance format using field existing {status:\'Y\', any:\'SAME AS PLAINT LOGIC\', etc...}
', - in: 'query', - type: 'string' - } - #swagger.parameters['filter'] = { - in: 'query', - type: 'string' - } - #swagger.parameters['order_field'] = { - in: 'query', - required: true, - type: 'string' - } - #swagger.parameters['order_direction'] = { - in: 'query', - required: true, - schema: { - '@enum': ['ASC', 'DESC'] - } - } - */ - - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow('').optional().label('Filter'), - order_field: Joi.string().required().label('Order Field'), - order_direction: Joi.string().allow('asc', 'desc').required().label('Order Direction'), - }); - - const param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await ItemMasterModel.list(filter); - const data = await query.getMany(); - - const filename = "item_master.csv"; - - res.setHeader('Content-Type', 'text/csv'); - res.setHeader('Content-Disposition', 'attachment; filename=' + filename); - - const csvStream = fastcsv.format({ - headers: true, - writeHeaders: true, - transform: (row: ItemMaster): any => ({ - ...row, - created_at: dayjs(row.created_at).format('DD-MM-YYYY HH:MM:ss'), - }) - }); - csvStream.pipe(res); - - const limit = 50; - - const fetchAndWrite = async (page: any) => { - - if (CommonHelper.countObject(data) === 0) { - csvStream.end(); - } else { - data.forEach((item: any) => csvStream.write(item)); - - if (CommonHelper.countObject(data) == limit) { - fetchAndWrite(page + 1); - } else { - csvStream.end(); - } - } - }; - - fetchAndWrite(1); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - ItemMaster'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/item_master" - } - } - } - } - */ - try { - const schema = Joi.object().keys({ - item_name: Joi.string().max(256).required().label('Item Name'), - generic_name_id: Joi.string().uuid().required().label('Generic Name ID'), - item_type_detail_id: Joi.string().uuid().required().label('Item Type Detail ID'), - item_category_id: Joi.string().uuid().required().label('Item Category ID'), - item_class_id: Joi.string().uuid().required().label('Item Class ID'), - item_class_detail_id: Joi.string().uuid().required().label('Item Class Detail ID'), - item_status_id: Joi.string().uuid().required().label('Item Status ID'), - factory_id: Joi.string().uuid().required().label('Factory ID'), - // unit_id: Joi.string().uuid().required().label('Unit ID'), - smallunit: Joi.string().required().label('Small Unit'), - largeunit: Joi.string().required().label('Large Unit'), - pack_size: Joi.number().integer().min(0).required().label('Pack Size'), - minimum_quantity: Joi.number().integer().min(0).required().label('Minimum Quantity'), - minimum_sales_quantity: Joi.number().integer().min(0).required().label('Minimum Sales Quantity'), - strength: Joi.number().min(0).required().label('Strength'), - active: Joi.boolean().required().label('Active'), - }); - - const param: any = await schema.validateAsync(req.body); - - const data = new ItemMaster() - data.item_name = param.item_name, - data.generic_name = param.generic_name_id, - data.type_detail = param.item_type_detail_id, - data.category = param.item_category_id, - data.item_class = param.item_class_id, - data.item_class_detail = param.item_class_detail_id, - data.status = param.item_status_id, - data.factory = param.factory_id, - data.smallunit = param.smallunit, - data.largeunit = param.largeunit, - data.pack_size = param.pack_size, - data.minimum_quantity = param.minimum_quantity, - data.minimum_sales_quantity = param.minimum_sales_quantity, - data.strength = param.strength, - data.active = param.active - data.created_by = req.auth?.data.name; - - await OrmHelper.DB.manager.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 401, Language.lang.failed_insert, err.message); - } - } - - static async update(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - ItemMaster'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'ItemMaster ID.', - required: true, - type: 'string' - } - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/item_master" - } - } - } - } - */ - - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID'), - item_name: Joi.string().max(256).required().label('Item Name'), - generic_name_id: Joi.string().uuid().required().label('Generic Name ID'), - item_type_detail_id: Joi.string().uuid().required().label('Item Type Detail ID'), - item_category_id: Joi.string().uuid().required().label('Item Category ID'), - item_class_id: Joi.string().uuid().required().label('Item Class ID'), - item_class_detail_id: Joi.string().uuid().required().label('Item Class Detail ID'), - item_status_id: Joi.string().uuid().required().label('Item Status ID'), - factory_id: Joi.string().uuid().required().label('Factory ID'), - smallunit: Joi.string().required().label('Small Unit'), - largeunit: Joi.string().required().label('Large Unit'), - pack_size: Joi.number().integer().min(0).required().label('Pack Size'), - minimum_quantity: Joi.number().integer().min(0).required().label('Minimum Quantity'), - minimum_sales_quantity: Joi.number().integer().min(0).required().label('Minimum Sales Quantity'), - strength: Joi.number().min(0).required().label('Strength'), - active: Joi.boolean().required().label('Active'), - }); - - req.body.id = req.params['id']; - - const param: any = await schema.validateAsync(req.body); - - const repo = OrmHelper.DB.getRepository(ItemMaster); - - const data = await repo.findOneBy({ id: param.id }); - - if (data != null) { - data.item_name = param.item_name, - data.generic_name = param.generic_name_id, - data.type_detail = param.item_type_detail_id, - data.category = param.item_category_id, - data.item_class = param.item_class_id, - data.item_class_detail = param.item_class_detail_id, - data.status = param.item_status_id, - data.factory = param.factory_id, - data.smallunit = param.smallunit, - data.largeunit = param.largeunit, data.pack_size = param.pack_size, - data.minimum_quantity = param.minimum_quantity, - data.minimum_sales_quantity = param.minimum_sales_quantity, - data.strength = param.strength, - data.active = param.active - data.updated_by = req.auth?.data.name; - - await repo.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_update, data); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_update, err.message); - } - } - - static async delete(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - ItemMaster'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'Item Master ID.', - required: true, - type: 'string' - } - #swagger.parameters['hard'] = { - in: 'path', - description: 'Is Hard Delete', - required: false, - type: 'boolean' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID'), - hard: Joi.bool().optional().allow('').label('Is hard delete?') - }); - - const param: { id: string, hard: boolean } = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(ItemMaster); - - const existData = await repo.findOne({ where: { id: param.id } }); - if (existData && !param.hard) { - existData.deleted_by = req.auth?.data.name; - await OrmHelper.DB.manager.save(existData); - } - - const affected = (!param.hard ? await repo.softDelete({ id: param.id }) : await repo.delete({ id: param.id })).affected || 0; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_delete, err.message); - } - } - - static async restore(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - ItemMaster'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.parameters['id'] = { - in: 'path', - description: 'ItemMaster ID.', - required: true, - type: 'string' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID') - }); - - const param: ItemMaster = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(ItemMaster); - - const affected = (await repo.restore({ id: param.id })).affected || 0; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_restore, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_restore, err.message); - } - } -} \ No newline at end of file diff --git a/src/controllers/pharmacy/item_origin.ts b/src/controllers/pharmacy/item_origin.ts deleted file mode 100644 index e5aeacf..0000000 --- a/src/controllers/pharmacy/item_origin.ts +++ /dev/null @@ -1,377 +0,0 @@ -import { Response, NextFunction, Application } from "express"; -import { Request } from "express-jwt"; -import { ReturnHelper } from "../../helpers/express/return"; -import { OrmHelper } from "../../helpers/orm"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import { Language } from "../../langs/lang"; -import { ItemOrigin, Paging } from "entity"; -import CommonHelper from "../../helpers/common"; -import * as fastcsv from 'fast-csv'; -import dayjs from "dayjs"; -import { ItemOriginModel } from "../../model/item_origin"; - -const log: Logger = new Logger({ name: '[ItemOriginController]', type: 'pretty' }); - -export class ItemOriginController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - ItemOrigin'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['filter'] = { description: '', in: 'query', type: 'string' } - #swagger.parameters['limit'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['page'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['with_deleted'] = { in: 'query', required: true, type: 'boolean' } - #swagger.parameters['order_field'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['order_direction'] = { in: 'query', required: true, schema: { '@enum': ['ASC', 'DESC'] } } - */ - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().required().label("With Deleted"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").required().label("Order Direction"), - }); - - let param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await ItemOriginModel.list(filter); - - const offset = (param.page - 1) * param.limit; - let limit = param.limit; - - const res_count = query; - const res_list = query - .orderBy("item_origin." + param.order_field, param.order_direction) - .offset(offset) - .limit(limit); - - if (param.with_deleted) { - res_count.withDeleted(); - res_list.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async option(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - ItemOrigin'] - #swagger.security = [{ "bearerAuth": [] }] - */ - try { - const query = await ItemOriginModel.list(); - - query.select([ - "item_origin.id", - "item_origin.origin_name", - ]).orderBy("item_origin.origin_name", "ASC"); - - const total_count_data = await query.getCount(); - const list_data = await query.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, 1, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async export(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - ItemOrigin'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['filter'] = { - description: 'Filter with 2 format :
  • Simple format use text plaint will filter eq:code or like %name%
  • Advance format using field existing {status:\'Y\', any:\'SAME AS PLAINT LOGIC\', etc...}
', - in: 'query', - type: 'string' - } - #swagger.parameters['filter'] = { - in: 'query', - type: 'string' - } - #swagger.parameters['order_field'] = { - in: 'query', - required: true, - type: 'string' - } - #swagger.parameters['order_direction'] = { - in: 'query', - required: true, - schema: { - '@enum': ['ASC', 'DESC'] - } - } - */ - - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow('').optional().label('Filter'), - order_field: Joi.string().required().label('Order Field'), - order_direction: Joi.string().allow('asc', 'desc').required().label('Order Direction'), - }); - - const param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await ItemOriginModel.list(filter); - const data = await query.getMany(); - - const filename = "item_origin.csv"; - - res.setHeader('Content-Type', 'text/csv'); - res.setHeader('Content-Disposition', 'attachment; filename=' + filename); - - const csvStream = fastcsv.format({ - headers: true, - writeHeaders: true, - transform: (row: ItemOrigin): any => ({ - ...row, - created_at: dayjs(row.created_at).format('DD-MM-YYYY HH:MM:ss'), - }) - }); - csvStream.pipe(res); - - const limit = 50; - - const fetchAndWrite = async (page: any) => { - - if (CommonHelper.countObject(data) === 0) { - csvStream.end(); - } else { - data.forEach((item: any) => csvStream.write(item)); - - if (CommonHelper.countObject(data) == limit) { - fetchAndWrite(page + 1); - } else { - csvStream.end(); - } - } - }; - - fetchAndWrite(1); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - ItemOrigin'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/item_origin" - } - } - } - } - */ - try { - const schema = Joi.object().keys({ - origin_name: Joi.string().max(256).required().label('Name'), - origin_description: Joi.string().max(256).required().label('Desc'), - department: Joi.string().max(256).optional().label('Department'), - account: Joi.string().max(256).optional().label('Account'), - - }); - - const param: any = await schema.validateAsync(req.body); - - const data = new ItemOrigin() - data.origin_name = param.origin_name - data.origin_description = param.origin_description - data.department = param.department - data.account = param.account - data.created_by = req.auth.data.name; - - await OrmHelper.DB.manager.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 401, Language.lang.failed_insert, err.message); - } - } - - static async update(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - ItemOrigin'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'ItemOrigin ID.', - required: true, - type: 'string' - } - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/item_origin" - } - } - } - } - */ - - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID'), - origin_name: Joi.string().max(256).required().label('Name'), - origin_description: Joi.string().max(256).required().label('Desc'), - department: Joi.string().max(256).required().label('Department'), - account: Joi.string().max(256).required().label('Account'), - }); - - req.body.id = req.params['id']; - - const param: any = await schema.validateAsync(req.body); - - const repo = OrmHelper.DB.getRepository(ItemOrigin); - - const data = await repo.findOneBy({ id: param.id }); - - if (data != null) { - data.origin_name = param.origin_name - data.origin_description = param.origin_description - data.department = param.department - data.account = param.account - data.updated_by = req.auth.data.name; - - await repo.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_update, data); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_update, err.message); - } - } - - static async delete(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - ItemOrigin'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'Item Origin ID.', - required: true, - type: 'string' - } - #swagger.parameters['hard'] = { - in: 'path', - description: 'Is Hard Delete', - required: false, - type: 'boolean' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID'), - hard: Joi.bool().optional().allow('').label('Is hard delete?') - }); - - const param: { id: string, hard: boolean } = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(ItemOrigin); - - const existData = await repo.findOne({ where: { id: param.id } }); - if (existData && !param.hard) { - existData.deleted_by = req.auth.data.name; - await OrmHelper.DB.manager.save(existData); - } - - const affected = (!param.hard ? await repo.softDelete({ id: param.id }) : await repo.delete({ id: param.id })).affected; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_delete, err.message); - } - } - - static async restore(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - ItemOrigin'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.parameters['id'] = { - in: 'path', - description: 'ItemOrigin ID.', - required: true, - type: 'string' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID') - }); - - const param: ItemOrigin = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(ItemOrigin); - - const affected = (await repo.restore({ id: param.id })).affected; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_restore, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_restore, err.message); - } - } -} \ No newline at end of file diff --git a/src/controllers/pharmacy/item_price.ts b/src/controllers/pharmacy/item_price.ts deleted file mode 100644 index 8f0627e..0000000 --- a/src/controllers/pharmacy/item_price.ts +++ /dev/null @@ -1,386 +0,0 @@ -import { Response, NextFunction, Application } from "express"; -import { Request } from "express-jwt"; -import { ReturnHelper } from "../../helpers/express/return"; -import { OrmHelper } from "../../helpers/orm"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import { Language } from "../../langs/lang"; -import { ItemPrice, Paging, ItemMaster } from "entity"; -import CommonHelper from "../../helpers/common"; -import * as fastcsv from 'fast-csv'; -import dayjs from "dayjs"; -import { ItemPriceModel } from "../../model/item_price"; - -const log: Logger = new Logger({ name: '[ItemPriceController]', type: 'pretty' }); - -export class ItemPriceController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - ItemPrice'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['filter'] = { description: '', in: 'query', type: 'string' } - #swagger.parameters['limit'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['page'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['with_deleted'] = { in: 'query', required: true, type: 'boolean' } - #swagger.parameters['order_field'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['order_direction'] = { in: 'query', required: true, schema: { '@enum': ['ASC', 'DESC'] } } - */ - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().required().label("With Deleted"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").required().label("Order Direction"), - }); - - let param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await ItemPriceModel.list(filter); - - const offset = (param.page - 1) * param.limit; - let limit = param.limit; - - const res_count = query; - const res_list = query - .orderBy("item_price." + param.order_field, param.order_direction) - .offset(offset) - .limit(limit); - - if (param.with_deleted) { - res_count.withDeleted(); - res_list.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async export(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - ItemPrice'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['filter'] = { - description: 'Filter with 2 format :
  • Simple format use text plaint will filter eq:code or like %name%
  • Advance format using field existing {status:\'Y\', any:\'SAME AS PLAINT LOGIC\', etc...}
', - in: 'query', - type: 'string' - } - #swagger.parameters['filter'] = { - in: 'query', - type: 'string' - } - #swagger.parameters['order_field'] = { - in: 'query', - required: true, - type: 'string' - } - #swagger.parameters['order_direction'] = { - in: 'query', - required: true, - schema: { - '@enum': ['ASC', 'DESC'] - } - } - */ - - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow('').optional().label('Filter'), - order_field: Joi.string().required().label('Order Field'), - order_direction: Joi.string().allow('asc', 'desc').required().label('Order Direction'), - }); - - const param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await ItemPriceModel.list(filter); - const data = await query.getMany(); - - const filename = "item_price.csv"; - - res.setHeader('Content-Type', 'text/csv'); - res.setHeader('Content-Disposition', 'attachment; filename=' + filename); - - const csvStream = fastcsv.format({ - headers: true, - writeHeaders: true, - transform: (row: ItemPrice): any => ({ - ...row, - created_at: dayjs(row.created_at).format('DD-MM-YYYY HH:MM:ss'), - }) - }); - csvStream.pipe(res); - - const limit = 50; - - const fetchAndWrite = async (page: any) => { - - if (CommonHelper.countObject(data) === 0) { - csvStream.end(); - } else { - data.forEach((item: any) => csvStream.write(item)); - - if (CommonHelper.countObject(data) == limit) { - fetchAndWrite(page + 1); - } else { - csvStream.end(); - } - } - }; - - fetchAndWrite(1); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - ItemPrice'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/item_price" - } - } - } - } - */ - try { - const schema = Joi.object().keys({ - item_master_id: Joi.string() - .uuid() - .required() - .label('Item Master Id'), - - purchase_price: Joi.number() - .min(0) - .required() - .label('Purchase Price'), - - selling_price: Joi.number() - .min(0) - .required() - .label('Selling Price'), - - // expired_date: Joi.date() - // .required() - // .label('Expired Date'), - }); - - const param: any = await schema.validateAsync(req.body); - - const data = new ItemPrice() - data.item_master = param.item_master_id - data.purchase_price = param.purchase_price - data.selling_price = param.selling_price - // data.expired_date = param.expired_date - data.created_by = req.auth?.data.name; - - await OrmHelper.DB.manager.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 401, Language.lang.failed_insert, err.message); - } - } - - static async update(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - ItemPrice'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'ItemMaster ID.', - required: true, - type: 'string' - } - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/item_price" - } - } - } - } - */ - - try { - const schema = Joi.object().keys({ - item_master_id: Joi.string() - .uuid() - .required() - .label('Item Master Id'), - - purchase_price: Joi.number() - .min(0) - .required() - .label('Purchase Price'), - - selling_price: Joi.number() - .min(0) - .required() - .label('Selling Price'), - }); - - const param: any = await schema.validateAsync(req.body); - - const itemMaster = await OrmHelper.DB.getRepository(ItemMaster).findOneBy({ id: req.params['id'] }); - if (!itemMaster) return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, "Item Master not found"); - - const repo = OrmHelper.DB.getRepository(ItemPrice); - - // ✅ Include withDeleted agar record soft-deleted ikut dicek - let data = await repo.findOne({ - where: { item_master: { id: req.params['id'] } }, - withDeleted: true - }); - - if (data) { - // UPDATE (termasuk restore jika soft-deleted) - data.purchase_price = param.purchase_price; - data.selling_price = param.selling_price; - data.deleted_at = null as any; - data.deleted_by = null as any; - data.updated_by = req.auth?.data.name; - } else { - // INSERT baru - data = new ItemPrice(); - data.item_master = itemMaster; - data.purchase_price = param.purchase_price; - data.selling_price = param.selling_price; - data.created_by = req.auth?.data.name; - data.updated_by = req.auth?.data.name; - } - - await repo.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_update, data); - - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_update, err.message); - } - } - - static async delete(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - ItemPrice'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'Item Price ID.', - required: true, - type: 'string' - } - #swagger.parameters['hard'] = { - in: 'path', - description: 'Is Hard Delete', - required: false, - type: 'boolean' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID'), - hard: Joi.bool().optional().allow('').label('Is hard delete?') - }); - - const param: { id: string, hard: boolean } = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(ItemPrice); - - const existData = await repo.findOne({ where: { id: param.id } }); - if (existData && !param.hard) { - existData.deleted_by = req.auth?.data.name; - await OrmHelper.DB.manager.save(existData); - } - - const affected = (!param.hard ? await repo.softDelete({ id: param.id }) : await repo.delete({ id: param.id })).affected || 0; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_delete, err.message); - } - } - - static async restore(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - ItemPrice'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.parameters['id'] = { - in: 'path', - description: 'ItemPrice ID.', - required: true, - type: 'string' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID') - }); - - const param: ItemPrice = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(ItemPrice); - - const affected = (await repo.restore({ id: param.id })).affected || 0; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_restore, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_restore, err.message); - } - } -} \ No newline at end of file diff --git a/src/controllers/pharmacy/item_status.ts b/src/controllers/pharmacy/item_status.ts deleted file mode 100644 index ccfe101..0000000 --- a/src/controllers/pharmacy/item_status.ts +++ /dev/null @@ -1,339 +0,0 @@ -import { Response, NextFunction, Application } from "express"; -import { Request } from "express-jwt"; -import { ReturnHelper } from "../../helpers/express/return"; -import { OrmHelper } from "../../helpers/orm"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import { Language } from "../../langs/lang"; -import { ItemStatus, Paging } from "entity"; -import CommonHelper from "../../helpers/common"; -import * as fastcsv from 'fast-csv'; -import dayjs from "dayjs"; -import { ItemStatusModel } from "../../model/item_status"; - -const log: Logger = new Logger({ name: '[ItemStatusController]', type: 'pretty' }); - -export class ItemStatusController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - ItemStatus'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['filter'] = { description: '', in: 'query', type: 'string' } - #swagger.parameters['limit'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['page'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['with_deleted'] = { in: 'query', required: true, type: 'boolean' } - #swagger.parameters['order_field'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['order_direction'] = { in: 'query', required: true, schema: { '@enum': ['ASC', 'DESC'] } } - */ - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().required().label("With Deleted"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").required().label("Order Direction"), - }); - - let param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await ItemStatusModel.list(filter); - - const offset = (param.page - 1) * param.limit; - let limit = param.limit; - - const res_count = query; - const res_list = query - .orderBy("item_status." + param.order_field, param.order_direction) - .offset(offset) - .limit(limit); - - if (param.with_deleted) { - res_count.withDeleted(); - res_list.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async export(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - ItemStatus'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['filter'] = { - description: 'Filter with 2 format :
  • Simple format use text plaint will filter eq:code or like %name%
  • Advance format using field existing {status:\'Y\', any:\'SAME AS PLAINT LOGIC\', etc...}
', - in: 'query', - type: 'string' - } - #swagger.parameters['filter'] = { - in: 'query', - type: 'string' - } - #swagger.parameters['order_field'] = { - in: 'query', - required: true, - type: 'string' - } - #swagger.parameters['order_direction'] = { - in: 'query', - required: true, - schema: { - '@enum': ['ASC', 'DESC'] - } - } - */ - - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow('').optional().label('Filter'), - order_field: Joi.string().required().label('Order Field'), - order_direction: Joi.string().allow('asc', 'desc').required().label('Order Direction'), - }); - - const param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await ItemStatusModel.list(filter); - const data = await query.getMany(); - - const filename = "item_status.csv"; - - res.setHeader('Content-Type', 'text/csv'); - res.setHeader('Content-Disposition', 'attachment; filename=' + filename); - - const csvStream = fastcsv.format({ - headers: true, - writeHeaders: true, - transform: (row: ItemStatus): any => ({ - ...row, - created_at: dayjs(row.created_at).format('DD-MM-YYYY HH:MM:ss'), - }) - }); - csvStream.pipe(res); - - const limit = 50; - - const fetchAndWrite = async (page: any) => { - - if (CommonHelper.countObject(data) === 0) { - csvStream.end(); - } else { - data.forEach((item: any) => csvStream.write(item)); - - if (CommonHelper.countObject(data) == limit) { - fetchAndWrite(page + 1); - } else { - csvStream.end(); - } - } - }; - - fetchAndWrite(1); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - ItemStatus'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/item_status" - } - } - } - } - */ - try { - const schema = Joi.object().keys({ - status_name: Joi.string().max(256).required().label('Name'), - }); - - const param: any = await schema.validateAsync(req.body); - - const data = new ItemStatus() - data.status_name = param.status_name - data.created_by = req.auth.data.name - - await OrmHelper.DB.manager.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 401, Language.lang.failed_insert, err.message); - } - } - - static async update(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - ItemStatus'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'ItemStatus ID.', - required: true, - type: 'string' - } - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/item_status" - } - } - } - } - */ - - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID'), - status_name: Joi.string().max(256).required().label('Name'), - }); - - req.body.id = req.params['id']; - - const param: any = await schema.validateAsync(req.body); - - const repo = OrmHelper.DB.getRepository(ItemStatus); - - const data = await repo.findOneBy({ id: param.id }); - - if (data != null) { - data.status_name = param.status_name - data.updated_by = req.auth.data.name - - await repo.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_update, data); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_update, err.message); - } - } - - static async delete(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - ItemStatus'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'ItemStatus ID.', - required: true, - type: 'string' - } - #swagger.parameters['hard'] = { - in: 'path', - description: 'Is Hard Delete', - required: false, - type: 'boolean' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID'), - hard: Joi.bool().optional().allow('').label('Is hard delete?') - }); - - const param: { id: string, hard: boolean } = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(ItemStatus); - - const existData = await repo.findOne({ where: { id: param.id } }); - if (existData && !param.hard) { - existData.deleted_by = req.auth.data.name; - await OrmHelper.DB.manager.save(existData); - } - - const affected = (!param.hard ? await repo.softDelete({ id: param.id }) : await repo.delete({ id: param.id })).affected; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_delete, err.message); - } - } - - static async restore(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - ItemStatus'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.parameters['id'] = { - in: 'path', - description: 'ItemStatus ID.', - required: true, - type: 'string' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID') - }); - - const param: ItemStatus = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(ItemStatus); - - const affected = (await repo.restore({ id: param.id })).affected; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_restore, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_restore, err.message); - } - } -} \ No newline at end of file diff --git a/src/controllers/pharmacy/item_type.ts b/src/controllers/pharmacy/item_type.ts deleted file mode 100644 index caff889..0000000 --- a/src/controllers/pharmacy/item_type.ts +++ /dev/null @@ -1,343 +0,0 @@ -import { Response, NextFunction, Application } from "express"; -import { Request } from "express-jwt"; -import { ReturnHelper } from "../../helpers/express/return"; -import { OrmHelper } from "../../helpers/orm"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import { Language } from "../../langs/lang"; -import { ItemType, Paging } from "entity"; -import CommonHelper from "../../helpers/common"; -import * as fastcsv from 'fast-csv'; -import dayjs from "dayjs"; -import { ItemTypeModel } from "../../model/item_type"; - -const log: Logger = new Logger({ name: '[ItemTypeController]', type: 'pretty' }); - -export class ItemTypeController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - ItemType'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['filter'] = { description: '', in: 'query', type: 'string' } - #swagger.parameters['limit'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['page'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['with_deleted'] = { in: 'query', required: true, type: 'boolean' } - #swagger.parameters['order_field'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['order_direction'] = { in: 'query', required: true, schema: { '@enum': ['ASC', 'DESC'] } } - */ - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().required().label("With Deleted"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").required().label("Order Direction"), - }); - - let param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await ItemTypeModel.list(filter); - - const offset = (param.page - 1) * param.limit; - let limit = param.limit; - - const res_count = query; - const res_list = query - .orderBy("item_type." + param.order_field, param.order_direction) - .offset(offset) - .limit(limit); - - if (param.with_deleted) { - res_count.withDeleted(); - res_list.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async export(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - ItemType'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['filter'] = { - description: 'Filter with 2 format :
  • Simple format use text plaint will filter eq:code or like %name%
  • Advance format using field existing {status:\'Y\', any:\'SAME AS PLAINT LOGIC\', etc...}
', - in: 'query', - type: 'string' - } - #swagger.parameters['filter'] = { - in: 'query', - type: 'string' - } - #swagger.parameters['order_field'] = { - in: 'query', - required: true, - type: 'string' - } - #swagger.parameters['order_direction'] = { - in: 'query', - required: true, - schema: { - '@enum': ['ASC', 'DESC'] - } - } - */ - - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow('').optional().label('Filter'), - order_field: Joi.string().required().label('Order Field'), - order_direction: Joi.string().allow('asc', 'desc').required().label('Order Direction'), - }); - - const param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await ItemTypeModel.list(filter); - const data = await query.getMany(); - - const filename = "item_type.csv"; - - res.setHeader('Content-Type', 'text/csv'); - res.setHeader('Content-Disposition', 'attachment; filename=' + filename); - - const csvStream = fastcsv.format({ - headers: true, - writeHeaders: true, - transform: (row: ItemType): any => ({ - ...row, - created_at: dayjs(row.created_at).format('DD-MM-YYYY HH:MM:ss'), - }) - }); - csvStream.pipe(res); - - const limit = 50; - - const fetchAndWrite = async (page: any) => { - - if (CommonHelper.countObject(data) === 0) { - csvStream.end(); - } else { - data.forEach((item: any) => csvStream.write(item)); - - if (CommonHelper.countObject(data) == limit) { - fetchAndWrite(page + 1); - } else { - csvStream.end(); - } - } - }; - - fetchAndWrite(1); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - ItemType'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/item_type" - } - } - } - } - */ - try { - const schema = Joi.object().keys({ - type_name: Joi.string().max(256).required().label('Name'), - item_group_id: Joi.string().uuid().required().label('Item Group ID'), - }); - - const param: any = await schema.validateAsync(req.body); - - const data = new ItemType() - data.type_name = param.type_name - data.item_group = param.item_group_id - data.created_by = req.auth.data.name - - await OrmHelper.DB.manager.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 401, Language.lang.failed_insert, err.message); - } - } - - static async update(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - ItemType'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'ItemType ID.', - required: true, - type: 'string' - } - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/item_type" - } - } - } - } - */ - - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID'), - type_name: Joi.string().max(256).required().label('Name'), - item_group_id: Joi.string().uuid().required().label('Item Group ID'), - }); - - req.body.id = req.params['id']; - - const param: any = await schema.validateAsync(req.body); - - const repo = OrmHelper.DB.getRepository(ItemType); - - const data = await repo.findOneBy({ id: param.id }); - - if (data != null) { - data.type_name = param.type_name - data.item_group = param.item_group_id - data.updated_by = req.auth.data.name; - - await repo.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_update, data); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_update, err.message); - } - } - - static async delete(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - ItemType'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'Item Type ID.', - required: true, - type: 'string' - } - #swagger.parameters['hard'] = { - in: 'path', - description: 'Is Hard Delete', - required: false, - type: 'boolean' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID'), - hard: Joi.bool().optional().allow('').label('Is hard delete?') - }); - - const param: { id: string, hard: boolean } = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(ItemType); - - const existData = await repo.findOne({ where: { id: param.id } }); - if (existData && !param.hard) { - existData.deleted_by = req.auth.data.name; - await OrmHelper.DB.manager.save(existData); - } - - const affected = (!param.hard ? await repo.softDelete({ id: param.id }) : await repo.delete({ id: param.id })).affected; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_delete, err.message); - } - } - - static async restore(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - ItemType'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.parameters['id'] = { - in: 'path', - description: 'ItemType ID.', - required: true, - type: 'string' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID') - }); - - const param: ItemType = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(ItemType); - - const affected = (await repo.restore({ id: param.id })).affected; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_restore, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_restore, err.message); - } - } -} \ No newline at end of file diff --git a/src/controllers/pharmacy/item_type_detail.ts b/src/controllers/pharmacy/item_type_detail.ts deleted file mode 100644 index 86afd82..0000000 --- a/src/controllers/pharmacy/item_type_detail.ts +++ /dev/null @@ -1,343 +0,0 @@ -import { Response, NextFunction, Application } from "express"; -import { Request } from "express-jwt"; -import { ReturnHelper } from "../../helpers/express/return"; -import { OrmHelper } from "../../helpers/orm"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import { Language } from "../../langs/lang"; -import { ItemTypeDetail, Paging } from "entity"; -import CommonHelper from "../../helpers/common"; -import * as fastcsv from 'fast-csv'; -import dayjs from "dayjs"; -import { ItemTypeDetailModel } from "../../model/item_type_detail"; - -const log: Logger = new Logger({ name: '[ItemTypeDetailController]', type: 'pretty' }); - -export class ItemTypeDetailController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - ItemTypeDetail'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['filter'] = { description: '', in: 'query', type: 'string' } - #swagger.parameters['limit'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['page'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['with_deleted'] = { in: 'query', required: true, type: 'boolean' } - #swagger.parameters['order_field'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['order_direction'] = { in: 'query', required: true, schema: { '@enum': ['ASC', 'DESC'] } } - */ - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().required().label("With Deleted"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").required().label("Order Direction"), - }); - - let param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await ItemTypeDetailModel.list(filter); - - const offset = (param.page - 1) * param.limit; - let limit = param.limit; - - const res_count = query; - const res_list = query - .orderBy("item_type_detail." + param.order_field, param.order_direction) - .offset(offset) - .limit(limit); - - if (param.with_deleted) { - res_count.withDeleted(); - res_list.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async export(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - ItemTypeDetail'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['filter'] = { - description: 'Filter with 2 format :
  • Simple format use text plaint will filter eq:code or like %name%
  • Advance format using field existing {status:\'Y\', any:\'SAME AS PLAINT LOGIC\', etc...}
', - in: 'query', - type: 'string' - } - #swagger.parameters['filter'] = { - in: 'query', - type: 'string' - } - #swagger.parameters['order_field'] = { - in: 'query', - required: true, - type: 'string' - } - #swagger.parameters['order_direction'] = { - in: 'query', - required: true, - schema: { - '@enum': ['ASC', 'DESC'] - } - } - */ - - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow('').optional().label('Filter'), - order_field: Joi.string().required().label('Order Field'), - order_direction: Joi.string().allow('asc', 'desc').required().label('Order Direction'), - }); - - const param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await ItemTypeDetailModel.list(filter); - const data = await query.getMany(); - - const filename = "item_type_detail.csv"; - - res.setHeader('Content-Type', 'text/csv'); - res.setHeader('Content-Disposition', 'attachment; filename=' + filename); - - const csvStream = fastcsv.format({ - headers: true, - writeHeaders: true, - transform: (row: ItemTypeDetail): any => ({ - ...row, - created_at: dayjs(row.created_at).format('DD-MM-YYYY HH:MM:ss'), - }) - }); - csvStream.pipe(res); - - const limit = 50; - - const fetchAndWrite = async (page: any) => { - - if (CommonHelper.countObject(data) === 0) { - csvStream.end(); - } else { - data.forEach((item: any) => csvStream.write(item)); - - if (CommonHelper.countObject(data) == limit) { - fetchAndWrite(page + 1); - } else { - csvStream.end(); - } - } - }; - - fetchAndWrite(1); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - ItemTypeDetail'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/item_type_detail" - } - } - } - } - */ - try { - const schema = Joi.object().keys({ - type_detail_name: Joi.string().max(256).required().label('Name'), - item_type_id: Joi.string().uuid().required().label('Item Group ID'), - }); - - const param: any = await schema.validateAsync(req.body); - - const data = new ItemTypeDetail() - data.type_detail_name = param.type_detail_name - data.item_type = param.item_type_id - data.created_by = req.auth?.data.name - - await OrmHelper.DB.manager.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 401, Language.lang.failed_insert, err.message); - } - } - - static async update(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - ItemTypeDetail'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'ItemTypeDetail ID.', - required: true, - type: 'string' - } - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/item_type_detail" - } - } - } - } - */ - - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID'), - type_detail_name: Joi.string().max(256).required().label('Name'), - item_type_id: Joi.string().uuid().required().label('Item Group ID'), - }); - - req.body.id = req.params['id']; - - const param: any = await schema.validateAsync(req.body); - - const repo = OrmHelper.DB.getRepository(ItemTypeDetail); - - const data = await repo.findOneBy({ id: param.id }); - - if (data != null) { - data.type_detail_name = param.type_detail_name - data.item_type = param.item_type_id - data.updated_by = req.auth?.data.name - - await repo.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_update, data); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_update, err.message); - } - } - - static async delete(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - ItemTypeDetail'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'Item Type Detail ID.', - required: true, - type: 'string' - } - #swagger.parameters['hard'] = { - in: 'path', - description: 'Is Hard Delete', - required: false, - type: 'boolean' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID'), - hard: Joi.bool().optional().allow('').label('Is hard delete?') - }); - - const param: { id: string, hard: boolean } = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(ItemTypeDetail); - - const existData = await repo.findOne({ where: { id: param.id } }); - if (existData && !param.hard) { - existData.deleted_by = req.auth?.data.name; - await OrmHelper.DB.manager.save(existData); - } - - const affected = (!param.hard ? await repo.softDelete({ id: param.id }) : await repo.delete({ id: param.id })).affected || 0; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_delete, err.message); - } - } - - static async restore(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - ItemTypeDetail'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.parameters['id'] = { - in: 'path', - description: 'ItemTypeDetail ID.', - required: true, - type: 'string' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID') - }); - - const param: ItemTypeDetail = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(ItemTypeDetail); - - const affected = (await repo.restore({ id: param.id })).affected || 0; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_restore, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_restore, err.message); - } - } -} \ No newline at end of file diff --git a/src/controllers/pharmacy/pharmacy_info.ts b/src/controllers/pharmacy/pharmacy_info.ts deleted file mode 100644 index 3a7e8c7..0000000 --- a/src/controllers/pharmacy/pharmacy_info.ts +++ /dev/null @@ -1,692 +0,0 @@ -import { Response, NextFunction, Application } from "express"; -import { Request } from "express-jwt"; -import { ReturnHelper } from "../../helpers/express/return"; -import { OrmHelper } from "../../helpers/orm"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import { Language } from "../../langs/lang"; -import { PharmacyInfo, Paging, Subdistrict } from "entity"; -import CommonHelper from "../../helpers/common"; -import * as fastcsv from 'fast-csv'; -import dayjs from "dayjs"; -import fileUpload from "express-fileupload"; -import fs from "fs"; -import path from "path"; -import { v4 as uuidv4 } from 'uuid'; -import config from "../../../config/stag.json"; -import { PharmacyInfoModel } from "../../model/pharmacy_info"; - -interface FileUploadRequest extends Request { - files?: fileUpload.FileArray | null; - body: any; -} - -const log: Logger = new Logger({ name: '[PharmacyInfoController]', type: 'pretty' }); - -export class PharmacyInfoController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - PharmacyInfo'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['filter'] = { description: '', in: 'query', type: 'string' } - #swagger.parameters['limit'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['page'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['with_deleted'] = { in: 'query', required: true, type: 'boolean' } - #swagger.parameters['order_field'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['order_direction'] = { in: 'query', required: true, schema: { '@enum': ['ASC', 'DESC'] } } - */ - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().required().label("With Deleted"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").required().label("Order Direction"), - }); - - let param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await PharmacyInfoModel.list(filter); - - const offset = (param.page - 1) * param.limit; - let limit = param.limit; - - const res_count = query; - const res_list = query - .orderBy("pharmacy_info." + param.order_field, param.order_direction) - .offset(offset) - .limit(limit); - - if (param.with_deleted) { - res_count.withDeleted(); - res_list.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = (await res_list.getMany()).map((item) => ({ - ...item, - logo: config.server.host_swagger + 'uploads/hospital-logo/' + item.logo, - file: item.logo - })); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async detail(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - PharmacyInfo'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { description: '', in: 'path', type: 'string' } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("Pharmacy Info Id"), - }); - - let param: any = await schema.validateAsync(req.params); - - let data = await PharmacyInfoModel.list({ "id": param.id }).then((q) => q.getOne()); - if (!data) throw { message: "Pharmacy Info Not Found" }; - - const result = { - ...data, - logo: config.server.host_swagger + 'uploads/hospital-logo/' + data.logo, - file: data.logo - }; - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_view, result); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_not_found, err.message); - } - } - static async export(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - PharmacyInfo'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['filter'] = { - description: 'Filter with 2 format :
  • Simple format use text plaint will filter eq:code or like %name%
  • Advance format using field existing {status:\'Y\', any:\'SAME AS PLAINT LOGIC\', etc...}
', - in: 'query', - type: 'string' - } - #swagger.parameters['filter'] = { - in: 'query', - type: 'string' - } - #swagger.parameters['order_field'] = { - in: 'query', - required: true, - type: 'string' - } - #swagger.parameters['order_direction'] = { - in: 'query', - required: true, - schema: { - '@enum': ['ASC', 'DESC'] - } - } - */ - - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow('').optional().label('Filter'), - order_field: Joi.string().required().label('Order Field'), - order_direction: Joi.string().allow('asc', 'desc').required().label('Order Direction'), - }); - - const param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await PharmacyInfoModel.list(filter); - const data = await query.getMany(); - - const filename = "pharmacy_info.csv"; - - res.setHeader('Content-Type', 'text/csv'); - res.setHeader('Content-Disposition', 'attachment; filename=' + filename); - - const csvStream = fastcsv.format({ - headers: true, - writeHeaders: true, - transform: (row: PharmacyInfo): any => ({ - ...row, - created_at: dayjs(row.created_at).format('DD-MM-YYYY HH:MM:ss'), - }) - }); - csvStream.pipe(res); - - const limit = 50; - - const fetchAndWrite = async (page: any) => { - - if (CommonHelper.countObject(data) === 0) { - csvStream.end(); - } else { - data.forEach((item: any) => csvStream.write(item)); - - if (CommonHelper.countObject(data) == limit) { - fetchAndWrite(page + 1); - } else { - csvStream.end(); - } - } - }; - - fetchAndWrite(1); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - PharmacyInfo'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/pharmacy_info" - } - } - } - } - */ - try { - const schema = Joi.object().keys({ - logo: Joi.string() - .max(256) - .required() - .label('Logo'), - - name: Joi.string() - .max(256) - .required() - .label('Name'), - - address: Joi.string() - .max(500) - .required() - .label('Address'), - - munisipiu: Joi.string() - .uuid() - .required() - .label('Munisipiu'), - - postu_admin: Joi.string() - .uuid() - .required() - .label('Postu Admin'), - - suco: Joi.string() - .uuid() - .required() - .label('Suco'), - - aldeia: Joi.string() - .uuid() - .required() - .label('Aldeia'), - - phone: Joi.string() - .max(30) - .optional() - .label('Phone'), - - default_room_id: Joi.string() - .uuid() - .required() - .label('Default Room'), - - // province: Joi.string().allow("").optional().label("Province Code"), - // city: Joi.string().allow("").optional().label("City Code"), - // subdistrict: Joi.string().allow("").optional().label("Subdistrict Code"), - // ward: Joi.string().allow("").optional().label("Ward Code"), - }); - - const param: any = await schema.validateAsync(req.body); - - const data = new PharmacyInfo() - data.name = param.name, - data.address = param.address - data.munisipiu = param.munisipiu, - data.postu_admin = param.postu_admin - data.suco = param.suco - data.aldeia = param.aldeia - data.phone = param.phone - data.default_room = param.default_room_id - data.logo = param.logo - // data.province = param.province - // data.city = param.city - // data.subdistrict = param.subdistrict - // data.ward = param.ward - data.created_by = req.auth?.data.name; - - await OrmHelper.DB.manager.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 401, Language.lang.failed_insert, err.message); - } - } - - static async update(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - PharmacyInfo'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'PharmacyInfo ID.', - required: true, - type: 'string' - } - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/pharmacy_info" - } - } - } - } - */ - - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID'), - logo: Joi.string() - .max(256) - .required() - .label('Logo'), - - name: Joi.string() - .max(256) - .required() - .label('Name'), - - address: Joi.string() - .max(500) - .required() - .label('Address'), - - munisipiu: Joi.string() - .uuid() - .allow('', null) - .label('Munisipiu'), - - postu_admin: Joi.string() - .uuid() - .allow('', null) - .label('Postu Admin'), - - suco: Joi.string() - .uuid() - .allow('', null) - .label('Suco'), - - aldeia: Joi.string() - .uuid() - .allow('', null) - .label('Aldeia'), - - - // province: Joi.string() - // .allow("", null) - // .label('Province'), - - // city: Joi.string() - // .allow("", null) - // .label('City'), - - // subdistrict: Joi.string() - // .allow("", null) - // .label('Subdistrict'), - - // ward: Joi.string() - // .allow("", null) - // .label('Ward'), - }); - - req.body.id = req.params['id']; - - const param: any = await schema.validateAsync(req.body); - - const repo = OrmHelper.DB.getRepository(PharmacyInfo); - - const data = await repo.findOneBy({ id: param.id }); - - if (data != null) { - data.name = param.name, - data.address = param.address - data.munisipiu = param.munisipiu, - data.postu_admin = param.postu_admin - data.suco = param.suco - data.aldeia = param.aldeia - data.phone = param.phone - data.default_room = param.default_room_id - data.logo = param.logo - // data.province = param.province - // data.city = param.city - // data.subdistrict = param.subdistrict - // data.ward = param.ward - data.updated_by = req.auth?.data.name; - - await repo.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_update, data); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_update, err.message); - } - } - - static async delete(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - PharmacyInfo'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'Pharmacy Info ID.', - required: true, - type: 'string' - } - #swagger.parameters['hard'] = { - in: 'path', - description: 'Is Hard Delete', - required: false, - type: 'boolean' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID'), - hard: Joi.bool().optional().allow('').label('Is hard delete?') - }); - - const param: { id: string, hard: boolean } = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(PharmacyInfo); - - const existData = await repo.findOne({ where: { id: param.id } }); - if (existData && !param.hard) { - existData.deleted_by = req.auth?.data.name; - await OrmHelper.DB.manager.save(existData); - } - - const affected = (!param.hard ? await repo.softDelete({ id: param.id }) : await repo.delete({ id: param.id })).affected ?? 0; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_delete, err.message); - } - } - - static async restore(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - PharmacyInfo'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.parameters['id'] = { - in: 'path', - description: 'PharmacyInfo ID.', - required: true, - type: 'string' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID') - }); - - const param: PharmacyInfo = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(PharmacyInfo); - - const affected = (await repo.restore({ id: param.id })).affected ?? 0; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_restore, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_restore, err.message); - } - } - - static async uploadlogo(req: FileUploadRequest, res: Response, next: NextFunction): Promise { - /* #swagger.tags = ['Pharmacy - PharmacyInfo'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.consumes = ['multipart/form-data'] - #swagger.requestBody = { - required: true, - content: { - "multipart/form-data": { - schema: { - type: "object", - properties: { - file: { - type: "string", - format: "binary", - description: "Image file (max 1MB, jpg/png/webp)" - }, - path: { - type: "string", - description: 'File path', - default: 'uploads/pharmacy-info' - }, - application: { - type: "string", - description: 'Application name', - default: 'saude' - } - }, - required: ["file", "path", "application"] - } - } - } - } - */ - try { - // Validation schema - const schema = Joi.object().keys({ - path: Joi.string().label('File Path'), - application: Joi.string().label('Application'), - }); - - log.info("body", req.body); - - const param: { path: string, application: string } = await schema.validateAsync(req.body); - - // Check if file exists - if (!req.files || !req.files.file) { - return ReturnHelper.errorResponse(res, 400, 404, Language.lang.failed_insert, "File not found"); - } - - const file = req.files.file as fileUpload.UploadedFile; - - // Validate file size (max 1MB) - const maxSize = 10 * 1024 * 1024; // 10MB - if (file.size > maxSize) { - return ReturnHelper.errorResponse( - res, - 400, - 400, - Language.lang.failed_insert, - "File size exceeds 10MB limit" - ); - } - - // Validate file type - const allowedMimes = ['image/jpeg', 'image/jpg', 'image/png', 'image/webp']; - if (!allowedMimes.includes(file.mimetype)) { - return ReturnHelper.errorResponse(res, 400, 400, Language.lang.failed_insert, "Invalid file type. Only JPG, PNG, and WEBP are allowed"); - } - - // Normalize path - param.path = param.path[param.path.length - 1] !== '/' ? param.path + '/' : param.path; - - if (param.path == undefined || param.path == null) param.path = 'uploads/pharmacy-info/'; - - // Generate unique filename - const ext = file.name.split('.'); - const name = uuidv4() + '.' + ext[ext.length - 1]; - - const result: { file: string } = { - // url: "", - // path: "", - file: "", - // mime: file.mimetype, - // size: file.size, - // md5: file.md5 - }; - - const folder_path = param.path; - const file_path = path.join(folder_path, name); - - // Create directory if it doesn't exist - if (!fs.existsSync(folder_path)) { - fs.mkdirSync(folder_path, { recursive: true }); - } - - // Move file to destination - await file.mv(file_path); - - // result.path = param.path[param.path.length - 1] === '/' ? param.path.substring(0, param.path.length - 1) : param.path; - result.file = name; - // result.url = `${result.path}/${name}`; // Generate URL - - log.info(`File uploaded successfully: ${file_path}`); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, result); - - } catch (e: unknown) { - // Proper error logging to avoid tslog serialization issues - if (e instanceof Error) { - log.error("File upload failed:", { - message: e.message, - stack: e.stack, - name: e.name - }); - return ReturnHelper.errorResponse(res, 500, 500, Language.lang.failed_insert, e.message); - } else { - log.error("File upload failed with unknown error:", String(e)); - return ReturnHelper.errorResponse(res, 500, 500, Language.lang.failed_insert, "Unknown error occurred"); - } - } - } - - static async deletelogo(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - PharmacyInfo'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.requestBody = { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/files" } } } } - */ - - try { - const schema = Joi.object().keys({ - file_name: Joi.string().required().label('File Name'), - }); - - const param: { file_name: string } = await schema.validateAsync(req.body); - - // const env = process.env.NODE_ENV + '/' - const fixedPath = 'uploads/pharmacy-info/'; - const file_path = fixedPath + param.file_name; - - // Check if file exists - if (!fs.existsSync(file_path)) { - return ReturnHelper.errorResponse(res, 404, 404, Language.lang.failed_not_found, "File not found"); - } - - // Delete file - fs.unlinkSync(file_path); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_delete, err.message); - } - } - - static async view(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - PharmacyInfo'] - #swagger.security = [{ "bearerAuth": [] }] - */ - try { - const data = await OrmHelper.DB - .getRepository(PharmacyInfo) - .findOne({ - where: {} - }); - - if (!data) return ReturnHelper.errorResponse(res, 404, 404, Language.lang.failed_view, "data not found"); - - const result = { - id: data.id, - name: data.name, - address: data.address, - phone: data.phone, - logo: config.server.host_swagger + 'uploads/hospital-logo/' + data.logo - }; - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_view, result); - - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } -} \ No newline at end of file diff --git a/src/controllers/pharmacy/planning_verificator.ts b/src/controllers/pharmacy/planning_verificator.ts deleted file mode 100644 index 536a7f0..0000000 --- a/src/controllers/pharmacy/planning_verificator.ts +++ /dev/null @@ -1,282 +0,0 @@ -import { Response, NextFunction, Application } from "express"; -import { Request } from "express-jwt"; -import { ReturnHelper } from "../../helpers/express/return"; -import { OrmHelper } from "../../helpers/orm"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import { Language } from "../../langs/lang"; -import { PlanningVerificator, Paging } from "entity"; -import CommonHelper from "../../helpers/common"; -import * as fastcsv from 'fast-csv'; -import dayjs from "dayjs"; -import { PlanningVerificatorModel } from "../../model/planning_verificator"; - -const log: Logger = new Logger({ name: '[PlanningVerificatorController]', type: 'pretty' }); - -export class PlanningVerificatorController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - PlanningVerificator'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['filter'] = { description: '', in: 'query', type: 'string' } - #swagger.parameters['limit'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['page'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['with_deleted'] = { in: 'query', required: true, type: 'boolean' } - #swagger.parameters['order_field'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['order_direction'] = { in: 'query', required: true, schema: { '@enum': ['ASC', 'DESC'] } } - */ - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().required().label("With Deleted"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").required().label("Order Direction"), - }); - - let param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await PlanningVerificatorModel.list(filter); - - const offset = (param.page - 1) * param.limit; - let limit = param.limit; - - const res_count = query; - const res_list = query - .orderBy("planning_verificator." + param.order_field, param.order_direction) - .offset(offset) - .limit(limit); - - if (param.with_deleted) { - res_count.withDeleted(); - res_list.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async export(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - PlanningVerificator'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['filter'] = { - description: 'Filter with 2 format :
  • Simple format use text plaint will filter eq:code or like %name%
  • Advance format using field existing {status:\'Y\', any:\'SAME AS PLAINT LOGIC\', etc...}
', - in: 'query', - type: 'string' - } - #swagger.parameters['filter'] = { - in: 'query', - type: 'string' - } - #swagger.parameters['order_field'] = { - in: 'query', - required: true, - type: 'string' - } - #swagger.parameters['order_direction'] = { - in: 'query', - required: true, - schema: { - '@enum': ['ASC', 'DESC'] - } - } - */ - - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow('').optional().label('Filter'), - order_field: Joi.string().required().label('Order Field'), - order_direction: Joi.string().allow('asc', 'desc').required().label('Order Direction'), - }); - - const param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await PlanningVerificatorModel.list(filter); - const data = await query.getMany(); - - const filename = "planning_verificator.csv"; - - res.setHeader('Content-Type', 'text/csv'); - res.setHeader('Content-Disposition', 'attachment; filename=' + filename); - - const csvStream = fastcsv.format({ - headers: true, - writeHeaders: true, - transform: (row: PlanningVerificator): any => ({ - ...row, - created_at: dayjs(row.created_at).format('DD-MM-YYYY HH:MM:ss'), - }) - }); - csvStream.pipe(res); - - const limit = 50; - - const fetchAndWrite = async (page: any) => { - - if (CommonHelper.countObject(data) === 0) { - csvStream.end(); - } else { - data.forEach((item: any) => csvStream.write(item)); - - if (CommonHelper.countObject(data) == limit) { - fetchAndWrite(page + 1); - } else { - csvStream.end(); - } - } - }; - - fetchAndWrite(1); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - PlanningVerificator'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/planning_verificator" - } - } - } - } - */ - try { - const schema = Joi.object().keys({ - user_id: Joi.string().max(256).required().label('User Id'), - }); - - const param: any = await schema.validateAsync(req.body); - - const data = new PlanningVerificator() - data.user = param.user_id - data.created_by = req.auth.data.name; - - await OrmHelper.DB.manager.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 401, Language.lang.failed_insert, err.message); - } - } - - static async delete(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - PlanningVerificator'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'Planning Verificator ID.', - required: true, - type: 'string' - } - #swagger.parameters['hard'] = { - in: 'path', - description: 'Is Hard Delete', - required: false, - type: 'boolean' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID'), - hard: Joi.bool().optional().allow('').label('Is hard delete?') - }); - - const param: { id: string, hard: boolean } = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(PlanningVerificator); - - const existData = await repo.findOne({ where: { id: param.id } }); - if (existData && !param.hard) { - existData.deleted_by = req.auth.data.name; - await OrmHelper.DB.manager.save(existData); - } - - const affected = (!param.hard ? await repo.softDelete({ id: param.id }) : await repo.delete({ id: param.id })).affected; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_delete, err.message); - } - } - - static async restore(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - PlanningVerificator'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.parameters['id'] = { - in: 'path', - description: 'PlanningVerificator ID.', - required: true, - type: 'string' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID') - }); - - const param: PlanningVerificator = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(PlanningVerificator); - - const affected = (await repo.restore({ id: param.id })).affected; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_restore, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_restore, err.message); - } - } -} \ No newline at end of file diff --git a/src/controllers/pharmacy/selling_price_percentage.ts b/src/controllers/pharmacy/selling_price_percentage.ts deleted file mode 100644 index 403fe96..0000000 --- a/src/controllers/pharmacy/selling_price_percentage.ts +++ /dev/null @@ -1,347 +0,0 @@ -import { Response, NextFunction, Application } from "express"; -import { Request } from "express-jwt"; -import { ReturnHelper } from "../../helpers/express/return"; -import { OrmHelper } from "../../helpers/orm"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import { Language } from "../../langs/lang"; -import { SellingPricePercentage, Paging } from "entity"; -import CommonHelper from "../../helpers/common"; -import * as fastcsv from 'fast-csv'; -import dayjs from "dayjs"; -import { SellingPricePercentageModel } from "../../model/selling_price_percentage"; - -const log: Logger = new Logger({ name: '[SellingPricePercentageController]', type: 'pretty' }); - -export class SellingPricePercentageController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - SellingPricePercentage'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['filter'] = { description: '', in: 'query', type: 'string' } - #swagger.parameters['limit'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['page'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['with_deleted'] = { in: 'query', required: true, type: 'boolean' } - #swagger.parameters['order_field'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['order_direction'] = { in: 'query', required: true, schema: { '@enum': ['ASC', 'DESC'] } } - */ - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().required().label("With Deleted"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").required().label("Order Direction"), - }); - - let param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await SellingPricePercentageModel.list(filter); - - const offset = (param.page - 1) * param.limit; - let limit = param.limit; - - const res_count = query; - const res_list = query - .orderBy("selling_price_percentage." + param.order_field, param.order_direction) - .offset(offset) - .limit(limit); - - if (param.with_deleted) { - res_count.withDeleted(); - res_list.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async export(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - SellingPricePercentage'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['filter'] = { - description: 'Filter with 2 format :
  • Simple format use text plaint will filter eq:code or like %name%
  • Advance format using field existing {status:\'Y\', any:\'SAME AS PLAINT LOGIC\', etc...}
', - in: 'query', - type: 'string' - } - #swagger.parameters['filter'] = { - in: 'query', - type: 'string' - } - #swagger.parameters['order_field'] = { - in: 'query', - required: true, - type: 'string' - } - #swagger.parameters['order_direction'] = { - in: 'query', - required: true, - schema: { - '@enum': ['ASC', 'DESC'] - } - } - */ - - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow('').optional().label('Filter'), - order_field: Joi.string().required().label('Order Field'), - order_direction: Joi.string().allow('asc', 'desc').required().label('Order Direction'), - }); - - const param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await SellingPricePercentageModel.list(filter); - const data = await query.getMany(); - - const filename = "selling_price_percentage.csv"; - - res.setHeader('Content-Type', 'text/csv'); - res.setHeader('Content-Disposition', 'attachment; filename=' + filename); - - const csvStream = fastcsv.format({ - headers: true, - writeHeaders: true, - transform: (row: SellingPricePercentage): any => ({ - ...row, - created_at: dayjs(row.created_at).format('DD-MM-YYYY HH:MM:ss'), - }) - }); - csvStream.pipe(res); - - const limit = 50; - - const fetchAndWrite = async (page: any) => { - - if (CommonHelper.countObject(data) === 0) { - csvStream.end(); - } else { - data.forEach((item: any) => csvStream.write(item)); - - if (CommonHelper.countObject(data) == limit) { - fetchAndWrite(page + 1); - } else { - csvStream.end(); - } - } - }; - - fetchAndWrite(1); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - SellingPricePercentage'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/selling_price_percentage" - } - } - } - } - */ - try { - const schema = Joi.object().keys({ - item_master_id: Joi.string().uuid().required().label('Item Master ID'), - item_origin_id: Joi.string().uuid().required().label('Item Origin ID'), - percentage: Joi.number().min(0).max(999.99).precision(2).required().label('Percentage'), - }); - - const param: any = await schema.validateAsync(req.body); - - const data = new SellingPricePercentage() - data.item_master = param.item_master_id - data.item_origin = param.item_origin_id - data.percentage = param.percentage - data.created_by = req.auth.data.name; - - await OrmHelper.DB.manager.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 401, Language.lang.failed_insert, err.message); - } - } - - static async update(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - SellingPricePercentage'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'SellingPricePercentage ID.', - required: true, - type: 'string' - } - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/selling_price_percentage" - } - } - } - } - */ - - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID'), - item_master_id: Joi.string().uuid().required().label('Item Master ID'), - item_origin_id: Joi.string().uuid().required().label('Item Origin ID'), - percentage: Joi.number().min(0).max(999.99).precision(2).required().label('Percentage'), - }); - - req.body.id = req.params['id']; - - const param: any = await schema.validateAsync(req.body); - - const repo = OrmHelper.DB.getRepository(SellingPricePercentage); - - const data = await repo.findOneBy({ id: param.id }); - - if (data != null) { - data.item_master = param.item_master_id - data.item_origin = param.item_origin_id - data.percentage = param.percentage - data.updated_by = req.auth.data.name; - - await repo.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_update, data); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_update, err.message); - } - } - - static async delete(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - SellingPricePercentage'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'Selling Price Percentage ID.', - required: true, - type: 'string' - } - #swagger.parameters['hard'] = { - in: 'path', - description: 'Is Hard Delete', - required: false, - type: 'boolean' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID'), - hard: Joi.bool().optional().allow('').label('Is hard delete?') - }); - - const param: { id: string, hard: boolean } = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(SellingPricePercentage); - - const existData = await repo.findOne({ where: { id: param.id } }); - if (existData && !param.hard) { - existData.deleted_by = req.auth.data.name; - await OrmHelper.DB.manager.save(existData); - } - - const affected = (!param.hard ? await repo.softDelete({ id: param.id }) : await repo.delete({ id: param.id })).affected; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_delete, err.message); - } - } - - static async restore(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - SellingPricePercentage'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.parameters['id'] = { - in: 'path', - description: 'SellingPricePercentage ID.', - required: true, - type: 'string' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID') - }); - - const param: SellingPricePercentage = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(SellingPricePercentage); - - const affected = (await repo.restore({ id: param.id })).affected; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_restore, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_restore, err.message); - } - } -} \ No newline at end of file diff --git a/src/controllers/pharmacy/supplier.ts b/src/controllers/pharmacy/supplier.ts deleted file mode 100644 index 6c156d4..0000000 --- a/src/controllers/pharmacy/supplier.ts +++ /dev/null @@ -1,376 +0,0 @@ -import { Response, NextFunction, Application } from "express"; -import { Request } from "express-jwt"; -import { ReturnHelper } from "../../helpers/express/return"; -import { OrmHelper } from "../../helpers/orm"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import { Language } from "../../langs/lang"; -import { Supplier, Paging } from "entity"; -import CommonHelper from "../../helpers/common"; -import * as fastcsv from 'fast-csv'; -import dayjs from "dayjs"; -import { SupplierModel } from "../../model/supplier"; - -const log: Logger = new Logger({ name: '[SupplierController]', type: 'pretty' }); - -export class SupplierController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - Supplier'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['filter'] = { description: '', in: 'query', type: 'string' } - #swagger.parameters['limit'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['page'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['with_deleted'] = { in: 'query', required: true, type: 'boolean' } - #swagger.parameters['order_field'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['order_direction'] = { in: 'query', required: true, schema: { '@enum': ['ASC', 'DESC'] } } - */ - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().required().label("With Deleted"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").required().label("Order Direction"), - }); - - let param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await SupplierModel.list(filter); - - const offset = (param.page - 1) * param.limit; - let limit = param.limit; - - const res_count = query; - const res_list = query - .orderBy("supplier." + param.order_field, param.order_direction) - .offset(offset) - .limit(limit); - - if (param.with_deleted) { - res_count.withDeleted(); - res_list.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async option(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - Supplier'] - #swagger.security = [{ "bearerAuth": [] }] - */ - try { - const query = await SupplierModel.list(); - - query.select([ - "supplier.id", - "supplier.supplier_name", - ]).orderBy("supplier.supplier_name", "ASC"); - - const total_count_data = await query.getCount(); - const list_data = await query.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, 1, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async export(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - Supplier'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['filter'] = { - description: 'Filter with 2 format :
  • Simple format use text plaint will filter eq:code or like %name%
  • Advance format using field existing {status:\'Y\', any:\'SAME AS PLAINT LOGIC\', etc...}
', - in: 'query', - type: 'string' - } - #swagger.parameters['filter'] = { - in: 'query', - type: 'string' - } - #swagger.parameters['order_field'] = { - in: 'query', - required: true, - type: 'string' - } - #swagger.parameters['order_direction'] = { - in: 'query', - required: true, - schema: { - '@enum': ['ASC', 'DESC'] - } - } - */ - - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow('').optional().label('Filter'), - order_field: Joi.string().required().label('Order Field'), - order_direction: Joi.string().allow('asc', 'desc').required().label('Order Direction'), - }); - - const param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await SupplierModel.list(filter); - const data = await query.getMany(); - - const filename = "supplier.csv"; - - res.setHeader('Content-Type', 'text/csv'); - res.setHeader('Content-Disposition', 'attachment; filename=' + filename); - - const csvStream = fastcsv.format({ - headers: true, - writeHeaders: true, - transform: (row: Supplier): any => ({ - ...row, - created_at: dayjs(row.created_at).format('DD-MM-YYYY HH:MM:ss'), - }) - }); - csvStream.pipe(res); - - const limit = 50; - - const fetchAndWrite = async (page: any) => { - - if (CommonHelper.countObject(data) === 0) { - csvStream.end(); - } else { - data.forEach((item: any) => csvStream.write(item)); - - if (CommonHelper.countObject(data) == limit) { - fetchAndWrite(page + 1); - } else { - csvStream.end(); - } - } - }; - - fetchAndWrite(1); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - Supplier'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/supplier" - } - } - } - } - */ - try { - const schema = Joi.object().keys({ - supplier_name: Joi.string().max(256).required().label('Name'), - address: Joi.string().max(512).allow('', null).label('Address'), - phone: Joi.string().max(50).allow('', null).label('Phone'), - email: Joi.string().email().max(256).allow('', null).label('Email') - }); - - const param: any = await schema.validateAsync(req.body); - - const data = new Supplier() - data.supplier_name = param.supplier_name - data.address = param.address - data.phone = param.phone - data.email = param.email - data.created_by = req.auth.data.name; - - await OrmHelper.DB.manager.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 401, Language.lang.failed_insert, err.message); - } - } - - static async update(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - Supplier'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'Supplier ID.', - required: true, - type: 'string' - } - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/supplier" - } - } - } - } - */ - - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID'), - supplier_name: Joi.string().max(256).required().label('Name'), - address: Joi.string().max(512).allow('', null).label('Address'), - phone: Joi.string().max(50).allow('', null).label('Phone'), - email: Joi.string().email().max(256).allow('', null).label('Email') - }); - - req.body.id = req.params['id']; - - const param: any = await schema.validateAsync(req.body); - - const repo = OrmHelper.DB.getRepository(Supplier); - - const data = await repo.findOneBy({ id: param.id }); - - if (data != null) { - data.supplier_name = param.supplier_name - data.address = param.address - data.phone = param.phone - data.email = param.email - data.updated_by = req.auth.data.name; - - await repo.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_update, data); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_update, err.message); - } - } - - static async delete(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - Supplier'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'Supplier ID.', - required: true, - type: 'string' - } - #swagger.parameters['hard'] = { - in: 'path', - description: 'Is Hard Delete', - required: false, - type: 'boolean' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID'), - hard: Joi.bool().optional().allow('').label('Is hard delete?') - }); - - const param: { id: string, hard: boolean } = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(Supplier); - - const existData = await repo.findOne({ where: { id: param.id } }); - if (existData && !param.hard) { - existData.deleted_by = req.auth.data.name; - await OrmHelper.DB.manager.save(existData); - } - - const affected = (!param.hard ? await repo.softDelete({ id: param.id }) : await repo.delete({ id: param.id })).affected; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_delete, err.message); - } - } - - static async restore(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - Supplier'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.parameters['id'] = { - in: 'path', - description: 'Supplier ID.', - required: true, - type: 'string' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID') - }); - - const param: Supplier = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(Supplier); - - const affected = (await repo.restore({ id: param.id })).affected; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_restore, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_restore, err.message); - } - } -} \ No newline at end of file diff --git a/src/controllers/pharmacy/unit.ts b/src/controllers/pharmacy/unit.ts deleted file mode 100644 index 8f2ef92..0000000 --- a/src/controllers/pharmacy/unit.ts +++ /dev/null @@ -1,347 +0,0 @@ -import { Response, NextFunction, Application } from "express"; -import { Request } from "express-jwt"; -import { ReturnHelper } from "../../helpers/express/return"; -import { OrmHelper } from "../../helpers/orm"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import { Language } from "../../langs/lang"; -import { Unit, Paging } from "entity"; -import CommonHelper from "../../helpers/common"; -import * as fastcsv from 'fast-csv'; -import dayjs from "dayjs"; -import { UnitModel } from "../../model/unit"; - -const log: Logger = new Logger({ name: '[UnitController]', type: 'pretty' }); - -export class UnitController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - Unit'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['filter'] = { description: '', in: 'query', type: 'string' } - #swagger.parameters['limit'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['page'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['with_deleted'] = { in: 'query', required: true, type: 'boolean' } - #swagger.parameters['order_field'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['order_direction'] = { in: 'query', required: true, schema: { '@enum': ['ASC', 'DESC'] } } - */ - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().required().label("With Deleted"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").required().label("Order Direction"), - }); - - let param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await UnitModel.list(filter); - - const offset = (param.page - 1) * param.limit; - let limit = param.limit; - - const res_count = query; - const res_list = query - .orderBy("unit." + param.order_field, param.order_direction) - .offset(offset) - .limit(limit); - - if (param.with_deleted) { - res_count.withDeleted(); - res_list.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async export(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - Unit'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['filter'] = { - description: 'Filter with 2 format :
  • Simple format use text plaint will filter eq:code or like %name%
  • Advance format using field existing {status:\'Y\', any:\'SAME AS PLAINT LOGIC\', etc...}
', - in: 'query', - type: 'string' - } - #swagger.parameters['filter'] = { - in: 'query', - type: 'string' - } - #swagger.parameters['order_field'] = { - in: 'query', - required: true, - type: 'string' - } - #swagger.parameters['order_direction'] = { - in: 'query', - required: true, - schema: { - '@enum': ['ASC', 'DESC'] - } - } - */ - - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow('').optional().label('Filter'), - order_field: Joi.string().required().label('Order Field'), - order_direction: Joi.string().allow('asc', 'desc').required().label('Order Direction'), - }); - - const param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await UnitModel.list(filter); - const data = await query.getMany(); - - const filename = "unit.csv"; - - res.setHeader('Content-Type', 'text/csv'); - res.setHeader('Content-Disposition', 'attachment; filename=' + filename); - - const csvStream = fastcsv.format({ - headers: true, - writeHeaders: true, - transform: (row: Unit): any => ({ - ...row, - created_at: dayjs(row.created_at).format('DD-MM-YYYY HH:MM:ss'), - }) - }); - csvStream.pipe(res); - - const limit = 50; - - const fetchAndWrite = async (page: any) => { - - if (CommonHelper.countObject(data) === 0) { - csvStream.end(); - } else { - data.forEach((item: any) => csvStream.write(item)); - - if (CommonHelper.countObject(data) == limit) { - fetchAndWrite(page + 1); - } else { - csvStream.end(); - } - } - }; - - fetchAndWrite(1); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - Unit'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/unit" - } - } - } - } - */ - try { - const schema = Joi.object().keys({ - unit_name: Joi.string().max(256).required().label('Name'), - small_unit: Joi.string().max(256).optional().allow('').label('Small Unit'), - large_unit: Joi.string().max(256).optional().allow('').label('Large Unit'), - }); - - const param: any = await schema.validateAsync(req.body); - - const data = new Unit() - data.unit_name = param.unit_name - data.small_unit = param.small_unit - data.large_unit = param.large_unit - data.created_by = req.auth.data.name - - await OrmHelper.DB.manager.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 401, Language.lang.failed_insert, err.message); - } - } - - static async update(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - Unit'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'Unit ID.', - required: true, - type: 'string' - } - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/unit" - } - } - } - } - */ - - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID'), - unit_name: Joi.string().max(256).required().label('Name'), - small_unit: Joi.string().max(256).optional().allow('').label('Small Unit'), - large_unit: Joi.string().max(256).optional().allow('').label('Large Unit'), - }); - - req.body.id = req.params['id']; - - const param: any = await schema.validateAsync(req.body); - - const repo = OrmHelper.DB.getRepository(Unit); - - const data = await repo.findOneBy({ id: param.id }); - - if (data != null) { - data.unit_name = param.unit_name - data.small_unit = param.small_unit - data.large_unit = param.large_unit - data.updated_by = req.auth.data.name - - await repo.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_update, data); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_update, err.message); - } - } - - static async delete(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - Unit'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'Unit ID.', - required: true, - type: 'string' - } - #swagger.parameters['hard'] = { - in: 'path', - description: 'Is Hard Delete', - required: false, - type: 'boolean' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID'), - hard: Joi.bool().optional().allow('').label('Is hard delete?') - }); - - const param: { id: string, hard: boolean } = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(Unit); - - const existData = await repo.findOne({ where: { id: param.id } }); - if (existData && !param.hard) { - existData.deleted_by = req.auth.data.name; - await OrmHelper.DB.manager.save(existData); - } - - const affected = (!param.hard ? await repo.softDelete({ id: param.id }) : await repo.delete({ id: param.id })).affected; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_delete, err.message); - } - } - - static async restore(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - Unit'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.parameters['id'] = { - in: 'path', - description: 'Unit ID.', - required: true, - type: 'string' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID') - }); - - const param: Unit = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(Unit); - - const affected = (await repo.restore({ id: param.id })).affected; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_restore, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_restore, err.message); - } - } -} \ No newline at end of file diff --git a/src/controllers/pharmacy/usage_instructions.ts b/src/controllers/pharmacy/usage_instructions.ts deleted file mode 100644 index 52ac896..0000000 --- a/src/controllers/pharmacy/usage_instructions.ts +++ /dev/null @@ -1,343 +0,0 @@ -import { Response, NextFunction, Application } from "express"; -import { Request } from "express-jwt"; -import { ReturnHelper } from "../../helpers/express/return"; -import { OrmHelper } from "../../helpers/orm"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import { Language } from "../../langs/lang"; -import { UsageInstructions, Paging } from "entity"; -import CommonHelper from "../../helpers/common"; -import * as fastcsv from 'fast-csv'; -import dayjs from "dayjs"; -import { UsageInstructionsModel } from "../../model/usage_instructions"; - -const log: Logger = new Logger({ name: '[UsageInstructionsController]', type: 'pretty' }); - -export class UsageInstructionsController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - UsageInstructions'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['filter'] = { description: '', in: 'query', type: 'string' } - #swagger.parameters['limit'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['page'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['with_deleted'] = { in: 'query', required: true, type: 'boolean' } - #swagger.parameters['order_field'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['order_direction'] = { in: 'query', required: true, schema: { '@enum': ['ASC', 'DESC'] } } - */ - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().required().label("With Deleted"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").required().label("Order Direction"), - }); - - let param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await UsageInstructionsModel.list(filter); - - const offset = (param.page - 1) * param.limit; - let limit = param.limit; - - const res_count = query; - const res_list = query - .orderBy("usage_instructions." + param.order_field, param.order_direction) - .offset(offset) - .limit(limit); - - if (param.with_deleted) { - res_count.withDeleted(); - res_list.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async export(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - UsageInstructions'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['filter'] = { - description: 'Filter with 2 format :
  • Simple format use text plaint will filter eq:code or like %name%
  • Advance format using field existing {status:\'Y\', any:\'SAME AS PLAINT LOGIC\', etc...}
', - in: 'query', - type: 'string' - } - #swagger.parameters['filter'] = { - in: 'query', - type: 'string' - } - #swagger.parameters['order_field'] = { - in: 'query', - required: true, - type: 'string' - } - #swagger.parameters['order_direction'] = { - in: 'query', - required: true, - schema: { - '@enum': ['ASC', 'DESC'] - } - } - */ - - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow('').optional().label('Filter'), - order_field: Joi.string().required().label('Order Field'), - order_direction: Joi.string().allow('asc', 'desc').required().label('Order Direction'), - }); - - const param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await UsageInstructionsModel.list(filter); - const data = await query.getMany(); - - const filename = "usage_instructions.csv"; - - res.setHeader('Content-Type', 'text/csv'); - res.setHeader('Content-Disposition', 'attachment; filename=' + filename); - - const csvStream = fastcsv.format({ - headers: true, - writeHeaders: true, - transform: (row: UsageInstructions): any => ({ - ...row, - created_at: dayjs(row.created_at).format('DD-MM-YYYY HH:MM:ss'), - }) - }); - csvStream.pipe(res); - - const limit = 50; - - const fetchAndWrite = async (page: any) => { - - if (CommonHelper.countObject(data) === 0) { - csvStream.end(); - } else { - data.forEach((item: any) => csvStream.write(item)); - - if (CommonHelper.countObject(data) == limit) { - fetchAndWrite(page + 1); - } else { - csvStream.end(); - } - } - }; - - fetchAndWrite(1); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - UsageInstructions'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/usage_instructions" - } - } - } - } - */ - try { - const schema = Joi.object().keys({ - usage_instructions_name: Joi.string().max(256).required().label('Name'), - usage_instructions_abbreviation: Joi.string().max(256).required().label('Abbreviation'), - }); - - const param: any = await schema.validateAsync(req.body); - - const data = new UsageInstructions() - data.usage_instructions_name = param.usage_instructions_name - data.usage_instructions_abbreviation = param.usage_instructions_abbreviation - data.created_by = req.auth.data.name; - - await OrmHelper.DB.manager.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 401, Language.lang.failed_insert, err.message); - } - } - - static async update(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - UsageInstructions'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'UsageInstructions ID.', - required: true, - type: 'string' - } - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/usage_instructions" - } - } - } - } - */ - - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID'), - usage_instructions_name: Joi.string().max(256).required().label('Name'), - usage_instructions_abbreviation: Joi.string().max(256).required().label('Abbreviation'), - }); - - req.body.id = req.params['id']; - - const param: any = await schema.validateAsync(req.body); - - const repo = OrmHelper.DB.getRepository(UsageInstructions); - - const data = await repo.findOneBy({ id: param.id }); - - if (data != null) { - data.usage_instructions_name = param.usage_instructions_name - data.usage_instructions_abbreviation = param.usage_instructions_abbreviation - data.updated_by = req.auth.data.name; - - await repo.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_update, data); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_update, err.message); - } - } - - static async delete(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - UsageInstructions'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'Usage Instructions ID.', - required: true, - type: 'string' - } - #swagger.parameters['hard'] = { - in: 'path', - description: 'Is Hard Delete', - required: false, - type: 'boolean' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID'), - hard: Joi.bool().optional().allow('').label('Is hard delete?') - }); - - const param: { id: string, hard: boolean } = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(UsageInstructions); - - const existData = await repo.findOne({ where: { id: param.id } }); - if (existData && !param.hard) { - existData.deleted_by = req.auth.data.name; - await OrmHelper.DB.manager.save(existData); - } - - const affected = (!param.hard ? await repo.softDelete({ id: param.id }) : await repo.delete({ id: param.id })).affected; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_delete, err.message); - } - } - - static async restore(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - UsageInstructions'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.parameters['id'] = { - in: 'path', - description: 'UsageInstructions ID.', - required: true, - type: 'string' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID') - }); - - const param: UsageInstructions = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(UsageInstructions); - - const affected = (await repo.restore({ id: param.id })).affected; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_restore, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_restore, err.message); - } - } -} \ No newline at end of file diff --git a/src/controllers/pharmacy/usage_time.ts b/src/controllers/pharmacy/usage_time.ts deleted file mode 100644 index 5663daa..0000000 --- a/src/controllers/pharmacy/usage_time.ts +++ /dev/null @@ -1,343 +0,0 @@ -import { Response, NextFunction, Application } from "express"; -import { Request } from "express-jwt"; -import { ReturnHelper } from "../../helpers/express/return"; -import { OrmHelper } from "../../helpers/orm"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import { Language } from "../../langs/lang"; -import { UsageTime, Paging } from "entity"; -import CommonHelper from "../../helpers/common"; -import * as fastcsv from 'fast-csv'; -import dayjs from "dayjs"; -import { UsageTimeModel } from "../../model/usage_time"; - -const log: Logger = new Logger({ name: '[UsageTimeController]', type: 'pretty' }); - -export class UsageTimeController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - UsageTime'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['filter'] = { description: '', in: 'query', type: 'string' } - #swagger.parameters['limit'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['page'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['with_deleted'] = { in: 'query', required: true, type: 'boolean' } - #swagger.parameters['order_field'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['order_direction'] = { in: 'query', required: true, schema: { '@enum': ['ASC', 'DESC'] } } - */ - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().required().label("With Deleted"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").required().label("Order Direction"), - }); - - let param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await UsageTimeModel.list(filter); - - const offset = (param.page - 1) * param.limit; - let limit = param.limit; - - const res_count = query; - const res_list = query - .orderBy("usage_time." + param.order_field, param.order_direction) - .offset(offset) - .limit(limit); - - if (param.with_deleted) { - res_count.withDeleted(); - res_list.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async export(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - UsageTime'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['filter'] = { - description: 'Filter with 2 format :
  • Simple format use text plaint will filter eq:code or like %name%
  • Advance format using field existing {status:\'Y\', any:\'SAME AS PLAINT LOGIC\', etc...}
', - in: 'query', - type: 'string' - } - #swagger.parameters['filter'] = { - in: 'query', - type: 'string' - } - #swagger.parameters['order_field'] = { - in: 'query', - required: true, - type: 'string' - } - #swagger.parameters['order_direction'] = { - in: 'query', - required: true, - schema: { - '@enum': ['ASC', 'DESC'] - } - } - */ - - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow('').optional().label('Filter'), - order_field: Joi.string().required().label('Order Field'), - order_direction: Joi.string().allow('asc', 'desc').required().label('Order Direction'), - }); - - const param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await UsageTimeModel.list(filter); - const data = await query.getMany(); - - const filename = "usage_time.csv"; - - res.setHeader('Content-Type', 'text/csv'); - res.setHeader('Content-Disposition', 'attachment; filename=' + filename); - - const csvStream = fastcsv.format({ - headers: true, - writeHeaders: true, - transform: (row: UsageTime): any => ({ - ...row, - created_at: dayjs(row.created_at).format('DD-MM-YYYY HH:MM:ss'), - }) - }); - csvStream.pipe(res); - - const limit = 50; - - const fetchAndWrite = async (page: any) => { - - if (CommonHelper.countObject(data) === 0) { - csvStream.end(); - } else { - data.forEach((item: any) => csvStream.write(item)); - - if (CommonHelper.countObject(data) == limit) { - fetchAndWrite(page + 1); - } else { - csvStream.end(); - } - } - }; - - fetchAndWrite(1); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - UsageTime'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/usage_time" - } - } - } - } - */ - try { - const schema = Joi.object().keys({ - usage_time_name: Joi.string().max(256).required().label('Name'), - usage_time_abbreviation: Joi.string().max(256).required().label('Abbreviation'), - }); - - const param: any = await schema.validateAsync(req.body); - - const data = new UsageTime() - data.usage_time_name = param.usage_time_name - data.usage_time_abbreviation = param.usage_time_abbreviation - data.created_by = req.auth.data.name; - - await OrmHelper.DB.manager.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 401, Language.lang.failed_insert, err.message); - } - } - - static async update(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - UsageTime'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'UsageTime ID.', - required: true, - type: 'string' - } - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/usage_time" - } - } - } - } - */ - - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID'), - usage_time_name: Joi.string().max(256).required().label('Name'), - usage_time_abbreviation: Joi.string().max(256).required().label('Abbreviation'), - }); - - req.body.id = req.params['id']; - - const param: any = await schema.validateAsync(req.body); - - const repo = OrmHelper.DB.getRepository(UsageTime); - - const data = await repo.findOneBy({ id: param.id }); - - if (data != null) { - data.usage_time_name = param.usage_time_name - data.usage_time_abbreviation = param.usage_time_abbreviation - data.updated_by = req.auth.data.name; - - await repo.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_update, data); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_update, err.message); - } - } - - static async delete(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - UsageTime'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'Usage Instructions ID.', - required: true, - type: 'string' - } - #swagger.parameters['hard'] = { - in: 'path', - description: 'Is Hard Delete', - required: false, - type: 'boolean' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID'), - hard: Joi.bool().optional().allow('').label('Is hard delete?') - }); - - const param: { id: string, hard: boolean } = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(UsageTime); - - const existData = await repo.findOne({ where: { id: param.id } }); - if (existData && !param.hard) { - existData.deleted_by = req.auth.data.name; - await OrmHelper.DB.manager.save(existData); - } - - const affected = (!param.hard ? await repo.softDelete({ id: param.id }) : await repo.delete({ id: param.id })).affected; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_delete, err.message); - } - } - - static async restore(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Pharmacy - UsageTime'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.parameters['id'] = { - in: 'path', - description: 'UsageTime ID.', - required: true, - type: 'string' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID') - }); - - const param: UsageTime = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(UsageTime); - - const affected = (await repo.restore({ id: param.id })).affected; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_restore, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_restore, err.message); - } - } -} \ No newline at end of file diff --git a/src/controllers/queue_monitoring.ts b/src/controllers/queue_monitoring.ts deleted file mode 100644 index 5538b9f..0000000 --- a/src/controllers/queue_monitoring.ts +++ /dev/null @@ -1,467 +0,0 @@ -import { QueueMonitoring, Paging, QueueMonitoringRooms, Status } from "entity"; -import { NextFunction, Response } from "express"; -import { Request } from "express-jwt"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import CommonHelper from "../helpers/common"; -import { ReturnHelper } from "../helpers/express/return"; -import { Language } from "../langs/lang"; -import { QueueMonitoringModel } from "../model/queue_monitoring"; -import { RoomModel } from "../model/room"; -import { OrmHelper } from "../helpers/orm"; -import moment from "moment"; - -const log: Logger = new Logger({ - name: "[QueueMonitoringController]", - type: "pretty", -}); - -export class QueueMonitoringController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Queue Monitoring'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['filter'] = { description: 'Filter: plain text or JSON object (status, slug, etc.)', in: 'query', type: 'string' } - #swagger.parameters['limit'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['page'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['with_deleted'] = { in: 'query', required: true, type: 'boolean' } - #swagger.parameters['order_field'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['order_direction'] = { in: 'query', required: true, schema: { '@enum': ['ASC', 'DESC'] } } - */ - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().required().label("With Deleted"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").required().label("Order Direction"), - }); - - let param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await QueueMonitoringModel.list(filter); - - const offset = (param.page - 1) * param.limit; - let limit = param.limit; - - const res_count = query; - const res_list = query - .leftJoinAndMapMany( - "QueueMonitoring.queue_monitoring_rooms", // - QueueMonitoringRooms, - "qmr", - 'qmr."queueMonitoringId" = "QueueMonitoring"."id"', - ) - .leftJoinAndSelect("qmr.room", "room") - .leftJoinAndSelect("room.department", "department") - .orderBy("QueueMonitoring." + param.order_field, param.order_direction) - .offset(offset) - .limit(limit); - - if (param.with_deleted) { - res_count.withDeleted(); - res_list.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - let list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - if (list_data && list_data.length > 0) { - list_data = list_data.map((item) => { - return { - ...item, - rooms: (item.queue_monitoring_rooms || []).map((qmr) => qmr.room), - }; - }); - - list_data = list_data.map(({ queue_monitoring_rooms, ...rest }) => rest); - } - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async detailBySlug(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Queue Monitoring'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['slug'] = { in: 'path', type: 'string' } - */ - try { - const schema = Joi.object().keys({ - slug: Joi.string().required().label("Queue Monitoring Slug"), - }); - - const param: any = await schema.validateAsync(req.params); - - const queueMonitoring = await QueueMonitoringModel.list({ "QueueMonitoring.slug": param.slug }).then((q) => - q // - .leftJoinAndMapMany( - "QueueMonitoring.queue_monitoring_rooms", // - QueueMonitoringRooms, - "qmr", - 'qmr."queueMonitoringId" = "QueueMonitoring"."id"', - ) - .leftJoinAndSelect("qmr.room", "room") - .leftJoinAndSelect("room.department", "department") - .getOne(), - ); - - if (!queueMonitoring) throw { message: "Queue Monitoring Not Found" }; - - if (queueMonitoring) { - queueMonitoring.rooms = (queueMonitoring.queue_monitoring_rooms || []).map((item) => item.room); - - delete queueMonitoring.queue_monitoring_rooms; - } - - if (queueMonitoring.rooms && queueMonitoring.rooms.length > 0) { - try { - const roomIds = queueMonitoring.rooms.map((room: any) => room.id); - const today = moment().format("YYYY-MM-DD"); - - const placeholders = roomIds.map((_: any, index: number) => `$${index + 1}`).join(", "); - const dateParamIndex = roomIds.length + 1; - const queryParams = [...roomIds, today]; - - const queueQuery = ` - SELECT - ro.id, - ro.qeue_number, - ro.registration_status, - ro."roomId", - ro.updated_at, - p.full_name AS fullname_patient - FROM emr.emr_registration_outpatient ro - LEFT JOIN emr.emr_registrations r ON ro."registrationId" = r.id - LEFT JOIN emr.emr_patients p ON r."patientId" = p.id - WHERE ro."roomId" IN (${placeholders}) - AND DATE(ro.visit_date) = $${dateParamIndex} - AND ro.registration_status IN ('ON GOING', 'REGISTERED') - ORDER BY ro."roomId", - CASE WHEN ro.registration_status = 'ON GOING' THEN 0 - WHEN ro.registration_status = 'REGISTERED' THEN 1 - ELSE 2 END, - ro.qeue_number ASC - `; - - const allQueues = await OrmHelper.DB.manager.query(queueQuery, queryParams); - - const queuesByRoom: { [key: string]: any[] } = {}; - allQueues.forEach((queue: any) => { - const roomId = queue.roomId; - if (roomId) { - if (!queuesByRoom[roomId]) { - queuesByRoom[roomId] = []; - } - queuesByRoom[roomId].push({ - id: queue.id, - qeue_number: queue.qeue_number, - registration_status: queue.registration_status, - fullname_patient: queue.fullname_patient, - }); - } - }); - - // room lookup - const roomIdToRoomObj: { [key: string]: any } = {}; - queueMonitoring.rooms.forEach((room: any) => { - roomIdToRoomObj[room.id] = room; - }); - - queueMonitoring.rooms = queueMonitoring.rooms.map((room: any) => ({ - ...room, - queues: queuesByRoom[room.id] || [], - })); - - const latestOnGoing = allQueues - .filter((q: any) => q.registration_status === "ON GOING") - .reduce((latest: any, current: any) => { - const latestDate = new Date(latest?.updated_at || latest?.updatedAt || 0); - const currentDate = new Date(current?.updated_at || current?.updatedAt || 0); - return currentDate > latestDate ? current : latest; - }, undefined); - - (queueMonitoring as any).currentQueue = latestOnGoing - ? { - room: roomIdToRoomObj[latestOnGoing.roomId]?.room || null, - id: latestOnGoing.id, - qeue_number: latestOnGoing.qeue_number, - registration_status: latestOnGoing.registration_status, - fullname_patient: latestOnGoing.fullname_patient, - } - : null; - } catch (queryError: any) { - log.warn(`Failed to fetch queue data from emr.emr_registration_outpatient: ${queryError.message}`); - queueMonitoring.rooms = queueMonitoring.rooms.map((room: any) => ({ - ...room, - queues: [], - })); - (queueMonitoring as any).currentQueue = null; - } - } - - const responseData = { - ...queueMonitoring, - }; - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_view, responseData); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_not_found, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Queue Monitoring'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.requestBody = { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/queueMonitoring" } } } } - */ - const queryRunner = OrmHelper.DB.createQueryRunner(); - await queryRunner.startTransaction(); - try { - const schema = Joi.object().keys({ - slug: Joi.string().required().label("Slug"), - name: Joi.string().required().label("Name"), - room_ids: Joi.array().items(Joi.string().uuid()).min(1).required().label("Room IDs"), - status: Joi.string().required().label("Status"), - }); - - let param: any = await schema.validateAsync(req.body); - - let queueMonitoring = new QueueMonitoring(); - queueMonitoring.slug = param.slug; - queueMonitoring.name = param.name; - queueMonitoring.status = param.status; - queueMonitoring.created_by = req.auth?.data.name; - queueMonitoring.updated_by = req.auth?.data.name; - await queryRunner.manager.save(queueMonitoring); - - if (param.room_ids && param.room_ids.length > 0) { - await queryRunner.manager.getRepository(QueueMonitoringRooms) - .createQueryBuilder() - .delete() - .from(QueueMonitoringRooms) - .where('"id" = :id', { id: queueMonitoring.id }) - .execute(); - - for (const roomId of param.room_ids) { - const room = await RoomModel.list({ id: roomId }).then((q) => q.getOne()); - if (!room) throw { message: `Room with id ${roomId} not found` }; - - let queueMonitoringRooms = new QueueMonitoringRooms(); - queueMonitoringRooms.queue_monitoring = queueMonitoring; - queueMonitoringRooms.room = room; - queueMonitoringRooms.status = param.status; - queueMonitoringRooms.created_by = req.auth?.data.name; - queueMonitoringRooms.updated_by = req.auth?.data.name; - await queryRunner.manager.save(queueMonitoringRooms); - } - } - - await queryRunner.commitTransaction(); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, queueMonitoring); - } catch (e: unknown) { - await queryRunner.rollbackTransaction(); - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } finally { - await queryRunner.release(); - } - } - - static async detail(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Queue Monitoring'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { in: 'path', type: 'string' } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("Queue Monitoring Id"), - }); - - let param: any = await schema.validateAsync(req.params); - - let queueMonitoring = await QueueMonitoringModel.list({ "QueueMonitoring.id": param.id }).then((q) => - q // - .leftJoinAndMapMany( - "QueueMonitoring.queue_monitoring_rooms", // - QueueMonitoringRooms, - "qmr", - 'qmr."queueMonitoringId" = "QueueMonitoring"."id"', - ) - .leftJoinAndSelect("qmr.room", "room") - .leftJoinAndSelect("room.department", "department") - .getOne(), - ); - - if (!queueMonitoring) throw { message: "Queue Monitoring Not Found" }; - - if (queueMonitoring) { - queueMonitoring.rooms = (queueMonitoring.queue_monitoring_rooms || []).map((item) => item.room); - - delete queueMonitoring.queue_monitoring_rooms; - } - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_view, queueMonitoring); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_not_found, err.message); - } - } - - static async update(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Queue Monitoring'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { in: 'path', type: 'string' } - #swagger.requestBody = { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/queueMonitoring" } } } } - */ - const queryRunner = OrmHelper.DB.createQueryRunner(); - await queryRunner.startTransaction(); - - try { - req.body.id = req.params["id"]; - - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("Queue Monitoring ID"), - slug: Joi.string().required().label("Slug"), - name: Joi.string().required().label("Name"), - room_ids: Joi.array().items(Joi.string().uuid()).min(1).required().label("Room IDs"), - status: Joi.string().required().label("Status"), - }); - - let param: any = await schema.validateAsync(req.body); - - let queueMonitoring = await QueueMonitoringModel.list({ "QueueMonitoring.id": param.id }).then((q) => q.getOne()); - - if (!queueMonitoring) throw { message: "Queue Monitoring " + Language.lang.failed_not_found }; - - queueMonitoring.slug = param.slug; - queueMonitoring.name = param.name; - queueMonitoring.status = param.status; - queueMonitoring.updated_by = req.auth.data.name; - await queryRunner.manager.save(queueMonitoring); - - if (param.room_ids && param.room_ids.length > 0) { - await queryRunner.manager // - .getRepository(QueueMonitoringRooms) - .createQueryBuilder() - .delete() - .from(QueueMonitoringRooms) - .where('"queueMonitoringId" = :id', { id: queueMonitoring.id }) - .execute(); - - for (const roomId of param.room_ids) { - const room = await RoomModel.list({ id: roomId }).then((q) => q.getOne()); - if (!room) throw { message: `Room with id ${roomId} not found` }; - - let queueMonitoringRooms = new QueueMonitoringRooms(); - queueMonitoringRooms.queue_monitoring = queueMonitoring; - queueMonitoringRooms.room = room; - queueMonitoringRooms.status = param.status; - queueMonitoringRooms.created_by = req.auth.data.name; - queueMonitoringRooms.updated_by = req.auth.data.name; - await queryRunner.manager.save(queueMonitoringRooms); - } - } - - await queryRunner.commitTransaction(); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_update, queueMonitoring); - } catch (e: unknown) { - await queryRunner.rollbackTransaction(); - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } finally { - await queryRunner.release(); - } - } - - static async delete(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Queue Monitoring'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { in: 'path', required: true, type: 'string' } - #swagger.parameters['hard'] = { in: 'path', description: 'Is Hard Delete', required: false, type: 'boolean' } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("ID"), - hard: Joi.bool().optional().allow("").label("Is hard delete?"), - }); - - const param: { id: string; hard: boolean } = await schema.validateAsync(req.params); - - let affected = 0; - if (!param.hard) { - let queueMonitoring: QueueMonitoring = await QueueMonitoringModel.list({ "QueueMonitoring.id": param.id }).then((q) => q.getOne()); - - if (!queueMonitoring) throw { message: "Queue Monitoring " + Language.lang.failed_not_found }; - - queueMonitoring.deleted_by = req.auth.data.name; - queueMonitoring.deleted_at = moment().toDate(); - await OrmHelper.DB.manager.save(queueMonitoring); - affected = 1; - } else { - const repo = OrmHelper.DB.getRepository(QueueMonitoring); - affected = (await repo.delete({ id: param.id })).affected ?? 0; - } - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_delete, err.message); - } - } - - static async restore(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Queue Monitoring'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { in: 'path', required: true, type: 'string' } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("ID"), - }); - - const param: any = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(QueueMonitoring); - - const affected = (await repo.restore({ id: param.id })).affected ?? 0; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_restore, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_restore, err.message); - } - } -} diff --git a/src/controllers/reference_range.ts b/src/controllers/reference_range.ts deleted file mode 100644 index fda5c47..0000000 --- a/src/controllers/reference_range.ts +++ /dev/null @@ -1,297 +0,0 @@ -import { ReferenceRange, Paging } from "entity"; -import { NextFunction, Response } from "express"; -import { Request } from "express-jwt"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import CommonHelper from "../helpers/common"; -import { ReturnHelper } from "../helpers/express/return"; -import { Language } from "../langs/lang"; -import { ReferenceRangeModel } from "../model/reference_range"; -import { OrmHelper } from "../helpers/orm"; -import moment from "moment"; - -const log: Logger = new Logger({ - name: "[ReferenceRangeController]", - type: "pretty", -}); - -export class ReferenceRangeController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Reference Range'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['filter'] = { description: 'Filter: plain text or JSON object (gender, age_range_min, age_range_max, etc.)', in: 'query', type: 'string' } - #swagger.parameters['limit'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['page'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['with_deleted'] = { in: 'query', required: true, type: 'boolean' } - #swagger.parameters['order_field'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['order_direction'] = { in: 'query', required: true, schema: { '@enum': ['ASC', 'DESC'] } } - */ - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().required().label("With Deleted"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").required().label("Order Direction"), - }); - - let param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - const filterAny = filter.any && filter.any !== "" ? String(filter.any) : ""; - let filterObj = { ...filter } as any; - delete filterObj.any; - - var query = await ReferenceRangeModel.list(filterObj); - if (filterAny !== "") { - const anyVal = filterAny.includes("%") ? filterAny : `%${filterAny}%`; - query.andWhere( - `( - "ReferenceRange".status::text ILIKE :any - OR "ReferenceRange".gender::text ILIKE :any - OR "ReferenceRange".age_range_min::text ILIKE :any - OR "ReferenceRange".age_range_max::text ILIKE :any - OR "ReferenceRange".value_min::text ILIKE :any - OR "ReferenceRange".value_max::text ILIKE :any - )`, - { any: anyVal }, - ); - } - - const offset = (param.page - 1) * param.limit; - let limit = param.limit; - - const res_count = query; - const res_list = query - .orderBy("ReferenceRange." + param.order_field, param.order_direction) - .offset(offset) - .limit(limit); - - if (param.with_deleted) { - res_count.withDeleted(); - res_list.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Reference Range'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.requestBody = { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/referenceRange" } } } } - */ - const queryRunner = OrmHelper.DB.createQueryRunner(); - await queryRunner.startTransaction(); - try { - const schema = Joi.object().keys({ - gender: Joi.string().valid("male", "female").required().label("Gender"), - age_range_min: Joi.number().integer().min(0).default(0).required().label("Age Range Min (days)"), - age_range_max: Joi.number().integer().min(0).default(36500).required().label("Age Range Max (days)"), - value_min: Joi.number().required().label("Value Min"), - value_max: Joi.number().required().label("Value Max"), - status: Joi.string().required().label("Status"), - }); - - let param: any = await schema.validateAsync(req.body); - - let referenceRange = new ReferenceRange(); - referenceRange.gender = param.gender; - referenceRange.age_range_min = param.age_range_min; - referenceRange.age_range_max = param.age_range_max; - referenceRange.value_min = param.value_min; - referenceRange.value_max = param.value_max; - referenceRange.status = param.status; - referenceRange.created_by = req.auth?.data.name; - referenceRange.updated_by = req.auth?.data.name; - await queryRunner.manager.save(referenceRange); - - await queryRunner.commitTransaction(); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, referenceRange); - } catch (e: unknown) { - await queryRunner.rollbackTransaction(); - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } finally { - await queryRunner.release(); - } - } - - static async detail(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Reference Range'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { in: 'path', type: 'string' } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("Reference Range Id"), - }); - - const param: any = await schema.validateAsync(req.params); - - // ❗ FIX: jangan pakai "ReferenceRange.id" - const referenceRange = await ReferenceRangeModel - .list({ id: param.id }) - .then((q) => q.getOne()); - - if (!referenceRange) { - throw { message: "Reference Range Not Found" }; - } - - return ReturnHelper.successResponseAny( - res, - 200, - Language.lang.success_view, - referenceRange - ); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse( - res, - 400, - 401, - Language.lang.failed_not_found, - err.message - ); - } - } - - static async update(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Reference Range'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { in: 'path', type: 'string' } - #swagger.requestBody = { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/referenceRange" } } } } - */ - const queryRunner = OrmHelper.DB.createQueryRunner(); - await queryRunner.startTransaction(); - - try { - req.body.id = req.params["id"]; - - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("Reference Range ID"), - gender: Joi.string().valid("male", "female").required().label("Gender"), - age_range_min: Joi.number().integer().min(0).default(0).required().label("Age Range Min (days)"), - age_range_max: Joi.number().integer().min(0).default(36500).required().label("Age Range Max (days)"), - value_min: Joi.number().required().label("Value Min"), - value_max: Joi.number().required().label("Value Max"), - status: Joi.string().required().label("Status"), - }); - - let param: any = await schema.validateAsync(req.body); - - let referenceRange = await ReferenceRangeModel.list({ "ReferenceRange.id": param.id }).then((q) => q.getOne()); - - if (!referenceRange) throw { message: "Reference Range " + Language.lang.failed_not_found }; - - referenceRange.gender = param.gender; - referenceRange.age_range_min = param.age_range_min - referenceRange.age_range_max = param.age_range_max; - referenceRange.value_min = param.value_min; - referenceRange.value_max = param.value_max; - referenceRange.status = param.status; - referenceRange.updated_by = req.auth?.data.name; - await queryRunner.manager.save(referenceRange); - - await queryRunner.commitTransaction(); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_update, referenceRange); - } catch (e: unknown) { - await queryRunner.rollbackTransaction(); - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } finally { - await queryRunner.release(); - } - } - - static async delete(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Reference Range'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { in: 'path', required: true, type: 'string' } - #swagger.parameters['hard'] = { in: 'path', description: 'Is Hard Delete', required: false, type: 'boolean' } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("ID"), - hard: Joi.bool().optional().allow("").label("Is hard delete?"), - }); - - const param: { id: string; hard: boolean } = await schema.validateAsync(req.params); - - let affected = 0; - if (!param.hard) { - let referenceRange: ReferenceRange = await ReferenceRangeModel.list({ "ReferenceRange.id": param.id }).then((q) => q.getOne()); - - if (!referenceRange) throw { message: "Reference Range " + Language.lang.failed_not_found }; - - referenceRange.deleted_by = req.auth?.data.name; - referenceRange.deleted_at = moment().toDate(); - await OrmHelper.DB.manager.save(referenceRange); - affected = 1; - } else { - const repo = OrmHelper.DB.getRepository(ReferenceRange); - affected = (await repo.delete({ id: param.id })).affected ?? 0; - } - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_delete, err.message); - } - } - - static async restore(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Reference Range'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { in: 'path', required: true, type: 'string' } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("ID"), - }); - - const param: any = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(ReferenceRange); - - const affected = (await repo.restore({ id: param.id })).affected ?? 0; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_restore, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_restore, err.message); - } - } -} diff --git a/src/controllers/refferal_hospital.ts b/src/controllers/refferal_hospital.ts deleted file mode 100644 index 4e591c1..0000000 --- a/src/controllers/refferal_hospital.ts +++ /dev/null @@ -1,375 +0,0 @@ -import { Response, NextFunction, Application } from "express"; -import { Request } from "express-jwt"; -import { ReturnHelper } from "../helpers/express/return"; -import { OrmHelper } from "../helpers/orm"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import { Language } from "../langs/lang"; -import { RefferalHospital, Paging, RefferalHospitalType } from "entity"; -import CommonHelper from "../helpers/common"; -import * as fastcsv from 'fast-csv'; -import dayjs from "dayjs"; -import { RefferalHospitalModel } from "../model/refferal_hospital"; - -const log: Logger = new Logger({ name: '[RefferalHospitalController]', type: 'pretty' }); - -export class RefferalHospitalController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['RefferalHospital'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['filter'] = { description: '', in: 'query', type: 'string' } - #swagger.parameters['limit'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['page'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['with_deleted'] = { in: 'query', required: true, type: 'boolean' } - #swagger.parameters['order_field'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['order_direction'] = { in: 'query', required: true, schema: { '@enum': ['ASC', 'DESC'] } } - */ - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().required().label("With Deleted"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").required().label("Order Direction"), - }); - - let param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await RefferalHospitalModel.list(filter); - - const offset = (param.page - 1) * param.limit; - let limit = param.limit; - - const res_count = query; - const res_list = query - .orderBy("refferal_hospital." + param.order_field, param.order_direction) - .offset(offset) - .limit(limit); - - if (param.with_deleted) { - res_count.withDeleted(); - res_list.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async option(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['RefferalHospital'] - #swagger.security = [{ "bearerAuth": [] }] - */ - try { - var query = await RefferalHospitalModel.list(); - - const res_count = query; - const res_list = query.orderBy("refferal_hospital.refferal_hospital_name", "ASC"); - - const current_page = 1; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async export(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['RefferalHospital'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['filter'] = { - description: 'Filter with 2 format :
  • Simple format use text plaint will filter eq:code or like %name%
  • Advance format using field existing {status:\'Y\', any:\'SAME AS PLAINT LOGIC\', etc...}
', - in: 'query', - type: 'string' - } - #swagger.parameters['filter'] = { - in: 'query', - type: 'string' - } - #swagger.parameters['order_field'] = { - in: 'query', - required: true, - type: 'string' - } - #swagger.parameters['order_direction'] = { - in: 'query', - required: true, - schema: { - '@enum': ['ASC', 'DESC'] - } - } - */ - - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow('').optional().label('Filter'), - order_field: Joi.string().required().label('Order Field'), - order_direction: Joi.string().allow('asc', 'desc').required().label('Order Direction'), - }); - - const param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await RefferalHospitalModel.list(filter); - const data = await query.getMany(); - - const filename = "refferal_hospital.csv"; - - res.setHeader('Content-Type', 'text/csv'); - res.setHeader('Content-Disposition', 'attachment; filename=' + filename); - - const csvStream = fastcsv.format({ - headers: true, - writeHeaders: true, - transform: (row: RefferalHospital): any => ({ - ...row, - created_at: dayjs(row.created_at).format('DD-MM-YYYY HH:MM:ss'), - }) - }); - csvStream.pipe(res); - - const limit = 50; - - const fetchAndWrite = async (page: any) => { - - if (CommonHelper.countObject(data) === 0) { - csvStream.end(); - } else { - data.forEach((item: any) => csvStream.write(item)); - - if (CommonHelper.countObject(data) == limit) { - fetchAndWrite(page + 1); - } else { - csvStream.end(); - } - } - }; - - fetchAndWrite(1); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['RefferalHospital'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/refferal_hospital" - } - } - } - } - */ - try { - const schema = Joi.object().keys({ - refferal_hospital_name: Joi.string().max(256).required().label('Name'), - type: Joi.string().valid(...Object.values(RefferalHospitalType)).optional().allow(null, "").label('Type'), - }); - - const param: any = await schema.validateAsync(req.body); - - const lastRow = await OrmHelper.DB.getRepository(RefferalHospital).findOne({ - order: { - order_number: "DESC" - }, - where: {} - }); - - const data = new RefferalHospital() - data.refferal_hospital_name = param.refferal_hospital_name - data.type = param.type || null; - data.order_number = lastRow && lastRow.order_number ? String(Number(lastRow.order_number) + 1) : "1"; - data.created_by = req.auth.data.name; - - await OrmHelper.DB.manager.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 401, Language.lang.failed_insert, err.message); - } - } - - static async update(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['RefferalHospital'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'RefferalHospital ID.', - required: true, - type: 'string' - } - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/refferal_hospital" - } - } - } - } - */ - - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID'), - refferal_hospital_name: Joi.string().max(256).required().label('Name'), - type: Joi.string().valid(...Object.values(RefferalHospitalType)).optional().allow(null, "").label('Type'), - }); - - req.body.id = req.params['id']; - - const param: any = await schema.validateAsync(req.body); - - const repo = OrmHelper.DB.getRepository(RefferalHospital); - - const data = await repo.findOneBy({ id: param.id }); - - if (data != null) { - data.refferal_hospital_name = param.refferal_hospital_name - data.type = param.type || null; - data.updated_by = req.auth.data.name; - - await repo.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_update, data); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_update, err.message); - } - } - - static async delete(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['RefferalHospital'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'Refferal Hospital ID.', - required: true, - type: 'string' - } - #swagger.parameters['hard'] = { - in: 'path', - description: 'Is Hard Delete', - required: false, - type: 'boolean' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID'), - hard: Joi.bool().optional().allow('').label('Is hard delete?') - }); - - const param: { id: string, hard: boolean } = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(RefferalHospital); - - const existData = await repo.findOne({ where: { id: param.id } }); - if (existData && !param.hard) { - existData.deleted_by = req.auth.data.name; - await OrmHelper.DB.manager.save(existData); - } - - const affected = (!param.hard ? await repo.softDelete({ id: param.id }) : await repo.delete({ id: param.id })).affected; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_delete, err.message); - } - } - - static async restore(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['RefferalHospital'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.parameters['id'] = { - in: 'path', - description: 'RefferalHospital ID.', - required: true, - type: 'string' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID') - }); - - const param: RefferalHospital = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(RefferalHospital); - - const affected = (await repo.restore({ id: param.id })).affected; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_restore, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_restore, err.message); - } - } -} \ No newline at end of file diff --git a/src/controllers/region.ts b/src/controllers/region.ts deleted file mode 100644 index ccc5156..0000000 --- a/src/controllers/region.ts +++ /dev/null @@ -1,164 +0,0 @@ -import { Response, NextFunction, Application } from "express"; -import { Request } from "express-jwt"; -import { ReturnHelper } from "../helpers/express/return"; -import { OrmHelper } from "../helpers/orm"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import { Language } from "../langs/lang"; -import { Paging } from "entity"; -import CommonHelper from "../helpers/common"; -import * as fastcsv from 'fast-csv'; -import dayjs from "dayjs"; -import { Province, City, Subdistrict, Ward } from "entity"; - -const log: Logger = new Logger({ name: '[RegionController]', type: 'pretty' }); - -export class RegionController { - static async province(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Region'] - #swagger.security = [{ - "bearerAuth": [] - }] - */ - - try { - const repo = OrmHelper.DB.getRepository(Province); - - const res_count = repo.createQueryBuilder("province"); - const res_list = repo.createQueryBuilder("province"); - - const current_page = 1; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async city(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Region'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['province_code'] = { - in: 'path', - description: 'Province Code.', - required: true, - type: 'string' - } - */ - - try { - const { province_code } = req.params; - - if (!/^\d{2}$/.test(province_code)) { - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, 0, 1, 0, []); - } - - const repo = OrmHelper.DB.getRepository(City); - const res_count = repo.createQueryBuilder("city") - .where("city.code LIKE :province_code", { province_code: `${province_code}%` }); - const res_list = repo.createQueryBuilder("city") - .where("city.code LIKE :province_code", { province_code: `${province_code}%` }); - - const current_page = 1; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async subdistrict(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Region'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['city_code'] = { - in: 'path', - description: 'City Code.', - required: true, - type: 'string' - } - */ - - try { - const { city_code } = req.params; - - if (!/^\d{2}\.\d{2}$/.test(city_code)) { - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, 0, 1, 0, []); - } - - const repo = OrmHelper.DB.getRepository(Subdistrict); - const res_count = repo.createQueryBuilder("subdistrict") - .where("subdistrict.code LIKE :city_code", { city_code: `${city_code}%` }); - const res_list = repo.createQueryBuilder("subdistrict") - .where("subdistrict.code LIKE :city_code", { city_code: `${city_code}%` }); - - const current_page = 1; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async ward(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Region'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['subdistric_code'] = { - in: 'path', - description: 'Subdistric Code.', - required: true, - type: 'string' - } - */ - - try { - const { subdistric_code } = req.params; - - if (!/^\d{2}\.\d{2}\.\d{2}$/.test(subdistric_code)) { - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, 0, 1, 0, []); - } - - const repo = OrmHelper.DB.getRepository(Ward); - const res_count = repo.createQueryBuilder("ward") - .where("ward.code LIKE :subdistric_code", { subdistric_code: `${subdistric_code}%` }); - const res_list = repo.createQueryBuilder("ward") - .where("ward.code LIKE :subdistric_code", { subdistric_code: `${subdistric_code}%` }); - - const current_page = 1; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } -} \ No newline at end of file diff --git a/src/controllers/registrationfee.ts b/src/controllers/registrationfee.ts deleted file mode 100644 index bab6a27..0000000 --- a/src/controllers/registrationfee.ts +++ /dev/null @@ -1,201 +0,0 @@ -import { NextFunction, Response } from "express"; -import { RegistrationFee, Service, Paging } from "entity"; -import { Request } from "express-jwt"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import CommonHelper from "../helpers/common"; -import { ReturnHelper } from "../helpers/express/return"; -import { Language } from "../langs/lang"; -import { OrmHelper } from "../helpers/orm"; -import moment from "moment"; - -const log: Logger = new Logger({ - name: "[RegistrationFee]", - type: "pretty", -}); - -const RegistrationFeeCreateAndUpdateSchema = { - service: Joi.array().items(Joi.string().allow(null, "").uuid()).optional().label("Service"), - type: Joi.string().valid("emergency", "outpatient").required().label("Type"), -}; - -export class RegistrationFeeController { - static async detail(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Registration Fee'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['filter'] = { - description: "Filter in JSON format. Available fields: type (string, exact match), service_name (string, partial match case-insensitive), service_id (number, exact match). Example: {\"type\":\"premium\",\"service_name\":\"konsultasi\",\"service_id\":5}", - in: 'query', - type: 'string' - } - #swagger.parameters['limit'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['page'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['with_deleted'] = { in: 'query', required: true, type: 'boolean' } - #swagger.parameters['order_field'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['order_direction'] = { in: 'query', required: true, schema: { '@enum': ['ASC', 'DESC'] } } - */ - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().required().label("With Deleted"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string().allow("ASC", "DESC").required().label("Order Direction"), - }); - - const param: Paging = await schema.validateAsync(req.query); - const filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - const offset = (param.page - 1) * param.limit; - - const baseQuery = OrmHelper.DB.getRepository(RegistrationFee) - .createQueryBuilder("RegistrationFee") - .leftJoinAndMapMany( - "RegistrationFee.services", - Service, - "service", - "service.id::text = ANY(RegistrationFee.service)" - ); - - // ── Filter RegistrationFee.type ─────────────────────────────────── - if (filter.type && filter.type !== "") { - baseQuery.andWhere("RegistrationFee.type ILIKE :type", { type:`%${filter.type}%` }); - } - - // ── Filter service.name ─────────────────────────────────────────── - if (filter.service_name && filter.service_name !== "") { - baseQuery.andWhere("service.name ILIKE :service_name", { service_name: `%${filter.service_name}%` }); - } - - // ── Filter service.id ───────────────────────────────────────────── - if (filter.service_id && filter.service_id !== "") { - baseQuery.andWhere("service.id = :service_id", { service_id: filter.service_id }); - } - - if (param.with_deleted) { - baseQuery.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await baseQuery.getCount(); - const list_data = await baseQuery - .orderBy("RegistrationFee." + param.order_field, param.order_direction) - .offset(offset) - .limit(param.limit) - .getMany(); - - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist( - res, - 200, - Language.lang.success_view, - count_data, - current_page, - total_count_data, - list_data - ); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Registration Fee'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.requestBody = { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/registration_fee" } } } } - */ - try { - const schema = Joi.object().keys({ - ...RegistrationFeeCreateAndUpdateSchema - }); - - const param: any = await schema.validateAsync(req.body); - - if (param.service && param.service.length > 0) { - for (const serviceId of param.service) { - const serviceExist = await OrmHelper.DB.getRepository(Service) - .createQueryBuilder("Service") - .where("Service.id = :id", { id: serviceId }) - .getOne(); - - if (!serviceExist) throw { message: `Service ID ${serviceId} not found` }; - } - } - - const data = new RegistrationFee(); - data.type = param.type; - data.service = Array.isArray(param.service) ? param.service : []; - data.created_by = req.auth?.data.name; - - await OrmHelper.DB.getRepository(RegistrationFee).save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 500, 401, Language.lang.failed_insert, err.message); - } - } - - static async update(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Registration Fee'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { description: 'ID', in: 'path', type: 'string' } - #swagger.requestBody = { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/registration_fee" } } } } - */ - const queryRunner = OrmHelper.DB.createQueryRunner(); - await queryRunner.startTransaction(); - - try { - const schema = Joi.object().keys({ - ...RegistrationFeeCreateAndUpdateSchema, - id: Joi.string().uuid().required().label("ID"), - }); - - const param: any = await schema.validateAsync({ - ...req.body, - id: req.params.id - }); - if (param.service && param.service.length > 0) { - for (const serviceId of param.service) { - const serviceExist = await OrmHelper.DB.getRepository(Service) - .createQueryBuilder("Service") - .where("Service.id = :id", { id: serviceId }) - .getOne(); - - if (!serviceExist) throw { message: `Service ID ${serviceId} not found` }; - } - } - - const registrationfee = await OrmHelper.DB.getRepository(RegistrationFee) - .findOne({ where: { id: param.id } }); - - if (!registrationfee) throw { message: "Registration Fee " + Language.lang.failed_not_found }; - - registrationfee.type = param.type; - registrationfee.service = Array.isArray(param.service) ? param.service : []; - registrationfee.updated_by = req.auth?.data.name; - - await OrmHelper.DB.manager.save(registrationfee); - - await queryRunner.commitTransaction(); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_update, registrationfee); - } catch (e: unknown) { - await queryRunner.rollbackTransaction(); - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } finally { - await queryRunner.release(); - } - } -} diff --git a/src/controllers/responsiblepartyconsent.ts b/src/controllers/responsiblepartyconsent.ts deleted file mode 100644 index ed78a61..0000000 --- a/src/controllers/responsiblepartyconsent.ts +++ /dev/null @@ -1,147 +0,0 @@ -import { ResponsiblePartyConsent } from "entity"; -import { NextFunction, Response } from "express"; -import { Request } from "express-jwt"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import { ReturnHelper } from "../helpers/express/return"; -import { Language } from "../langs/lang"; -import { OrmHelper } from "../helpers/orm"; -import moment from "moment"; - -const log: Logger = new Logger({ - name: "[ResponsiblePartyConsentController]", - type: "pretty", -}); - -export class ResponsiblePartyConsentController { - static async body(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Responsible Party Consent'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['type'] = { in: 'query', required: false, type: 'string' } - */ - try { - const schema = Joi.object({ - type: Joi.string().optional().allow("").label("Type"), - }); - - const { type } = await schema.validateAsync(req.query); - - let query = OrmHelper.DB.getRepository(ResponsiblePartyConsent) - .createQueryBuilder("ResponsiblePartyConsent"); - - if (type && type !== "") { - query = query.where("ResponsiblePartyConsent.type = :type", { type }); - } - - const data = await query.getMany(); - - return ReturnHelper.successResponselist( - res, - 200, - Language.lang.success_view, - data.length, - 1, - data.length, - data - ); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Responsible Party Consent'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.requestBody = { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/responsiblepartyconsent" } } } } - */ - const queryRunner = OrmHelper.DB.createQueryRunner(); - await queryRunner.startTransaction(); - try { - const typeEnum = [ - "responsible-party-consent", - "patient-education", - "inpatient-admission-consent", - "provision-of-information", - "ward-class-upgrade-entitlement", - ]; - - // create - const schema = Joi.object().keys({ - bodytext: Joi.string().required().label("Body Text"), - type: Joi.string().valid(...typeEnum).required().label("Type"), - }); - - let param: any = await schema.validateAsync(req.body); - - let responsiblepartyconsent = new ResponsiblePartyConsent(); - responsiblepartyconsent.body = param.bodytext; - responsiblepartyconsent.type = param.type; - responsiblepartyconsent.created_by = req.auth?.data.name; - responsiblepartyconsent.updated_by = req.auth?.data.name; - await queryRunner.manager.save(responsiblepartyconsent); - - await queryRunner.commitTransaction(); - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, responsiblepartyconsent); - } catch (e: unknown) { - await queryRunner.rollbackTransaction(); - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } finally { - await queryRunner.release(); - } - } - - static async update(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Responsible Party Consent'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { in: 'path', type: 'string' } - #swagger.requestBody = { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/responsiblepartyconsent" } } } } - */ - const queryRunner = OrmHelper.DB.createQueryRunner(); - await queryRunner.startTransaction(); - try { - req.body.id = req.params["id"]; - const typeEnum = [ - "responsible-party-consent", - "patient-education", - "inpatient-admission-consent", - "provision-of-information", - "ward-class-upgrade-entitlement", - ]; - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("Room ID"), - bodytext: Joi.string().required().label("Body Text"), - type: Joi.string().valid(...typeEnum).required().label("Type"), - }); - let param: any = await schema.validateAsync(req.body); - - let responsiblepartyconsent = await OrmHelper.DB.getRepository(ResponsiblePartyConsent) - .createQueryBuilder("ResponsiblePartyConsent") - .where("ResponsiblePartyConsent.id = :id", { id: param.id }) - .getOne(); - if (!responsiblepartyconsent) throw { message: "Responsible Party Consent " + Language.lang.failed_not_found }; - - responsiblepartyconsent.body = param.bodytext; - responsiblepartyconsent.type = param.type; - responsiblepartyconsent.updated_by = req.auth?.data.name; - responsiblepartyconsent.updated_at = moment().toDate(); - await queryRunner.manager.save(responsiblepartyconsent); - - await queryRunner.commitTransaction(); - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_update, responsiblepartyconsent); - } catch (e: unknown) { - await queryRunner.rollbackTransaction(); - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } finally { - await queryRunner.release(); - } - } -} diff --git a/src/controllers/room.ts b/src/controllers/room.ts deleted file mode 100644 index c429766..0000000 --- a/src/controllers/room.ts +++ /dev/null @@ -1,578 +0,0 @@ -import { Room, Paging, Service, SpecialistForm } from "entity"; -import { NextFunction, Response } from "express"; -import { Request } from "express-jwt"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import CommonHelper from "../helpers/common"; -import { ReturnHelper } from "../helpers/express/return"; -import { Language } from "../langs/lang"; -import { RoomModel } from "../model/room"; -import { DepartmentModel } from "../model/department"; -import { ServiceClassModel } from "../model/service_class"; -import { OrmHelper } from "../helpers/orm"; -import moment from "moment"; -import fileUpload from "express-fileupload"; -import { v4 as uuidv4 } from "uuid"; -import fs from "fs"; -import path from "path"; -import { Brackets, In } from "typeorm"; -import config from "../../config/stag.json"; - -const log: Logger = new Logger({ - name: "[RoomController]", - type: "pretty", -}); - -interface FileUploadRequest extends Request { - files?: fileUpload.FileArray | null; - body: any; -} - -export class RoomController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Room'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['filter'] = { description: 'Filter: plain text or JSON object (status, code, departmentId, etc.)', in: 'query', type: 'string' } - #swagger.parameters['limit'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['page'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['with_deleted'] = { in: 'query', required: true, type: 'boolean' } - #swagger.parameters['order_field'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['order_direction'] = { in: 'query', required: true, schema: { '@enum': ['ASC', 'DESC'] } } - */ - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().required().label("With Deleted"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").required().label("Order Direction"), - }); - - let param: Paging = await schema.validateAsync(req.query); - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - const filterAny = filter.any && filter.any !== "" ? String(filter.any) : ""; - let filterObj = { ...filter } as any; - delete filterObj.any; - - var query = await RoomModel.list(filterObj); - - query.leftJoinAndSelect("Room.department", "department"); - query.leftJoinAndSelect("Room.serviceclass", "serviceclass"); - - if (filterAny !== "") { - const anyVal = filterAny.includes("%") ? filterAny : `%${filterAny}%`; - query.andWhere( - new Brackets((qb) => { - qb.where("Room.code ILIKE :searchVal", { searchVal: anyVal }) - .orWhere("Room.room ILIKE :searchVal", { searchVal: anyVal }) - .orWhere("Room.number ILIKE :searchVal", { searchVal: anyVal }) - .orWhere("department.name ILIKE :searchVal", { searchVal: anyVal }); - }), - ); - } - - const offset = (param.page - 1) * param.limit; - const res_list = query - .orderBy("Room." + param.order_field, param.order_direction) - .take(param.limit) - .skip(offset); - - if (param.with_deleted) { - res_list.withDeleted(); - } - - const photoBaseUrl = config.server.host_swagger + "uploads/room-picture/"; - - const current_page = param.page; - const [list_data, total_count_data] = await res_list.getManyAndCount(); - const mapped_data = list_data.map((item: any) => ({ - ...item, - picture: item.picture ? photoBaseUrl + item.picture : null, - })); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, mapped_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async option(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Room'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { - in: 'query', - type: 'string', - required: false, - description: 'Department Id (optional)' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().optional().label("Department Id"), - }); - - let param: any = await schema.validateAsync(req.query); - - const query = await RoomModel.list(); - - query.select(["Room.id", "Room.room"]).orderBy("Room.room", "ASC"); - - // ✅ optional filter by departmentId - if (param.id) { - query.andWhere("Room.departmentId = :departmentId", { - departmentId: param.id, - }); - } - - const total_count_data = await query.getCount(); - const list_data = await query.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, 1, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Room'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.requestBody = { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/room" } } } } - */ - const queryRunner = OrmHelper.DB.createQueryRunner(); - await queryRunner.startTransaction(); - try { - const schema = Joi.object().keys({ - room: Joi.string().max(256).required().label("Room"), - code: Joi.string().max(128).required().label("Code"), - number: Joi.string().allow("").max(128).optional().label("Number"), - description: Joi.string().allow("").max(512).optional().label("Description"), - department_id: Joi.string().uuid().required().label("Department ID"), - serviceclass: Joi.string().uuid().required().label("Service Class ID"), - status: Joi.string().required().label("Status"), - location: Joi.string().required().label("Location"), - floor: Joi.number().required().label("Floor"), - picture: Joi.string().required().label("picture"), - specialist_form: Joi.string().valid(...Object.values(SpecialistForm)).optional().allow(null, "").label("Specialist Form"), - }); - - let param: any = await schema.validateAsync(req.body); - - let exist = await RoomModel.list({ code: param.code }).then((q) => q.getOne()); - if (exist) throw { message: "Room " + Language.lang.failed_duplicate }; - - let department = await DepartmentModel.list({ id: param.department_id }).then((q) => q.getOne()); - if (!department) throw { message: "Department not found" }; - - let serviceclass = await ServiceClassModel.list({ id: param.serviceclass }).then((q) => q.getOne()); - if (!serviceclass) throw { message: "Class not found" }; - - - - let room = new Room(); - room.room = param.room; - room.code = param.code; - room.number = param.number || null; - room.description = param.description || null; - room.department = department; - room.serviceclass = param.serviceclass; - room.status = param.status; - room.location = param.location; - room.picture = param.picture; - room.floor = param.floor; - room.specialist_form = param.specialist_form || null; - room.created_by = req.auth?.data.name; - room.updated_by = req.auth?.data.name; - await queryRunner.manager.save(room); - - await queryRunner.commitTransaction(); - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, room); - } catch (e: unknown) { - await queryRunner.rollbackTransaction(); - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } finally { - await queryRunner.release(); - } - } - - static async detail(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Room'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { in: 'path', type: 'string' } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("Room Id"), - }); - let param: any = await schema.validateAsync(req.params); - let room = await RoomModel.list({ "Room.id": param.id }).then((q) => q.leftJoinAndSelect("Room.department", "department").leftJoinAndSelect("Room.serviceclass", "serviceclass").getOne()); - if (!room) throw { message: "Room Not Found" }; - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_view, room); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_not_found, err.message); - } - } - - static async update(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Room'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { in: 'path', type: 'string' } - #swagger.requestBody = { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/room" } } } } - */ - const queryRunner = OrmHelper.DB.createQueryRunner(); - await queryRunner.startTransaction(); - try { - req.body.id = req.params["id"]; - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("Room ID"), - room: Joi.string().max(256).required().label("Room"), - code: Joi.string().max(128).required().label("Code"), - number: Joi.string().allow("").max(128).optional().label("Number"), - description: Joi.string().allow("").max(512).optional().label("Description"), - department_id: Joi.string().uuid().required().label("Department ID"), - serviceclass: Joi.string().uuid().required().label("Service Class ID"), - floor: Joi.number().required().label("Floor"), - status: Joi.string().required().label("Status"), - location: Joi.string().required().label("Location"), - picture: Joi.string().required().label("picture"), - specialist_form: Joi.string().valid(...Object.values(SpecialistForm)).optional().allow(null, "").label("Specialist Form"), - }); - let param: any = await schema.validateAsync(req.body); - - let exist = await RoomModel.list({ code: param.code }).then((q) => q.getOne()); - if (exist && exist.id != param.id) throw { message: "Room " + Language.lang.failed_duplicate }; - - let department = await DepartmentModel.list({ id: param.department_id }).then((q) => q.getOne()); - if (!department) throw { message: "Department not found" }; - - let serviceclass = await ServiceClassModel.list({ id: param.serviceclass }).then((q) => q.getOne()); - if (!serviceclass) throw { message: "Class not found" }; - - let room = await RoomModel.list({ "Room.id": param.id }).then((q) => q.getOne()); - if (!room) throw { message: "Room " + Language.lang.failed_not_found }; - - - - room.room = param.room; - room.code = param.code; - room.number = param.number || null; - room.description = param.description || null; - room.serviceclass = param.serviceclass; - room.department = department; - room.status = param.status; - room.floor = param.floor; - room.location = param.location; - room.picture = param.picture; - room.specialist_form = param.specialist_form || null; - room.updated_by = req.auth?.data.name; - await queryRunner.manager.save(room); - - await queryRunner.commitTransaction(); - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_update, room); - } catch (e: unknown) { - await queryRunner.rollbackTransaction(); - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } finally { - await queryRunner.release(); - } - } - - static async delete(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Room'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { in: 'path', required: true, type: 'string' } - #swagger.parameters['hard'] = { in: 'path', required: false, type: 'boolean' } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("ID"), - hard: Joi.bool().optional().allow("").label("Is hard delete?"), - }); - const param: { id: string; hard: boolean } = await schema.validateAsync(req.params); - - let affected = 0; - if (!param.hard) { - let room: Room = await RoomModel.list({ "Room.id": param.id }).then((q) => q.getOne()); - if (!room) throw { message: "Room " + Language.lang.failed_not_found }; - room.deleted_by = req.auth?.data.name; - room.deleted_at = moment().toDate(); - await OrmHelper.DB.manager.save(room); - affected = 1; - } else { - const repo = OrmHelper.DB.getRepository(Room); - affected = (await repo.delete({ id: param.id })).affected ?? 0; - } - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_delete, err.message); - } - } - - static async restore(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Room'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { in: 'path', required: true, type: 'string' } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("ID"), - }); - const param: any = await schema.validateAsync(req.params); - const repo = OrmHelper.DB.getRepository(Room); - const affected = (await repo.restore({ id: param.id })).affected ?? 0; - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_restore, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_restore, err.message); - } - } - - static async uploadpicture(req: FileUploadRequest, res: Response, next: NextFunction): Promise { - /* #swagger.tags = ['Room'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.consumes = ['multipart/form-data'] - #swagger.requestBody = { - required: true, - content: { - "multipart/form-data": { - schema: { - type: "object", - properties: { - file: { - type: "string", - format: "binary", - description: "Image file (max 1MB, jpg/png/webp)" - }, - }, - required: ["file"] - } - } - } - } - */ - try { - // Validation schema - const schema = Joi.object().keys({ - // path: Joi.string().label('File Path'), - // application: Joi.string().label('Application'), - }); - - log.info("body", req.body); - - // const param: { path: string, application: string } = await schema.validateAsync(req.body); - - // Check if file exists - if (!req.files || !req.files.file) { - return ReturnHelper.errorResponse(res, 400, 404, Language.lang.failed_insert, "File not found"); - } - - const file = req.files.file as fileUpload.UploadedFile; - - // Validate file size (max 1MB) - const maxSize = 1024 * 1024; // 1MB - if (file.size > maxSize) { - return ReturnHelper.errorResponse(res, 400, 400, Language.lang.failed_insert, "File size exceeds 1MB limit"); - } - - // Validate file type - const allowedMimes = ["image/jpeg", "image/jpg", "image/png", "image/webp", "image/svg+xml", "image/svg"]; - if (!allowedMimes.includes(file.mimetype)) { - return ReturnHelper.errorResponse(res, 400, 400, Language.lang.failed_insert, "Invalid file type. Only JPG, PNG, WEBP, and SVG are allowed"); - } - - // Normalize path - // param.path = param.path[param.path.length - 1] !== '/' ? param.path + '/' : param.path; - - // if (param.path == undefined || param.path == null) param.path = 'uploads/room-picture/'; - - // Generate unique filename - const ext = file.name.split("."); - const name = uuidv4() + "." + ext[ext.length - 1]; - - const result: { file: string } = { - // url: "", - // path: "", - file: "", - // mime: file.mimetype, - // size: file.size, - // md5: file.md5 - }; - - const folder_path = "uploads/room-picture/"; - const file_path = path.join(folder_path, name); - - // Create directory if it doesn't exist - if (!fs.existsSync(folder_path)) { - fs.mkdirSync(folder_path, { recursive: true }); - } - - // Move file to destination - await file.mv(file_path); - - // result.path = param.path[param.path.length - 1] === '/' ? param.path.substring(0, param.path.length - 1) : param.path; - result.file = name; - // result.url = `${result.path}/${name}`; // Generate URL - - log.info(`File uploaded successfully: ${file_path}`); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, result); - } catch (e: unknown) { - // Proper error logging to avoid tslog serialization issues - if (e instanceof Error) { - log.error("File upload failed:", { - message: e.message, - stack: e.stack, - name: e.name, - }); - return ReturnHelper.errorResponse(res, 500, 500, Language.lang.failed_insert, e.message); - } else { - log.error("File upload failed with unknown error:", String(e)); - return ReturnHelper.errorResponse(res, 500, 500, Language.lang.failed_insert, "Unknown error occurred"); - } - } - } - - static async deletepicture(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Room'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.requestBody = { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/files" } } } } - */ - - try { - const schema = Joi.object().keys({ - file_name: Joi.string().required().label("File Name"), - }); - - const param: { file_name: string } = await schema.validateAsync(req.body); - - // Prevent deletion of files starting with "template_" - if (param.file_name.startsWith("template_")) { - return ReturnHelper.errorResponse(res, 403, 403, Language.lang.failed_delete, "Cannot delete files that start with 'template_'"); - } - - // const env = process.env.NODE_ENV + '/' - const fixedPath = "uploads/room-picture/"; - const file_path = fixedPath + param.file_name; - - // Check if file exists - if (!fs.existsSync(file_path)) { - return ReturnHelper.errorResponse(res, 404, 404, Language.lang.failed_not_found, "File not found"); - } - - // Delete file - fs.unlinkSync(file_path); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_delete, err.message); - } - } - - static async gettemplatepicture(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Room'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.description = 'Get all room pictures from uploads/room-picture/template directory".' - */ - try { - const filePath = "uploads/room-picture/template/"; - if (!fs.existsSync(filePath)) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_view, []); - } - - const files = fs.readdirSync(filePath); - - const photoBaseUrl = config.server.host_swagger + "uploads/room-picture/template/"; - const filesWithUrl = files.map((filename, index) => ({ - id: index, - name: `template/${filename}`, - url: photoBaseUrl + filename, - })); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_view, filesWithUrl); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 500, 401, Language.lang.failed_view, err.message); - } - } - - static async listLocation(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Room'] - #swagger.security = [{ "bearerAuth": [] }] - */ - try { - const query = await RoomModel.list(); - const list_data = await query - .select(["Room.id AS id", "Room.room AS room", "Room.location AS location"]) - .orderBy("Room.location", "ASC") - .addOrderBy("Room.room", "ASC") - .getRawMany(); - - const grouped_data = list_data.reduce( - (acc: Record>, item: { id: string; room: string; location: string }) => { - const locationKey = item.location || "unknown"; - if (!acc[locationKey]) { - acc[locationKey] = []; - } - - acc[locationKey].push({ - id: item.id, - room: item.room, - }); - - return acc; - }, - {}, - ); - - const formatted_data = Object.entries(grouped_data).map(([location, rooms]) => ({ - location, - rooms, - })); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_view, formatted_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } -} diff --git a/src/controllers/room_number.ts b/src/controllers/room_number.ts deleted file mode 100644 index 151ea7d..0000000 --- a/src/controllers/room_number.ts +++ /dev/null @@ -1,237 +0,0 @@ -import { RoomNumber, Paging } from "entity"; -import { NextFunction, Response } from "express"; -import { Request } from "express-jwt"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import CommonHelper from "../helpers/common"; -import { ReturnHelper } from "../helpers/express/return"; -import { Language } from "../langs/lang"; -import { RoomNumberModel } from "../model/room_number"; -import { OrmHelper } from "../helpers/orm"; -import moment from "moment"; - -const log: Logger = new Logger({ - name: "[RoomNumberController]", - type: "pretty", -}); - -export class RoomNumberController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['RoomNumber'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['filter'] = { description: 'Filter: plain text or JSON object (number, departmentId, etc.)', in: 'query', type: 'string' } - #swagger.parameters['limit'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['page'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['with_deleted'] = { in: 'query', required: true, type: 'boolean' } - #swagger.parameters['order_field'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['order_direction'] = { in: 'query', required: true, schema: { '@enum': ['ASC', 'DESC'] } } - */ - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().required().label("With Deleted"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").required().label("Order Direction"), - }); - - let param: Paging = await schema.validateAsync(req.query); - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - const filterAny = filter.any && filter.any !== "" ? String(filter.any) : ""; - let filterObj = { ...filter } as any; - delete filterObj.any; - - var query = await RoomNumberModel.list(filterObj); - - if (filterAny !== "") { - const anyVal = filterAny.includes("%") ? filterAny : `%${filterAny}%`; - query.andWhere("RoomNumber.number ILIKE :any", { any: anyVal }); - } - - const offset = (param.page - 1) * param.limit; - const res_count = query; - const res_list = query - .orderBy("RoomNumber." + param.order_field, param.order_direction) - .offset(offset) - .limit(param.limit); - - if (param.with_deleted) { - res_count.withDeleted(); - res_list.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['RoomNumber'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.requestBody = { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/room_number" } } } } - */ - const queryRunner = OrmHelper.DB.createQueryRunner(); - await queryRunner.startTransaction(); - try { - const schema = Joi.object().keys({ - number: Joi.string().max(256).required().label("Room Number"), - }); - - let param: any = await schema.validateAsync(req.body); - - let exist = await RoomNumberModel.list({ number: param.number }).then((q) => q.getOne()); - if (exist) throw { message: "Room Number " + Language.lang.failed_duplicate }; - - let roomNumber = new RoomNumber(); - roomNumber.number = param.number; - roomNumber.created_by = req.auth?.data.name; - roomNumber.updated_by = req.auth?.data.name; - await queryRunner.manager.save(roomNumber); - - await queryRunner.commitTransaction(); - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, roomNumber); - } catch (e: unknown) { - await queryRunner.rollbackTransaction(); - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } finally { - await queryRunner.release(); - } - } - - static async detail(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['RoomNumber'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { in: 'path', type: 'string' } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("Room Number Id"), - }); - let param: any = await schema.validateAsync(req.params); - let roomNumber = await RoomNumberModel.list({ "RoomNumber.id": param.id }).then((q) => q.getOne()); - if (!roomNumber) throw { message: "Room Number Not Found" }; - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_view, roomNumber); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_not_found, err.message); - } - } - - static async update(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['RoomNumber'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { in: 'path', type: 'string' } - #swagger.requestBody = { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/room_number" } } } } - */ - const queryRunner = OrmHelper.DB.createQueryRunner(); - await queryRunner.startTransaction(); - try { - req.body.id = req.params["id"]; - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("ID"), - number: Joi.string().max(256).required().label("Room Number"), - }); - let param: any = await schema.validateAsync(req.body); - - let exist = await RoomNumberModel.list({ number: param.number }).then((q) => q.getOne()); - if (exist && exist.id != param.id) throw { message: "Room Number " + Language.lang.failed_duplicate }; - - let roomNumber = await RoomNumberModel.list({ "RoomNumber.id": param.id }).then((q) => q.getOne()); - if (!roomNumber) throw { message: "Room Number " + Language.lang.failed_not_found }; - - roomNumber.number = param.number; - roomNumber.updated_by = req.auth?.data.name; - await queryRunner.manager.save(roomNumber); - - await queryRunner.commitTransaction(); - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_update, roomNumber); - } catch (e: unknown) { - await queryRunner.rollbackTransaction(); - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } finally { - await queryRunner.release(); - } - } - - static async delete(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['RoomNumber'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { in: 'path', required: true, type: 'string' } - #swagger.parameters['hard'] = { in: 'path', required: false, type: 'boolean' } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("ID"), - hard: Joi.bool().optional().allow("").label("Is hard delete?"), - }); - const param: { id: string; hard: boolean } = await schema.validateAsync(req.params); - - let affected = 0; - if (!param.hard) { - let roomNumber: RoomNumber = await RoomNumberModel.list({ "RoomNumber.id": param.id }).then((q) => q.getOne()); - if (!roomNumber) throw { message: "Room Number " + Language.lang.failed_not_found }; - roomNumber.deleted_by = req.auth?.data.name; - roomNumber.deleted_at = moment().toDate(); - await OrmHelper.DB.manager.save(roomNumber); - affected = 1; - } else { - const repo = OrmHelper.DB.getRepository(RoomNumber); - affected = (await repo.delete({ id: param.id })).affected ?? 0; - } - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_delete, err.message); - } - } - - static async restore(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['RoomNumber'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { in: 'path', required: true, type: 'string' } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("ID"), - }); - const param: any = await schema.validateAsync(req.params); - const repo = OrmHelper.DB.getRepository(RoomNumber); - const affected = (await repo.restore({ id: param.id })).affected ?? 0; - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_restore, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_restore, err.message); - } - } -} diff --git a/src/controllers/room_services.ts b/src/controllers/room_services.ts deleted file mode 100644 index c3f2a05..0000000 --- a/src/controllers/room_services.ts +++ /dev/null @@ -1,406 +0,0 @@ -import { Paging } from "entity"; -import { NextFunction, Response } from "express"; -import { Request } from "express-jwt"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import CommonHelper from "../helpers/common"; -import { ReturnHelper } from "../helpers/express/return"; -import { Language } from "../langs/lang"; -import { ServiceModel } from "../model/service"; -import { RoomServicesModel } from "../model/room_services"; -import { RoomModel } from "../model/room"; -import { DepartmentModel } from "../model/department"; -import { OrmHelper } from "../helpers/orm"; - -const log: Logger = new Logger({ - name: "[RoomServicesController]", - type: "pretty", -}); - -export class RoomServicesController { - - // Controller - List (Room-sided, default) - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Room Services'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['filter'] = { - description: 'Filter data in JSON format. Available fields: {\"any\": \"value\"} for searching by Room.code, Room.room, or Department.name (case-insensitive, supports partial match)', - in: 'query', - type: 'string', - example: '{\"any\": \"radiology\"}' - } - #swagger.parameters['limit'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['page'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['with_deleted'] = { in: 'query', required: true, type: 'boolean' } - #swagger.parameters['order_field'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['order_direction'] = { in: 'query', required: true, schema: { '@enum': ['ASC', 'DESC'] } } - */ - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().required().label("With Deleted"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").required().label("Order Direction"), - }); - - let param: Paging = await schema.validateAsync(req.query); - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - const filterAny = filter.any && filter.any !== "" ? String(filter.any) : ""; - let filterObj = { ...filter } as any; - delete filterObj.any; - - // Get total count of rooms - const query = await RoomServicesModel.listByRoom(filterObj, param.with_deleted); - if (filterAny !== "") { - const anyVal = filterAny.includes("%") ? filterAny : `%${filterAny}%`; - query.andWhere( - "(Room.code ILIKE :any OR Room.room ILIKE :any OR Department.name ILIKE :any)", - { any: anyVal } - ); - } - - const total_count_data = await query.getCount(); - - // Get all rooms with services - const rooms = await query - .orderBy("Room." + param.order_field, param.order_direction) - .skip((param.page - 1) * param.limit) - .take(param.limit) - .getMany(); - - const { byTypeId, typeMeta } = await RoomServicesModel.getActiveServicesGroupedByType(); - - const list_data = rooms.map((room) => { - const service_types = RoomServicesModel.deriveTypesForRoomWithMap(room, byTypeId, typeMeta); - - return { - id: room.id, - room: room.room, - code: room.code, - description: room.description, - status: room.status, - department: room.department - ? { - id: room.department.id, - name: room.department.name, - } - : null, - service_types, - services: room.services - ? room.services.map((service) => ({ - id: service.id, - name: service.name, - service_type: service.serviceType - ? { - id: service.serviceType.id, - name: service.serviceType.name, - } - : null, - })) - : [], - }; - }); - - const count_data = list_data.length; - - return ReturnHelper.successResponselist( - res, - 200, - Language.lang.success_view, - count_data, - param.page, - total_count_data, - list_data - ); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse( - res, - 400, - 401, - Language.lang.failed_view, - err.message - ); - } - } - - // Controller - List by Service (Service-sided) - static async listServices(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Room Services'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['room_id'] = { description: 'Room ID', in: 'path', type: 'string' } - #swagger.parameters['filter'] = { description: '', in: 'query', type: 'string' } - #swagger.parameters['limit'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['page'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['with_deleted'] = { in: 'query', required: true, type: 'boolean' } - #swagger.parameters['order_field'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['order_direction'] = { in: 'query', required: true, schema: { '@enum': ['ASC', 'DESC'] } } - */ - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().required().label("With Deleted"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").required().label("Order Direction"), - }); - - let param: Paging = await schema.validateAsync(req.query); - - const roomId = req.params["room_id"]; - const room = await RoomModel.list({ "Room.id": roomId }).then((q) => q.getOne()); - if (!room) throw { message: "Room " + Language.lang.failed_not_found }; - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await ServiceModel.list(filter); - - const offset = (param.page - 1) * param.limit; - let limit = param.limit; - - const base_query = query - .select([ - "Service.id", - "Service.name", - "Service.created_at", - "Service.created_by", - "serviceType.id", - "serviceType.name", - "serviceFare.id", - "serviceFare.fare", - "fareType.id", - "fareType.name", - ]) - .leftJoin("Service.serviceType", "serviceType") - .leftJoin("Service.rooms", "room") - .innerJoin("Service.servicefare", "serviceFare") - .innerJoin("serviceFare.serviceClass", "serviceClass") - .innerJoin("serviceFare.faretype", "fareType") - .andWhere("room.id = :roomId", { roomId }); - // .select([ - // "Service.id", - // "Service.name", - // "Service.created_at", - // "Service.created_by", - // "serviceType.id", - // "serviceType.name", - // "serviceFare.id", - // "serviceFare.fare", - // "fareType.id", - // "fareType.name", - // ]) - // .leftJoin("Service.serviceType", "serviceType") - // .leftJoin("Service.rooms", "room") - // .leftJoin("room.serviceclass", "roomClass") - // .innerJoin("Service.servicefare", "serviceFare") - // .innerJoin("serviceFare.serviceClass", "serviceClass", "serviceClass.id = roomClass.id") - // .innerJoin("serviceFare.faretype", "fareType") - // .andWhere("room.id = :roomId", { roomId }); - - const res_count = base_query.clone(); - const res_list = base_query - .orderBy("Service." + param.order_field, param.order_direction) - .skip(offset) - .take(limit); - - if (param.with_deleted) { - res_count.withDeleted(); - res_list.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse( - res, - 400, - 401, - Language.lang.failed_view, - err.message - ); - } - } - - static async detail(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Room Services'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { description: 'Room ID', in: 'path', type: 'string' } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("Room ID"), - }); - - let param: any = await schema.validateAsync(req.params); - - let room = await RoomModel.list({ "Room.id": param.id }) - .then((q) => q.leftJoinAndSelect("Room.services", "s") - .leftJoinAndSelect("s.serviceType", "serviceType") - .leftJoinAndSelect("Room.department", "department").getOne()); - - if (!room) throw { message: "Room " + Language.lang.failed_not_found }; - - const detail_data = await RoomServicesModel.formatRoomResponse(room); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_view, detail_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse( - res, - 400, - 401, - Language.lang.failed_not_found, - err.message - ); - } - } - - static async update(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Room Services'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { description: 'Room ID', in: 'path', type: 'string' } - #swagger.requestBody = { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/roomServices" } } } } - */ - const queryRunner = OrmHelper.DB.createQueryRunner(); - await queryRunner.startTransaction(); - - try { - req.body.id = req.params["id"]; - - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("Room ID"), - service_type_ids: Joi.array().items(Joi.string().uuid()).default([]).label("Service Type IDs"), - }); - - let param: any = await schema.validateAsync(req.body); - - let room = await RoomModel.list({ "Room.id": param.id }) - .then((q) => q.leftJoinAndSelect("Room.services", "s") - .leftJoinAndSelect("Room.department", "department").getOne()); - - if (!room) throw { message: "Room " + Language.lang.failed_not_found }; - - room = await RoomServicesModel.applyTypesToRoom( - queryRunner.manager, - room, - param.service_type_ids ?? [], - req.auth.data.name - ); - - await queryRunner.commitTransaction(); - - const response_data = await RoomServicesModel.formatRoomResponse( - room, - queryRunner.manager - ); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_update, response_data); - } catch (e: unknown) { - await queryRunner.rollbackTransaction(); - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } finally { - await queryRunner.release(); - } - } - - // Controller - List Ancillary Services (Service-sided) - static async listAncillaryServices(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Room Services'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['filter'] = { description: '', in: 'query', type: 'string' } - #swagger.parameters['limit'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['page'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['with_deleted'] = { in: 'query', required: true, type: 'boolean' } - #swagger.parameters['order_field'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['order_direction'] = { in: 'query', required: true, schema: { '@enum': ['ASC', 'DESC'] } } - */ - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().required().label("With Deleted"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").required().label("Order Direction"), - }); - - let param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await ServiceModel.list(filter); - - const offset = (param.page - 1) * param.limit; - let limit = param.limit; - - const base_query = query - .select([ - "Service.id", - "Service.name", - "Service.created_at", - "Service.created_by", - "serviceType.id", - "serviceType.name", - "serviceFare.id", - "serviceFare.fare", - "fareType.id", - "fareType.name", - "room.id", - "room.room", - ]) - .leftJoin("Service.serviceType", "serviceType") - .leftJoin("Service.rooms", "room") - .leftJoin("room.department", "department") - .innerJoin("Service.servicefare", "serviceFare") - .innerJoin("serviceFare.serviceClass", "serviceClass") - .innerJoin("serviceFare.faretype", "fareType") - .andWhere("department.code = :code", { code: "08" }); - - const res_count = base_query.clone(); - const res_list = base_query - .orderBy("Service." + param.order_field, param.order_direction) - .skip(offset) - .take(limit); - - if (param.with_deleted) { - res_count.withDeleted(); - res_list.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse( - res, - 400, - 401, - Language.lang.failed_view, - err.message - ); - } - } -} diff --git a/src/controllers/room_to_pharmacy.ts b/src/controllers/room_to_pharmacy.ts deleted file mode 100644 index b3c56cc..0000000 --- a/src/controllers/room_to_pharmacy.ts +++ /dev/null @@ -1,507 +0,0 @@ -import { Response, NextFunction, Application } from "express"; -import { Request } from "express-jwt"; -import { ReturnHelper } from "../helpers/express/return"; -import { OrmHelper } from "../helpers/orm"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import { Language } from "../langs/lang"; -import { RoomToPharmacy, Paging, Room } from "entity"; -import CommonHelper from "../helpers/common"; -import * as fastcsv from 'fast-csv'; -import dayjs from "dayjs"; -import { RoomToPharmacyModel } from "../model/room_to_pharmacy"; - -const log: Logger = new Logger({ name: '[RoomToPharmacyController]', type: 'pretty' }); - -export class RoomToPharmacyController { - // static async list(req: Request, res: Response, next: NextFunction): Promise { - // /* - // #swagger.tags = ['RoomToPharmacy'] - // #swagger.security = [{ "bearerAuth": [] }] - // #swagger.parameters['filter'] = { description: '', in: 'query', type: 'string' } - // #swagger.parameters['limit'] = { in: 'query', required: true, type: 'number' } - // #swagger.parameters['page'] = { in: 'query', required: true, type: 'number' } - // #swagger.parameters['with_deleted'] = { in: 'query', required: true, type: 'boolean' } - // #swagger.parameters['order_field'] = { in: 'query', required: true, type: 'string' } - // #swagger.parameters['order_direction'] = { in: 'query', required: true, schema: { '@enum': ['ASC', 'DESC'] } } - // */ - // try { - // const schema = Joi.object().keys({ - // filter: Joi.string().allow("").optional().label("Filter"), - // page: Joi.number().required().min(1).label("Page"), - // limit: Joi.number().required().min(1).label("Limit"), - // with_deleted: Joi.bool().required().label("With Deleted"), - // order_field: Joi.string().required().label("Order Field"), - // order_direction: Joi.string().allow("ASC", "DESC").required().label("Order Direction"), - // }); - // const param: Paging = await schema.validateAsync(req.query); - - // const filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - // const filterAny = filter.any && filter.any !== "" ? filter.any : ""; - // let filterObj = { ...filter } as any; - // delete filterObj.any; - - // const query = await RoomToPharmacyModel.list(filterObj); - // const offset = (param.page - 1) * param.limit; - - // const res_count = query; - // const res_list = query - // .leftJoinAndSelect("room_to_pharmacy.pharmacy_room", "emrregistration") - // .leftJoinAndSelect("room_to_pharmacy.room", "room") - // .orderBy("room_to_pharmacy." + param.order_field, param.order_direction) - // .offset(offset) - // .limit(param.limit); - - // if (param.with_deleted) { - // res_count.withDeleted(); - // res_list.withDeleted(); - // } - - // const current_page = param.page; - // const total_count_data = await res_count.getCount(); - // const list_data = await res_list.getMany(); - // const count_data = CommonHelper.countObject(list_data); - - // return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - // } catch (e: unknown) { - // log.error(e); - // const err = e as Error; - // return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - // } - // } - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['RoomToPharmacy'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['filter'] = { - description: "Filter in JSON format. Available fields: room (string, partial match case-insensitive), code (string, partial match case-insensitive), status (string, exact match), pharmacy_room (string, partial match case-insensitive). Example: {\"room\":\"igd\",\"code\":\"R01\",\"status\":\"active\",\"pharmacy_room\":\"apotek\"}", - in: 'query', - type: 'string' - } - #swagger.parameters['limit'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['page'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['with_deleted'] = { in: 'query', required: true, type: 'boolean' } - #swagger.parameters['order_field'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['order_direction'] = { in: 'query', required: true, schema: { '@enum': ['ASC', 'DESC'] } } - */ - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().required().label("With Deleted"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").required().label("Order Direction"), - }); - - let param: Paging = await schema.validateAsync(req.query); - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - const offset = (param.page - 1) * param.limit; - const limit = param.limit; - - const roomQuery = OrmHelper.DB.getRepository(Room) - .createQueryBuilder("room") - .leftJoinAndSelect("room.department", "department") - .leftJoinAndMapMany( - "room.roomToPharmacies", - RoomToPharmacy, - "room_to_pharmacy", - "room_to_pharmacy.room_id = room.id" - ) - .leftJoinAndMapOne( - "room_to_pharmacy.pharmacy_room", - Room, - "pharmacy_room", - "pharmacy_room.id = room_to_pharmacy.pharmacy_room_id" - ) - .where("department.id IN (:...departmentIds)", { - departmentIds: [ - '42bc42a7-e2a7-4f95-a788-9d9e51a51a20', - '3fc39ff1-b4bc-4276-92ef-def7ca9432fb', - 'a0d2ef11-6927-4e5c-8628-6acf26351071', - ] - }) - .orderBy("room." + param.order_field, param.order_direction as "ASC" | "DESC"); - - if (param.with_deleted) { - roomQuery.withDeleted(); - } - - // Filter tambahan jika ada - const roomNameFilter = filter["room.name"] ?? filter.room; - if (roomNameFilter !== undefined && roomNameFilter !== "") { - const roomVal = String(roomNameFilter); - roomQuery.andWhere("room.room ILIKE :room", { room: roomVal.includes("%") ? roomVal : `%${roomVal}%` }); - } - if (filter.status) { - roomQuery.andWhere("room.status = :status", { status: filter.status }); - } - - // Filter room.code - if (filter.code && filter.code !== "") { - roomQuery.andWhere("room.code ILIKE :code", { code: `%${filter.code}%` }); - } - - // Filter pharmacy_room.room - if (filter.pharmacy_room && filter.pharmacy_room !== "") { - roomQuery.andWhere("pharmacy_room.room ILIKE :pharmacy_room", { pharmacy_room: `%${filter.pharmacy_room}%` }); - } - - const total_count_data = await roomQuery.clone().getCount(); - - const rooms = await roomQuery - .offset(offset) - .limit(limit) - .getMany(); - - // Transform: { room_name: { pharmacy_room_1: {}, pharmacy_room_2: {} } } - const list_data_return = rooms.map((room: any) => { - const roomToPharmacies: any[] = room.roomToPharmacies ?? []; - - const pharmacyRooms: Record = {}; - roomToPharmacies.forEach((rtp: any, index: number) => { - const pharmacy: Room | null = rtp.pharmacy_room ?? null; - pharmacyRooms[`pharmacy_room_${index + 1}`] = pharmacy ? { - id: pharmacy.id, - room: pharmacy.room, - code: pharmacy.code, - description: pharmacy.description ?? null, - status: pharmacy.status, - } : null; - }); - - return { - rooms: { - id: room.id, - room: room.room, - code: room.code, - description: room.description ?? null, - status: room.status, - department: room.department ? { - id: room.department.id, - name: room.department.name, - } : null, - pharmacy_rooms: Object.keys(pharmacyRooms).length > 0 - ? pharmacyRooms - : null, - } - }; - }); - - const count_data = CommonHelper.countObject(list_data_return); - - return ReturnHelper.successResponselist( - res, - 200, - Language.lang.success_view, - count_data, - param.page, - total_count_data, - list_data_return - ); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async export(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['RoomToPharmacy'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['filter'] = { - description: 'Filter with 2 format :
  • Simple format use text plaint will filter eq:code or like %name%
  • Advance format using field existing {status:\'Y\', any:\'SAME AS PLAINT LOGIC\', etc...}
', - in: 'query', - type: 'string' - } - #swagger.parameters['filter'] = { - in: 'query', - type: 'string' - } - #swagger.parameters['order_field'] = { - in: 'query', - required: true, - type: 'string' - } - #swagger.parameters['order_direction'] = { - in: 'query', - required: true, - schema: { - '@enum': ['ASC', 'DESC'] - } - } - */ - - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow('').optional().label('Filter'), - order_field: Joi.string().required().label('Order Field'), - order_direction: Joi.string().allow('asc', 'desc').required().label('Order Direction'), - }); - - const param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await RoomToPharmacyModel.list(filter); - const data = await query.getMany(); - - const filename = "room_to_pharmacy.csv"; - - res.setHeader('Content-Type', 'text/csv'); - res.setHeader('Content-Disposition', 'attachment; filename=' + filename); - - const csvStream = fastcsv.format({ - headers: true, - writeHeaders: true, - transform: (row: RoomToPharmacy): any => ({ - ...row, - created_at: dayjs(row.created_at).format('DD-MM-YYYY HH:MM:ss'), - }) - }); - csvStream.pipe(res); - - const limit = 50; - - const fetchAndWrite = async (page: any) => { - - if (CommonHelper.countObject(data) === 0) { - csvStream.end(); - } else { - data.forEach((item: any) => csvStream.write(item)); - - if (CommonHelper.countObject(data) == limit) { - fetchAndWrite(page + 1); - } else { - csvStream.end(); - } - } - }; - - fetchAndWrite(1); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['RoomToPharmacy'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/room_to_pharmacy" - } - } - } - } - */ - try { - const schema = Joi.object().keys({ - pharmacy_room_id: Joi.string() - .uuid() - .required() - .label("Pharmacy Room ID"), - - room_id: Joi.string() - .uuid() - .required() - .label("Room ID"), - - // room_ids: Joi.array() - // .items(Joi.string().uuid().required()) - // .min(1) - // .required() - // .label("Room IDs") - }); - - const param: any = await schema.validateAsync(req.body); - - const data = new RoomToPharmacy() - data.pharmacy_room = param.pharmacy_room_id; - data.room = param.room_id; - data.created_by = req.auth?.data.name; - - await OrmHelper.DB.manager.save(data); - - // await RoomToPharmacyRepo - // .createQueryBuilder() - // .delete() - // .from(RoomToPharmacy) - // .where("pharmacy_room_id = :pharmacyRoomId", { pharmacyRoomId: param.pharmacy_room_id }) - // .execute(); - - // let relation : RoomToPharmacy; - // for (const roomId of param.room_ids) { - // relation = new RoomToPharmacy(); - // relation.room = await roomRepo.findOneBy({ id: roomId }); - // relation.pharmacy_room = await roomRepo.findOneBy({ id: param.pharmacy_room_id }); - // relation.created_by = req.auth.data.name; - - // await RoomToPharmacyRepo.save(relation); - // } - - // const data = await RoomToPharmacyRepo.createQueryBuilder("room_to_pharmacy") - // .leftJoinAndSelect("room_to_pharmacy.room", "room") - // .leftJoinAndSelect("room_to_pharmacy.pharmacy_room", "pharmacy_room") - // .where("room_to_pharmacy.pharmacy_room_id = :pharmacyRoomId", { pharmacyRoomId: param.pharmacy_room_id }).getMany(); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 401, Language.lang.failed_insert, err.message); - } - } - - static async update(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['RoomToPharmacy'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.parameters['room_id'] = { - in: 'path', - description: 'Room ID.', - required: true, - type: 'string' - } - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/room_to_pharmacy" - } - } - } - } - */ - try { - const schema = Joi.object().keys({ - room_id: Joi.string().uuid().required(), - pharmacy_room_id: Joi.string().uuid().required(), - }); - - req.body.room_id = req.params['room_id']; - - const param: any = await schema.validateAsync(req.body); - - const repo = OrmHelper.DB.getRepository(RoomToPharmacy); - - // ✅ cari berdasarkan room saja - let data = await repo.findOne({ - where: { - room: { id: param.room_id } - }, - relations: ["room", "pharmacy_room"] - }); - - // ambil pharmacy room - const pharmacyRoom = await OrmHelper.DB.getRepository(Room).findOneBy({ - id: param.pharmacy_room_id - }); - - if (!pharmacyRoom) { - throw new Error("Pharmacy Room not found"); - } - - if (data) { - data.pharmacy_room = pharmacyRoom; - data.updated_by = req.auth?.data.name; - - await repo.save(data); - } else { - const room = await OrmHelper.DB.getRepository(Room).findOneBy({ - id: param.room_id - }); - - if (!room) throw new Error("Room not found"); - - data = new RoomToPharmacy(); - data.room = room; - data.pharmacy_room = pharmacyRoom; - data.created_by = req.auth?.data.name; - data.updated_by = req.auth?.data.name; - - await repo.save(data); - } - - return ReturnHelper.successResponseAny( - res, - 200, - Language.lang.success_update, - data - ); - - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse( - res, - 500, - 401, - Language.lang.failed_update, - err.message - ); - } - } - - static async detail(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['RoomToPharmacy'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { description: '', in: 'path', type: 'string' } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("Room Id"), - }); - - let param: any = await schema.validateAsync(req.params); - - let data = await OrmHelper.DB.getRepository(Room) - .createQueryBuilder("room") - .leftJoinAndSelect("room.department", "department") - .leftJoinAndMapMany( - "room.roomToPharmacies", - RoomToPharmacy, - "room_to_pharmacy", - "room_to_pharmacy.room_id = room.id" - ) - .leftJoinAndMapOne( - "room_to_pharmacy.pharmacy_room", - Room, - "pharmacy_room", - "pharmacy_room.id = room_to_pharmacy.pharmacy_room_id" - ) - .where("room.id = :id", { id: param.id }) - .getOne(); - - if (!data) throw { message: "RoomToPharmacy Not Found" }; - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_view, data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_not_found, err.message); - } - } -} \ No newline at end of file diff --git a/src/controllers/schedule.ts b/src/controllers/schedule.ts deleted file mode 100644 index bc60572..0000000 --- a/src/controllers/schedule.ts +++ /dev/null @@ -1,407 +0,0 @@ -import { NextFunction, Response } from "express"; -import { Request } from "express-jwt"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import { ReturnHelper } from "../helpers/express/return"; -import { Language } from "../langs/lang"; -import { ScheduleModel } from "../model/schedule"; -import CommonHelper from "../helpers/common"; - -const log: Logger = new Logger({ - name: "[ScheduleController]", - type: "pretty", -}); - -export class ScheduleController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Schedule'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['filter'] = { description: '', in: 'query', type: 'string' } - #swagger.parameters['limit'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['page'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['with_deleted'] = { in: 'query', required: true, type: 'boolean' } - #swagger.parameters['order_field'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['order_direction'] = { in: 'query', required: true, schema: { '@enum': ['ASC', 'DESC'] } } - #swagger.responses[200] = { - description: 'Schedule series paginated list', - schema: { - status: true, - code: 200, - message: 'success', - data: { count: 1, page: 1, total_count: 1, list: [{ id: 'uuid-string', title: 'Practice Schedule' }] } - } - } - */ - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().required().label("With Deleted"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").required().label("Order Direction"), - }); - - const param: { - filter?: string; - page: number; - limit: number; - with_deleted: boolean; - order_field: string; - order_direction: "asc" | "desc"; - } = await schema.validateAsync(req.query); - - const filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - const filterAny = filter.any && filter.any !== "" ? String(filter.any) : ""; - const filterObj = { ...filter } as any; - delete filterObj.any; - - const query = await ScheduleModel.listSeries(filterObj); - if (filterAny !== "") { - const anyVal = filterAny.includes("%") ? filterAny : `%${filterAny}%`; - query.andWhere( - "(ScheduleSeries.title ILIKE :any OR Room.room ILIKE :any OR Room.code ILIKE :any OR Doctor.name ILIKE :any OR Doctor.username ILIKE :any)", - { any: anyVal } - ); - } - const orderDirection = param.order_direction.toUpperCase() as "ASC" | "DESC"; - - const offset = (param.page - 1) * param.limit; - const resCount = query; - const resList = query - .orderBy("ScheduleSeries." + param.order_field, orderDirection) - .offset(offset) - .limit(param.limit); - - if (param.with_deleted) { - resCount.withDeleted(); - resList.withDeleted(); - } - - const currentPage = param.page; - const totalCountData = await resCount.getCount(); - const listData = await resList.getMany(); - const countData = CommonHelper.countObject(listData); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, countData, currentPage, totalCountData, listData); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async options(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Schedule'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['filter'] = { in: 'query', required: false, type: 'string', description: 'Filter by room id (optional)' } - #swagger.responses[200] = { - description: 'Schedule options', - schema: { - status: true, - code: 200, - message: 'success', - data: { - doctors: [{ id: 'uuid-string', title: 'Doctor Name' }], - rooms: [{ id: 'uuid-string', title: 'Room Name' }] - } - } - } - */ - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - }); - - const param: { filter?: string } = await schema.validateAsync(req.query); - const filterObj = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - const result = await ScheduleModel.getScheduleOptions(filterObj); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_view, result); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async calendar(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Schedule'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['start_date'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['end_date'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['filter'] = { in: 'query', required: false, type: 'string' } - #swagger.parameters['limit'] = { in: 'query', required: false, type: 'number' } - #swagger.parameters['page'] = { in: 'query', required: false, type: 'number' } - #swagger.responses[200] = { - description: 'Schedule calendar rooms and events', - schema: { - status: true, - code: 200, - message: 'success', - data: { - count: 1, - page: 1, - total_count: 1, - list: { - rooms: [{ - id: 'uuid-string', - name: 'string', - code: 'string', - picture: 'string', - location: 'string', - status: 'string', - department: { - name: 'string', - }, - }], - events: [{ - id: 'occ:series-101:2026-03-20', - series_id: 'series-101', - room_id: 'room-1', - room_name: 'Room 1', - doctor_id: 'doctor-1', - doctor_name: 'Doctor 1', - title: 'Practice', - start_at: '2026-03-20T09:00:00+07:00', - end_at: '2026-03-20T12:00:00+07:00', - quota: 10, - used_quota: 5, - left_quota: 5, - is_recurring: true, - is_exception: false, - status: 'confirmed' - }], - } - } - } - } - */ - try { - const schema = Joi.object().keys({ - start_date: Joi.string().required().label("Start Date"), - end_date: Joi.string().required().label("End Date"), - filter: Joi.string().allow("").optional().label("Filter"), - limit: Joi.number().min(1).optional().label("Limit"), - page: Joi.number().min(1).optional().label("Page"), - }); - - const param: { - start_date: string; - end_date: string; - filter?: string; - limit?: number; - page?: number; - } = await schema.validateAsync(req.query); - const filterObj = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - const result = await ScheduleModel.getScheduleCalendarRange(param.start_date, param.end_date, filterObj, { - limit: param.limit, - page: param.page, - }); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_view, result); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async detail(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Schedule'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { in: 'path', required: true, type: 'string' } - #swagger.responses[200] = { - description: 'Schedule series detail', - schema: { - status: true, - code: 200, - message: 'success', - data: { - series: { - id: 'uuid-string', - title: 'Practice Schedule', - recurrence: { $ref: '#/components/schemas/scheduleRecurrence' } - }, - exceptions: [{ id: 'uuid-string', occurrence_date: '2026-03-24' }] - } - } - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("Series ID"), - }); - - const param: { id: string } = await schema.validateAsync(req.params); - const result = await ScheduleModel.getSeriesById(param.id); - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_view, result); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Schedule'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.requestBody = { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/scheduleSeriesCreate" } } } } - #swagger.responses[200] = { - description: 'Schedule series created', - schema: { status: true, code: 200, message: 'success', data: { id: 'uuid-string' } } - } - */ - try { - const schema = Joi.object().keys({ - roomId: Joi.string().uuid().required(), - doctorId: Joi.string().uuid().required(), - title: Joi.string().max(256).required(), - quota: Joi.number().integer().min(0).allow(null).optional(), - startDate: Joi.string().required(), - untilDate: Joi.string().allow("", null).optional(), - startTime: Joi.string().required(), - endTime: Joi.string().required(), - recurrence: Joi.object({ - type: Joi.string().valid("daily", "weekly", "monthly").required(), - interval: Joi.number().min(1).optional(), - daysOfWeek: Joi.array().items(Joi.string().valid("SU", "MO", "TU", "WE", "TH", "FR", "SA")).optional(), - }) - .allow(null) - .optional(), - }); - - const param = await schema.validateAsync(req.body); - const actor = req.auth?.data?.name || "system"; - const result = await ScheduleModel.createSeries(param, actor); - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, result); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_insert, err.message); - } - } - - static async update(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Schedule'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { in: 'path', required: true, type: 'string' } - #swagger.requestBody = { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/scheduleSeriesUpdate" } } } } - #swagger.responses[200] = { - description: 'Schedule series updated', - schema: { status: true, code: 200, message: 'success', data: { id: 'uuid-string' } } - } - */ - try { - req.body.id = req.params["id"]; - const schema = Joi.object().keys({ - id: Joi.string().uuid().required(), - roomId: Joi.string().uuid().required(), - doctorId: Joi.string().uuid().required(), - title: Joi.string().max(256).required(), - quota: Joi.number().integer().min(0).allow(null).optional(), - startDate: Joi.string().required(), - untilDate: Joi.string().allow("", null).optional(), - startTime: Joi.string().required(), - endTime: Joi.string().required(), - recurrence: Joi.object({ - type: Joi.string().valid("daily", "weekly", "monthly").required(), - interval: Joi.number().min(1).optional(), - daysOfWeek: Joi.array().items(Joi.string().valid("SU", "MO", "TU", "WE", "TH", "FR", "SA")).optional(), - }) - .allow(null) - .optional(), - }); - - const param = await schema.validateAsync(req.body); - const actor = req.auth?.data?.name || "system"; - const result = await ScheduleModel.updateSeries(param.id, param, actor); - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_update, result); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_update, err.message); - } - } - - static async createException(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Schedule'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { in: 'path', required: true, type: 'string' } - #swagger.requestBody = { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/scheduleExceptionCreate" } } } } - #swagger.responses[200] = { - description: 'Schedule exception created or updated', - schema: { status: true, code: 200, message: 'success', data: { id: 'uuid-string' } } - } - */ - try { - req.body.id = req.params["id"]; - const schema = Joi.object().keys({ - id: Joi.string().uuid().required(), - occurrenceDate: Joi.string().required(), - isCancelled: Joi.boolean().optional(), - overrideRoomId: Joi.string().uuid().allow("", null).optional(), - overrideDoctorId: Joi.string().uuid().allow("", null).optional(), - overrideTitle: Joi.string().max(256).allow("", null).optional(), - overrideStartAt: Joi.string().allow("", null).optional(), - overrideEndAt: Joi.string().allow("", null).optional(), - }); - - const param = await schema.validateAsync(req.body); - const actor = req.auth?.data?.name || "system"; - const result = await ScheduleModel.createSeriesException(param.id, param, actor); - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, result); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_insert, err.message); - } - } - - static async delete(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Schedule'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { in: 'path', required: true, type: 'string' } - #swagger.parameters['hard'] = { in: 'path', description: 'Is Hard Delete', required: false, type: 'boolean' } - #swagger.responses[200] = { - description: 'Schedule series deleted', - schema: { status: true, code: 200, message: 'success', data: {} } - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("ID"), - hard: Joi.alternatives() - .try(Joi.boolean(), Joi.string().valid("", "true", "false", "1", "0")) - .optional() - .label("Is hard delete?"), - }); - - const param: { id: string; hard?: boolean | string } = await schema.validateAsync(req.params); - - const isHardDelete = - param.hard === true || param.hard === "true" || param.hard === "1"; - - const actor = req.auth?.data?.name || "system"; - const affected = await ScheduleModel.deleteSeries(param.id, isHardDelete, actor); - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_delete, err.message); - } - } -} diff --git a/src/controllers/service.ts b/src/controllers/service.ts deleted file mode 100644 index bfcbf50..0000000 --- a/src/controllers/service.ts +++ /dev/null @@ -1,348 +0,0 @@ -import { Service, Paging, Status } from "entity"; -import { NextFunction, Response } from "express"; -import { Request } from "express-jwt"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import CommonHelper from "../helpers/common"; -import { ReturnHelper } from "../helpers/express/return"; -import { Language } from "../langs/lang"; -import { ServiceModel } from "../model/service"; -import { ServiceTypeModel } from "../model/service_type"; -import { ServiceFareModel } from "../model/service_fare"; -import { RoomServicesModel } from "../model/room_services"; -import { OrmHelper } from "../helpers/orm"; -import moment from "moment"; - -const log: Logger = new Logger({ - name: "[ServiceController]", - type: "pretty", -}); - -export class ServiceController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Service'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['filter'] = { description: '', in: 'query', type: 'string' } - #swagger.parameters['limit'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['page'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['with_deleted'] = { in: 'query', required: true, type: 'boolean' } - #swagger.parameters['order_field'] = { in: 'query', required: false, type: 'string', default: 'created_at' } - #swagger.parameters['order_direction'] = { in: 'query', required: false, schema: { '@enum': ['ASC', 'DESC'], default: 'DESC' } } - */ - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().required().label("With Deleted"), - order_field: Joi.string().optional().default("created_at").label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").optional().default("desc").label("Order Direction"), - }); - - let param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - let filterAny = filter.any && filter.any !== "" ? filter.any : ""; - - let filterObj = { ...filter } as any; - delete filterObj.any; - - var query = await ServiceModel.list(filterObj, filterAny); - - const offset = (param.page - 1) * param.limit; - let limit = param.limit; - - const res_count = query; - const res_list = query - .orderBy("Service." + param.order_field, param.order_direction) - .leftJoinAndSelect("Service.serviceType", "serviceType") - .offset(offset) - .limit(limit); - - if (param.with_deleted) { - res_count.withDeleted(); - res_list.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Service'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.requestBody = { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/service" } } } } - */ - const queryRunner = OrmHelper.DB.createQueryRunner(); - await queryRunner.startTransaction(); - try { - const schema = Joi.object().keys({ - name: Joi.string().max(256).required().label("Name"), - service_type_id: Joi.string().uuid().required().label("Service Type ID"), - status: Joi.string().required().label("Status"), - }); - - let param: any = await schema.validateAsync(req.body); - - let serviceType = await ServiceTypeModel.list({ id: param.service_type_id }).then((q) => q.getOne()); - if (!serviceType) throw { message: "Service Type not found" }; - - let service = new Service(); - service.name = param.name; - service.serviceType = serviceType; - service.status = param.status; - service.created_by = req.auth?.data.name; - service.updated_by = req.auth?.data.name; - await queryRunner.manager.save(service); - - await queryRunner.commitTransaction(); - - const saved = await ServiceModel.list({ "Service.id": service.id }) - .then((q) => q.leftJoinAndSelect("Service.serviceType", "serviceType").getOne()); - if (saved) { - await RoomServicesModel.syncRoomsOnServiceCreated(OrmHelper.DB.manager, saved); - } - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, service); - } catch (e: unknown) { - await queryRunner.rollbackTransaction(); - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } finally { - await queryRunner.release(); - } - } - - static async detail(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Service'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { description: '', in: 'path', type: 'string' } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("Service Id"), - }); - - let param: any = await schema.validateAsync(req.params); - - let service = await ServiceModel.list({ "Service.id": param.id }) - .then((q) => q - .leftJoinAndSelect("Service.serviceType", "serviceType") - .getOne()); - - if (!service) throw { message: "Service Not Found" }; - - let serviceFares = await ServiceFareModel.list({ "ServiceFare.serviceId": param.id }) - .then((q) => q - .leftJoinAndSelect("ServiceFare.serviceClass", "serviceClass") - .getMany()); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_view, { ...service, serviceFares }); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_not_found, err.message); - } - } - - static async update(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Service'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { description: '', in: 'path', type: 'string' } - #swagger.requestBody = { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/service" } } } } - */ - const queryRunner = OrmHelper.DB.createQueryRunner(); - await queryRunner.startTransaction(); - - try { - req.body.id = req.params["id"]; - - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("Service ID"), - name: Joi.string().max(256).required().label("Name"), - service_type_id: Joi.string().uuid().required().label("Service Type ID"), - status: Joi.string().required().label("Status"), - }); - - let param: any = await schema.validateAsync(req.body); - - let serviceType = await ServiceTypeModel.list({ id: param.service_type_id }).then((q) => q.getOne()); - if (!serviceType) throw { message: "Service Type not found" }; - - let service = await ServiceModel.list({ "Service.id": param.id }) - .then((q) => q.leftJoinAndSelect("Service.serviceType", "st").getOne()); - - if (!service) throw { message: "Service " + Language.lang.failed_not_found }; - - const oldTypeId = service.serviceType?.id; - - service.name = param.name; - service.serviceType = serviceType; - service.status = param.status; - service.updated_by = req.auth?.data.name; - await queryRunner.manager.save(service); - - await queryRunner.commitTransaction(); - - const saved = await ServiceModel.list({ "Service.id": service.id }) - .then((q) => q.leftJoinAndSelect("Service.serviceType", "serviceType").getOne()); - if (saved) { - await RoomServicesModel.syncRoomsOnServiceUpdated( - OrmHelper.DB.manager, - saved, - oldTypeId - ); - } - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_update, service); - } catch (e: unknown) { - await queryRunner.rollbackTransaction(); - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } finally { - await queryRunner.release(); - } - } - - // static async updateservicerooms(req: Request, res: Response, next: NextFunction): Promise { - // /* - // #swagger.tags = ['Service'] - // #swagger.security = [{ "bearerAuth": [] }] - // #swagger.parameters['id'] = { description: '', in: 'path', type: 'string' } - // #swagger.requestBody = { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/servicerooms" } } } } - // */ - // const queryRunner = OrmHelper.DB.createQueryRunner(); - // await queryRunner.startTransaction(); - - // try { - // req.body.id = req.params["id"]; - - // const schema = Joi.object().keys({ - // id: Joi.string().uuid().required().label("Service ID"), - // room_ids: Joi.array().items(Joi.string().uuid()).optional().label("Room IDs"), - // }); - - // let param: any = await schema.validateAsync(req.body); - - // let service = await ServiceModel.list({ "Service.id": param.id }) - // .then((q) => q.leftJoinAndSelect("Service.serviceType", "st").leftJoinAndSelect("Service.rooms", "r").getOne()); - - // if (!service) throw { message: "Service " + Language.lang.failed_not_found }; - - // let rooms: any[] = []; - // if (param.room_ids && param.room_ids.length > 0) { - // for (const roomId of param.room_ids) { - // const room = await RoomModel.list({ id: roomId }).then((q) => q.getOne()); - // if (room) rooms.push(room); - // } - // } - - // service.rooms = rooms; - // service.updated_by = req.auth.data.name; - // await queryRunner.manager.save(service); - - // await queryRunner.commitTransaction(); - - // return ReturnHelper.successResponseAny(res, 200, Language.lang.success_update, service); - // } catch (e: unknown) { - // await queryRunner.rollbackTransaction(); - // log.error(e); - // const err = e as Error; - // return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - // } finally { - // await queryRunner.release(); - // } - // } - - static async delete(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Service'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { in: 'path', required: true, type: 'string' } - #swagger.parameters['hard'] = { in: 'path', description: 'Is Hard Delete', required: false, type: 'boolean' } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("ID"), - hard: Joi.bool().optional().allow("").label("Is hard delete?"), - }); - - const param: { id: string; hard: boolean } = await schema.validateAsync(req.params); - - let affected = 0; - if (!param.hard) { - let service: Service = await ServiceModel.list({ "Service.id": param.id }).then((q) => q.getOne()); - - if (!service) throw { message: "Service " + Language.lang.failed_not_found }; - - service.deleted_by = req.auth?.data.name; - service.deleted_at = moment().toDate(); - await OrmHelper.DB.manager.save(service); - affected = 1; - } else { - const repo = OrmHelper.DB.getRepository(Service); - affected = (await repo.delete({ id: param.id })).affected ?? 0; - } - - if (affected > 0) { - await RoomServicesModel.syncRoomsOnServiceDeleted(OrmHelper.DB.manager, param.id); - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_delete, err.message); - } - } - - static async restore(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Service'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { in: 'path', required: true, type: 'string' } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("ID"), - }); - - const param: any = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(Service); - - const affected = (await repo.restore({ id: param.id })).affected ?? 0; - - if (affected > 0) { - const service = await ServiceModel.list({ "Service.id": param.id }) - .then((q) => q.leftJoinAndSelect("Service.serviceType", "serviceType").getOne()); - if (service && service.status === Status.Active) { - await RoomServicesModel.syncRoomsOnServiceCreated(OrmHelper.DB.manager, service); - } - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_restore, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_restore, err.message); - } - } -} diff --git a/src/controllers/service_class.ts b/src/controllers/service_class.ts deleted file mode 100644 index 3dffe38..0000000 --- a/src/controllers/service_class.ts +++ /dev/null @@ -1,251 +0,0 @@ -import { ServiceClass, Paging } from "entity"; -import { NextFunction, Response } from "express"; -import { Request } from "express-jwt"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import CommonHelper from "../helpers/common"; -import { ReturnHelper } from "../helpers/express/return"; -import { Language } from "../langs/lang"; -import { ServiceClassModel } from "../model/service_class"; -import { OrmHelper } from "../helpers/orm"; -import moment from "moment"; - -const log: Logger = new Logger({ - name: "[ServiceClassController]", - type: "pretty", -}); - -export class ServiceClassController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Service Class'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['filter'] = { description: '', in: 'query', type: 'string' } - #swagger.parameters['limit'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['page'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['with_deleted'] = { in: 'query', required: true, type: 'boolean' } - #swagger.parameters['order_field'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['order_direction'] = { in: 'query', required: true, schema: { '@enum': ['ASC', 'DESC'] } } - */ - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().required().label("With Deleted"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").required().label("Order Direction"), - }); - - let param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await ServiceClassModel.list(filter); - - const offset = (param.page - 1) * param.limit; - let limit = param.limit; - - const res_count = query; - const res_list = query - .orderBy("ServiceClass." + param.order_field, param.order_direction) - .offset(offset) - .limit(limit); - - if (param.with_deleted) { - res_count.withDeleted(); - res_list.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Service Class'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.requestBody = { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/serviceClass" } } } } - */ - const queryRunner = OrmHelper.DB.createQueryRunner(); - await queryRunner.startTransaction(); - try { - const schema = Joi.object().keys({ - name: Joi.string().max(256).required().label("Name"), - }); - - let param: any = await schema.validateAsync(req.body); - - let filter = { name: param.name }; - let exist = await ServiceClassModel.list(filter).then((q) => q.getOne()); - if (exist) throw { message: "Service Class " + Language.lang.failed_duplicate }; - - let serviceClass = new ServiceClass(); - serviceClass.name = param.name; - serviceClass.created_by = req.auth.data.name; - serviceClass.updated_by = req.auth.data.name; - await queryRunner.manager.save(serviceClass); - - await queryRunner.commitTransaction(); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, serviceClass); - } catch (e: unknown) { - await queryRunner.rollbackTransaction(); - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } finally { - await queryRunner.release(); - } - } - - static async detail(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Service Class'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { description: '', in: 'path', type: 'string' } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("Service Class Id"), - }); - - let param: any = await schema.validateAsync(req.params); - - let serviceClass = await ServiceClassModel.list({ "ServiceClass.id": param.id }).then((q) => q.getOne()); - - if (!serviceClass) throw { message: "Service Class Not Found" }; - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_view, serviceClass); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_not_found, err.message); - } - } - - static async update(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Service Class'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { description: '', in: 'path', type: 'string' } - #swagger.requestBody = { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/serviceClass" } } } } - */ - const queryRunner = OrmHelper.DB.createQueryRunner(); - await queryRunner.startTransaction(); - - try { - req.body.id = req.params["id"]; - - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("Service Class ID"), - name: Joi.string().max(256).required().label("Name"), - }); - - let param: any = await schema.validateAsync(req.body); - - let filter = { name: param.name }; - let exist = await ServiceClassModel.list(filter).then((q) => q.getOne()); - if (exist && exist.id != param.id) throw { message: "Service Class " + Language.lang.failed_duplicate }; - - let serviceClass = await ServiceClassModel.list({ "ServiceClass.id": param.id }).then((q) => q.getOne()); - - if (!serviceClass) throw { message: "Service Class " + Language.lang.failed_not_found }; - - serviceClass.name = param.name; - serviceClass.updated_by = req.auth.data.name; - await queryRunner.manager.save(serviceClass); - - await queryRunner.commitTransaction(); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_update, serviceClass); - } catch (e: unknown) { - await queryRunner.rollbackTransaction(); - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } finally { - await queryRunner.release(); - } - } - - static async delete(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Service Class'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { in: 'path', required: true, type: 'string' } - #swagger.parameters['hard'] = { in: 'path', description: 'Is Hard Delete', required: false, type: 'boolean' } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("ID"), - hard: Joi.bool().optional().allow("").label("Is hard delete?"), - }); - - const param: { id: string; hard: boolean } = await schema.validateAsync(req.params); - - let affected = 0; - if (!param.hard) { - let serviceClass: ServiceClass = await ServiceClassModel.list({ "ServiceClass.id": param.id }).then((q) => q.getOne()); - - if (!serviceClass) throw { message: "Service Class " + Language.lang.failed_not_found }; - - serviceClass.deleted_by = req.auth.data.name; - serviceClass.deleted_at = moment().toDate(); - await OrmHelper.DB.manager.save(serviceClass); - affected = 1; - } else { - const repo = OrmHelper.DB.getRepository(ServiceClass); - affected = (await repo.delete({ id: param.id })).affected ?? 0; - } - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_delete, err.message); - } - } - - static async restore(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Service Class'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { in: 'path', required: true, type: 'string' } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("ID"), - }); - - const param: any = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(ServiceClass); - - const affected = (await repo.restore({ id: param.id })).affected ?? 0; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_restore, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_restore, err.message); - } - } -} diff --git a/src/controllers/service_examination.ts b/src/controllers/service_examination.ts deleted file mode 100644 index 1ea9065..0000000 --- a/src/controllers/service_examination.ts +++ /dev/null @@ -1,216 +0,0 @@ -import { Service, Paging } from "entity"; -import { NextFunction, Response } from "express"; -import { Request } from "express-jwt"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import CommonHelper from "../helpers/common"; -import { ReturnHelper } from "../helpers/express/return"; -import { Language } from "../langs/lang"; -import { ServiceModel } from "../model/service"; -import { ExaminationDetailModel } from "../model/examination_detail"; -import { OrmHelper } from "../helpers/orm"; - -const log: Logger = new Logger({ - name: "[ServiceExaminationController]", - type: "pretty", -}); - -export class ServiceExaminationController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Service Examination'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['filter'] = { description: 'Filter: plain text or JSON object (service_id, etc.)', in: 'query', type: 'string' } - #swagger.parameters['limit'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['page'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['with_deleted'] = { in: 'query', required: true, type: 'boolean' } - #swagger.parameters['order_field'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['order_direction'] = { in: 'query', required: true, schema: { '@enum': ['ASC', 'DESC'] } } - */ - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().required().label("With Deleted"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").required().label("Order Direction"), - }); - - let param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - const offset = (param.page - 1) * param.limit; - let limit = param.limit; - - var query = await ServiceModel.list(filter); - - const res_count = query; - const res_list = query - .leftJoinAndSelect("Service.serviceType", "serviceType") - .leftJoinAndSelect("Service.examination_details", "examinationDetails") - .leftJoinAndSelect("examinationDetails.measurement_unit", "measurementUnit") - .leftJoinAndSelect("examinationDetails.reference_range", "referenceRange") - .orderBy("Service." + param.order_field, param.order_direction) - .skip(offset) - .take(limit); - - if (param.with_deleted) { - res_count.withDeleted(); - res_list.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist( - res, 200, - Language.lang.success_view, - count_data, - current_page, - total_count_data, - list_data - ); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Service Examination'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { $ref: "#/components/schemas/serviceExaminationCreate" } - } - } - } - */ - - const queryRunner = OrmHelper.DB.createQueryRunner(); - await queryRunner.startTransaction(); - - try { - const schema = Joi.object().keys({ - service_id: Joi.string().uuid().required().label("Service ID"), - examination_detail_ids: Joi.array() - .items(Joi.string().uuid()) - .optional() - .label("Examination Detail IDs"), - }); - - let param: any = await schema.validateAsync(req.body); - - // ✅ ambil service - let service = await ServiceModel.list({ "Service.id": param.service_id }) - .then((q) => q.leftJoinAndSelect("Service.serviceType", "st") - .leftJoinAndSelect("Service.examination_details", "ed") - .getOne()); - - if (!service) throw { message: "Service " + Language.lang.failed_not_found }; - - // ✅ ambil examination details - let examinationDetails: any[] = []; - if (param.examination_detail_ids && param.examination_detail_ids.length > 0) { - for (const examinationDetailId of param.examination_detail_ids) { - const examinationDetail = await ExaminationDetailModel - .list({ "ExaminationDetail.id": examinationDetailId }) - .then((q) => q.getOne()); - - if (examinationDetail) { - examinationDetails.push(examinationDetail); - } - } - } - - // ✅ assign (CREATE behavior) - service.examination_details = examinationDetails; - service.created_by = req.auth?.data.name; - service.updated_by = req.auth?.data.name; - - await queryRunner.manager.save(service); - - await queryRunner.commitTransaction(); - - return ReturnHelper.successResponseAny( - res, - 200, - Language.lang.success_insert, - service - ); - - } catch (e: unknown) { - await queryRunner.rollbackTransaction(); - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse( - res, - 400, - 401, - Language.lang.failed_view, - err.message - ); - } finally { - await queryRunner.release(); - } - } - - static async update(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Service Examination'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { in: 'path', type: 'string' } - #swagger.requestBody = { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/serviceExamination" } } } } - */ - const queryRunner = OrmHelper.DB.createQueryRunner(); - await queryRunner.startTransaction(); - - try { - req.body.id = req.params["id"]; - - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("Service ID"), - examination_detail_ids: Joi.array().items(Joi.string().uuid()).optional().label("Examination Detail IDs"), - }); - - let param: any = await schema.validateAsync(req.body); - - let service = await ServiceModel.list({ "Service.id": param.id }) - .then((q) => q.leftJoinAndSelect("Service.serviceType", "st").leftJoinAndSelect("Service.examination_details", "ed").getOne()); - - if (!service) throw { message: "Service " + Language.lang.failed_not_found }; - - let examinationDetails: any[] = []; - if (param.examination_detail_ids && param.examination_detail_ids.length > 0) { - for (const examinationDetailId of param.examination_detail_ids) { - const examinationDetail = await ExaminationDetailModel.list({ "ExaminationDetail.id": examinationDetailId }).then((q) => q.getOne()); - if (examinationDetail) examinationDetails.push(examinationDetail); - } - } - - service.examination_details = examinationDetails; - service.updated_by = req.auth?.data.name; - await queryRunner.manager.save(service); - - await queryRunner.commitTransaction(); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_update, service); - } catch (e: unknown) { - await queryRunner.rollbackTransaction(); - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } finally { - await queryRunner.release(); - } - } -} diff --git a/src/controllers/service_fare.ts b/src/controllers/service_fare.ts deleted file mode 100644 index faf70ee..0000000 --- a/src/controllers/service_fare.ts +++ /dev/null @@ -1,424 +0,0 @@ -import { ServiceFare, ServiceClass, Service, FareType, Paging } from "entity"; -import { NextFunction, Response } from "express"; -import { Request } from "express-jwt"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import CommonHelper from "../helpers/common"; -import { ReturnHelper } from "../helpers/express/return"; -import { Language } from "../langs/lang"; -import { ServiceFareModel } from "../model/service_fare"; -import { ServiceClassModel } from "../model/service_class"; -import { ServiceModel } from "../model/service"; -import { OrmHelper } from "../helpers/orm"; -import moment from "moment"; - -const log: Logger = new Logger({ - name: "[ServiceFareController]", - type: "pretty", -}); - -export class ServiceFareController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Service Fare'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['filter'] = { - description: 'Filter data in JSON format. Available fields: {\"any\": \"value\"} for searching by Service.name or service type name (case-insensitive, supports partial match)', - in: 'query', - type: 'string', - example: '{\"any\": \"express\"}' - } - #swagger.parameters['limit'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['page'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['with_deleted'] = { in: 'query', required: true, type: 'boolean' } - #swagger.parameters['order_field'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['order_direction'] = { in: 'query', required: true, schema: { '@enum': ['ASC', 'DESC'] } } - */ - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().required().label("With Deleted"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string().valid("ASC", "DESC").uppercase().required().label("Order Direction"), - }); - - let param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - const offset = (param.page - 1) * param.limit; - const limit = param.limit; - - const filterAny = filter.any && filter.any !== "" ? String(filter.any) : ""; - let filterObj = { ...filter } as any; - delete filterObj.any; - - var query = await ServiceModel.list(filterObj); - - const base_query = query - .select([ - "Service.id", - "Service.name", - ]) - .leftJoin("Service.serviceType", "st") - .addSelect("st.name", "service_type_name") - .leftJoin( - qb => { - return qb - .select('sf."serviceId"', "serviceId") - .addSelect("COALESCE(MIN(sf.fare), 0)", "min") - .addSelect("COALESCE(MAX(sf.fare), 0)", "max") - .from("service_fares", "sf") - .innerJoin("fare_type", "ft", 'sf."faretypeId" = ft.id AND ft.deleted_at IS NULL') - .innerJoin("service_classes", "sc", 'sf."serviceClassId" = sc.id AND sc.deleted_at IS NULL') - .innerJoin("services", "s", 'sf."serviceId" = s.id AND s.deleted_at IS NULL') - .groupBy('sf."serviceId"'); - }, - "sfa", - 'sfa."serviceId" = Service.id' - ) - .addSelect('COALESCE(sfa.min, 0)', "min_fare") - .addSelect('COALESCE(sfa.max, 0)', "max_fare"); - - const res_count = base_query.clone(); - const res_list = base_query - .orderBy("Service." + param.order_field, param.order_direction) - .skip(offset) - .take(limit); - - if (filterAny !== "") { - const anyVal = filterAny.includes("%") ? filterAny : `%${filterAny}%`; - res_list.andWhere("(Service.name ILIKE :any OR st.name ILIKE :any)", { any: anyVal }); - res_count.andWhere("(Service.name ILIKE :any OR st.name ILIKE :any)", { any: anyVal }); - } - - if (param.with_deleted) { - res_count.withDeleted(); - res_list.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getRawAndEntities(); - - const merged = list_data.entities.map((entity, index) => ({ - ...entity, - min_fare: list_data.raw[index]?.min_fare ?? null, - max_fare: list_data.raw[index]?.max_fare ?? null, - service_type_name: list_data.raw[index]?.service_type_name ?? null, - })); - - const count_data = CommonHelper.countObject(merged); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, merged); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async option(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Service Fare'] - #swagger.security = [{ "bearerAuth": [] }] - */ - try { - const [services, fareTypes, serviceClasses] = await Promise.all([ - OrmHelper.DB.getRepository(Service) - .createQueryBuilder("Service") - .select(["Service.id", "Service.name"]) - .getMany(), - - OrmHelper.DB.getRepository(FareType) - .createQueryBuilder("FareType") - .select(["FareType.id", "FareType.name"]) - .getMany(), - - OrmHelper.DB.getRepository(ServiceClass) - .createQueryBuilder("ServiceClass") - .select(["ServiceClass.id", "ServiceClass.name"]) - .getMany(), - ]); - - // Semua FareType dapat semua ServiceClass - const fareTypesWithClass = fareTypes.map((ft) => ({ - id: ft.id, - name: ft.name, - service_class: serviceClasses.map((sc) => ({ - id: sc.id, - name: sc.name, - })), - })); - - // Semua Service dapat semua FareType (yang sudah berisi ServiceClass) - const list_data = services.map((svc) => ({ - service: { - id: svc.id, - name: svc.name, - faretype: fareTypesWithClass, - }, - })); - - const total_count_data = list_data.length; - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist( - res, 200, - Language.lang.success_view, - count_data, - 1, - total_count_data, - list_data - ); - - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Service Fare'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.requestBody = { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/serviceFare" } } } } - */ - const queryRunner = OrmHelper.DB.createQueryRunner(); - await queryRunner.startTransaction(); - try { - const schema = Joi.object().keys({ - service_id: Joi.string().uuid().required().label("Service ID"), - faretype: Joi.array().items( - Joi.object().keys({ - faretype_id: Joi.string().uuid().required().label("Fare Type ID"), - service_class: Joi.array().items( - Joi.object().keys({ - service_class_id: Joi.string().uuid().required().label("Service Class ID"), - fare: Joi.number().min(0).allow(null).label("Fare"), - }) - ).min(1).required().label("Service Class"), - }) - ).min(1).required().label("Fare Type"), - }); - - let param: any = await schema.validateAsync(req.body); - - // Validasi Service - let service = await ServiceModel.list({ "Service.id": param.service_id }).then((q) => q.getOne()); - if (!service) throw { message: "Service not found" }; - - const savedServiceFares: ServiceFare[] = []; - - // Loop tiap faretype - for (const ft of param.faretype) { - - // Validasi FareType - let fareType = await OrmHelper.DB.getRepository("FareType") - .createQueryBuilder("FareType") - .where("FareType.id = :id", { id: ft.faretype_id }) - .getOne(); - if (!fareType) throw { message: `Fare Type ID ${ft.faretype_id} not found` }; - - - for (const sc of ft.service_class) { - - let serviceClass = await ServiceClassModel.list({ "ServiceClass.id": sc.service_class_id }).then((q) => q.getOne()); - if (!serviceClass) throw { message: `Service Class ID ${sc.service_class_id} not found` }; - - let serviceFare = await ServiceFareModel.list({ - "ServiceFare.serviceId": param.service_id, - "ServiceFare.faretype": ft.faretype_id, - "ServiceFare.serviceClassId": sc.service_class_id, - }).then((q) => q.getOne()); - - if (!serviceFare) { - serviceFare = new ServiceFare(); - serviceFare.service = service; - serviceFare.faretype = ft.faretype_id; - serviceFare.serviceClass = serviceClass; - serviceFare.created_by = req.auth?.data.name; - } - - serviceFare.fare = String(sc.fare ?? 0); - serviceFare.updated_by = req.auth?.data.name; - - const saved = await queryRunner.manager.save(serviceFare); - savedServiceFares.push(saved); - } - } - - await queryRunner.commitTransaction(); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, savedServiceFares); - - } catch (e: unknown) { - await queryRunner.rollbackTransaction(); - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } finally { - await queryRunner.release(); - } - } - - static async detail(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Service Fare'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { description: 'Service ID', in: 'path', type: 'string' } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("Service Id"), // ← label diupdate - }); - - let param: any = await schema.validateAsync(req.params); - - let serviceFare = await ServiceModel.list({ "Service.id": param.id }) - .then((q) => - q - .select([ - "Service.id", - "Service.name", - "servicefare.id", - "servicefare.fare", - "serviceClass.id", - "serviceClass.name", - "faretype.id", - "faretype.name", - ]) - .leftJoin("Service.servicefare", "servicefare") - .leftJoin("servicefare.serviceClass", "serviceClass") - .leftJoin("servicefare.faretype", "faretype") - .getOne() - ); - - if (!serviceFare || serviceFare.length === 0) throw { message: "Service Fare Not Found" }; - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_view, serviceFare); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_not_found, err.message); - } - } - - static async update(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Service Fare'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { description: 'Service Fare ID', in: 'path', type: 'string' } - #swagger.requestBody = { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/serviceFareUpdate" } } } } - */ - const queryRunner = OrmHelper.DB.createQueryRunner(); - await queryRunner.startTransaction(); - - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("Service Fare ID"), - fare: Joi.number().min(0).required().label("Fare"), - }); - - let param: any = await schema.validateAsync({ - ...req.body, - id: req.params.id, - }); - - // Cari data berdasarkan ID - let serviceFare = await ServiceFareModel.list({ "ServiceFare.id": param.id }).then((q) => q.getOne()); - if (!serviceFare) throw { message: "Service Fare " + Language.lang.failed_not_found }; - - // Update fare saja - serviceFare.fare = String(param.fare); - serviceFare.updated_by = req.auth?.data.name; - - await queryRunner.manager.save(serviceFare); - await queryRunner.commitTransaction(); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_update, serviceFare); - - } catch (e: unknown) { - await queryRunner.rollbackTransaction(); - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } finally { - await queryRunner.release(); - } - } - - static async delete(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Service Fare'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { in: 'path', required: true, type: 'string' } - #swagger.parameters['hard'] = { in: 'path', description: 'Is Hard Delete', required: false, type: 'boolean' } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("ID"), - hard: Joi.bool().optional().allow("").label("Is hard delete?"), - }); - - const param: { id: string; hard: boolean } = await schema.validateAsync(req.params); - - let affected = 0; - if (!param.hard) { - let serviceFare: ServiceFare = await ServiceFareModel.list({ "ServiceFare.id": param.id }).then((q) => q.getOne()); - - if (!serviceFare) throw { message: "Service Fare " + Language.lang.failed_not_found }; - - serviceFare.deleted_by = req.auth?.data.name; - serviceFare.deleted_at = moment().toDate(); - await OrmHelper.DB.manager.save(serviceFare); - affected = 1; - } else { - const repo = OrmHelper.DB.getRepository(ServiceFare); - affected = (await repo.delete({ id: param.id })).affected ?? 0; - } - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_delete, err.message); - } - } - - static async restore(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Service Fare'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { in: 'path', required: true, type: 'string' } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("ID"), - }); - - const param: any = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(ServiceFare); - - const affected = (await repo.restore({ id: param.id })).affected ?? 0; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_restore, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_restore, err.message); - } - } -} diff --git a/src/controllers/service_package.ts b/src/controllers/service_package.ts deleted file mode 100644 index 5d3b5bb..0000000 --- a/src/controllers/service_package.ts +++ /dev/null @@ -1,287 +0,0 @@ -import { ServicePackage, Paging } from "entity"; -import { NextFunction, Response } from "express"; -import { Request } from "express-jwt"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import CommonHelper from "../helpers/common"; -import { ReturnHelper } from "../helpers/express/return"; -import { Language } from "../langs/lang"; -import { ServicePackageModel } from "../model/service_package"; -import { ServiceClassModel } from "../model/service_class"; -import { ServiceModel } from "../model/service"; -import { OrmHelper } from "../helpers/orm"; -import moment from "moment"; - -const log: Logger = new Logger({ - name: "[ServicePackageController]", - type: "pretty", -}); - -export class ServicePackageController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Service Package'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['filter'] = { description: '', in: 'query', type: 'string' } - #swagger.parameters['limit'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['page'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['with_deleted'] = { in: 'query', required: true, type: 'boolean' } - #swagger.parameters['order_field'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['order_direction'] = { in: 'query', required: true, schema: { '@enum': ['ASC', 'DESC'] } } - */ - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().required().label("With Deleted"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").required().label("Order Direction"), - }); - - let param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await ServicePackageModel.list(filter); - - const offset = (param.page - 1) * param.limit; - let limit = param.limit; - - const res_count = query; - const res_list = query - .leftJoinAndSelect("ServicePackage.serviceClass", "serviceClass") - .leftJoinAndSelect("ServicePackage.services", "services") - .orderBy("ServicePackage." + param.order_field, param.order_direction) - .offset(offset) - .limit(limit); - - if (param.with_deleted) { - res_count.withDeleted(); - res_list.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Service Package'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.requestBody = { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/servicePackage" } } } } - */ - const queryRunner = OrmHelper.DB.createQueryRunner(); - await queryRunner.startTransaction(); - try { - const schema = Joi.object().keys({ - name: Joi.string().max(256).required().label("Name"), - service_class_id: Joi.string().uuid().required().label("Service Class ID"), - fare: Joi.number().min(0).required().label("Fare"), - service_ids: Joi.array().items(Joi.string().uuid()).optional().label("Service IDs"), - }); - - let param: any = await schema.validateAsync(req.body); - - let serviceClass = await ServiceClassModel.list({ id: param.service_class_id }).then((q) => q.getOne()); - if (!serviceClass) throw { message: "Service Class not found" }; - - let services: any[] = []; - if (param.service_ids && param.service_ids.length > 0) { - for (const serviceId of param.service_ids) { - const svc = await ServiceModel.list({ id: serviceId }).then((q) => q.getOne()); - if (svc) services.push(svc); - } - } - - let servicePackage = new ServicePackage(); - servicePackage.name = param.name; - servicePackage.serviceClass = serviceClass; - servicePackage.fare = String(param.fare); - servicePackage.services = services; - servicePackage.created_by = req.auth.data.name; - servicePackage.updated_by = req.auth.data.name; - await queryRunner.manager.save(servicePackage); - - await queryRunner.commitTransaction(); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, servicePackage); - } catch (e: unknown) { - await queryRunner.rollbackTransaction(); - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } finally { - await queryRunner.release(); - } - } - - static async detail(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Service Package'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { description: '', in: 'path', type: 'string' } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("Service Package Id"), - }); - - let param: any = await schema.validateAsync(req.params); - - let servicePackage = await ServicePackageModel.list({ "ServicePackage.id": param.id }) - .then((q) => - q - .leftJoinAndSelect("ServicePackage.serviceClass", "serviceClass") - .leftJoinAndSelect("ServicePackage.services", "services") - .getOne() - ); - - if (!servicePackage) throw { message: "Service Package Not Found" }; - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_view, servicePackage); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_not_found, err.message); - } - } - - static async update(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Service Package'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { description: '', in: 'path', type: 'string' } - #swagger.requestBody = { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/servicePackage" } } } } - */ - const queryRunner = OrmHelper.DB.createQueryRunner(); - await queryRunner.startTransaction(); - - try { - req.body.id = req.params["id"]; - - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("Service Package ID"), - name: Joi.string().max(256).required().label("Name"), - service_class_id: Joi.string().uuid().required().label("Service Class ID"), - fare: Joi.number().min(0).required().label("Fare"), - service_ids: Joi.array().items(Joi.string().uuid()).optional().label("Service IDs"), - }); - - let param: any = await schema.validateAsync(req.body); - - let serviceClass = await ServiceClassModel.list({ id: param.service_class_id }).then((q) => q.getOne()); - if (!serviceClass) throw { message: "Service Class not found" }; - - let servicePackage = await ServicePackageModel.list({ "ServicePackage.id": param.id }) - .then((q) => q.leftJoinAndSelect("ServicePackage.serviceClass", "sc").leftJoinAndSelect("ServicePackage.services", "s").getOne()); - if (!servicePackage) throw { message: "Service Package " + Language.lang.failed_not_found }; - - let services: any[] = []; - if (param.service_ids && param.service_ids.length > 0) { - for (const serviceId of param.service_ids) { - const svc = await ServiceModel.list({ id: serviceId }).then((q) => q.getOne()); - if (svc) services.push(svc); - } - } - - servicePackage.name = param.name; - servicePackage.serviceClass = serviceClass; - servicePackage.fare = String(param.fare); - servicePackage.services = services; - servicePackage.updated_by = req.auth.data.name; - await queryRunner.manager.save(servicePackage); - - await queryRunner.commitTransaction(); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_update, servicePackage); - } catch (e: unknown) { - await queryRunner.rollbackTransaction(); - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } finally { - await queryRunner.release(); - } - } - - static async delete(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Service Package'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { in: 'path', required: true, type: 'string' } - #swagger.parameters['hard'] = { in: 'path', description: 'Is Hard Delete', required: false, type: 'boolean' } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("ID"), - hard: Joi.bool().optional().allow("").label("Is hard delete?"), - }); - - const param: { id: string; hard: boolean } = await schema.validateAsync(req.params); - - let affected = 0; - if (!param.hard) { - let servicePackage: ServicePackage = await ServicePackageModel.list({ "ServicePackage.id": param.id }).then((q) => q.getOne()); - - if (!servicePackage) throw { message: "Service Package " + Language.lang.failed_not_found }; - - servicePackage.deleted_by = req.auth.data.name; - servicePackage.deleted_at = moment().toDate(); - await OrmHelper.DB.manager.save(servicePackage); - affected = 1; - } else { - const repo = OrmHelper.DB.getRepository(ServicePackage); - affected = (await repo.delete({ id: param.id })).affected ?? 0; - } - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_delete, err.message); - } - } - - static async restore(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Service Package'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { in: 'path', required: true, type: 'string' } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("ID"), - }); - - const param: any = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(ServicePackage); - - const affected = (await repo.restore({ id: param.id })).affected ?? 0; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_restore, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_restore, err.message); - } - } -} diff --git a/src/controllers/service_type.ts b/src/controllers/service_type.ts deleted file mode 100644 index e9e7f47..0000000 --- a/src/controllers/service_type.ts +++ /dev/null @@ -1,255 +0,0 @@ -import { ServiceType, Paging } from "entity"; -import { NextFunction, Response } from "express"; -import { Request } from "express-jwt"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import CommonHelper from "../helpers/common"; -import { ReturnHelper } from "../helpers/express/return"; -import { Language } from "../langs/lang"; -import { ServiceTypeModel } from "../model/service_type"; -import { OrmHelper } from "../helpers/orm"; -import moment from "moment"; - -const log: Logger = new Logger({ - name: "[ServiceTypeController]", - type: "pretty", -}); - -export class ServiceTypeController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Service Type'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['filter'] = { description: '', in: 'query', type: 'string' } - #swagger.parameters['limit'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['page'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['with_deleted'] = { in: 'query', required: true, type: 'boolean' } - #swagger.parameters['order_field'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['order_direction'] = { in: 'query', required: true, schema: { '@enum': ['ASC', 'DESC'] } } - */ - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().required().label("With Deleted"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").required().label("Order Direction"), - }); - - let param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await ServiceTypeModel.list(filter); - - const offset = (param.page - 1) * param.limit; - let limit = param.limit; - - const res_count = query; - const res_list = query - .orderBy("ServiceType." + param.order_field, param.order_direction) - .offset(offset) - .limit(limit); - - if (param.with_deleted) { - res_count.withDeleted(); - res_list.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Service Type'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.requestBody = { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/serviceType" } } } } - */ - const queryRunner = OrmHelper.DB.createQueryRunner(); - await queryRunner.startTransaction(); - try { - const schema = Joi.object().keys({ - name: Joi.string().max(256).required().label("Name"), - status: Joi.string().required().label("Status"), - }); - - let param: any = await schema.validateAsync(req.body); - - let filter = { name: param.name }; - let exist = await ServiceTypeModel.list(filter).then((q) => q.getOne()); - if (exist) throw { message: "Service Type " + Language.lang.failed_duplicate }; - - let serviceType = new ServiceType(); - serviceType.name = param.name; - serviceType.status = param.status; - serviceType.created_by = req.auth.data.name; - serviceType.updated_by = req.auth.data.name; - await queryRunner.manager.save(serviceType); - - await queryRunner.commitTransaction(); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, serviceType); - } catch (e: unknown) { - await queryRunner.rollbackTransaction(); - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } finally { - await queryRunner.release(); - } - } - - static async detail(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Service Type'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { description: '', in: 'path', type: 'string' } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("Service Type Id"), - }); - - let param: any = await schema.validateAsync(req.params); - - let serviceType = await ServiceTypeModel.list({ "ServiceType.id": param.id }).then((q) => q.getOne()); - - if (!serviceType) throw { message: "Service Type Not Found" }; - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_view, serviceType); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_not_found, err.message); - } - } - - static async update(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Service Type'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { description: '', in: 'path', type: 'string' } - #swagger.requestBody = { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/serviceType" } } } } - */ - const queryRunner = OrmHelper.DB.createQueryRunner(); - await queryRunner.startTransaction(); - - try { - req.body.id = req.params["id"]; - - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("Service Type ID"), - name: Joi.string().max(256).required().label("Name"), - status: Joi.string().required().label("Status"), - }); - - let param: any = await schema.validateAsync(req.body); - - let filter = { name: param.name }; - let exist = await ServiceTypeModel.list(filter).then((q) => q.getOne()); - if (exist && exist.id != param.id) throw { message: "Service Type " + Language.lang.failed_duplicate }; - - let serviceType = await ServiceTypeModel.list({ "ServiceType.id": param.id }).then((q) => q.getOne()); - - if (!serviceType) throw { message: "Service Type " + Language.lang.failed_not_found }; - - serviceType.name = param.name; - serviceType.status = param.status; - serviceType.updated_by = req.auth.data.name; - await queryRunner.manager.save(serviceType); - - await queryRunner.commitTransaction(); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_update, serviceType); - } catch (e: unknown) { - await queryRunner.rollbackTransaction(); - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } finally { - await queryRunner.release(); - } - } - - static async delete(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Service Type'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { in: 'path', required: true, type: 'string' } - #swagger.parameters['hard'] = { in: 'path', description: 'Is Hard Delete', required: false, type: 'boolean' } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("ID"), - hard: Joi.bool().optional().allow("").label("Is hard delete?"), - }); - - const param: { id: string; hard: boolean } = await schema.validateAsync(req.params); - - let affected = 0; - if (!param.hard) { - let serviceType: ServiceType = await ServiceTypeModel.list({ "ServiceType.id": param.id }).then((q) => q.getOne()); - - if (!serviceType) throw { message: "Service Type " + Language.lang.failed_not_found }; - - serviceType.deleted_by = req.auth.data.name; - serviceType.deleted_at = moment().toDate(); - await OrmHelper.DB.manager.save(serviceType); - affected = 1; - } else { - const repo = OrmHelper.DB.getRepository(ServiceType); - affected = (await repo.delete({ id: param.id })).affected ?? 0; - } - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_delete, err.message); - } - } - - static async restore(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Service Type'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { in: 'path', required: true, type: 'string' } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("ID"), - }); - - const param: any = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(ServiceType); - - const affected = (await repo.restore({ id: param.id })).affected ?? 0; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_restore, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_restore, err.message); - } - } -} diff --git a/src/controllers/aldeia.ts b/src/controllers/sitepoints.ts similarity index 66% rename from src/controllers/aldeia.ts rename to src/controllers/sitepoints.ts index bfd7201..a18562f 100644 --- a/src/controllers/aldeia.ts +++ b/src/controllers/sitepoints.ts @@ -9,19 +9,19 @@ import { Paging } from "entity"; import CommonHelper from "../helpers/common"; import * as fastcsv from 'fast-csv'; import dayjs from "dayjs"; -import { Aldeia, Suco } from "entity"; +import { SitePoints } from "entity"; -const log: Logger = new Logger({ name: '[AldeiaController]', type: 'pretty' }); +const log: Logger = new Logger({ name: '[SitePointsController]', type: 'pretty' }); -export class AldeiaController { +export class SitePointsController { static async list(req: Request, res: Response, next: NextFunction): Promise { /* - #swagger.tags = ['Aldeia'] + #swagger.tags = ['Site Points'] #swagger.security = [{ "bearerAuth": [] }] #swagger.parameters['filter'] = { - description: 'Filter with 2 format :
  • Simple format use text plaint will filter eq:code or like %name%
  • Advance format using field existing {status:\'Y\', any:\'SAME AS PLAINT LOGIC\', etc...}
', + description: '', in: 'query', type: 'string' } @@ -66,42 +66,38 @@ export class AldeiaController { const param: Paging = await schema.validateAsync(req.query); - const repo = OrmHelper.DB.getRepository(Aldeia); + const repo = OrmHelper.DB.getRepository(SitePoints); const offset = (param.page - 1) * param.limit const filterObj = param.filter ? JSON.parse(param.filter) : {}; - // Remove foreign key from filter for CommonHelper.handleFilter - const filterWithoutFK = { ...filterObj }; - delete filterWithoutFK.suco_id; - const filterStrWithoutFK = JSON.stringify(filterWithoutFK); - + const { whereAttr, whereVal } = CommonHelper.handleFilter({ - filter: filterStrWithoutFK, - col_any_eq: ['code'], - col_any_like: ['name'] + filter: param.filter, + col_any_eq: [''], + col_any_like: ['sector', 'cell', 'site', 'location'] }); - const res_count = repo.createQueryBuilder("Aldeia") - .leftJoin("Aldeia.suco", "suco") + const res_count = repo.createQueryBuilder("SitePoints") + // .leftJoin("Administrativu.munisipo", "munisipo") .where(whereAttr || "1=1", whereVal); - - // Handle foreign key filter with relation - if (filterObj.suco_id) { - res_count.andWhere("suco.id = :sucoId", { sucoId: filterObj.suco_id }); - } - const res_list = repo.createQueryBuilder("Aldeia") - .leftJoin("Aldeia.suco", "suco") + // Handle foreign key filter with relation + // if (filterObj.munisipo_id) { + // res_count.andWhere("munisipo.id = :munisipoId", { munisipoId: filterObj.munisipo_id }); + // } + + const res_list = repo.createQueryBuilder("SitePoints") + // .leftJoin("Administrativu.munisipo", "munisipo") .where(whereAttr || "1=1", whereVal) - .orderBy("Aldeia." + param.order_field, param.order_direction) + .orderBy("SitePoints." + param.order_field, param.order_direction) .offset(offset) .limit(param.limit); - + // Handle foreign key filter with relation - if (filterObj.suco_id) { - res_list.andWhere("suco.id = :sucoId", { sucoId: filterObj.suco_id }); - } + // if (filterObj.munisipo_id) { + // res_list.andWhere("munisipo.id = :munisipoId", { munisipoId: filterObj.munisipo_id }); + // } if (param.with_deleted) { res_count.withDeleted(); @@ -122,14 +118,35 @@ export class AldeiaController { } } + static async alldatas(req: Request, res: Response, next: NextFunction): Promise { + /* + #swagger.tags = ['Site Points'] + #swagger.security = [{ + "bearerAuth": [] + }] + */ + try { + const repo = OrmHelper.DB.getRepository(SitePoints); + const list_data = await repo.find(); + const count_data = CommonHelper.countObject(list_data); + + return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, 1, list_data.length, list_data); + } catch (e: unknown) { + log.error(e); + const err = e as Error; + + return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); + } + } + static async export(req: Request, res: Response, next: NextFunction): Promise { /* - #swagger.tags = ['Aldeia'] + #swagger.tags = ['Site Points'] #swagger.security = [{ "bearerAuth": [] }] #swagger.parameters['filter'] = { - description: 'Filter with 2 format :
  • Simple format use text plaint will filter eq:code or like %name%
  • Advance format using field existing {status:\'Y\', any:\'SAME AS PLAINT LOGIC\', etc...}
', + description: '', in: 'query', type: 'string' } @@ -160,21 +177,21 @@ export class AldeiaController { const param: Paging = await schema.validateAsync(req.query); - const repo = OrmHelper.DB.getRepository(Aldeia); + const repo = OrmHelper.DB.getRepository(SitePoints); const filterObj = param.filter ? JSON.parse(param.filter) : {}; // Remove foreign key from filter for CommonHelper.handleFilter - const filterWithoutFK = { ...filterObj }; - delete filterWithoutFK.suco_id; - const filterStrWithoutFK = JSON.stringify(filterWithoutFK); - + // const filterWithoutFK = { ...filterObj }; + // delete filterWithoutFK.munisipo_id; + // const filterStrWithoutFK = JSON.stringify(filterWithoutFK); + const { whereAttr, whereVal } = CommonHelper.handleFilter({ - filter: filterStrWithoutFK, - col_any_eq: ['code'], - col_any_like: ['name'] + filter: param.filter, + col_any_eq: [''], + col_any_like: ['sector', 'cell', 'site', 'location'] }); - const filename = "aldeia.csv"; + const filename = "site_points.csv"; res.setHeader('Content-Type', 'text/csv'); res.setHeader('Content-Disposition', 'attachment; filename=' + filename); @@ -182,7 +199,7 @@ export class AldeiaController { const csvStream = fastcsv.format({ headers: true, writeHeaders: true, - transform: (row: Aldeia): any => ({ + transform: (row: SitePoints): any => ({ ...row, created_at: dayjs(row.created_at).format('DD-MM-YYYY HH:MM:ss'), }) @@ -194,23 +211,27 @@ export class AldeiaController { const fetchAndWrite = async (page: any) => { const offset = (page - 1) * limit - let query = repo.createQueryBuilder("Aldeia") - .leftJoin("Aldeia.suco", "suco") + let query = repo.createQueryBuilder("sitepoints") + // .leftJoin("Administrativu.munisipo", "munisipo") .where(whereAttr || "1=1", whereVal); - + // Handle foreign key filter with relation - if (filterObj.suco_id) { - query = query.andWhere("suco.id = :sucoId", { sucoId: filterObj.suco_id }); - } - + // if (filterObj.munisipo_id) { + // query = query.andWhere("munisipo.id = :munisipoId", { munisipoId: filterObj.munisipo_id }); + // } + const data = await query .select([ - 'Aldeia.id', - 'Aldeia.code', - 'Aldeia.name', - 'Aldeia.status', - 'Aldeia.created_at']) - .orderBy("Aldeia." + param.order_field, param.order_direction) + 'sitepoints.id', + 'sitepoints.cell', + 'sitepoints.sector', + 'sitepoints.site', + 'sitepoints.lat', + 'sitepoints.lng', + 'sitepoints.location', + 'sitepoints.created_at' + ]) + .orderBy("sitepoints." + param.order_field, param.order_direction) .offset(offset) .limit(limit).getRawMany(); @@ -238,7 +259,7 @@ export class AldeiaController { static async create(req: Request, res: Response, next: NextFunction): Promise { /* - #swagger.tags = ['Aldeia'] + #swagger.tags = ['Site Points'] #swagger.security = [{ "bearerAuth": [] }] @@ -248,7 +269,7 @@ export class AldeiaController { content: { "application/json": { schema: { - $ref: "#/components/schemas/aldeia" + $ref: "#/components/schemas/site_points" } } } @@ -257,19 +278,23 @@ export class AldeiaController { try { const schema = Joi.object().keys({ - code: Joi.string().max(128).required().label('Code'), - name: Joi.string().max(256).required().label('Name'), - status: Joi.string().required().label('Status'), - suco_id: Joi.string().uuid().required().label('Suco'), + cell: Joi.string().allow('').label('Cell'), + sector: Joi.string().allow('').label('Sector'), + site: Joi.string().allow('').label('Site'), + lat: Joi.number().allow(null).label('Latitude'), + lng: Joi.number().allow(null).label('Longitude'), + location: Joi.string().allow('').label('Location'), }); const param: any = await schema.validateAsync(req.body); - const data = new Aldeia() - data.code = param.code - data.name = param.name - data.status = param.status - data.suco = await OrmHelper.DB.getRepository(Suco).findOneByOrFail({ id: param.suco_id }); + const data = new SitePoints() + data.cell = param.cell + data.sector = param.sector + data.site = param.site + data.lat = param.lat + data.lng = param.lng + data.location = param.location await OrmHelper.DB.manager.save(data); @@ -284,23 +309,23 @@ export class AldeiaController { static async update(req: Request, res: Response, next: NextFunction): Promise { /* - #swagger.tags = ['Aldeia'] + #swagger.tags = ['Site Points'] #swagger.security = [{ "bearerAuth": [] }] #swagger.parameters['id'] = { in: 'path', - description: 'Aldeia ID.', + description: 'Site Points ID.', required: true, type: 'string' } - + #swagger.requestBody = { required: true, content: { "application/json": { schema: { - $ref: "#/components/schemas/aldeia" + $ref: "#/components/schemas/site_points" } } } @@ -310,25 +335,29 @@ export class AldeiaController { try { const schema = Joi.object().keys({ id: Joi.string().uuid().required().label('ID'), - code: Joi.string().max(128).required().label('Code'), - name: Joi.string().max(256).required().label('Name'), - status: Joi.string().required().label('Status'), - suco_id: Joi.string().uuid().required().label('Suco'), + cell: Joi.string().allow('').label('Cell'), + sector: Joi.string().allow('').label('Sector'), + site: Joi.string().allow('').label('Site'), + lat: Joi.number().allow(null).label('Latitude'), + lng: Joi.number().allow(null).label('Longitude'), + location: Joi.string().allow('').label('Location'), }); req.body.id = req.params['id']; const param: any = await schema.validateAsync(req.body); - const repo = OrmHelper.DB.getRepository(Aldeia); + const repo = OrmHelper.DB.getRepository(SitePoints); const data = await repo.findOneBy({ id: param.id }); if (data != null) { - data.code = param.code - data.name = param.name - data.status = param.status - data.suco = await OrmHelper.DB.getRepository(Suco).findOneByOrFail({ id: param.suco_id }); + data.cell = param.cell + data.sector = param.sector + data.site = param.site + data.lat = param.lat + data.lng = param.lng + data.location = param.location await repo.save(data); @@ -346,13 +375,13 @@ export class AldeiaController { static async delete(req: Request, res: Response, next: NextFunction): Promise { /* - #swagger.tags = ['Aldeia'] + #swagger.tags = ['Site Points'] #swagger.security = [{ "bearerAuth": [] }] #swagger.parameters['id'] = { in: 'path', - description: 'Aldeia ID.', + description: 'Site Points ID.', required: true, type: 'string' } @@ -371,9 +400,9 @@ export class AldeiaController { const param: { id: string, hard: boolean } = await schema.validateAsync(req.params); - const repo = OrmHelper.DB.getRepository(Aldeia); + const repo = OrmHelper.DB.getRepository(SitePoints); - const affected = (!param.hard ? await repo.softDelete({ id: param.id }) : await repo.delete({ id: param.id })).affected; + let affected = (!param.hard ? await repo.softDelete({ id: param.id }) : await repo.delete({ id: param.id })).affected || 0; if (affected > 0) { return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); @@ -390,14 +419,14 @@ export class AldeiaController { static async restore(req: Request, res: Response, next: NextFunction): Promise { /* - #swagger.tags = ['Aldeia'] + #swagger.tags = ['Site Points'] #swagger.security = [{ "bearerAuth": [] }] #swagger.parameters['id'] = { in: 'path', - description: 'Aldeia ID.', + description: 'Site Points ID.', required: true, type: 'string' } @@ -407,11 +436,11 @@ export class AldeiaController { id: Joi.string().uuid().required().label('ID') }); - const param: Aldeia = await schema.validateAsync(req.params); + const param: SitePoints = await schema.validateAsync(req.params); - const repo = OrmHelper.DB.getRepository(Aldeia); + const repo = OrmHelper.DB.getRepository(SitePoints); - const affected = (await repo.restore({ id: param.id })).affected; + let affected = (await repo.restore({ id: param.id })).affected || 0; if (affected > 0) { return ReturnHelper.successResponseAny(res, 200, Language.lang.success_restore, {}); diff --git a/src/controllers/suco.ts b/src/controllers/suco.ts deleted file mode 100644 index ef934f1..0000000 --- a/src/controllers/suco.ts +++ /dev/null @@ -1,428 +0,0 @@ -import { Response, NextFunction, Application } from "express"; -import { Request } from "express-jwt"; -import { ReturnHelper } from "../helpers/express/return"; -import { OrmHelper } from "../helpers/orm"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import { Language } from "../langs/lang"; -import { Paging } from "entity"; -import CommonHelper from "../helpers/common"; -import * as fastcsv from 'fast-csv'; -import dayjs from "dayjs"; -import { Suco, Administrativu } from "entity"; - -const log: Logger = new Logger({ name: '[SucoController]', type: 'pretty' }); - -export class SucoController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Suco'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['filter'] = { - description: 'Filter with 2 format :
  • Simple format use text plaint will filter eq:code or like %name%
  • Advance format using field existing {status:\'Y\', any:\'SAME AS PLAINT LOGIC\', etc...}
', - in: 'query', - type: 'string' - } - #swagger.parameters['limit'] = { - in: 'query', - required: true, - type: 'number' - } - #swagger.parameters['page'] = { - in: 'query', - required: true, - type: 'number' - } - #swagger.parameters['with_deleted'] = { - in: 'query', - required: true, - type: 'boolean' - } - #swagger.parameters['order_field'] = { - in: 'query', - required: true, - type: 'string' - } - #swagger.parameters['order_direction'] = { - in: 'query', - required: true, - schema: { - '@enum': ['ASC', 'DESC'] - } - } - */ - - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow('').optional().label('Filter'), - page: Joi.number().required().min(1).label('Page'), - limit: Joi.number().required().min(1).label('Limit'), - with_deleted: Joi.bool().required().label('With Deleted'), - order_field: Joi.string().required().label('Order Field'), - order_direction: Joi.string().allow('asc', 'desc').required().label('Order Direction'), - }); - - const param: Paging = await schema.validateAsync(req.query); - - const repo = OrmHelper.DB.getRepository(Suco); - - const offset = (param.page - 1) * param.limit - - const filterObj = param.filter ? JSON.parse(param.filter) : {}; - // Remove foreign key from filter for CommonHelper.handleFilter - const filterWithoutFK = { ...filterObj }; - delete filterWithoutFK.administrativu_id; - const filterStrWithoutFK = JSON.stringify(filterWithoutFK); - - const { whereAttr, whereVal } = CommonHelper.handleFilter({ - filter: filterStrWithoutFK, - col_any_eq: ['code'], - col_any_like: ['name'] - }); - - const res_count = repo.createQueryBuilder("Suco") - .leftJoin("Suco.administrativu", "administrativu") - .where(whereAttr || "1=1", whereVal); - - // Handle foreign key filter with relation - if (filterObj.administrativu_id) { - res_count.andWhere("administrativu.id = :administrativuId", { administrativuId: filterObj.administrativu_id }); - } - - const res_list = repo.createQueryBuilder("Suco") - .leftJoin("Suco.administrativu", "administrativu") - .where(whereAttr || "1=1", whereVal) - .orderBy("Suco." + param.order_field, param.order_direction) - .offset(offset) - .limit(param.limit); - - // Handle foreign key filter with relation - if (filterObj.administrativu_id) { - res_list.andWhere("administrativu.id = :administrativuId", { administrativuId: filterObj.administrativu_id }); - } - - if (param.with_deleted) { - res_count.withDeleted(); - res_list.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async export(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Suco'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['filter'] = { - description: 'Filter with 2 format :
  • Simple format use text plaint will filter eq:code or like %name%
  • Advance format using field existing {status:\'Y\', any:\'SAME AS PLAINT LOGIC\', etc...}
', - in: 'query', - type: 'string' - } - #swagger.parameters['filter'] = { - in: 'query', - type: 'string' - } - #swagger.parameters['order_field'] = { - in: 'query', - required: true, - type: 'string' - } - #swagger.parameters['order_direction'] = { - in: 'query', - required: true, - schema: { - '@enum': ['ASC', 'DESC'] - } - } - */ - - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow('').optional().label('Filter'), - order_field: Joi.string().required().label('Order Field'), - order_direction: Joi.string().allow('asc', 'desc').required().label('Order Direction'), - }); - - const param: Paging = await schema.validateAsync(req.query); - - const repo = OrmHelper.DB.getRepository(Suco); - - const filterObj = param.filter ? JSON.parse(param.filter) : {}; - // Remove foreign key from filter for CommonHelper.handleFilter - const filterWithoutFK = { ...filterObj }; - delete filterWithoutFK.administrativu_id; - const filterStrWithoutFK = JSON.stringify(filterWithoutFK); - - const { whereAttr, whereVal } = CommonHelper.handleFilter({ - filter: filterStrWithoutFK, - col_any_eq: ['code'], - col_any_like: ['name'] - }); - - const filename = "suco.csv"; - - res.setHeader('Content-Type', 'text/csv'); - res.setHeader('Content-Disposition', 'attachment; filename=' + filename); - - const csvStream = fastcsv.format({ - headers: true, - writeHeaders: true, - transform: (row: Suco): any => ({ - ...row, - created_at: dayjs(row.created_at).format('DD-MM-YYYY HH:MM:ss'), - }) - }); - csvStream.pipe(res); - - const limit = 50; - - const fetchAndWrite = async (page: any) => { - const offset = (page - 1) * limit - - let query = repo.createQueryBuilder("Suco") - .leftJoin("Suco.administrativu", "administrativu") - .where(whereAttr || "1=1", whereVal); - - // Handle foreign key filter with relation - if (filterObj.administrativu_id) { - query = query.andWhere("administrativu.id = :administrativuId", { administrativuId: filterObj.administrativu_id }); - } - - const data = await query - .select([ - 'Suco.id', - 'Suco.code', - 'Suco.name', - 'Suco.status', - 'Suco.created_at']) - .orderBy("Suco." + param.order_field, param.order_direction) - .offset(offset) - .limit(limit).getRawMany(); - - if (CommonHelper.countObject(data) === 0) { - csvStream.end(); - } else { - data.forEach((item: any) => csvStream.write(item)); - - if (CommonHelper.countObject(data) == limit) { - fetchAndWrite(page + 1); - } else { - csvStream.end(); - } - } - }; - - fetchAndWrite(1); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Suco'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/suco" - } - } - } - } - */ - - try { - const schema = Joi.object().keys({ - code: Joi.string().max(128).required().label('Code'), - name: Joi.string().max(256).required().label('Name'), - status: Joi.string().required().label('Status'), - administrativu_id: Joi.string().uuid().required().label('Administrativu'), - }); - - const param: any = await schema.validateAsync(req.body); - - const data = new Suco() - data.code = param.code - data.name = param.name - data.status = param.status - data.administrativu = await OrmHelper.DB.getRepository(Administrativu).findOneByOrFail({ id: param.administrativu_id }); - - await OrmHelper.DB.manager.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 401, Language.lang.failed_insert, err.message); - } - } - - static async update(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Suco'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'Suco ID.', - required: true, - type: 'string' - } - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/suco" - } - } - } - } - */ - - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID'), - code: Joi.string().max(128).required().label('Code'), - name: Joi.string().max(256).required().label('Name'), - status: Joi.string().required().label('Status'), - administrativu_id: Joi.string().uuid().required().label('Administrativu'), - }); - - req.body.id = req.params['id']; - - const param: any = await schema.validateAsync(req.body); - - const repo = OrmHelper.DB.getRepository(Suco); - - const data = await repo.findOneBy({ id: param.id }); - - if (data != null) { - data.code = param.code - data.name = param.name - data.status = param.status - data.administrativu = await OrmHelper.DB.getRepository(Administrativu).findOneByOrFail({ id: param.administrativu_id }); - - await repo.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_update, data); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_update, err.message); - } - } - - static async delete(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Suco'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'Suco ID.', - required: true, - type: 'string' - } - #swagger.parameters['hard'] = { - in: 'path', - description: 'Is Hard Delete', - required: false, - type: 'boolean' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID'), - hard: Joi.bool().optional().allow('').label('Is hard delete?') - }); - - const param: { id: string, hard: boolean } = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(Suco); - - const affected = (!param.hard ? await repo.softDelete({ id: param.id }) : await repo.delete({ id: param.id })).affected; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_delete, err.message); - } - } - - static async restore(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Suco'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.parameters['id'] = { - in: 'path', - description: 'Suco ID.', - required: true, - type: 'string' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label('ID') - }); - - const param: Suco = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(Suco); - - const affected = (await repo.restore({ id: param.id })).affected; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_restore, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_restore, err.message); - } - } -} \ No newline at end of file diff --git a/src/controllers/surgery_room.ts b/src/controllers/surgery_room.ts deleted file mode 100644 index b8f12bf..0000000 --- a/src/controllers/surgery_room.ts +++ /dev/null @@ -1,290 +0,0 @@ -import { Paging, Room, SurgeryRoom } from "entity"; -import { NextFunction, Response } from "express"; -import { Request } from "express-jwt"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import CommonHelper from "../helpers/common"; -import { ReturnHelper } from "../helpers/express/return"; -import { OrmHelper } from "../helpers/orm"; -import { Language } from "../langs/lang"; -import { RoomModel } from "../model/room"; -import { SurgeryRoomModel } from "../model/surgery_room"; - -const log: Logger = new Logger({ - name: "[SurgeryRoomController]", - type: "pretty", -}); - -export class SurgeryRoomController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Surgery Room'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['filter'] = { - description:'', - in: 'query', - type: 'string' - } - #swagger.parameters['limit'] = { - in: 'query', - required: true, - type: 'number' - } - #swagger.parameters['page'] = { - in: 'query', - required: true, - type: 'number' - } - #swagger.parameters['with_deleted'] = { - in: 'query', - required: true, - type: 'boolean' - } - #swagger.parameters['order_field'] = { - in: 'query', - required: true, - type: 'string' - } - #swagger.parameters['order_direction'] = { - in: 'query', - required: true, - schema: { - '@enum': ['ASC', 'DESC'] - } - } - */ - - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().required().label("With Deleted"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").required().label("Order Direction"), - }); - - const param: Paging = await schema.validateAsync(req.query); - const offset = (param.page - 1) * param.limit; - const filter = JSON.parse(param.filter); - const query = await SurgeryRoomModel.list(filter); - const limit = param.limit; - - const res_count = query; - const res_list = query - .leftJoinAndSelect("SurgeryRoom.room", "room") - .leftJoinAndSelect("room.serviceclass", "service_class") - .orderBy("SurgeryRoom." + param.order_field, param.order_direction) - .offset(offset) - .limit(limit); - - if (param.with_deleted) { - res_count.withDeleted(); - res_list.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Surgery Room'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/surgery_room" - } - } - } - } - */ - - try { - const schema = Joi.object().keys({ - room_id: Joi.string().uuid().required().label("Room ID"), - name: Joi.string().required().label("Name"), - }); - - const param = await schema.validateAsync(req.body); - - let room: Room = await RoomModel.list({ id: param.room_id }).then((q) => q.getOne()); - if (!room) throw { message: "Room " + Language.lang.failed_not_found }; - - const data = new SurgeryRoom(); - data.room = room; - data.name = param.name; - data.created_by = req.auth?.data.name; - - await OrmHelper.DB.manager.save(data); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_insert, err.message); - } - } - - static async detail(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Surgery Room'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'Surgery Room ID.', - required: true, - type: 'string' - } - */ - - try { - const schema = Joi.object().keys({ - id: Joi.string().required().label("ID"), - }); - - let param: any = await schema.validateAsync(req.params); - - let data = await SurgeryRoomModel.list({ "SurgeryRoom.id": param.id }).then((q) => - q // - .leftJoinAndSelect("SurgeryRoom.room", "room") - .getOne(), - ); - - if (!data) throw { message: "Surgery Room " + Language.lang.failed_not_found }; - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_view, data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_view, err.message); - } - } - - static async update(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Surgery Room'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - description:'', - in: 'path', - type: 'string' - } - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/surgery_room" - } - } - } - } - */ - - const queryRunner = OrmHelper.DB.createQueryRunner(); - await queryRunner.startTransaction(); - - try { - req.body.id = req.params["id"]; - - const schema = Joi.object().keys({ - id: Joi.string().required().label("Surgery Room ID"), - room_id: Joi.string().uuid().required().label("Room ID"), - name: Joi.string().required().label("Name"), - }); - - let param: any = await schema.validateAsync(req.body); - - let surgeryRoom: SurgeryRoom = await SurgeryRoomModel.list({ id: param.id }).then((q) => q.getOne()); - if (!surgeryRoom) throw { message: "Surgery Room " + Language.lang.failed_not_found }; - - let room: Room = await RoomModel.list({ id: param.room_id }).then((q) => q.getOne()); - if (!room) throw { message: "Room " + Language.lang.failed_not_found }; - - surgeryRoom.room = room; - surgeryRoom.name = param.name; - surgeryRoom.updated_by = req.auth?.data.name; - - await queryRunner.manager.save(surgeryRoom); - - await queryRunner.commitTransaction(); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_update, surgeryRoom); - } catch (e: unknown) { - await queryRunner.rollbackTransaction(); - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } finally { - await queryRunner.release(); - } - } - - static async delete(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Surgery Room'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['id'] = { - in: 'path', - description: 'Surgery Room ID.', - required: true, - type: 'string' - } - #swagger.parameters['hard'] = { - in: 'path', - description: 'Is Hard Delete', - required: false, - type: 'boolean' - } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("ID"), - hard: Joi.bool().optional().allow("").label("Is hard delete?"), - }); - - const param: { id: string; hard: boolean } = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(SurgeryRoom); - - const affected = (!param.hard ? await repo.softDelete({ id: param.id }) : await repo.delete({ id: param.id })).affected ?? 0; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_delete, err.message); - } - } -} diff --git a/src/controllers/surgery_type.ts b/src/controllers/surgery_type.ts deleted file mode 100644 index 20a59d2..0000000 --- a/src/controllers/surgery_type.ts +++ /dev/null @@ -1,197 +0,0 @@ -import { SurgeryType, Paging } from "entity"; -import { NextFunction, Response } from "express"; -import { Request } from "express-jwt"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import CommonHelper from "../helpers/common"; -import { ReturnHelper } from "../helpers/express/return"; -import { OrmHelper } from "../helpers/orm"; -import { Language } from "../langs/lang"; -import { SurgeryTypeModel } from "../model/surgery_type"; - -const log: Logger = new Logger({ - name: "[SurgeryTypeController]", - type: "pretty", -}); - -export class SurgeryTypeController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Surgery Type'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['filter'] = { description: '', in: 'query', type: 'string' } - #swagger.parameters['limit'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['page'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['with_deleted'] = { in: 'query', required: true, type: 'boolean' } - #swagger.parameters['order_field'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['order_direction'] = { in: 'query', required: true, schema: { '@enum': ['ASC', 'DESC'] } } - */ - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().required().label("With Deleted"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").required().label("Order Direction"), - }); - - let param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - let filterAny = filter.any && filter.any !== "" ? filter.any : ""; - - let filterObj = { ...filter } as any; - delete filterObj.any; - filterObj = { ...filterObj }; - - var query = await SurgeryTypeModel.list(filterObj, filterAny); - - const offset = (param.page - 1) * param.limit; - let limit = param.limit; - - const res_count = query; - const res_list = query - .orderBy("SurgeryType." + param.order_field, param.order_direction) - .offset(offset) - .limit(limit); - - if (param.with_deleted) { - res_count.withDeleted(); - res_list.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist(res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Surgery Type'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.requestBody = { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/surgery_type" } } } } - */ - try { - const schema = Joi.object().keys({ - name: Joi.string().required().label("Name"), - }); - - let param: { name: string } = await schema.validateAsync(req.body); - - let exist = await SurgeryTypeModel.list({ name: param.name }).then((q) => q.getOne()); - if (exist) throw { message: "Surgery Type " + Language.lang.failed_duplicate }; - - let surgeryType = new SurgeryType(); - surgeryType.name = param.name; - surgeryType.created_by = req.auth?.data.name; - surgeryType.updated_by = req.auth?.data.name; - await OrmHelper.DB.manager.save(surgeryType); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, surgeryType); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_insert, err.message); - } - } - - static async detail(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Surgery Type'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { description: '', in: 'path', type: 'string' } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("Surgery Type Id"), - }); - - let param: { id: string } = await schema.validateAsync(req.params); - - let surgeryType = await SurgeryTypeModel.list({ "SurgeryType.id": param.id }).then((q) => q.getOne()); - - if (!surgeryType) throw { message: "Surgery Type " + Language.lang.failed_not_found }; - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_view, surgeryType); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_view, err.message); - } - } - - static async update(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Surgery Type'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { description: '', in: 'path', type: 'string' } - #swagger.requestBody = { required: true, content: { "application/json": { schema: { $ref: "#/components/schemas/surgery_type" } } } } - */ - try { - req.body.id = req.params["id"]; - - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("Surgery Type ID"), - name: Joi.string().required().label("Name"), - }); - - let param: { id: string; name: string } = await schema.validateAsync(req.body); - - let exist = await SurgeryTypeModel.list({ name: param.name }).then((q) => q.getOne()); - if (exist && exist.id != param.id) throw { message: "Surgery Type " + Language.lang.failed_duplicate }; - - let surgeryType = await SurgeryTypeModel.list({ "SurgeryType.id": param.id }).then((q) => q.getOne()); - - if (!surgeryType) throw { message: "Surgery Type " + Language.lang.failed_not_found }; - - surgeryType.name = param.name; - surgeryType.updated_by = req.auth?.data.name; - await OrmHelper.DB.manager.save(surgeryType); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_update, surgeryType); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async delete(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['Surgery Type'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { in: 'path', required: true, type: 'string' } - #swagger.parameters['hard'] = { in: 'path', description: 'Is Hard Delete (ignored; entity has no soft delete)', required: false, type: 'boolean' } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("ID"), - hard: Joi.bool().optional().allow("").label("Is hard delete?"), - }); - - const param: { id: string; hard: boolean } = await schema.validateAsync(req.params); - - const repo = OrmHelper.DB.getRepository(SurgeryType); - const affected = (await repo.delete({ id: param.id })).affected ?? 0; - - if (affected > 0) { - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_delete, {}); - } else { - return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_delete, err.message); - } - } -} diff --git a/src/controllers/user_to_room.ts b/src/controllers/user_to_room.ts deleted file mode 100644 index c3620f8..0000000 --- a/src/controllers/user_to_room.ts +++ /dev/null @@ -1,573 +0,0 @@ -import { Response, NextFunction, Application } from "express"; -import { Request } from "express-jwt"; -import { ReturnHelper } from "../helpers/express/return"; -import { OrmHelper } from "../helpers/orm"; -import Joi from "joi"; -import { ILogObj, Logger } from "tslog"; -import { Language } from "../langs/lang"; -import { UserToRoom, Paging, User, Room } from "entity"; -import CommonHelper from "../helpers/common"; -import * as fastcsv from 'fast-csv'; -import dayjs from "dayjs"; -import { UserToRoomModel } from "../model/user_to_room"; -import { RoomModel } from "../model/room"; - -const log: Logger = new Logger({ name: '[UserToRoomController]', type: 'pretty' }); - -export class UserToRoomController { - static async list(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['UserToRoom'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['filter'] = { - description: "Filter in JSON format. Available fields: user_id (string, uuid, exact match), name (string, partial match case-insensitive), status (string, exact match). Example: {\"user_id\":\"uuid-here\",\"name\":\"john\",\"status\":\"active\"}", - in: 'query', - type: 'string' - } - #swagger.parameters['limit'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['page'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['with_deleted'] = { in: 'query', required: true, type: 'boolean' } - #swagger.parameters['order_field'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['order_direction'] = { in: 'query', required: true, schema: { '@enum': ['ASC', 'DESC'] } } - */ - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().required().label("With Deleted"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").required().label("Order Direction"), - }); - - let param: Paging = await schema.validateAsync(req.query); - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - const offset = (param.page - 1) * param.limit; - const limit = param.limit; - - // Base filter builder (reusable untuk step 1 & count) - const applyFilters = (qb: any) => { - if (param.with_deleted) qb.withDeleted(); - const userIdFilter = filter["user.id"] ?? filter.user_id ?? filter.doctor_id ?? filter.id; - if (userIdFilter !== undefined && userIdFilter !== "") { - qb.andWhere("user.id = :userId", { userId: userIdFilter }); - } - - const userNameFilter = filter["user.name"] ?? filter.name; - if (userNameFilter !== undefined && userNameFilter !== "") { - const userNameVal = String(userNameFilter); - qb.andWhere("user.name ILIKE :name", { name: userNameVal.includes("%") ? userNameVal : `%${userNameVal}%` }); - } - - const userStatusFilter = filter["user.status"] ?? filter.status; - if (userStatusFilter !== undefined && userStatusFilter !== "") qb.andWhere("user.status = :status", { status: userStatusFilter }); - return qb; - }; - - // Step 1: Ambil paginated user IDs dulu (tanpa join room) - const idQuery = OrmHelper.DB.getRepository(User) - .createQueryBuilder("user") - .select("user.id") - .orderBy("user." + param.order_field, param.order_direction as "ASC" | "DESC") - .offset(offset) - .limit(limit); - - applyFilters(idQuery); - - const paginatedUserIds = await idQuery.getRawMany(); - const userIds = paginatedUserIds.map((row) => row.user_id); - - if (userIds.length === 0) { - return ReturnHelper.successResponselist( - res, - 200, - Language.lang.success_view, - 0, - param.page, - 0, - [] - ); - } - - // Step 2: Count total (tanpa join room, tanpa offset/limit) - const countQuery = OrmHelper.DB.getRepository(User) - .createQueryBuilder("user") - .select("user.id"); - - applyFilters(countQuery); - - const total_count_data = await countQuery.getCount(); - - // Step 3: Fetch data lengkap hanya untuk IDs yang sudah dipaginasi - const userQuery = OrmHelper.DB.getRepository(User) - .createQueryBuilder("user") - .leftJoinAndSelect("user.roles", "roles") - .leftJoinAndMapMany( - "user.userToRooms", - UserToRoom, - "user_to_room", - "user_to_room.user = user.id" - ) - .leftJoinAndMapOne( - "user_to_room.roomData", - Room, - "room", - "room.id = user_to_room.room" - ) - .whereInIds(userIds) - .orderBy("user." + param.order_field, param.order_direction as "ASC" | "DESC"); - - if (param.with_deleted) userQuery.withDeleted(); - - const users = await userQuery.getMany(); - - // Transform data - const list_data_return = users.map((user: any) => { - const userToRooms: any[] = user.userToRooms ?? []; - - const rooms: Record = {}; - userToRooms.forEach((utr: any, index: number) => { - const room = utr.roomData ?? null; - rooms[`room_${index + 1}`] = room ? { - id: room.id, - room: room.room, - code: room.code, - } : null; - }); - - return { - id: user.id, - name: user.name, - username: user.username, - email: user.email, - status: user.status, - roles: user.roles ? user.roles.map((role: any) => ({ - id: role.id, - name: role.name, - })) : [], - rooms: Object.keys(rooms).length > 0 ? rooms : null, - }; - }); - - const count_data = CommonHelper.countObject(list_data_return); - - return ReturnHelper.successResponselist( - res, - 200, - Language.lang.success_view, - count_data, - param.page, - total_count_data, - list_data_return - ); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async export(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['UserToRoom'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['filter'] = { - description: 'Filter with 2 format :
  • Simple format use text plaint will filter eq:code or like %name%
  • Advance format using field existing {status:\'Y\', any:\'SAME AS PLAINT LOGIC\', etc...}
', - in: 'query', - type: 'string' - } - #swagger.parameters['filter'] = { - in: 'query', - type: 'string' - } - #swagger.parameters['order_field'] = { - in: 'query', - required: true, - type: 'string' - } - #swagger.parameters['order_direction'] = { - in: 'query', - required: true, - schema: { - '@enum': ['ASC', 'DESC'] - } - } - */ - - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow('').optional().label('Filter'), - order_field: Joi.string().required().label('Order Field'), - order_direction: Joi.string().allow('asc', 'desc').required().label('Order Direction'), - }); - - const param: Paging = await schema.validateAsync(req.query); - - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - var query = await UserToRoomModel.list(filter); - const data = await query.getMany(); - - const filename = "user_to_room.csv"; - - res.setHeader('Content-Type', 'text/csv'); - res.setHeader('Content-Disposition', 'attachment; filename=' + filename); - - const csvStream = fastcsv.format({ - headers: true, - writeHeaders: true, - transform: (row: UserToRoom): any => ({ - ...row, - created_at: dayjs(row.created_at).format('DD-MM-YYYY HH:MM:ss'), - }) - }); - csvStream.pipe(res); - - const limit = 50; - - const fetchAndWrite = async (page: any) => { - - if (CommonHelper.countObject(data) === 0) { - csvStream.end(); - } else { - data.forEach((item: any) => csvStream.write(item)); - - if (CommonHelper.countObject(data) == limit) { - fetchAndWrite(page + 1); - } else { - csvStream.end(); - } - } - }; - - fetchAndWrite(1); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_view, err.message); - } - } - - static async create(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['UserToRoom'] - #swagger.security = [{ - "bearerAuth": [] - }] - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/user_to_room" - } - } - } - } - */ - try { - const schema = Joi.object().keys({ - user_id: Joi.string() - .uuid() - .required() - .label("User ID"), - - room_id: Joi.string() - .uuid() - .required() - .label("Room ID"), - - // room_ids: Joi.array() - // .items(Joi.string().uuid().required()) - // .min(1) - // .required() - // .label("Factory IDs") - }); - - const param: any = await schema.validateAsync(req.body); - - // const userToRoomRepo = OrmHelper.DB.getRepository(UserToRoom); - // const userRepo = OrmHelper.DB.getRepository(User); - // const roomRepo = OrmHelper.DB.getRepository(Room); - - // await userToRoomRepo - // .createQueryBuilder() - // .delete() - // .from(UserToRoom) - // .where("service_id = :userId", { userId: param.user_id }) - // .execute(); - - const data = new UserToRoom() - data.user = param.user_id; - data.room = param.room_id; - data.created_by = req.auth?.data.name; - - await OrmHelper.DB.manager.save(data); - - // let relation : UserToRoom; - // for (const roomId of param.room_ids) { - // relation = new UserToRoom(); - // relation.user = await userRepo.findOneBy({ id: param.user_id }); - // relation.room = await roomRepo.findOneBy({ id: roomId }); - // relation.created_by = req.auth.data.name; - - // await userToRoomRepo.save(relation); - // } - - // const data = await userToRoomRepo.createQueryBuilder("user_to_room") - // .leftJoinAndSelect("user_to_room.user", "user") - // .leftJoinAndSelect("user_to_room.room", "room") - // .where("user_to_room.service_id = :userId", { userId: param.user_id }).getMany(); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_insert, data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 401, Language.lang.failed_insert, err.message); - } - } - - static async update(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['UserToRoom'] - #swagger.security = [{ - "bearerAuth": [] - }] - #swagger.parameters['user_id'] = { - in: 'path', - description: 'User ID.', - required: true, - type: 'string' - } - - #swagger.requestBody = { - required: true, - content: { - "application/json": { - schema: { - $ref: "#/components/schemas/user_to_room_update" - } - } - } - } - */ - - try { - const schema = Joi.object().keys({ - user_id: Joi.string().uuid().required().label('User ID'), - room_ids: Joi.array() - .items(Joi.string().uuid().required()) - .min(1) - .required() - .label("Factory IDs") - // room_id: Joi.string().uuid().required().label('Room ID'), - }); - - req.body.user_id = req.params['user_id']; - - const param: any = await schema.validateAsync(req.body); - - const userToRoomRepo = OrmHelper.DB.getRepository(UserToRoom); - const userRepo = OrmHelper.DB.getRepository(User); - const roomRepo = OrmHelper.DB.getRepository(Room); - - await userToRoomRepo - .createQueryBuilder() - .delete() - .from(UserToRoom) - .where("user = :userId", { userId: param.user_id }) - .execute(); - - let relation: UserToRoom | any; - for (const roomId of param.room_ids) { - relation = new UserToRoom(); - relation.user = await userRepo.findOneBy({ id: param.user_id }); - relation.room = await roomRepo.findOneBy({ id: roomId }); - relation.created_by = req.auth?.data.name; - - await userToRoomRepo.save(relation); - } - - const data = await userToRoomRepo.createQueryBuilder("user_to_room") - .leftJoinAndSelect("user_to_room.user", "user") - .leftJoinAndSelect("user_to_room.room", "room") - .where("user_to_room.user = :userId", { userId: param.user_id }).getMany(); - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_update, data); - - // const repo = OrmHelper.DB.getRepository(UserToRoom); - - // const data = await repo.findOneBy({ id: param.id }); - - // if (data != null) { - // data.user = param.user_id; - // data.room = param.room_id; - // data.updated_by = req.auth.data.name; - - // await repo.save(data); - - // return ReturnHelper.successResponseAny(res, 200, Language.lang.success_update, data); - // } else { - // return ReturnHelper.errorResponse(res, 404, 401, Language.lang.failed_not_found, ""); - // } - } catch (e: unknown) { - log.error(e); - const err = e as Error; - - return ReturnHelper.errorResponse(res, 500, 402, Language.lang.failed_update, err.message); - } - } - - static async detail(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['UserToRoom'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['id'] = { description: '', in: 'path', type: 'string' } - */ - try { - const schema = Joi.object().keys({ - id: Joi.string().uuid().required().label("UserToRoom Id"), - }); - - let param: any = await schema.validateAsync(req.params); - - let data = await UserToRoomModel.list({ "id": param.id }).then((q) => q.getOne()); - if (!data) throw { message: "UserToRoom Not Found" }; - - return ReturnHelper.successResponseAny(res, 200, Language.lang.success_view, data); - } catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_not_found, err.message); - } - } - - static async listRoom(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['UserToRoom'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['filter'] = { description: 'Filter in JSON format. Available fields: user_id (string, uuid, exact match), name (string, partial match case-insensitive), status (string, exact match). Example: {\"user_id\":\"uuid-here\",\"name\":\"john\",\"status\":\"active\"}', in: 'query', type: 'string' } - #swagger.parameters['limit'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['page'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['with_deleted'] = { in: 'query', required: true, type: 'boolean' } - #swagger.parameters['order_field'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['order_direction'] = { in: 'query', required: true, schema: { '@enum': ['ASC', 'DESC'] } } - */ - try { - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().required().label("With Deleted"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").required().label("Order Direction"), - }); - - let param: Paging = await schema.validateAsync(req.query); - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - const query = await RoomModel.list(filter); - - const offset = (param.page - 1) * param.limit; - const limit = param.limit; - - const res_count = query; - const res_list = query - .leftJoinAndSelect("Room.department", "department") - .orderBy("Room." + param.order_field, param.order_direction as "ASC" | "DESC") - .take(limit) - .skip(offset); - - if (param.with_deleted) { - res_count.withDeleted(); - res_list.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist( - res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data - ); - } - catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_not_found, err.message); - } - } - - static async listRoomByUser(req: Request, res: Response, next: NextFunction): Promise { - /* - #swagger.tags = ['UserToRoom'] - #swagger.security = [{ "bearerAuth": [] }] - #swagger.parameters['user_id'] = { description: 'User ID.', in: 'path', type: 'string' } - #swagger.parameters['filter'] = { description: 'Filter in JSON format. Available fields: user_id (string, uuid, exact match), name (string, partial match case-insensitive), status (string, exact match). Example: {\"user_id\":\"uuid-here\",\"name\":\"john\",\"status\":\"active\"}', in: 'query', type: 'string' } - #swagger.parameters['limit'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['page'] = { in: 'query', required: true, type: 'number' } - #swagger.parameters['with_deleted'] = { in: 'query', required: true, type: 'boolean' } - #swagger.parameters['order_field'] = { in: 'query', required: true, type: 'string' } - #swagger.parameters['order_direction'] = { in: 'query', required: true, schema: { '@enum': ['ASC', 'DESC'] } } - */ - try { - const paramPathSchema = Joi.object().keys({ - user_id: Joi.string().uuid().required().label("User ID"), - }); - - const schema = Joi.object().keys({ - filter: Joi.string().allow("").optional().label("Filter"), - page: Joi.number().required().min(1).label("Page"), - limit: Joi.number().required().min(1).label("Limit"), - with_deleted: Joi.bool().required().label("With Deleted"), - order_field: Joi.string().required().label("Order Field"), - order_direction: Joi.string().allow("asc", "desc").required().label("Order Direction"), - }); - - const paramPath = await paramPathSchema.validateAsync(req.params); - let param: Paging = await schema.validateAsync(req.query); - let filter = param.filter && param.filter !== "" ? JSON.parse(param.filter) : {}; - - const query = await RoomModel.list(filter); - - const offset = (param.page - 1) * param.limit; - const limit = param.limit; - - query.innerJoin(UserToRoom, "user_to_room", "user_to_room.room = Room.id") - .andWhere("user_to_room.user = :userId", { userId: paramPath.user_id }); - - const res_count = query; - const res_list = query - .leftJoinAndSelect("Room.department", "department") - .orderBy("Room." + param.order_field, param.order_direction as "ASC" | "DESC") - .take(limit) - .skip(offset); - - if (param.with_deleted) { - res_count.withDeleted(); - res_list.withDeleted(); - } - - const current_page = param.page; - const total_count_data = await res_count.getCount(); - const list_data = await res_list.getMany(); - const count_data = CommonHelper.countObject(list_data); - - return ReturnHelper.successResponselist( - res, 200, Language.lang.success_view, count_data, current_page, total_count_data, list_data - ); - } - catch (e: unknown) { - log.error(e); - const err = e as Error; - return ReturnHelper.errorResponse(res, 400, 401, Language.lang.failed_not_found, err.message); - } - } -} \ No newline at end of file diff --git a/src/helpers/express/return.ts b/src/helpers/express/return.ts index 3d23d81..473d930 100644 --- a/src/helpers/express/return.ts +++ b/src/helpers/express/return.ts @@ -1,5 +1,5 @@ import { Response } from 'express'; -import { ErrorType, ErrorValidation } from 'entity'; +// import { ErrorType, ErrorValidation } from 'entity'; export class ReturnHelper { static successResponseAny( diff --git a/src/helpers/express/upload.ts b/src/helpers/express/upload.ts deleted file mode 100644 index 1b8820d..0000000 --- a/src/helpers/express/upload.ts +++ /dev/null @@ -1,12 +0,0 @@ -import config from 'config'; -import express from 'express'; -import fileUpload from 'express-fileupload' - -export class UploadHelper { - static setup(app: express.Application) { - app.use(fileUpload({ - limits: { fileSize: 10485760 }, - abortOnLimit: true, - })); - } -} \ No newline at end of file diff --git a/src/helpers/orm.ts b/src/helpers/orm.ts index 75ca71f..58afbfd 100644 --- a/src/helpers/orm.ts +++ b/src/helpers/orm.ts @@ -2,106 +2,11 @@ import config from "config"; import { DataSource } from "typeorm"; import { ILogObj, Logger } from "tslog"; import { - ResponsiblePartyConsent, - Province, - City, - Subdistrict, - Ward, - RefferalHospital, - RegistrationFee, - FareType, - RoomStock, - Administrativu, - Aldeia, - District, - Menu, - Munisipo, - Suco, - Application, - Nationality, - Diagnosis, - DiagnosticProcedure, - Room, - MedicalForm, - ServiceType, - ServiceClass, - Service, - ServiceFare, - ServicePackage, - Department, - DoctorSchedule, - MeasurementUnit, - ReferenceRange, - QueueMonitoring, - QueueMonitoringRooms, - ExaminationDetail, - ExaminationType, - User, - UserRole, - HrmsEmployee, - HrmsDepartment, - HrmsPosition, - HrmsShift, - HospitalInformation, - ItemOrigin, - ItemType, - ItemTypeDetail, - Unit, - ItemCategory, - ItemStatus, - UsageInstructions, - UsageTime, - ItemClass, - ItemClassDetail, - GenericName, - Factory, - Supplier, - FactoryToSupplier, - ItemMaster, - ItemGroup, - PharmacyInfo, - ItemPrice, - SellingPricePercentage, - PatientGroup, - Currency, - InpatientRoom, - SurgeryRoom, - SurgeryType, - PatientGuarantor, - InitialStock, - DoctorItem, - DoctorItemPackage, - UserToRoom, - RoomToPharmacy, - PlanningVerificator, - ScheduleSeries, - ScheduleException, - CardType, - PaymentMethod, - FosterCareHistory, - InpatientRoomBed, - EmrBoardingRoom, - EmrPatient, - EmrRegistration, - EmrDiagnosis, - EmrRegistrationOutpatient, - EmrRegistrationEmergency, - EmrRegistrationEmergencyResponsible, - DischargeStatusEmergency, - EmrInternalConsultation, - Counter, - RoomNumber, - MainDisease, - CardKeySet, - CardPrintQueue, - EmrRegistrationTreatment, - TreatmentPlanSession, - TreatmentPlan, - PatientPastMedicalDocument + SitePoints, } from "entity"; export class OrmHelper { - static DB: DataSource = null; + static DB: DataSource; static setup() { const log: Logger = new Logger({ @@ -118,106 +23,10 @@ export class OrmHelper { username: String(config.get("database.username")), password: String(config.get("database.password")), database: String(config.get("database.database")), - synchronize: true, + synchronize: false, logging: config.get("database.logging"), entities: [ - // - Menu, - Administrativu, - Aldeia, - District, - Munisipo, - Suco, - Application, - Nationality, - Diagnosis, - DiagnosticProcedure, - Room, - MedicalForm, - ServiceType, - ServiceClass, - Service, - ServiceFare, - ServicePackage, - Department, - DoctorSchedule, - MeasurementUnit, - ReferenceRange, - QueueMonitoring, - QueueMonitoringRooms, - ExaminationDetail, - ExaminationType, - User, - UserRole, - HrmsEmployee, - HrmsDepartment, - HrmsPosition, - HospitalInformation, - HrmsShift, - ItemGroup, - ItemOrigin, - ItemType, - ItemTypeDetail, - Unit, - Currency, - InpatientRoom, - InpatientRoomBed, - EmrPatient, - EmrRegistration, - EmrDiagnosis, - EmrRegistrationOutpatient, - EmrRegistrationEmergency, - EmrRegistrationEmergencyResponsible, - DischargeStatusEmergency, - EmrInternalConsultation, - EmrBoardingRoom, - SurgeryRoom, - SurgeryType, - ItemCategory, - ItemStatus, - UsageInstructions, - UsageTime, - ItemClass, - ItemClassDetail, - GenericName, - Factory, - Supplier, - FactoryToSupplier, - ItemMaster, - PharmacyInfo, - ItemPrice, - SellingPricePercentage, - PatientGroup, - PatientGuarantor, - InitialStock, - DoctorItem, - DoctorItemPackage, - UserToRoom, - RoomToPharmacy, - PlanningVerificator, - RoomStock, - ScheduleSeries, - ScheduleException, - FareType, - CardType, - PaymentMethod, - RegistrationFee, - RefferalHospital, - Province, - City, - Subdistrict, - Ward, - ResponsiblePartyConsent, - FosterCareHistory, - Counter, - RoomNumber, - MainDisease, - CardKeySet, - CardPrintQueue, - EmrRegistrationTreatment, - TreatmentPlanSession, - TreatmentPlan, - PatientPastMedicalDocument + SitePoints, ], subscribers: [], migrations: [], @@ -230,3 +39,37 @@ export class OrmHelper { .catch((error: any) => log.error(error)); } } +// for seed datas +// export class OrmHelper { +// static DB: DataSource; + +// static async setup(): Promise { +// const log: Logger = new Logger({ +// name: "[OrmHelper]", +// type: "pretty", +// }); + +// const engine: "mysql" | "postgres" = config.get("database.engine"); + +// OrmHelper.DB = new DataSource({ +// type: engine, +// host: config.get("database.host"), +// port: Number(config.get("database.port")), +// username: String(config.get("database.username")), +// password: String(config.get("database.password")), +// database: String(config.get("database.database")), +// synchronize: true, +// logging: config.get("database.logging"), +// entities: [SitePoints], +// subscribers: [], +// migrations: [], +// }); + +// try { +// await OrmHelper.DB.initialize(); +// } catch (error: any) { +// log.error(error); +// throw error; +// } +// } +// } \ No newline at end of file diff --git a/src/model/card_key_sets.ts b/src/model/card_key_sets.ts deleted file mode 100644 index bfdb204..0000000 --- a/src/model/card_key_sets.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { CardKeySet } from "entity"; -import { SelectQueryBuilder } from "typeorm"; -import CommonHelper from "../helpers/common"; -import { OrmHelper } from "../helpers/orm"; - -export class CardKeySetModel { - static async list(filter = {}): Promise> { - const repo = OrmHelper.DB.getRepository(CardKeySet); - let whereAttr: string[] = []; - let whereVal: any = {}; - if (filter && Object.keys(filter).length > 0) { - whereAttr = [...whereAttr, ...CommonHelper.handleQueryFilter(filter).whereAttr]; - whereVal = { ...whereVal, ...CommonHelper.handleQueryFilter(filter).whereVal }; - } - - var query = repo.createQueryBuilder("CardKeySet"); - if (whereAttr.length != 0) { - query = query.where(whereAttr.join(" and "), whereVal); - } - - return query; - } -} diff --git a/src/model/card_print_queue.ts b/src/model/card_print_queue.ts deleted file mode 100644 index f48c5e2..0000000 --- a/src/model/card_print_queue.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { SelectQueryBuilder } from "typeorm"; -import CommonHelper from "../helpers/common"; -import { OrmHelper } from "../helpers/orm"; -import { CardPrintQueue } from "entity"; - -export class CardPrintQueueModel { - static async list(filterObj = {}, filterAny: string = ""): Promise> { - const repo = OrmHelper.DB.getRepository(CardPrintQueue); - let whereAttr = []; - let whereVal: any = {}; - if (filterObj) { - const filterResult = CommonHelper.handleQueryFilter(filterObj); - whereAttr = [...whereAttr, ...filterResult.whereAttr]; - whereVal = { ...whereVal, ...filterResult.whereVal }; - } - - if (filterAny && filterAny !== "" && filterAny !== null && filterAny !== undefined) { - const filterResult = CommonHelper.handleFilter({ - filter: JSON.stringify({ any: filterAny }), - col_any_eq: [], - col_any_like: ["name", "mrn"], - }); - - if (filterResult.whereAttr && filterResult.whereAttr !== "") { - whereAttr = [...whereAttr, filterResult.whereAttr]; - whereVal = { ...whereVal, ...filterResult.whereVal }; - } - } - - var query = repo.createQueryBuilder("card_print_queue"); - if (whereAttr.length != 0) { - query = query.where(whereAttr.join(" and "), whereVal); - } - - return query; - } -} diff --git a/src/model/card_type.ts b/src/model/card_type.ts deleted file mode 100644 index 3cff273..0000000 --- a/src/model/card_type.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { SelectQueryBuilder } from "typeorm"; -import CommonHelper from "../helpers/common"; -import { OrmHelper } from "../helpers/orm"; -import { CardType } from "entity"; - -export class CardTypeModel { - static async list(filterObj = {}, filterAny: string = ""): Promise> { - const repo = OrmHelper.DB.getRepository(CardType); - let whereAttr = []; - let whereVal: any = {}; - if (filterObj) { - const filterResult = CommonHelper.handleQueryFilter(filterObj); - whereAttr = [...whereAttr, ...filterResult.whereAttr]; - whereVal = { ...whereVal, ...filterResult.whereVal }; - } - - if (filterAny && filterAny !== "" && filterAny !== null && filterAny !== undefined) { - const filterResult = CommonHelper.handleFilter({ - filter: JSON.stringify({ any: filterAny }), - col_any_eq: [], - col_any_like: ["name"], - }); - - if (filterResult.whereAttr && filterResult.whereAttr !== "") { - whereAttr = [...whereAttr, filterResult.whereAttr]; - whereVal = { ...whereVal, ...filterResult.whereVal }; - } - } - - var query = repo.createQueryBuilder("card_type"); - if (whereAttr.length != 0) { - query = query.where(whereAttr.join(" and "), whereVal); - } - - return query; - } -} \ No newline at end of file diff --git a/src/model/currencies.ts b/src/model/currencies.ts deleted file mode 100644 index b16d9b4..0000000 --- a/src/model/currencies.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { Currency } from "entity"; -import { SelectQueryBuilder } from "typeorm"; -import CommonHelper from "../helpers/common"; -import { OrmHelper } from "../helpers/orm"; - -export class CurrencyModel { - static async list(filter = {}): Promise> { - const repo = OrmHelper.DB.getRepository(Currency); - let whereAttr = []; - let whereVal: any = {}; - if (filter) { - whereAttr = [...whereAttr, ...CommonHelper.handleQueryFilter(filter).whereAttr]; - whereVal = { - ...whereVal, - ...CommonHelper.handleQueryFilter(filter).whereVal, - }; - } - - var query = null; - query = repo.createQueryBuilder(); - if (whereAttr.length != 0) { - query = query.where(whereAttr.join(" and "), whereVal); - } - - return query; - } -} diff --git a/src/model/department.ts b/src/model/department.ts deleted file mode 100644 index afd87d7..0000000 --- a/src/model/department.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { Department } from "entity"; -import { SelectQueryBuilder } from "typeorm"; -import CommonHelper from "../helpers/common"; -import { OrmHelper } from "../helpers/orm"; - -export class DepartmentModel { - static async list(filter = {}): Promise> { - const repo = OrmHelper.DB.getRepository(Department); - let whereAttr: string[] = []; - let whereVal: any = {}; - if (filter && Object.keys(filter).length > 0) { - whereAttr = [...whereAttr, ...CommonHelper.handleQueryFilter(filter).whereAttr]; - whereVal = { ...whereVal, ...CommonHelper.handleQueryFilter(filter).whereVal }; - } - - var query = repo.createQueryBuilder("Department"); - if (whereAttr.length != 0) { - query = query.where(whereAttr.join(" and "), whereVal); - } - - return query; - } -} diff --git a/src/model/diagnosis.ts b/src/model/diagnosis.ts deleted file mode 100644 index 6e3139b..0000000 --- a/src/model/diagnosis.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { Diagnosis } from "entity"; -import { SelectQueryBuilder } from "typeorm"; -import CommonHelper from "../helpers/common"; -import { OrmHelper } from "../helpers/orm"; - -export class DiagnosisModel { - static async list(filter = {}): Promise> { - const repo = OrmHelper.DB.getRepository(Diagnosis); - let whereAttr: string[] = []; - let whereVal: any = {}; - if (filter && Object.keys(filter).length > 0) { - whereAttr = [...whereAttr, ...CommonHelper.handleQueryFilter(filter).whereAttr]; - whereVal = { ...whereVal, ...CommonHelper.handleQueryFilter(filter).whereVal }; - } - - var query = repo.createQueryBuilder("Diagnosis"); - if (whereAttr.length != 0) { - query = query.where(whereAttr.join(" and "), whereVal); - } - - return query; - } -} diff --git a/src/model/diagnostic_procedure.ts b/src/model/diagnostic_procedure.ts deleted file mode 100644 index ebb298f..0000000 --- a/src/model/diagnostic_procedure.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { DiagnosticProcedure } from "entity"; -import { SelectQueryBuilder } from "typeorm"; -import CommonHelper from "../helpers/common"; -import { OrmHelper } from "../helpers/orm"; - -export class DiagnosticProcedureModel { - static async list(filter = {}): Promise> { - const repo = OrmHelper.DB.getRepository(DiagnosticProcedure); - let whereAttr = []; - let whereVal: any = {}; - if (filter) { - whereAttr = [...whereAttr, ...CommonHelper.handleQueryFilter(filter).whereAttr]; - whereVal = { ...whereVal, ...CommonHelper.handleQueryFilter(filter).whereVal }; - } - - var query = null; - query = repo.createQueryBuilder("DiagnosticProcedure"); - if (whereAttr.length != 0) { - query = query.where(whereAttr.join(" and "), whereVal); - } - - return query; - } -} diff --git a/src/model/doctor_item.ts b/src/model/doctor_item.ts deleted file mode 100644 index beb6d81..0000000 --- a/src/model/doctor_item.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { DoctorItem } from "entity"; -import { SelectQueryBuilder } from "typeorm"; -import CommonHelper from "../helpers/common"; -import { OrmHelper } from "../helpers/orm"; - -export class DoctorItemModel { - static async list(filter = {}): Promise> { - const repo = OrmHelper.DB.getRepository(DoctorItem); - let whereAttr: string[] = []; - let whereVal: any = {}; - - if (filter && Object.keys(filter).length > 0) { - const filterResult = CommonHelper.handleQueryFilter(filter, "DoctorItem"); - whereAttr = [...whereAttr, ...filterResult.whereAttr]; - whereVal = { ...whereVal, ...filterResult.whereVal }; - } - - let query = repo - .createQueryBuilder("DoctorItem") - - if (whereAttr.length != 0) { - query = query.where(whereAttr.join(" and "), whereVal); - } - - return query; - } -} diff --git a/src/model/doctor_item_package.ts b/src/model/doctor_item_package.ts deleted file mode 100644 index 1a026d3..0000000 --- a/src/model/doctor_item_package.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { DoctorItemPackage } from "entity"; -import { SelectQueryBuilder } from "typeorm"; -import CommonHelper from "../helpers/common"; -import { OrmHelper } from "../helpers/orm"; - -export class DoctorItemPackageModel { - static async list(filter = {}, filterAny: string = ""): Promise> { - const repo = OrmHelper.DB.getRepository(DoctorItemPackage); - let whereAttr: string[] = []; - let whereVal: any = {}; - - if (filter && Object.keys(filter).length > 0) { - const filterResult = CommonHelper.handleQueryFilter(filter, "DoctorItemPackage"); - whereAttr = [...whereAttr, ...filterResult.whereAttr]; - whereVal = { ...whereVal, ...filterResult.whereVal }; - } - if (filterAny && filterAny !== "" && filterAny !== null && filterAny !== undefined) { - const filterResult = CommonHelper.handleFilter({ - filter: JSON.stringify({ any: filterAny.toLowerCase() }), - col_any_eq: [], - col_any_like: ["DoctorItemPackage.name"], - }); - - if (filterResult.whereAttr && filterResult.whereAttr !== "") { - whereAttr = [...whereAttr, filterResult.whereAttr]; - whereVal = { ...whereVal, ...filterResult.whereVal }; - } - } - - let query = repo - .createQueryBuilder("DoctorItemPackage") - if (whereAttr.length != 0) { - query = query.where(whereAttr.join(" and "), whereVal); - } - - return query; - } -} diff --git a/src/model/doctor_schedule.ts b/src/model/doctor_schedule.ts deleted file mode 100644 index 1091f97..0000000 --- a/src/model/doctor_schedule.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { DoctorSchedule } from "entity"; -import { SelectQueryBuilder } from "typeorm"; -import CommonHelper from "../helpers/common"; -import { OrmHelper } from "../helpers/orm"; - -export class DoctorScheduleModel { - static async list(filter = {}): Promise> { - const repo = OrmHelper.DB.getRepository(DoctorSchedule); - let whereAttr: string[] = []; - let whereVal: any = {}; - if (filter && Object.keys(filter).length > 0) { - const filterResult = CommonHelper.handleQueryFilter(filter); - whereAttr = [...whereAttr, ...filterResult.whereAttr]; - whereVal = { ...whereVal, ...filterResult.whereVal }; - } - - var query = repo.createQueryBuilder("DoctorSchedule") - .leftJoinAndSelect("DoctorSchedule.doctor", "Doctor") - .leftJoinAndSelect("DoctorSchedule.room", "Room"); - if (whereAttr.length != 0) { - query = query.where(whereAttr.join(" and "), whereVal); - } - - return query; - } -} diff --git a/src/model/examination_detail.ts b/src/model/examination_detail.ts deleted file mode 100644 index b66d9e6..0000000 --- a/src/model/examination_detail.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { ExaminationDetail } from "entity"; -import { SelectQueryBuilder } from "typeorm"; -import CommonHelper from "../helpers/common"; -import { OrmHelper } from "../helpers/orm"; - -export class ExaminationDetailModel { - static async list(filter = {}): Promise> { - const repo = OrmHelper.DB.getRepository(ExaminationDetail); - let whereAttr: string[] = []; - let whereVal: any = {}; - if (filter && Object.keys(filter).length > 0) { - whereAttr = [...whereAttr, ...CommonHelper.handleQueryFilter(filter).whereAttr]; - whereVal = { ...whereVal, ...CommonHelper.handleQueryFilter(filter).whereVal }; - } - - var query = repo.createQueryBuilder("ExaminationDetail"); - if (whereAttr.length != 0) { - query = query.where(whereAttr.join(" and "), whereVal); - } - - return query; - } -} diff --git a/src/model/examination_type.ts b/src/model/examination_type.ts deleted file mode 100644 index 83f1638..0000000 --- a/src/model/examination_type.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { ExaminationType } from "entity"; -import { SelectQueryBuilder } from "typeorm"; -import CommonHelper from "../helpers/common"; -import { OrmHelper } from "../helpers/orm"; - -export class ExaminationTypeModel { - static async list(filter = {}): Promise> { - const repo = OrmHelper.DB.getRepository(ExaminationType); - let whereAttr: string[] = []; - let whereVal: any = {}; - if (filter && Object.keys(filter).length > 0) { - whereAttr = [...whereAttr, ...CommonHelper.handleQueryFilter(filter).whereAttr]; - whereVal = { ...whereVal, ...CommonHelper.handleQueryFilter(filter).whereVal }; - } - - var query = repo.createQueryBuilder("ExaminationType"); - if (whereAttr.length != 0) { - query = query.where(whereAttr.join(" and "), whereVal); - } - - return query; - } -} diff --git a/src/model/factory.ts b/src/model/factory.ts deleted file mode 100644 index d959fd9..0000000 --- a/src/model/factory.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { Factory } from "entity"; -import { SelectQueryBuilder } from "typeorm"; -import CommonHelper from "../helpers/common"; -import { OrmHelper } from "../helpers/orm"; - -export class FactoryModel { - static async list(filter = {}): Promise> { - const repo = OrmHelper.DB.getRepository(Factory); - let whereAttr: string[] = []; - let whereVal: any = {}; - if (filter && Object.keys(filter).length > 0) { - whereAttr = [...whereAttr, ...CommonHelper.handleQueryFilter(filter, "factory").whereAttr]; - whereVal = { ...whereVal, ...CommonHelper.handleQueryFilter(filter, "factory").whereVal }; - } - - var query = repo.createQueryBuilder("factory"); - if (whereAttr.length != 0) { - query = query.where(whereAttr.join(" and "), whereVal); - } - - return query; - } -} \ No newline at end of file diff --git a/src/model/factory_to_supplier.ts b/src/model/factory_to_supplier.ts deleted file mode 100644 index 410ca70..0000000 --- a/src/model/factory_to_supplier.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { SelectQueryBuilder } from "typeorm"; -import CommonHelper from "../helpers/common"; -import { OrmHelper } from "../helpers/orm"; -import { FactoryToSupplier } from "entity"; - -export class FactoryToSupplierModel { - static async list(filter = {}): Promise> { - const repo = OrmHelper.DB.getRepository(FactoryToSupplier); - let whereAttr: string[] = []; - let whereVal: any = {}; - if (filter && Object.keys(filter).length > 0) { - whereAttr = [...whereAttr, ...CommonHelper.handleQueryFilter(filter, "factory_to_supplier").whereAttr]; - whereVal = { ...whereVal, ...CommonHelper.handleQueryFilter(filter, "factory_to_supplier").whereVal }; - } - - var query = repo.createQueryBuilder("factory_to_supplier") - .leftJoinAndSelect("factory_to_supplier.factory", "factory") - .leftJoinAndSelect("factory_to_supplier.supplier", "supplier") - if (whereAttr.length != 0) { - query = query.where(whereAttr.join(" and "), whereVal); - } - - return query; - } -} \ No newline at end of file diff --git a/src/model/faretype.ts b/src/model/faretype.ts deleted file mode 100644 index dfc3bed..0000000 --- a/src/model/faretype.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { FareType } from "entity"; -import { SelectQueryBuilder } from "typeorm"; -import CommonHelper from "../helpers/common"; -import { OrmHelper } from "../helpers/orm"; - -export class FareTypeModel { - static async list(filter = {}): Promise> { - const repo = OrmHelper.DB.getRepository(FareType); - let whereAttr: string[] = []; - let whereVal: any = {}; - if (filter && Object.keys(filter).length > 0) { - whereAttr = [...whereAttr, ...CommonHelper.handleQueryFilter(filter).whereAttr]; - whereVal = { ...whereVal, ...CommonHelper.handleQueryFilter(filter).whereVal }; - } - - var query = repo.createQueryBuilder("FareType"); - if (whereAttr.length != 0) { - query = query.where(whereAttr.join(" and "), whereVal); - } - - return query; - } -} diff --git a/src/model/fostercarehistory.ts b/src/model/fostercarehistory.ts deleted file mode 100644 index 93b2024..0000000 --- a/src/model/fostercarehistory.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { FosterCareHistory } from "entity"; -import { SelectQueryBuilder } from "typeorm"; -import CommonHelper from "../helpers/common"; -import { OrmHelper } from "../helpers/orm"; - -export class FosterCareHistoryModel { - static async list(filterObj = {}, filterAny: string = ""): Promise> { - const repo = OrmHelper.DB.getRepository(FosterCareHistory); - let whereAttr: string[] = []; - let whereVal: any = {}; - if (filterObj && Object.keys(filterObj).length > 0) { - const filterResult = CommonHelper.handleQueryFilter(filterObj); - whereAttr = [...whereAttr, ...filterResult.whereAttr]; - whereVal = { ...whereVal, ...filterResult.whereVal }; - } - - if (filterAny && filterAny !== "" && filterAny !== null && filterAny !== undefined) { - const filterResult = CommonHelper.handleFilter({ - filter: JSON.stringify({ any: filterAny }), - col_any_eq: [], - col_any_like: ["foster_care_history_code", "foster_care_history_name", "foster_care_history_type"], - }); - - if (filterResult.whereAttr && filterResult.whereAttr !== "") { - whereAttr = [...whereAttr, filterResult.whereAttr]; - whereVal = { ...whereVal, ...filterResult.whereVal }; - } - } - - var query = repo.createQueryBuilder("FosterCareHistory"); - if (whereAttr.length != 0) { - query = query.where(whereAttr.join(" and "), whereVal); - } - - return query; - } -} diff --git a/src/model/generic_name.ts b/src/model/generic_name.ts deleted file mode 100644 index a8becaf..0000000 --- a/src/model/generic_name.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { GenericName } from "entity"; -import { SelectQueryBuilder } from "typeorm"; -import CommonHelper from "../helpers/common"; -import { OrmHelper } from "../helpers/orm"; - -export class GenericNameModel { - static async list(filter = {}): Promise> { - const repo = OrmHelper.DB.getRepository(GenericName); - let whereAttr: string[] = []; - let whereVal: any = {}; - if (filter && Object.keys(filter).length > 0) { - whereAttr = [...whereAttr, ...CommonHelper.handleQueryFilter(filter, "generic_name").whereAttr]; - whereVal = { ...whereVal, ...CommonHelper.handleQueryFilter(filter, "generic_name").whereVal }; - } - - var query = repo.createQueryBuilder("generic_name"); - if (whereAttr.length != 0) { - query = query.where(whereAttr.join(" and "), whereVal); - } - - return query; - } -} \ No newline at end of file diff --git a/src/model/initial_stock.ts b/src/model/initial_stock.ts deleted file mode 100644 index 4ea9cdf..0000000 --- a/src/model/initial_stock.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { InitialStock } from "entity"; -import { SelectQueryBuilder } from "typeorm"; -import CommonHelper from "../helpers/common"; -import { OrmHelper } from "../helpers/orm"; - -export class InitialStockModel { - static async list(filter = {}): Promise> { - const repo = OrmHelper.DB.getRepository(InitialStock); - let whereAttr: string[] = []; - let whereVal: any = {}; - if (filter && Object.keys(filter).length > 0) { - whereAttr = [...whereAttr, ...CommonHelper.handleQueryFilter(filter, "InitialStock").whereAttr]; - whereVal = { ...whereVal, ...CommonHelper.handleQueryFilter(filter, "InitialStock").whereVal }; - } - - var query = repo.createQueryBuilder("InitialStock"); - if (whereAttr.length != 0) { - query = query.where(whereAttr.join(" and "), whereVal); - } - - return query; - } -} \ No newline at end of file diff --git a/src/model/inpatient_room.ts b/src/model/inpatient_room.ts deleted file mode 100644 index 0c7d7fd..0000000 --- a/src/model/inpatient_room.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { InpatientRoom } from "entity"; -import { SelectQueryBuilder } from "typeorm"; -import CommonHelper from "../helpers/common"; -import { OrmHelper } from "../helpers/orm"; - -export class InpatientRoomModel { - static async list(filter = {}): Promise> { - const repo = OrmHelper.DB.getRepository(InpatientRoom); - let whereAttr = []; - let whereVal: any = {}; - if (filter) { - whereAttr = [...whereAttr, ...CommonHelper.handleQueryFilter(filter).whereAttr]; - whereVal = { - ...whereVal, - ...CommonHelper.handleQueryFilter(filter).whereVal, - }; - } - - var query = null; - query = repo.createQueryBuilder(); - if (whereAttr.length != 0) { - query = query.where(whereAttr.join(" and "), whereVal); - } - - return query; - } -} - diff --git a/src/model/item_category.ts b/src/model/item_category.ts deleted file mode 100644 index 26b6e4a..0000000 --- a/src/model/item_category.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { ItemCategory } from "entity"; -import { SelectQueryBuilder } from "typeorm"; -import CommonHelper from "../helpers/common"; -import { OrmHelper } from "../helpers/orm"; - -export class ItemCategoryModel { - static async list(filter = {}): Promise> { - const repo = OrmHelper.DB.getRepository(ItemCategory); - let whereAttr: string[] = []; - let whereVal: any = {}; - if (filter && Object.keys(filter).length > 0) { - whereAttr = [...whereAttr, ...CommonHelper.handleQueryFilter(filter, "item_category").whereAttr]; - whereVal = { ...whereVal, ...CommonHelper.handleQueryFilter(filter, "item_category").whereVal }; - } - - var query = repo.createQueryBuilder("item_category"); - if (whereAttr.length != 0) { - query = query.where(whereAttr.join(" and "), whereVal); - } - - return query; - } -} \ No newline at end of file diff --git a/src/model/item_class.ts b/src/model/item_class.ts deleted file mode 100644 index 10aa00c..0000000 --- a/src/model/item_class.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { ItemClass } from "entity"; -import { SelectQueryBuilder } from "typeorm"; -import CommonHelper from "../helpers/common"; -import { OrmHelper } from "../helpers/orm"; - -export class ItemClassModel { - static async list(filter = {}): Promise> { - const repo = OrmHelper.DB.getRepository(ItemClass); - let whereAttr: string[] = []; - let whereVal: any = {}; - if (filter && Object.keys(filter).length > 0) { - whereAttr = [...whereAttr, ...CommonHelper.handleQueryFilter(filter, "item_class").whereAttr]; - whereVal = { ...whereVal, ...CommonHelper.handleQueryFilter(filter, "item_class").whereVal }; - } - - var query = repo.createQueryBuilder("item_class"); - if (whereAttr.length != 0) { - query = query.where(whereAttr.join(" and "), whereVal); - } - - return query; - } -} \ No newline at end of file diff --git a/src/model/item_class_detail.ts b/src/model/item_class_detail.ts deleted file mode 100644 index a1907d3..0000000 --- a/src/model/item_class_detail.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { ItemClassDetail } from "entity"; -import { SelectQueryBuilder } from "typeorm"; -import CommonHelper from "../helpers/common"; -import { OrmHelper } from "../helpers/orm"; - -export class ItemClassDetailModel { - static async list(filter = {}): Promise> { - const repo = OrmHelper.DB.getRepository(ItemClassDetail); - let whereAttr: string[] = []; - let whereVal: any = {}; - if (filter && Object.keys(filter).length > 0) { - whereAttr = [...whereAttr, ...CommonHelper.handleQueryFilter(filter, "item_class_detail").whereAttr]; - whereVal = { ...whereVal, ...CommonHelper.handleQueryFilter(filter, "item_class_detail").whereVal }; - } - - var query = repo.createQueryBuilder("item_class_detail"); - if (whereAttr.length != 0) { - query = query.where(whereAttr.join(" and "), whereVal); - } - - return query; - } -} \ No newline at end of file diff --git a/src/model/item_group.ts b/src/model/item_group.ts deleted file mode 100644 index 7eb189a..0000000 --- a/src/model/item_group.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { ItemGroup } from "entity"; -import { SelectQueryBuilder } from "typeorm"; -import CommonHelper from "../helpers/common"; -import { OrmHelper } from "../helpers/orm"; - -export class ItemGroupModel { - static async list(filter = {}): Promise> { - const repo = OrmHelper.DB.getRepository(ItemGroup); - let whereAttr: string[] = []; - let whereVal: any = {}; - if (filter && Object.keys(filter).length > 0) { - whereAttr = [...whereAttr, ...CommonHelper.handleQueryFilter(filter, "item_group").whereAttr]; - whereVal = { ...whereVal, ...CommonHelper.handleQueryFilter(filter, "item_group").whereVal }; - } - - var query = repo.createQueryBuilder("item_group"); - if (whereAttr.length != 0) { - query = query.where(whereAttr.join(" and "), whereVal); - } - - return query; - } -} \ No newline at end of file diff --git a/src/model/item_master.ts b/src/model/item_master.ts deleted file mode 100644 index b27d073..0000000 --- a/src/model/item_master.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { SelectQueryBuilder } from "typeorm"; -import CommonHelper from "../helpers/common"; -import { OrmHelper } from "../helpers/orm"; -import { ItemMaster } from "entity"; - -export class ItemMasterModel { - static async list(filter = {}): Promise> { - const repo = OrmHelper.DB.getRepository(ItemMaster); - let whereAttr: string[] = []; - let whereVal: any = {}; - if (filter && Object.keys(filter).length > 0) { - whereAttr = [...whereAttr, ...CommonHelper.handleQueryFilter(filter, "item_master").whereAttr]; - whereVal = { ...whereVal, ...CommonHelper.handleQueryFilter(filter, "item_master").whereVal }; - } - - var query = repo - .createQueryBuilder("item_master") - .leftJoinAndSelect("item_master.generic_name", "generic_name") - .leftJoinAndSelect("item_master.type_detail", "type_detail") - .leftJoinAndSelect("item_master.category", "category") - .leftJoinAndSelect("item_master.item_class", "item_class") - .leftJoinAndSelect("item_master.item_class_detail", "item_class_detail") - .leftJoinAndSelect("item_master.status", "status") - .leftJoinAndSelect("item_master.factory", "factory") - // .leftJoinAndSelect("item_master.unit", "unit") - if (whereAttr.length != 0) { - query = query.where(whereAttr.join(" and "), whereVal); - } - - return query; - } -} \ No newline at end of file diff --git a/src/model/item_origin.ts b/src/model/item_origin.ts deleted file mode 100644 index 3f93eb5..0000000 --- a/src/model/item_origin.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { SelectQueryBuilder } from "typeorm"; -import CommonHelper from "../helpers/common"; -import { OrmHelper } from "../helpers/orm"; -import { ItemOrigin } from "entity"; - -export class ItemOriginModel { - static async list(filter = {}): Promise> { - const repo = OrmHelper.DB.getRepository(ItemOrigin); - let whereAttr: string[] = []; - let whereVal: any = {}; - if (filter && Object.keys(filter).length > 0) { - whereAttr = [...whereAttr, ...CommonHelper.handleQueryFilter(filter, "item_origin").whereAttr]; - whereVal = { ...whereVal, ...CommonHelper.handleQueryFilter(filter, "item_origin").whereVal }; - } - - var query = repo.createQueryBuilder("item_origin"); - if (whereAttr.length != 0) { - query = query.where(whereAttr.join(" and "), whereVal); - } - - return query; - } -} \ No newline at end of file diff --git a/src/model/item_price.ts b/src/model/item_price.ts deleted file mode 100644 index 2e18908..0000000 --- a/src/model/item_price.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { SelectQueryBuilder } from "typeorm"; -import CommonHelper from "../helpers/common"; -import { OrmHelper } from "../helpers/orm"; -import { ItemPrice,ItemMaster } from "entity"; - -export class ItemPriceModel { - static async list(filter = {}): Promise> { - const repo = OrmHelper.DB.getRepository(ItemMaster); - let whereAttr: string[] = []; - let whereVal: any = {}; - if (filter && Object.keys(filter).length > 0) { - whereAttr = [...whereAttr, ...CommonHelper.handleQueryFilter(filter, "item_master").whereAttr]; - whereVal = { ...whereVal, ...CommonHelper.handleQueryFilter(filter, "item_master").whereVal }; - } - - var query = repo.createQueryBuilder("item_master").leftJoinAndSelect("item_master.item_price", "item_price"); - if (whereAttr.length != 0) { - query = query.where(whereAttr.join(" and "), whereVal); - } - - return query; - } -} \ No newline at end of file diff --git a/src/model/item_status.ts b/src/model/item_status.ts deleted file mode 100644 index c5cb9a5..0000000 --- a/src/model/item_status.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { ItemStatus } from "entity"; -import { SelectQueryBuilder } from "typeorm"; -import CommonHelper from "../helpers/common"; -import { OrmHelper } from "../helpers/orm"; - -export class ItemStatusModel { - static async list(filter = {}): Promise> { - const repo = OrmHelper.DB.getRepository(ItemStatus); - let whereAttr: string[] = []; - let whereVal: any = {}; - if (filter && Object.keys(filter).length > 0) { - whereAttr = [...whereAttr, ...CommonHelper.handleQueryFilter(filter, "item_status").whereAttr]; - whereVal = { ...whereVal, ...CommonHelper.handleQueryFilter(filter, "item_status").whereVal }; - } - - var query = repo.createQueryBuilder("item_status"); - if (whereAttr.length != 0) { - query = query.where(whereAttr.join(" and "), whereVal); - } - - return query; - } -} \ No newline at end of file diff --git a/src/model/item_type.ts b/src/model/item_type.ts deleted file mode 100644 index 570af5e..0000000 --- a/src/model/item_type.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { SelectQueryBuilder } from "typeorm"; -import CommonHelper from "../helpers/common"; -import { OrmHelper } from "../helpers/orm"; -import { ItemType } from "entity"; - -export class ItemTypeModel { - static async list(filter = {}): Promise> { - const repo = OrmHelper.DB.getRepository(ItemType); - let whereAttr: string[] = []; - let whereVal: any = {}; - if (filter && Object.keys(filter).length > 0) { - whereAttr = [...whereAttr, ...CommonHelper.handleQueryFilter(filter, "item_type").whereAttr]; - whereVal = { ...whereVal, ...CommonHelper.handleQueryFilter(filter, "item_type").whereVal }; - } - - var query = repo.createQueryBuilder("item_type").leftJoinAndSelect("item_type.item_group", "item_group"); - if (whereAttr.length != 0) { - query = query.where(whereAttr.join(" and "), whereVal); - } - - return query; - } -} \ No newline at end of file diff --git a/src/model/item_type_detail.ts b/src/model/item_type_detail.ts deleted file mode 100644 index b740ba3..0000000 --- a/src/model/item_type_detail.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { SelectQueryBuilder } from "typeorm"; -import CommonHelper from "../helpers/common"; -import { OrmHelper } from "../helpers/orm"; -import { ItemTypeDetail } from "entity"; - -export class ItemTypeDetailModel { - static async list(filter = {}): Promise> { - const repo = OrmHelper.DB.getRepository(ItemTypeDetail); - let whereAttr: string[] = []; - let whereVal: any = {}; - if (filter && Object.keys(filter).length > 0) { - whereAttr = [...whereAttr, ...CommonHelper.handleQueryFilter(filter, "item_type_detail").whereAttr]; - whereVal = { ...whereVal, ...CommonHelper.handleQueryFilter(filter, "item_type_detail").whereVal }; - } - - var query = repo.createQueryBuilder("item_type_detail").leftJoinAndSelect("item_type_detail.item_type", "item_type"); - if (whereAttr.length != 0) { - query = query.where(whereAttr.join(" and "), whereVal); - } - - return query; - } -} \ No newline at end of file diff --git a/src/model/main_disease.ts b/src/model/main_disease.ts deleted file mode 100644 index 12d2241..0000000 --- a/src/model/main_disease.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { MainDisease } from "entity"; -import { SelectQueryBuilder } from "typeorm"; -import CommonHelper from "../helpers/common"; -import { OrmHelper } from "../helpers/orm"; - -export class MainDiseaseModel { - static async list(filter = {}): Promise> { - const repo = OrmHelper.DB.getRepository(MainDisease); - let whereAttr: string[] = []; - let whereVal: any = {}; - if (filter && Object.keys(filter).length > 0) { - whereAttr = [...whereAttr, ...CommonHelper.handleQueryFilter(filter).whereAttr]; - whereVal = { ...whereVal, ...CommonHelper.handleQueryFilter(filter).whereVal }; - } - - var query = repo.createQueryBuilder("MainDisease"); - if (whereAttr.length != 0) { - query = query.where(whereAttr.join(" and "), whereVal); - } - - return query; - } -} diff --git a/src/model/measurement_unit.ts b/src/model/measurement_unit.ts deleted file mode 100644 index f195d90..0000000 --- a/src/model/measurement_unit.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { MeasurementUnit } from "entity"; -import { SelectQueryBuilder } from "typeorm"; -import CommonHelper from "../helpers/common"; -import { OrmHelper } from "../helpers/orm"; - -export class MeasurementUnitModel { - static async list(filter = {}): Promise> { - const repo = OrmHelper.DB.getRepository(MeasurementUnit); - let whereAttr: string[] = []; - let whereVal: any = {}; - if (filter && Object.keys(filter).length > 0) { - whereAttr = [...whereAttr, ...CommonHelper.handleQueryFilter(filter).whereAttr]; - whereVal = { ...whereVal, ...CommonHelper.handleQueryFilter(filter).whereVal }; - } - - var query = repo.createQueryBuilder("MeasurementUnit"); - if (whereAttr.length != 0) { - query = query.where(whereAttr.join(" and "), whereVal); - } - - return query; - } -} diff --git a/src/model/medical_form.ts b/src/model/medical_form.ts deleted file mode 100644 index 2443874..0000000 --- a/src/model/medical_form.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { MedicalForm } from "entity"; -import { SelectQueryBuilder } from "typeorm"; -import CommonHelper from "../helpers/common"; -import { OrmHelper } from "../helpers/orm"; - -export class MedicalFormModel { - static async list(filter = {}): Promise> { - const repo = OrmHelper.DB.getRepository(MedicalForm); - let whereAttr: string[] = []; - let whereVal: any = {}; - if (filter && Object.keys(filter).length > 0) { - whereAttr = [...whereAttr, ...CommonHelper.handleQueryFilter(filter).whereAttr]; - whereVal = { ...whereVal, ...CommonHelper.handleQueryFilter(filter).whereVal }; - } - - var query = repo.createQueryBuilder("MedicalForm"); - if (whereAttr.length != 0) { - query = query.where(whereAttr.join(" and "), whereVal); - } - - return query; - } -} diff --git a/src/model/patient_group.ts b/src/model/patient_group.ts deleted file mode 100644 index 35132bd..0000000 --- a/src/model/patient_group.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { PatientGroup } from "entity"; -import { SelectQueryBuilder } from "typeorm"; -import CommonHelper from "../helpers/common"; -import { OrmHelper } from "../helpers/orm"; - -export class PatientGroupModel { - static async list(filter = {}): Promise> { - const repo = OrmHelper.DB.getRepository(PatientGroup); - let whereAttr: string[] = []; - let whereVal: any = {}; - if (filter && Object.keys(filter).length > 0) { - whereAttr = [...whereAttr, ...CommonHelper.handleQueryFilter(filter, "patient_group").whereAttr]; - whereVal = { ...whereVal, ...CommonHelper.handleQueryFilter(filter, "patient_group").whereVal }; - } - - var query = repo.createQueryBuilder("patient_group"); - if (whereAttr.length != 0) { - query = query.where(whereAttr.join(" and "), whereVal); - } - - return query; - } -} \ No newline at end of file diff --git a/src/model/patient_guarantor.ts b/src/model/patient_guarantor.ts deleted file mode 100644 index 55862d3..0000000 --- a/src/model/patient_guarantor.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { SelectQueryBuilder } from "typeorm"; -import CommonHelper from "../helpers/common"; -import { OrmHelper } from "../helpers/orm"; -import { PatientGuarantor } from "entity"; - -export class PatientGuarantorModel { - static async list(filterObj = {}, filterAny: string = ""): Promise> { - const repo = OrmHelper.DB.getRepository(PatientGuarantor); - let whereAttr = []; - let whereVal: any = {}; - if (filterObj) { - const filterResult = CommonHelper.handleQueryFilter(filterObj); - whereAttr = [...whereAttr, ...filterResult.whereAttr]; - whereVal = { ...whereVal, ...filterResult.whereVal }; - } - - if (filterAny && filterAny !== "" && filterAny !== null && filterAny !== undefined) { - const filterResult = CommonHelper.handleFilter({ - filter: JSON.stringify({ any: filterAny }), - col_any_eq: [], - col_any_like: ["guarantor_name", "phone"], - }); - - if (filterResult.whereAttr && filterResult.whereAttr !== "") { - whereAttr = [...whereAttr, filterResult.whereAttr]; - whereVal = { ...whereVal, ...filterResult.whereVal }; - } - } - - var query = repo.createQueryBuilder("patient_guarantor") - .leftJoinAndSelect("patient_guarantor.patient_group", "patient_group") - .leftJoinAndSelect("patient_guarantor.faretype", "faretype") - .leftJoinAndSelect("patient_guarantor.administrativu", "administrativu") - .leftJoinAndSelect("patient_guarantor.suco", "suco") - .leftJoinAndSelect("patient_guarantor.aldeia", "aldeia") - .leftJoinAndSelect("patient_guarantor.munisipo", "munisipo"); - if (whereAttr.length != 0) { - query = query.where(whereAttr.join(" and "), whereVal); - } - - return query; - } -} \ No newline at end of file diff --git a/src/model/payment_method.ts b/src/model/payment_method.ts deleted file mode 100644 index 2e6840e..0000000 --- a/src/model/payment_method.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { SelectQueryBuilder } from "typeorm"; -import CommonHelper from "../helpers/common"; -import { OrmHelper } from "../helpers/orm"; -import { PaymentMethod } from "entity"; - -export class PaymentMethodModel { - static async list(filterObj = {}, filterAny: string = ""): Promise> { - const repo = OrmHelper.DB.getRepository(PaymentMethod); - let whereAttr = []; - let whereVal: any = {}; - if (filterObj) { - const filterResult = CommonHelper.handleQueryFilter(filterObj); - whereAttr = [...whereAttr, ...filterResult.whereAttr]; - whereVal = { ...whereVal, ...filterResult.whereVal }; - } - - if (filterAny && filterAny !== "" && filterAny !== null && filterAny !== undefined) { - const filterResult = CommonHelper.handleFilter({ - filter: JSON.stringify({ any: filterAny }), - col_any_eq: [], - col_any_like: ["name"], - }); - - if (filterResult.whereAttr && filterResult.whereAttr !== "") { - whereAttr = [...whereAttr, filterResult.whereAttr]; - whereVal = { ...whereVal, ...filterResult.whereVal }; - } - } - - var query = repo.createQueryBuilder("payment_method"); - if (whereAttr.length != 0) { - query = query.where(whereAttr.join(" and "), whereVal); - } - - return query; - } -} \ No newline at end of file diff --git a/src/model/pharmacy_info.ts b/src/model/pharmacy_info.ts deleted file mode 100644 index c4d137a..0000000 --- a/src/model/pharmacy_info.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { SelectQueryBuilder } from "typeorm"; -import CommonHelper from "../helpers/common"; -import { OrmHelper } from "../helpers/orm"; -import { PharmacyInfo } from "entity"; - -export class PharmacyInfoModel { - static async list(filter = {}): Promise> { - const repo = OrmHelper.DB.getRepository(PharmacyInfo); - let whereAttr: string[] = []; - let whereVal: any = {}; - if (filter && Object.keys(filter).length > 0) { - whereAttr = [...whereAttr, ...CommonHelper.handleQueryFilter(filter, "pharmacy_info").whereAttr]; - whereVal = { ...whereVal, ...CommonHelper.handleQueryFilter(filter, "pharmacy_info").whereVal }; - } - - var query = repo.createQueryBuilder("pharmacy_info") - .leftJoinAndSelect("pharmacy_info.default_room", "default_room") - .leftJoinAndSelect("pharmacy_info.munisipiu", "munisipiu") - .leftJoinAndSelect("pharmacy_info.postu_admin", "postu_admin") - .leftJoinAndSelect("pharmacy_info.suco", "suco") - .leftJoinAndSelect("pharmacy_info.aldeia", "aldeia") - // .leftJoinAndSelect("pharmacy_info.province", "province") - // .leftJoinAndSelect("pharmacy_info.city", "city") - // .leftJoinAndSelect("pharmacy_info.subdistrict", "subdistrict") - // .leftJoinAndSelect("pharmacy_info.ward", "ward"); - if (whereAttr.length != 0) { - query = query.where(whereAttr.join(" and "), whereVal); - } - - return query; - } -} \ No newline at end of file diff --git a/src/model/planning_verificator.ts b/src/model/planning_verificator.ts deleted file mode 100644 index da6fbc7..0000000 --- a/src/model/planning_verificator.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { PlanningVerificator } from "entity"; -import { SelectQueryBuilder } from "typeorm"; -import CommonHelper from "../helpers/common"; -import { OrmHelper } from "../helpers/orm"; - -export class PlanningVerificatorModel { - static async list(filter = {}): Promise> { - const repo = OrmHelper.DB.getRepository(PlanningVerificator); - let whereAttr: string[] = []; - let whereVal: any = {}; - if (filter && Object.keys(filter).length > 0) { - whereAttr = [...whereAttr, ...CommonHelper.handleQueryFilter(filter, "planning_verificator").whereAttr]; - whereVal = { ...whereVal, ...CommonHelper.handleQueryFilter(filter, "planning_verificator").whereVal }; - } - - var query = repo.createQueryBuilder("planning_verificator").leftJoinAndSelect("planning_verificator.user", "user"); - if (whereAttr.length != 0) { - query = query.where(whereAttr.join(" and "), whereVal); - } - - return query; - } -} \ No newline at end of file diff --git a/src/model/queue_monitoring.ts b/src/model/queue_monitoring.ts deleted file mode 100644 index 90b23c6..0000000 --- a/src/model/queue_monitoring.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { QueueMonitoring } from "entity"; -import { SelectQueryBuilder } from "typeorm"; -import CommonHelper from "../helpers/common"; -import { OrmHelper } from "../helpers/orm"; - -export class QueueMonitoringModel { - static async list(filter = {}): Promise> { - const repo = OrmHelper.DB.getRepository(QueueMonitoring); - let whereAttr: string[] = []; - let whereVal: any = {}; - if (filter && Object.keys(filter).length > 0) { - whereAttr = [...whereAttr, ...CommonHelper.handleQueryFilter(filter).whereAttr]; - whereVal = { ...whereVal, ...CommonHelper.handleQueryFilter(filter).whereVal }; - } - - var query = repo.createQueryBuilder("QueueMonitoring"); - if (whereAttr.length != 0) { - query = query.where(whereAttr.join(" and "), whereVal); - } - - return query; - } -} diff --git a/src/model/reference_range.ts b/src/model/reference_range.ts deleted file mode 100644 index 0119ae1..0000000 --- a/src/model/reference_range.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { ReferenceRange } from "entity"; -import { SelectQueryBuilder } from "typeorm"; -import { OrmHelper } from "../helpers/orm"; - -export class ReferenceRangeModel { - static async list(filter: Record = {}): Promise> { - const repo = OrmHelper.DB.getRepository(ReferenceRange); - - const query = repo.createQueryBuilder("ReferenceRange"); - - if (filter && Object.keys(filter).length > 0) { - Object.entries(filter).forEach(([key, value]) => { - if (value !== undefined && value !== null && value !== "") { - - // 🔥 Handle kalau ada yang kirim "ReferenceRange.id" - const field = key.includes(".") ? key.split(".")[1] : key; - - query.andWhere(`ReferenceRange.${field} = :${field}`, { - [field]: value, - }); - } - }); - } - - return query; - } -} \ No newline at end of file diff --git a/src/model/refferal_hospital.ts b/src/model/refferal_hospital.ts deleted file mode 100644 index ec40389..0000000 --- a/src/model/refferal_hospital.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { RefferalHospital } from "entity"; -import { SelectQueryBuilder } from "typeorm"; -import CommonHelper from "../helpers/common"; -import { OrmHelper } from "../helpers/orm"; - -export class RefferalHospitalModel { - static async list(filter = {}): Promise> { - const repo = OrmHelper.DB.getRepository(RefferalHospital); - let whereAttr: string[] = []; - let whereVal: any = {}; - if (filter && Object.keys(filter).length > 0) { - whereAttr = [...whereAttr, ...CommonHelper.handleQueryFilter(filter, "refferal_hospital").whereAttr]; - whereVal = { ...whereVal, ...CommonHelper.handleQueryFilter(filter, "refferal_hospital").whereVal }; - } - - var query = repo.createQueryBuilder("refferal_hospital"); - if (whereAttr.length != 0) { - query = query.where(whereAttr.join(" and "), whereVal); - } - - return query; - } -} \ No newline at end of file diff --git a/src/model/room.ts b/src/model/room.ts deleted file mode 100644 index bc35c93..0000000 --- a/src/model/room.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { Room } from "entity"; -import { SelectQueryBuilder } from "typeorm"; -import CommonHelper from "../helpers/common"; -import { OrmHelper } from "../helpers/orm"; - -export class RoomModel { - static async list(filter = {}): Promise> { - const repo = OrmHelper.DB.getRepository(Room); - let whereAttr = []; - let whereVal: any = {}; - if (filter) { - const filterResult = CommonHelper.handleQueryFilter(filter, "Room"); - whereAttr = [...whereAttr, ...filterResult.whereAttr]; - whereVal = { ...whereVal, ...filterResult.whereVal }; - } - - var query = null; - query = repo.createQueryBuilder("Room"); - if (whereAttr.length != 0) { - query = query.where(whereAttr.join(" and "), whereVal); - } - - return query; - } -} diff --git a/src/model/room_number.ts b/src/model/room_number.ts deleted file mode 100644 index 0d9cb0b..0000000 --- a/src/model/room_number.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { RoomNumber } from "entity"; -import { SelectQueryBuilder } from "typeorm"; -import CommonHelper from "../helpers/common"; -import { OrmHelper } from "../helpers/orm"; - -export class RoomNumberModel { - static async list(filter = {}): Promise> { - const repo = OrmHelper.DB.getRepository(RoomNumber); - let whereAttr: string[] = []; - let whereVal: any = {}; - if (filter && Object.keys(filter).length > 0) { - const filterResult = CommonHelper.handleQueryFilter(filter, "RoomNumber"); - whereAttr = [...whereAttr, ...filterResult.whereAttr]; - whereVal = { ...whereVal, ...filterResult.whereVal }; - } - - var query = repo.createQueryBuilder("RoomNumber"); - if (whereAttr.length != 0) { - query = query.where(whereAttr.join(" and "), whereVal); - } - - return query; - } -} diff --git a/src/model/room_services.ts b/src/model/room_services.ts deleted file mode 100644 index 51b6668..0000000 --- a/src/model/room_services.ts +++ /dev/null @@ -1,316 +0,0 @@ -// RoomServicesModel.ts -import { Room, Service, Status } from "entity"; -import { EntityManager, In, SelectQueryBuilder } from "typeorm"; -import CommonHelper from "../helpers/common"; -import { OrmHelper } from "../helpers/orm"; -import { ServiceModel } from "./service"; - -export class RoomServicesModel { - static async listByService(filter = {}, withDeleted = false): Promise> { - const repo = OrmHelper.DB.getRepository(Service); - let whereAttr: string[] = []; - let whereVal: any = {}; - - if (filter && Object.keys(filter).length > 0) { - const filterResult = CommonHelper.handleQueryFilter(filter); - whereAttr = [...whereAttr, ...filterResult.whereAttr]; - whereVal = { ...whereVal, ...filterResult.whereVal }; - } - - let query = repo.createQueryBuilder("Service") - .leftJoinAndSelect("Service.rooms", "Room") - .leftJoinAndSelect("Room.department", "Department") - .leftJoinAndSelect("Service.serviceType", "ServiceType"); - - if (whereAttr.length != 0) { - query = query.where(whereAttr.join(" and "), whereVal); - } - - if (withDeleted) { - query = query.withDeleted(); - } - - return query; - } - - static async listByRoom(filter = {}, withDeleted = false): Promise> { - const repo = OrmHelper.DB.getRepository(Room); - let whereAttr: string[] = []; - let whereVal: any = {}; - - if (filter && Object.keys(filter).length > 0) { - const filterResult = CommonHelper.handleQueryFilter(filter, "Room"); - whereAttr = [...whereAttr, ...filterResult.whereAttr]; - whereVal = { ...whereVal, ...filterResult.whereVal }; - } - - let query = repo.createQueryBuilder("Room") - .leftJoinAndSelect("Room.services", "Service") - .leftJoinAndSelect("Room.department", "Department") - .leftJoinAndSelect("Service.serviceType", "ServiceType"); - - if (whereAttr.length != 0) { - query = query.where(whereAttr.join(" and "), whereVal); - } - - if (withDeleted) { - query = query.withDeleted(); - } - - return query; - } - - static async countRooms(filter = {}, withDeleted = false): Promise { - const repo = OrmHelper.DB.getRepository(Service); - - let queryBuilder = repo.createQueryBuilder("Service") - .innerJoin("Service.rooms", "Room") - .select("COUNT(DISTINCT Room.id)", "count"); - - if (filter && Object.keys(filter).length > 0) { - const filterResult = CommonHelper.handleQueryFilter(filter); - if (filterResult.whereAttr.length > 0) { - queryBuilder = queryBuilder.where(filterResult.whereAttr.join(" and "), filterResult.whereVal); - } - } - - if (withDeleted) { - queryBuilder = queryBuilder.withDeleted(); - } - - const result = await queryBuilder.getRawOne(); - return parseInt(result.count) || 0; - } - - static async countServices(filter = {}, withDeleted = false): Promise { - const repo = OrmHelper.DB.getRepository(Room); - - let queryBuilder = repo.createQueryBuilder("Room") - .innerJoin("Room.services", "Service") - .select("COUNT(DISTINCT Service.id)", "count"); - - if (filter && Object.keys(filter).length > 0) { - const filterResult = CommonHelper.handleQueryFilter(filter, "Room"); - if (filterResult.whereAttr.length > 0) { - queryBuilder = queryBuilder.where(filterResult.whereAttr.join(" and "), filterResult.whereVal); - } - } - - if (withDeleted) { - queryBuilder = queryBuilder.withDeleted(); - } - - const result = await queryBuilder.getRawOne(); - return parseInt(result.count) || 0; - } - - static async expandTypeIdsToServices( - manager: EntityManager, - serviceTypeIds: string[] - ): Promise { - if (!serviceTypeIds || serviceTypeIds.length === 0) { - return []; - } - - return manager.getRepository(Service).find({ - where: { - serviceType: { id: In(serviceTypeIds) }, - status: Status.Active, - }, - relations: ["serviceType"], - }); - } - - static async getActiveServicesGroupedByType(manager: EntityManager = OrmHelper.DB.manager) { - const services = await manager.getRepository(Service).find({ - where: { status: Status.Active }, - relations: ["serviceType"], - }); - - const byTypeId = new Map(); - const typeMeta = new Map(); - - for (const service of services) { - const typeId = service.serviceType?.id; - if (!typeId) { - continue; - } - - if (!byTypeId.has(typeId)) { - byTypeId.set(typeId, []); - } - byTypeId.get(typeId)!.push(service.id); - - if (!typeMeta.has(typeId)) { - typeMeta.set(typeId, { id: typeId, name: service.serviceType!.name }); - } - } - - return { byTypeId, typeMeta }; - } - - static deriveTypesForRoomWithMap( - room: Room, - byTypeId: Map, - typeMeta: Map - ): { id: string; name: string }[] { - const roomServiceIds = new Set((room.services || []).map((s) => s.id)); - const derived: { id: string; name: string }[] = []; - - for (const [typeId, serviceIds] of byTypeId) { - if (serviceIds.length === 0) { - continue; - } - - const allInRoom = serviceIds.every((id) => roomServiceIds.has(id)); - if (allInRoom) { - const meta = typeMeta.get(typeId); - if (meta) { - derived.push(meta); - } - } - } - - return derived.sort((a, b) => a.name.localeCompare(b.name)); - } - - static async deriveTypesForRoom( - room: Room, - manager: EntityManager = OrmHelper.DB.manager - ): Promise<{ id: string; name: string }[]> { - const { byTypeId, typeMeta } = await RoomServicesModel.getActiveServicesGroupedByType(manager); - return RoomServicesModel.deriveTypesForRoomWithMap(room, byTypeId, typeMeta); - } - - static async formatRoomResponse( - room: Room, - manager: EntityManager = OrmHelper.DB.manager - ) { - const service_types = await RoomServicesModel.deriveTypesForRoom(room, manager); - - return { - id: room.id, - room: room.room, - code: room.code, - description: room.description, - status: room.status, - department: room.department - ? { - id: room.department.id, - name: room.department.name, - } - : null, - service_types, - services: room.services - ? room.services.map((service) => ({ - id: service.id, - name: service.name, - service_type: service.serviceType - ? { - id: service.serviceType.id, - name: service.serviceType.name, - } - : null, - })) - : [], - }; - } - - static async applyTypesToRoom( - manager: EntityManager, - room: Room, - serviceTypeIds: string[], - updatedBy: string - ): Promise { - const services = await RoomServicesModel.expandTypeIdsToServices(manager, serviceTypeIds); - room.services = services; - room.updated_by = updatedBy; - return manager.save(room); - } - - static async removeServiceFromAllRooms(manager: EntityManager, serviceId: string): Promise { - await manager - .createQueryBuilder() - .delete() - .from("service_rooms") - .where("service_id = :serviceId", { serviceId }) - .execute(); - } - - static async syncRoomsOnServiceCreated( - manager: EntityManager, - service: Service - ): Promise { - const typeId = service.serviceType?.id; - if (!typeId) { - return; - } - - const othersOfType = await manager.getRepository(Service).find({ - where: { - serviceType: { id: typeId }, - status: Status.Active, - }, - }); - - const otherIds = othersOfType.filter((s) => s.id !== service.id).map((s) => s.id); - if (otherIds.length === 0) { - return; - } - - const rooms = await manager.getRepository(Room).find({ - relations: ["services"], - }); - - for (const room of rooms) { - const roomIds = new Set((room.services || []).map((s) => s.id)); - const hadFullType = otherIds.every((id) => roomIds.has(id)); - if (!hadFullType) { - continue; - } - if (roomIds.has(service.id)) { - continue; - } - room.services = [...(room.services || []), service]; - await manager.save(room); - } - } - - static async syncRoomsOnServiceUpdated( - manager: EntityManager, - service: Service, - oldTypeId?: string - ): Promise { - const newTypeId = service.serviceType?.id; - const typeChanged = oldTypeId !== newTypeId; - - if (service.status !== Status.Active) { - await RoomServicesModel.removeServiceFromAllRooms(manager, service.id); - return; - } - - if (!typeChanged) { - return; - } - - await RoomServicesModel.removeServiceFromAllRooms(manager, service.id); - - if (!newTypeId) { - return; - } - - const reloaded = await ServiceModel.list({ "Service.id": service.id }) - .then((q) => q.leftJoinAndSelect("Service.serviceType", "serviceType").getOne()); - - if (reloaded) { - await RoomServicesModel.syncRoomsOnServiceCreated(manager, reloaded); - } - } - - static async syncRoomsOnServiceDeleted( - manager: EntityManager, - serviceId: string - ): Promise { - await RoomServicesModel.removeServiceFromAllRooms(manager, serviceId); - } -} diff --git a/src/model/room_to_pharmacy.ts b/src/model/room_to_pharmacy.ts deleted file mode 100644 index ac48dfd..0000000 --- a/src/model/room_to_pharmacy.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { SelectQueryBuilder } from "typeorm"; -import CommonHelper from "../helpers/common"; -import { OrmHelper } from "../helpers/orm"; -import { RoomToPharmacy, Room } from "entity"; - -export class RoomToPharmacyModel { - static async list(filter = {}): Promise> { - - const repo = OrmHelper.DB.getRepository(RoomToPharmacy); - let whereAttr: string[] = []; - let whereVal: any = {}; - if (filter && Object.keys(filter).length > 0) { - whereAttr = [...whereAttr, ...CommonHelper.handleQueryFilter(filter).whereAttr]; - whereVal = { ...whereVal, ...CommonHelper.handleQueryFilter(filter).whereVal }; - } - - var query = repo.createQueryBuilder("room_to_pharmacy"); - if (whereAttr.length != 0) { - query = query.where(whereAttr.join(" and "), whereVal); - } - - return query; - } -} \ No newline at end of file diff --git a/src/model/schedule.ts b/src/model/schedule.ts deleted file mode 100644 index 323c429..0000000 --- a/src/model/schedule.ts +++ /dev/null @@ -1,569 +0,0 @@ -import { Room, ScheduleException, ScheduleSeries, Status, User } from "entity"; -import { IsNull, SelectQueryBuilder } from "typeorm"; -import CommonHelper from "../helpers/common"; -import { OrmHelper } from "../helpers/orm"; -import dayjs from "dayjs"; -import { RoomModel } from "./room"; -import { filter } from "compression"; - -type RecurrenceInput = { - type: "daily" | "weekly" | "monthly"; - interval?: number; - daysOfWeek?: string[]; -}; - -type ScheduleSeriesPayload = { - roomId: string; - doctorId: string; - title: string; - quota?: number | null; - startDate: string; - untilDate?: string | null; - startTime: string; - endTime: string; - recurrence?: RecurrenceInput | null; -}; - -type ScheduleExceptionPayload = { - occurrenceDate: string; - isCancelled?: boolean; - overrideRoomId?: string | null; - overrideDoctorId?: string | null; - overrideTitle?: string | null; - overrideStartAt?: string | null; - overrideEndAt?: string | null; -}; - -type CalendarQueryOptions = { - limit?: number; - page?: number; -}; - -export class ScheduleModel { - static async listSeries(filterObj = {}): Promise> { - const repo = OrmHelper.DB.getRepository(ScheduleSeries); - let whereAttr: string[] = []; - let whereVal: any = {}; - if (filterObj && Object.keys(filterObj).length > 0) { - const filterResult = CommonHelper.handleQueryFilter(filterObj); - whereAttr = [...whereAttr, ...filterResult.whereAttr]; - whereVal = { ...whereVal, ...filterResult.whereVal }; - } - - let query = repo - .createQueryBuilder("ScheduleSeries") - .leftJoinAndSelect("ScheduleSeries.doctor", "Doctor") - .leftJoinAndSelect("ScheduleSeries.room", "Room"); - if (whereAttr.length !== 0) { - query = query.where(whereAttr.join(" and "), whereVal); - } - return query; - } - - static async getScheduleCalendarRange(start: string, end: string, filterObj: any, options: CalendarQueryOptions = {}): Promise { - const startDate = dayjs(start); - const endDate = dayjs(end); - if (!startDate.isValid() || !endDate.isValid()) { - throw new Error("Invalid start or end date"); - } - - const rangeStart = startDate.startOf("day").toDate(); - const rangeEnd = endDate.endOf("day").toDate(); - if (rangeStart > rangeEnd) { - throw new Error("Start date must be before end date"); - } - - const filterRoomId = filterObj && filterObj.roomId !== "" && filterObj.roomId !== null && filterObj.roomId !== undefined ? String(filterObj.roomId) : ""; - const filterDoctorId = filterObj && filterObj.doctorId !== "" && filterObj.doctorId !== null && filterObj.doctorId !== undefined ? String(filterObj.doctorId) : ""; - - const page = options.page ?? 1; - const limit = options.limit ?? 10; - const offset = (page - 1) * limit; - - const query = await RoomModel.list({ ...filterObj, with_deleted: false }); - const roomQuery = query - .select(["Room.id", "Room.room", "Room.code", "Room.picture", "Room.location", "Room.status", "Department.name"]) - .leftJoin("Room.department", "Department") - .where("Department.name = :departmentName", { departmentName: "Outpatient" }) - .andWhere(filterRoomId !== "" ? "Room.id = :roomId" : "1=1", { roomId: filterRoomId }); - - const roomTotalCount = await roomQuery - .getCount(); - const rooms = await roomQuery - .orderBy("Room.room", "ASC") - .offset(offset) - .limit(limit) - .getMany(); - const roomIds = rooms.map((room) => room.id); - - const seriesQuery = await ScheduleModel.listSeries(filterObj); - const seriesList = await seriesQuery - .where("ScheduleSeries.room_id IN (:...roomIds)", { roomIds }) - .andWhere("ScheduleSeries.start_date <= :rangeEndDate", { rangeEndDate: dayjs(rangeEnd).format("YYYY-MM-DD") }) - .andWhere("(ScheduleSeries.until_date IS NULL OR ScheduleSeries.until_date >= :rangeStartDate)", { rangeStartDate: dayjs(rangeStart).format("YYYY-MM-DD") }) - .andWhere("ScheduleSeries.deleted_at IS NULL") - .andWhere(filterDoctorId !== "" ? "ScheduleSeries.doctor_id = :doctorId" : "1=1", { doctorId: filterDoctorId }) - .orderBy("ScheduleSeries.start_time", "ASC") - .getMany(); - - const allEvents: any[] = []; - if (seriesList.length > 0) { - const seriesIds = seriesList.map((series) => series.id); - const usageMap = await ScheduleModel.getDailyUsedQuotaMap(seriesIds, rangeStart, rangeEnd); - - const exceptionRepo = OrmHelper.DB.getRepository(ScheduleException); - const exceptions = await exceptionRepo - .createQueryBuilder("ScheduleException") - .leftJoinAndSelect("ScheduleException.override_room", "OverrideRoom") - .leftJoinAndSelect("ScheduleException.override_doctor", "OverrideDoctor") - .where("ScheduleException.series_id IN (:...seriesIds)", { seriesIds }) - .andWhere("ScheduleException.occurrence_date BETWEEN :rangeStart AND :rangeEnd", { - rangeStart: ScheduleModel.formatYmd(rangeStart), - rangeEnd: ScheduleModel.formatYmd(rangeEnd), - }) - .andWhere("ScheduleException.deleted_at IS NULL") - .getMany(); - - const exceptionMap = new Map(); - for (const ex of exceptions) { - const key = `${ex.series_id}:${dayjs(ex.occurrence_date).format("YYYY-MM-DD")}`; - exceptionMap.set(key, ex); - } - - for (const series of seriesList) { - const occurrenceDates = ScheduleModel.expandSeriesOccurrences(series, rangeStart, rangeEnd); - for (const occurrenceDate of occurrenceDates) { - const occurrenceYmd = dayjs(occurrenceDate).format("YYYY-MM-DD"); - const exception = exceptionMap.get(`${series.id}:${occurrenceYmd}`); - if (exception && exception.is_cancelled) continue; - - const defaultStart = ScheduleModel.combineDateAndTime(occurrenceYmd, series.start_time); - const defaultEnd = ScheduleModel.combineDateAndTime(occurrenceYmd, series.end_time); - - const doctor = exception?.override_doctor ?? series.doctor; - const room = exception?.override_room ?? series.room; - const eventStart = exception?.override_start_at ? exception.override_start_at : defaultStart; - const eventEnd = exception?.override_end_at ? exception.override_end_at : defaultEnd; - const eventTitle = exception?.override_title || series.title; - - const roomId = room?.id || null; - const doctorId = doctor?.id || null; - const roomName = (room as any)?.room || (room as any)?.name || (room as any)?.code || ""; - const doctorName = (doctor as any)?.name || (doctor as any)?.fullname || (doctor as any)?.username || ""; - - allEvents.push({ - id: `occ:${series.id}:${occurrenceYmd}`, - series_id: series.id, - title: eventTitle, - room_id: roomId, - room_name: roomName, - doctor_id: doctorId, - doctor_name: doctorName, - start_at: eventStart, - end_at: eventEnd, - quota: series.quota ?? null, - used_quota: usageMap.get(`${series.id}:${occurrenceYmd}`) || 0, - left_quota: - typeof series.quota === "number" - ? Math.max(0, series.quota - (usageMap.get(`${series.id}:${occurrenceYmd}`) || 0)) - : null, - is_recurring: !!series.recurrence_rule, - is_exception: !!exception, - status: "confirmed", - }); - } - } - } - - for (const room of rooms) { - const roomEvents = allEvents.filter((event) => event.room_id === room.id); - room.events = roomEvents; - } - - return { - count: rooms.length, - page: page, - total_count: roomTotalCount, - list: rooms, - }; - } - - static async getScheduleOptions(filterObj = {}): Promise { - const query = await ScheduleModel.listSeries(filterObj); - query.andWhere("ScheduleSeries.deleted_at IS NULL"); - const seriesList: ScheduleSeries[] = await query.getMany(); - - const doctorsMap = new Map(); - const roomsMap = new Map(); - - for (const series of seriesList) { - if (series.doctor?.id) { - doctorsMap.set(series.doctor.id, { - id: series.doctor.id, - title: (series.doctor as any).name || (series.doctor as any).username || "Doctor", - }); - } - if (series.room?.id) { - roomsMap.set(series.room.id, { - id: series.room.id, - title: (series.room as any).room || (series.room as any).code || "Room", - }); - } - } - - return { - doctors: [...doctorsMap.values()], - rooms: [...roomsMap.values()], - }; - } - - static async getSeriesById(id: string): Promise { - const series = await OrmHelper.DB.getRepository(ScheduleSeries) - .createQueryBuilder("ScheduleSeries") - .leftJoinAndSelect("ScheduleSeries.doctor", "Doctor") - .leftJoinAndSelect("ScheduleSeries.room", "Room") - .where("ScheduleSeries.id = :id", { id }) - .andWhere("ScheduleSeries.deleted_at IS NULL") - .getOne(); - - if (!series) throw new Error("Schedule series not found"); - - const exceptions = await OrmHelper.DB.getRepository(ScheduleException) - .createQueryBuilder("ScheduleException") - .leftJoinAndSelect("ScheduleException.override_room", "OverrideRoom") - .leftJoinAndSelect("ScheduleException.override_doctor", "OverrideDoctor") - .where("ScheduleException.series_id = :id", { id }) - .andWhere("ScheduleException.deleted_at IS NULL") - .orderBy("ScheduleException.occurrence_date", "ASC") - .getMany(); - - const recurrenceRule = series.recurrence_rule; - const { recurrence_rule: _omitRule, ...seriesRest } = series as ScheduleSeries & { recurrence_rule?: string | null }; - - return { - series: { - ...seriesRest, - recurrence: ScheduleModel.rRuleToRecurrence(recurrenceRule), - }, - exceptions, - }; - } - - static async createSeries(payload: ScheduleSeriesPayload, actor: string): Promise { - const room = await OrmHelper.DB.getRepository(Room).findOne({ where: { id: payload.roomId } }); - if (!room) throw new Error("Room not found"); - - const doctor = await OrmHelper.DB.getRepository(User).findOne({ where: { id: payload.doctorId } }); - if (!doctor) throw new Error("Doctor not found"); - - const series = new ScheduleSeries(); - series.room_id = payload.roomId; - series.doctor_id = payload.doctorId; - series.room = room; - series.doctor = doctor; - series.title = payload.title; - series.quota = payload.quota ?? null; - series.start_date = new Date(payload.startDate); - series.until_date = payload.untilDate ? new Date(payload.untilDate) : null; - series.start_time = payload.startTime; - series.end_time = payload.endTime; - series.recurrence_rule = ScheduleModel.recurrenceToRRule(payload.recurrence || null); - series.status = Status.Active; - series.created_by = actor; - series.updated_by = actor; - - return OrmHelper.DB.manager.save(series); - } - - static async updateSeries(id: string, payload: ScheduleSeriesPayload, actor: string): Promise { - const series = await OrmHelper.DB.getRepository(ScheduleSeries) - .createQueryBuilder("ScheduleSeries") - .where("ScheduleSeries.id = :id", { id }) - .andWhere("ScheduleSeries.deleted_at IS NULL") - .getOne(); - if (!series) throw new Error("Schedule series not found"); - - const room = await OrmHelper.DB.getRepository(Room).findOne({ where: { id: payload.roomId } }); - if (!room) throw new Error("Room not found"); - - const doctor = await OrmHelper.DB.getRepository(User).findOne({ where: { id: payload.doctorId } }); - if (!doctor) throw new Error("Doctor not found"); - - series.room_id = payload.roomId; - series.doctor_id = payload.doctorId; - series.room = room; - series.doctor = doctor; - series.title = payload.title; - series.quota = payload.quota ?? null; - series.start_date = new Date(payload.startDate); - series.until_date = payload.untilDate ? new Date(payload.untilDate) : null; - series.start_time = payload.startTime; - series.end_time = payload.endTime; - series.recurrence_rule = ScheduleModel.recurrenceToRRule(payload.recurrence || null); - series.updated_by = actor; - - return OrmHelper.DB.manager.save(series); - } - - static async createSeriesException(seriesId: string, payload: ScheduleExceptionPayload, actor: string): Promise { - const series = await OrmHelper.DB.getRepository(ScheduleSeries).findOne({ where: { id: seriesId } }); - if (!series) throw new Error("Schedule series not found"); - - let overrideRoom: Room = null; - if (payload.overrideRoomId) { - overrideRoom = await OrmHelper.DB.getRepository(Room).findOne({ where: { id: payload.overrideRoomId } }); - if (!overrideRoom) throw new Error("Override room not found"); - } - - let overrideDoctor: User = null; - if (payload.overrideDoctorId) { - overrideDoctor = await OrmHelper.DB.getRepository(User).findOne({ where: { id: payload.overrideDoctorId } }); - if (!overrideDoctor) throw new Error("Override doctor not found"); - } - - const occurrenceDate = new Date(payload.occurrenceDate); - const occurrenceYmd = ScheduleModel.formatYmd(occurrenceDate); - - let exception = await OrmHelper.DB.getRepository(ScheduleException) - .createQueryBuilder("ScheduleException") - .where("ScheduleException.series_id = :seriesId", { seriesId }) - .andWhere("ScheduleException.occurrence_date = :occurrenceDate", { occurrenceDate: occurrenceYmd }) - .andWhere("ScheduleException.deleted_at IS NULL") - .getOne(); - - if (!exception) { - exception = new ScheduleException(); - exception.series_id = seriesId; - exception.series = series; - exception.occurrence_date = occurrenceDate; - exception.created_by = actor; - } - - exception.is_cancelled = !!payload.isCancelled; - exception.override_room_id = payload.overrideRoomId || null; - exception.override_doctor_id = payload.overrideDoctorId || null; - exception.override_room = overrideRoom; - exception.override_doctor = overrideDoctor; - exception.override_title = payload.overrideTitle || null; - exception.override_start_at = payload.overrideStartAt ? new Date(payload.overrideStartAt) : null; - exception.override_end_at = payload.overrideEndAt ? new Date(payload.overrideEndAt) : null; - exception.updated_by = actor; - - return OrmHelper.DB.manager.save(exception); - } - - static async deleteSeries(id: string, hard: boolean, actor: string): Promise { - const manager = OrmHelper.DB.manager; - - if (hard) { - await manager.delete(ScheduleException, { series_id: id }); - const result = await manager.delete(ScheduleSeries, { id }); - return result.affected ?? 0; - } - - const series = await OrmHelper.DB.getRepository(ScheduleSeries) - .createQueryBuilder("ScheduleSeries") - .where("ScheduleSeries.id = :id", { id }) - .andWhere("ScheduleSeries.deleted_at IS NULL") - .getOne(); - - if (!series) return 0; - - const now = new Date(); - - await manager.transaction(async (tx) => { - await tx - .createQueryBuilder() - .update(ScheduleException) - .set({ deleted_at: now, deleted_by: actor }) - .where("series_id = :id", { id }) - .andWhere("deleted_at IS NULL") - .execute(); - - series.deleted_at = now; - series.deleted_by = actor; - await tx.save(series); - }); - - return 1; - } - - private static expandSeriesOccurrences(series: ScheduleSeries, rangeStart: Date, rangeEnd: Date): Date[] { - const seriesStart = ScheduleModel.startOfDay(new Date(series.start_date)); - const seriesUntil = series.until_date ? ScheduleModel.endOfDay(new Date(series.until_date)) : null; - const rule = ScheduleModel.parseRRule(series.recurrence_rule || ""); - const ruleUntil = rule.until ? ScheduleModel.endOfDay(rule.until) : null; - - const effectiveStart = new Date(Math.max(rangeStart.getTime(), seriesStart.getTime())); - let effectiveEnd = new Date(rangeEnd); - if (seriesUntil && seriesUntil < effectiveEnd) effectiveEnd = seriesUntil; - if (ruleUntil && ruleUntil < effectiveEnd) effectiveEnd = ruleUntil; - if (effectiveStart > effectiveEnd) return []; - - if (!rule.freq) { - return seriesStart >= effectiveStart && seriesStart <= effectiveEnd ? [seriesStart] : []; - } - - const dates: Date[] = []; - let generatedCount = 0; - let current = new Date(seriesStart); - const byDay = rule.byDay?.length ? rule.byDay : [ScheduleModel.weekdayToRRule(seriesStart.getDay())]; - const interval = rule.interval || 1; - - while (current <= effectiveEnd) { - if (ScheduleModel.matchesRule(current, seriesStart, rule.freq, interval, byDay)) { - generatedCount += 1; - if (current >= effectiveStart) { - dates.push(new Date(current)); - } - if (rule.count && generatedCount >= rule.count) break; - } - current.setDate(current.getDate() + 1); - } - - return dates; - } - - private static matchesRule(date: Date, start: Date, freq: string, interval: number, byDay: string[]): boolean { - const diffDays = Math.floor((ScheduleModel.startOfDay(date).getTime() - ScheduleModel.startOfDay(start).getTime()) / 86400000); - if (diffDays < 0) return false; - - if (freq === "DAILY") return diffDays % interval === 0; - if (freq === "WEEKLY") { - const weekIndex = Math.floor(diffDays / 7); - return weekIndex % interval === 0 && byDay.includes(ScheduleModel.weekdayToRRule(date.getDay())); - } - if (freq === "MONTHLY") { - const months = (date.getFullYear() - start.getFullYear()) * 12 + (date.getMonth() - start.getMonth()); - return months % interval === 0 && date.getDate() === start.getDate(); - } - return false; - } - - private static parseRRule(rule: string): { freq?: string; interval?: number; count?: number; until?: Date; byDay?: string[] } { - if (!rule) return {}; - const pairs = rule.split(";").map((x) => x.trim()).filter(Boolean); - const out: { [key: string]: string } = {}; - for (const p of pairs) { - const [k, v] = p.split("="); - if (k && v) out[k.toUpperCase()] = v; - } - - const untilRaw = out.UNTIL; - let untilDate: Date = null; - if (untilRaw) { - if (/^\d{8}$/.test(untilRaw)) { - untilDate = new Date(`${untilRaw.slice(0, 4)}-${untilRaw.slice(4, 6)}-${untilRaw.slice(6, 8)}T00:00:00`); - } else if (/^\d{8}T\d{6}Z$/.test(untilRaw)) { - untilDate = new Date(`${untilRaw.slice(0, 4)}-${untilRaw.slice(4, 6)}-${untilRaw.slice(6, 8)}T${untilRaw.slice(9, 11)}:${untilRaw.slice(11, 13)}:${untilRaw.slice(13, 15)}Z`); - } else { - untilDate = new Date(untilRaw); - } - } - - return { - freq: out.FREQ?.toUpperCase(), - interval: out.INTERVAL ? Number(out.INTERVAL) : 1, - count: out.COUNT ? Number(out.COUNT) : undefined, - until: untilDate && !isNaN(untilDate.getTime()) ? untilDate : undefined, - byDay: out.BYDAY ? out.BYDAY.split(",").map((x) => x.trim().toUpperCase()) : undefined, - }; - } - - private static combineDateAndTime(ymd: string, hhmmss: string) { - return `${ymd} ${hhmmss}`; - } - - private static startOfDay(date: Date): Date { - return new Date(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0, 0); - } - - private static endOfDay(date: Date): Date { - return new Date(date.getFullYear(), date.getMonth(), date.getDate(), 23, 59, 59, 999); - } - - private static formatYmd(date: Date): string { - const y = date.getFullYear(); - const m = String(date.getMonth() + 1).padStart(2, "0"); - const d = String(date.getDate()).padStart(2, "0"); - return `${y}-${m}-${d}`; - } - - private static weekdayToRRule(day: number): string { - return ["SU", "MO", "TU", "WE", "TH", "FR", "SA"][day]; - } - - private static recurrenceToRRule(recurrence: RecurrenceInput | null): string { - if (!recurrence) return null; - const interval = recurrence.interval && recurrence.interval > 0 ? recurrence.interval : 1; - if (recurrence.type === "weekly") { - const byDay = recurrence.daysOfWeek && recurrence.daysOfWeek.length > 0 ? recurrence.daysOfWeek.join(",") : ""; - return byDay ? `FREQ=WEEKLY;INTERVAL=${interval};BYDAY=${byDay}` : `FREQ=WEEKLY;INTERVAL=${interval}`; - } - if (recurrence.type === "daily") { - return `FREQ=DAILY;INTERVAL=${interval}`; - } - if (recurrence.type === "monthly") { - return `FREQ=MONTHLY;INTERVAL=${interval}`; - } - throw new Error("Unsupported recurrence type"); - } - - private static rRuleToRecurrence(recurrence_rule: string | null): RecurrenceInput | null { - if (!recurrence_rule || !String(recurrence_rule).trim()) return null; - const parsed = ScheduleModel.parseRRule(recurrence_rule); - if (!parsed.freq) return null; - - const interval = parsed.interval && parsed.interval > 0 ? parsed.interval : 1; - const freq = parsed.freq.toUpperCase(); - - if (freq === "DAILY") { - return { type: "daily", interval }; - } - if (freq === "WEEKLY") { - const out: RecurrenceInput = { type: "weekly", interval }; - if (parsed.byDay && parsed.byDay.length > 0) { - out.daysOfWeek = parsed.byDay; - } - return out; - } - if (freq === "MONTHLY") { - return { type: "monthly", interval }; - } - return null; - } - - private static async getDailyUsedQuotaMap(seriesIds: string[], rangeStart: Date, rangeEnd: Date): Promise> { - const usedQuotaMap = new Map(); - if (seriesIds.length === 0) return usedQuotaMap; - - const placeholders = seriesIds.map((_, index) => `$${index + 1}`).join(", "); - const startParamIndex = seriesIds.length + 1; - const endParamIndex = seriesIds.length + 2; - const params = [...seriesIds, ScheduleModel.formatYmd(rangeStart), ScheduleModel.formatYmd(rangeEnd)]; - - const query = ` - SELECT - ro.schedule_series_id AS series_id, - DATE(ro.visit_date) AS visit_date, - COUNT(ro.id) AS used_count - FROM emr.emr_registration_outpatient ro - WHERE ro.schedule_series_id IN (${placeholders}) - AND DATE(ro.visit_date) BETWEEN $${startParamIndex} AND $${endParamIndex} - AND ro.deleted_at IS NULL - GROUP BY ro.schedule_series_id, DATE(ro.visit_date) - `; - - const rows: Array<{ series_id: string; visit_date: string | Date; used_count: string | number }> = await OrmHelper.DB.manager.query( - query, - params - ); - - for (const row of rows) { - const occurrenceYmd = ScheduleModel.formatYmd(new Date(row.visit_date)); - usedQuotaMap.set(`${row.series_id}:${occurrenceYmd}`, Number(row.used_count) || 0); - } - - return usedQuotaMap; - } -} diff --git a/src/model/selling_price_percentage.ts b/src/model/selling_price_percentage.ts deleted file mode 100644 index e5f2002..0000000 --- a/src/model/selling_price_percentage.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { SelectQueryBuilder } from "typeorm"; -import CommonHelper from "../helpers/common"; -import { OrmHelper } from "../helpers/orm"; -import { SellingPricePercentage } from "entity"; - -export class SellingPricePercentageModel { - static async list(filter = {}): Promise> { - const repo = OrmHelper.DB.getRepository(SellingPricePercentage); - let whereAttr: string[] = []; - let whereVal: any = {}; - if (filter && Object.keys(filter).length > 0) { - whereAttr = [...whereAttr, ...CommonHelper.handleQueryFilter(filter, "selling_price_percentage").whereAttr]; - whereVal = { ...whereVal, ...CommonHelper.handleQueryFilter(filter, "selling_price_percentage").whereVal }; - } - - var query = repo.createQueryBuilder("selling_price_percentage") - .leftJoinAndSelect("selling_price_percentage.item_master", "item_master") - .leftJoinAndSelect("selling_price_percentage.item_origin", "item_origin"); - if (whereAttr.length != 0) { - query = query.where(whereAttr.join(" and "), whereVal); - } - - return query; - } -} \ No newline at end of file diff --git a/src/model/service.ts b/src/model/service.ts deleted file mode 100644 index ffc25dd..0000000 --- a/src/model/service.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { Service } from "entity"; -import { SelectQueryBuilder } from "typeorm"; -import CommonHelper from "../helpers/common"; -import { OrmHelper } from "../helpers/orm"; - -export class ServiceModel { - static async list(filterObj = {}, filterAny: string = ""): Promise> { - const repo = OrmHelper.DB.getRepository(Service); - let whereAttr: string[] = []; - let whereVal: any = {}; - if (filterObj && Object.keys(filterObj).length > 0) { - const filterResult = CommonHelper.handleQueryFilter(filterObj, "Service"); - whereAttr = [...whereAttr, ...filterResult.whereAttr]; - whereVal = { ...whereVal, ...filterResult.whereVal }; - } - - if (filterAny && filterAny !== "" && filterAny !== null && filterAny !== undefined) { - const filterResult = CommonHelper.handleFilter({ - filter: JSON.stringify({ any: filterAny }), - col_any_eq: [], - col_any_like: ["Service.name"], - }); - - if (filterResult.whereAttr && filterResult.whereAttr !== "") { - whereAttr = [...whereAttr, filterResult.whereAttr]; - whereVal = { ...whereVal, ...filterResult.whereVal }; - } - } - - var query = repo - .createQueryBuilder("Service") - - if (whereAttr.length != 0) { - query = query.where(whereAttr.join(" and "), whereVal); - } - - return query; - } -} diff --git a/src/model/service_class.ts b/src/model/service_class.ts deleted file mode 100644 index c9d08e0..0000000 --- a/src/model/service_class.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { ServiceClass } from "entity"; -import { SelectQueryBuilder } from "typeorm"; -import CommonHelper from "../helpers/common"; -import { OrmHelper } from "../helpers/orm"; - -export class ServiceClassModel { - static async list(filter = {}): Promise> { - const repo = OrmHelper.DB.getRepository(ServiceClass); - let whereAttr: string[] = []; - let whereVal: any = {}; - if (filter && Object.keys(filter).length > 0) { - whereAttr = [...whereAttr, ...CommonHelper.handleQueryFilter(filter).whereAttr]; - whereVal = { ...whereVal, ...CommonHelper.handleQueryFilter(filter).whereVal }; - } - - var query = repo.createQueryBuilder("ServiceClass"); - if (whereAttr.length != 0) { - query = query.where(whereAttr.join(" and "), whereVal); - } - - return query; - } -} diff --git a/src/model/service_fare.ts b/src/model/service_fare.ts deleted file mode 100644 index 99e55dc..0000000 --- a/src/model/service_fare.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { ServiceFare } from "entity"; -import { SelectQueryBuilder } from "typeorm"; -import CommonHelper from "../helpers/common"; -import { OrmHelper } from "../helpers/orm"; - -export class ServiceFareModel { - static async list(filter = {}): Promise> { - const repo = OrmHelper.DB.getRepository(ServiceFare); - let whereAttr: string[] = []; - let whereVal: any = {}; - if (filter && Object.keys(filter).length > 0) { - whereAttr = [...whereAttr, ...CommonHelper.handleQueryFilter(filter).whereAttr]; - whereVal = { ...whereVal, ...CommonHelper.handleQueryFilter(filter).whereVal }; - } - - var query = repo.createQueryBuilder("ServiceFare"); - if (whereAttr.length != 0) { - query = query.where(whereAttr.join(" and "), whereVal); - } - - return query; - } -} diff --git a/src/model/service_package.ts b/src/model/service_package.ts deleted file mode 100644 index c2bf0d0..0000000 --- a/src/model/service_package.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { ServicePackage } from "entity"; -import { SelectQueryBuilder } from "typeorm"; -import CommonHelper from "../helpers/common"; -import { OrmHelper } from "../helpers/orm"; - -export class ServicePackageModel { - static async list(filter = {}): Promise> { - const repo = OrmHelper.DB.getRepository(ServicePackage); - let whereAttr: string[] = []; - let whereVal: any = {}; - if (filter && Object.keys(filter).length > 0) { - whereAttr = [...whereAttr, ...CommonHelper.handleQueryFilter(filter).whereAttr]; - whereVal = { ...whereVal, ...CommonHelper.handleQueryFilter(filter).whereVal }; - } - - var query = repo.createQueryBuilder("ServicePackage"); - if (whereAttr.length != 0) { - query = query.where(whereAttr.join(" and "), whereVal); - } - - return query; - } -} diff --git a/src/model/service_type.ts b/src/model/service_type.ts deleted file mode 100644 index d53002f..0000000 --- a/src/model/service_type.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { ServiceType } from "entity"; -import { SelectQueryBuilder } from "typeorm"; -import CommonHelper from "../helpers/common"; -import { OrmHelper } from "../helpers/orm"; - -export class ServiceTypeModel { - static async list(filter = {}): Promise> { - const repo = OrmHelper.DB.getRepository(ServiceType); - let whereAttr: string[] = []; - let whereVal: any = {}; - if (filter && Object.keys(filter).length > 0) { - whereAttr = [...whereAttr, ...CommonHelper.handleQueryFilter(filter).whereAttr]; - whereVal = { ...whereVal, ...CommonHelper.handleQueryFilter(filter).whereVal }; - } - - var query = repo.createQueryBuilder("ServiceType"); - if (whereAttr.length != 0) { - query = query.where(whereAttr.join(" and "), whereVal); - } - - return query; - } -} diff --git a/src/model/supplier.ts b/src/model/supplier.ts deleted file mode 100644 index 6ae9711..0000000 --- a/src/model/supplier.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { Supplier } from "entity"; -import { SelectQueryBuilder } from "typeorm"; -import CommonHelper from "../helpers/common"; -import { OrmHelper } from "../helpers/orm"; - -export class SupplierModel { - static async list(filter = {}): Promise> { - const repo = OrmHelper.DB.getRepository(Supplier); - let whereAttr: string[] = []; - let whereVal: any = {}; - if (filter && Object.keys(filter).length > 0) { - whereAttr = [...whereAttr, ...CommonHelper.handleQueryFilter(filter, "supplier").whereAttr]; - whereVal = { ...whereVal, ...CommonHelper.handleQueryFilter(filter, "supplier").whereVal }; - } - - var query = repo.createQueryBuilder("supplier"); - if (whereAttr.length != 0) { - query = query.where(whereAttr.join(" and "), whereVal); - } - - return query; - } -} \ No newline at end of file diff --git a/src/model/surgery_room.ts b/src/model/surgery_room.ts deleted file mode 100644 index 872c5c8..0000000 --- a/src/model/surgery_room.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { SurgeryRoom } from "entity"; -import { SelectQueryBuilder } from "typeorm"; -import CommonHelper from "../helpers/common"; -import { OrmHelper } from "../helpers/orm"; - -export class SurgeryRoomModel { - static async list(filter = {}): Promise> { - const repo = OrmHelper.DB.getRepository(SurgeryRoom); - let whereAttr = []; - let whereVal: any = {}; - if (filter) { - whereAttr = [...whereAttr, ...CommonHelper.handleQueryFilter(filter).whereAttr]; - whereVal = { - ...whereVal, - ...CommonHelper.handleQueryFilter(filter).whereVal, - }; - } - - var query = null; - query = repo.createQueryBuilder(); - if (whereAttr.length != 0) { - query = query.where(whereAttr.join(" and "), whereVal); - } - - return query; - } -} diff --git a/src/model/surgery_type.ts b/src/model/surgery_type.ts deleted file mode 100644 index 0751ad1..0000000 --- a/src/model/surgery_type.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { SurgeryType } from "entity"; -import { SelectQueryBuilder } from "typeorm"; -import CommonHelper from "../helpers/common"; -import { OrmHelper } from "../helpers/orm"; - -export class SurgeryTypeModel { - static async list(filterObj = {}, filterAny: string = ""): Promise> { - const repo = OrmHelper.DB.getRepository(SurgeryType); - let whereAttr = []; - let whereVal: any = {}; - if (filterObj) { - const filterResult = CommonHelper.handleQueryFilter(filterObj); - whereAttr = [...whereAttr, ...filterResult.whereAttr]; - whereVal = { ...whereVal, ...filterResult.whereVal }; - } - if (filterAny && filterAny !== "" && filterAny !== null && filterAny !== undefined) { - const filterResult = CommonHelper.handleFilter({ - filter: JSON.stringify({ any: filterAny }), - col_any_eq: [], - col_any_like: ["name"], - }); - - if (filterResult.whereAttr && filterResult.whereAttr !== "") { - whereAttr = [...whereAttr, filterResult.whereAttr]; - whereVal = { ...whereVal, ...filterResult.whereVal }; - } - } - - var query = repo.createQueryBuilder("SurgeryType"); - if (whereAttr.length != 0) { - query = query.where(whereAttr.join(" and "), whereVal); - } - - return query; - } -} diff --git a/src/model/unit.ts b/src/model/unit.ts deleted file mode 100644 index 8bbe643..0000000 --- a/src/model/unit.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { Unit } from "entity"; -import { SelectQueryBuilder } from "typeorm"; -import CommonHelper from "../helpers/common"; -import { OrmHelper } from "../helpers/orm"; - -export class UnitModel { - static async list(filter = {}): Promise> { - const repo = OrmHelper.DB.getRepository(Unit); - let whereAttr: string[] = []; - let whereVal: any = {}; - if (filter && Object.keys(filter).length > 0) { - whereAttr = [...whereAttr, ...CommonHelper.handleQueryFilter(filter, "unit").whereAttr]; - whereVal = { ...whereVal, ...CommonHelper.handleQueryFilter(filter, "unit").whereVal }; - } - - var query = repo.createQueryBuilder("unit"); - if (whereAttr.length != 0) { - query = query.where(whereAttr.join(" and "), whereVal); - } - - return query; - } -} \ No newline at end of file diff --git a/src/model/usage_instructions.ts b/src/model/usage_instructions.ts deleted file mode 100644 index c9ce07a..0000000 --- a/src/model/usage_instructions.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { UsageInstructions } from "entity"; -import { SelectQueryBuilder } from "typeorm"; -import CommonHelper from "../helpers/common"; -import { OrmHelper } from "../helpers/orm"; - -export class UsageInstructionsModel { - static async list(filter = {}): Promise> { - const repo = OrmHelper.DB.getRepository(UsageInstructions); - let whereAttr: string[] = []; - let whereVal: any = {}; - if (filter && Object.keys(filter).length > 0) { - whereAttr = [...whereAttr, ...CommonHelper.handleQueryFilter(filter, "usage_instructions").whereAttr]; - whereVal = { ...whereVal, ...CommonHelper.handleQueryFilter(filter, "usage_instructions").whereVal }; - } - - var query = repo.createQueryBuilder("usage_instructions"); - if (whereAttr.length != 0) { - query = query.where(whereAttr.join(" and "), whereVal); - } - - return query; - } -} \ No newline at end of file diff --git a/src/model/usage_time.ts b/src/model/usage_time.ts deleted file mode 100644 index e423c45..0000000 --- a/src/model/usage_time.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { UsageTime } from "entity"; -import { SelectQueryBuilder } from "typeorm"; -import CommonHelper from "../helpers/common"; -import { OrmHelper } from "../helpers/orm"; - -export class UsageTimeModel { - static async list(filter = {}): Promise> { - const repo = OrmHelper.DB.getRepository(UsageTime); - let whereAttr: string[] = []; - let whereVal: any = {}; - if (filter && Object.keys(filter).length > 0) { - whereAttr = [...whereAttr, ...CommonHelper.handleQueryFilter(filter, "usage_time").whereAttr]; - whereVal = { ...whereVal, ...CommonHelper.handleQueryFilter(filter, "usage_time").whereVal }; - } - - var query = repo.createQueryBuilder("usage_time"); - if (whereAttr.length != 0) { - query = query.where(whereAttr.join(" and "), whereVal); - } - - return query; - } -} \ No newline at end of file diff --git a/src/model/user_to_room.ts b/src/model/user_to_room.ts deleted file mode 100644 index 2b4a4c7..0000000 --- a/src/model/user_to_room.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { SelectQueryBuilder } from "typeorm"; -import CommonHelper from "../helpers/common"; -import { OrmHelper } from "../helpers/orm"; -import { UserToRoom } from "entity"; - -export class UserToRoomModel { - static async list(filter = {}): Promise> { - const repo = OrmHelper.DB.getRepository(UserToRoom); - let whereAttr: string[] = []; - let whereVal: any = {}; - if (filter && Object.keys(filter).length > 0) { - whereAttr = [...whereAttr, ...CommonHelper.handleQueryFilter(filter, "user_to_room").whereAttr]; - whereVal = { ...whereVal, ...CommonHelper.handleQueryFilter(filter, "user_to_room").whereVal }; - } - - var query = repo.createQueryBuilder("user_to_room") - .leftJoinAndSelect("user_to_room.user", "user") - .leftJoinAndSelect("user_to_room.room", "room"); - if (whereAttr.length != 0) { - query = query.where(whereAttr.join(" and "), whereVal); - } - - return query; - } -} \ No newline at end of file diff --git a/src/routes/private.ts b/src/routes/private.ts index 8c44828..ea8c116 100644 --- a/src/routes/private.ts +++ b/src/routes/private.ts @@ -1,81 +1,7 @@ import express from "express"; import { Language } from "../langs/lang"; import JwtHelper from "../helpers/jwt"; -import { MenuController } from "../controllers/menu"; -import { AdministrativuController } from "../controllers/administrativu"; -import { AldeiaController } from "../controllers/aldeia"; -import { DistrictController } from "../controllers/district"; -import { MunisipoController } from "../controllers/munisipo"; -import { SucoController } from "../controllers/suco"; -import { ApplicationController } from "../controllers/application"; -import { NationalityController } from "../controllers/nationality"; -import { DiagnosisController } from "../controllers/diagnosis"; -import { DiagnosticProcedureController } from "../controllers/diagnostic_procedure"; -import { RoomController } from "../controllers/room"; -import { RoomNumberController } from "../controllers/room_number"; -import { RoomServicesController } from "../controllers/room_services"; -import { ServiceTypeController } from "../controllers/service_type"; -import { ServiceClassController } from "../controllers/service_class"; -import { ServiceController } from "../controllers/service"; -import { ServiceFareController } from "../controllers/service_fare"; -import { ServicePackageController } from "../controllers/service_package"; -import { DepartmentController } from "../controllers/department"; -import { DoctorScheduleController } from "../controllers/doctor_schedule"; -import { DoctorItemPackageController } from "../controllers/doctor_item_package"; -import { MeasurementUnitController } from "../controllers/measurement_unit"; -import { ReferenceRangeController } from "../controllers/reference_range"; -import { QueueMonitoringController } from "../controllers/queue_monitoring"; -import { ExaminationDetailController } from "../controllers/examination_detail"; -import { ExaminationTypeController } from "../controllers/examination_type"; -import { ServiceExaminationController } from "../controllers/service_examination"; -import { LaboratoryController } from "../controllers/laboratory"; -import { PharmacyController } from "../controllers/pharmacy"; -import { HospitalInformationController } from "../controllers/hospital_information"; -import { ItemCategoryController } from "../controllers/pharmacy/item_category"; -import { ItemStatusController } from "../controllers/pharmacy/item_status"; -import { UnitController } from "../controllers/pharmacy/unit"; -import { ItemTypeDetailController } from "../controllers/pharmacy/item_type_detail"; -import { ItemTypeController } from "../controllers/pharmacy/item_type"; -import { ItemOriginController } from "../controllers/pharmacy/item_origin"; -import { ItemGroupController } from "../controllers/pharmacy/item_group"; -import { UsageInstructionsController } from "../controllers/pharmacy/usage_instructions"; -import { UsageTimeController } from "../controllers/pharmacy/usage_time"; -import { ItemClassController } from "../controllers/pharmacy/item_class"; -import { ItemClassDetailController } from "../controllers/pharmacy/item_class_detail"; -import { FactoryController } from "../controllers/pharmacy/factory"; -import { SupplierController } from "../controllers/pharmacy/supplier"; -import { ItemMasterController } from "../controllers/pharmacy/item_master"; -import { PharmacyInfoController } from "../controllers/pharmacy/pharmacy_info"; -import { ItemPriceController } from "../controllers/pharmacy/item_price"; -import { SellingPricePercentageController } from "../controllers/pharmacy/selling_price_percentage"; -import { FactorytoSupplierController } from "../controllers/pharmacy/factory_to_supplier"; -import { PatientGroupController } from "../controllers/patient_group"; -import { PatientGuarantorController } from "../controllers/patient_guarantor"; -import { GenericNameController } from "../controllers/pharmacy/generic_name"; -import { RefferalHospital } from "entity"; -import { RefferalHospitalController } from "../controllers/refferal_hospital"; -import { InitialStockController } from "../controllers/pharmacy/initial_stock"; -import { DoctorItemController } from "../controllers/doctor_item"; -import { UserToRoomController } from "../controllers/user_to_room"; -import { RoomToPharmacyController } from "../controllers/room_to_pharmacy"; -import { PlanningVerificatorController } from "../controllers/pharmacy/planning_verificator"; -import { ScheduleController } from "../controllers/schedule"; -import { FareTypeController } from "../controllers/faretype"; -import { CardTypeController } from "../controllers/card_type"; -import { CardPrintQueueController } from "../controllers/card_print_queue"; -import { PaymentMethodController } from "../controllers/payment-method"; -import { RegistrationFeeController } from "../controllers/registrationfee"; -import { RegionController } from "../controllers/region"; -import { ResponsiblePartyConsentController } from "../controllers/responsiblepartyconsent"; -import { CurrencyController } from "../controllers/currency"; -import { InpatientRoomController } from "../controllers/inpatient_room"; -import { SurgeryRoomController } from "../controllers/surgery_room"; -import { SurgeryTypeController } from "../controllers/surgery_type"; -import { FosterCareHistoryController } from "../controllers/fostercarehistory"; -import { FileController } from "../controllers/file/file"; -import { MedicalFormController } from "../controllers/medical_form"; -import { MainDiseaseController } from "../controllers/main_disease"; -import { CardKeySetsController } from "../controllers/card_key_sets"; +import { SitePointsController } from "../controllers/sitepoints"; export class RoutePrivate { static setup(app: express.Application) { @@ -83,497 +9,12 @@ export class RoutePrivate { JwtHelper.secure(app); - app.get("/api/main-disease/list", MainDiseaseController.list); - app.post("/api/main-disease/create", MainDiseaseController.create); - app.get("/api/main-disease/detail/:id", MainDiseaseController.detail); - app.put("/api/main-disease/update/:id", MainDiseaseController.update); - app.delete("/api/main-disease/delete/:id/:hard", MainDiseaseController.delete); - app.put("/api/main-disease/restore/:id", MainDiseaseController.restore); - - app.get("/api/card-key-sets/list", CardKeySetsController.list); - app.get("/api/card-key-sets/active", CardKeySetsController.active); - app.post("/api/card-key-sets/create", CardKeySetsController.create); - app.get("/api/card-key-sets/detail/:key_set_id", CardKeySetsController.detail); - - app.get("/api/menu/list", MenuController.list); - app.get("/api/menu/export", MenuController.export); - app.post("/api/menu/create", MenuController.create); - app.put("/api/menu/update/:id", MenuController.update); - app.delete("/api/menu/delete/:id/:hard", MenuController.delete); - app.put("/api/menu/restore/:id", MenuController.restore); - - app.post("/api/upload", FileController.upload); - app.delete("/api/delete", FileController.delete); - app.get("/api/download", FileController.download); - - app.get("/api/administrativu/list", AdministrativuController.list); - app.get("/api/administrativu/export", AdministrativuController.export); - app.post("/api/administrativu/create", AdministrativuController.create); - app.put("/api/administrativu/update/:id", AdministrativuController.update); - app.delete("/api/administrativu/delete/:id/:hard", AdministrativuController.delete); - app.put("/api/administrativu/restore/:id", AdministrativuController.restore); - - app.get("/api/aldeia/list", AldeiaController.list); - app.get("/api/aldeia/export", AldeiaController.export); - app.post("/api/aldeia/create", AldeiaController.create); - app.put("/api/aldeia/update/:id", AldeiaController.update); - app.delete("/api/aldeia/delete/:id/:hard", AldeiaController.delete); - app.put("/api/aldeia/restore/:id", AldeiaController.restore); - - app.get("/api/district/list", DistrictController.list); - app.get("/api/district/export", DistrictController.export); - app.post("/api/district/create", DistrictController.create); - app.put("/api/district/update/:id", DistrictController.update); - app.delete("/api/district/delete/:id/:hard", DistrictController.delete); - app.put("/api/district/restore/:id", DistrictController.restore); - - app.get("/api/munisipo/list", MunisipoController.list); - app.get("/api/munisipo/export", MunisipoController.export); - app.post("/api/munisipo/create", MunisipoController.create); - app.put("/api/munisipo/update/:id", MunisipoController.update); - app.delete("/api/munisipo/delete/:id/:hard", MunisipoController.delete); - app.put("/api/munisipo/restore/:id", MunisipoController.restore); - - app.get("/api/suco/list", SucoController.list); - app.get("/api/suco/export", SucoController.export); - app.post("/api/suco/create", SucoController.create); - app.put("/api/suco/update/:id", SucoController.update); - app.delete("/api/suco/delete/:id/:hard", SucoController.delete); - app.put("/api/suco/restore/:id", SucoController.restore); - - app.get("/api/application/list", ApplicationController.list); - app.get("/api/application/export", ApplicationController.export); - app.post("/api/application/create", ApplicationController.create); - app.put("/api/application/update/:id", ApplicationController.update); - app.delete("/api/application/delete/:id/:hard", ApplicationController.delete); - app.put("/api/application/restore/:id", ApplicationController.restore); - - app.get("/api/nationality/list", NationalityController.list); - app.get("/api/nationality/export", NationalityController.export); - app.post("/api/nationality/create", NationalityController.create); - app.put("/api/nationality/update/:id", NationalityController.update); - app.delete("/api/nationality/delete/:id/:hard", NationalityController.delete); - app.put("/api/nationality/restore/:id", NationalityController.restore); - - app.get("/api/diagnosis/list", DiagnosisController.list); - app.post("/api/diagnosis/create", DiagnosisController.create); - app.get("/api/diagnosis/detail/:id", DiagnosisController.detail); - app.put("/api/diagnosis/update/:id", DiagnosisController.update); - app.delete("/api/diagnosis/delete/:id/:hard", DiagnosisController.delete); - app.put("/api/diagnosis/restore/:id", DiagnosisController.restore); - - app.get("/api/diagnostic-procedure/list", DiagnosticProcedureController.list); - app.post("/api/diagnostic-procedure/create", DiagnosticProcedureController.create); - app.get("/api/diagnostic-procedure/detail/:id", DiagnosticProcedureController.detail); - app.put("/api/diagnostic-procedure/update/:id", DiagnosticProcedureController.update); - app.delete("/api/diagnostic-procedure/delete/:id/:hard", DiagnosticProcedureController.delete); - app.put("/api/diagnostic-procedure/restore/:id", DiagnosticProcedureController.restore); - - app.get("/api/room/list", RoomController.list); - app.get("/api/room/option", RoomController.option); - app.post("/api/room/create", RoomController.create); - app.get("/api/room/detail/:id", RoomController.detail); - app.put("/api/room/update/:id", RoomController.update); - app.delete("/api/room/delete/:id/:hard", RoomController.delete); - app.put("/api/room/restore/:id", RoomController.restore); - app.post("/api/room/upload-picture", RoomController.uploadpicture); - app.delete("/api/room/delete-picture", RoomController.deletepicture); - app.get("/api/room/get-template-picture", RoomController.gettemplatepicture); - app.get("/api/room/list-location", RoomController.listLocation); - - app.get("/api/room-number/list", RoomNumberController.list); - app.post("/api/room-number/create", RoomNumberController.create); - app.get("/api/room-number/detail/:id", RoomNumberController.detail); - app.put("/api/room-number/update/:id", RoomNumberController.update); - app.delete("/api/room-number/delete/:id/:hard", RoomNumberController.delete); - app.put("/api/room-number/restore/:id", RoomNumberController.restore); - - app.get("/api/laboratory/list", LaboratoryController.list); - - app.get("/api/pharmacy/list", PharmacyController.list); - - app.get("/api/room-services/list", RoomServicesController.list); - app.get("/api/room-services/list-services/:room_id", RoomServicesController.listServices); - app.get("/api/room-services/list-ancillary-services", RoomServicesController.listAncillaryServices); - app.get("/api/room-services/detail/:id", RoomServicesController.detail); - app.put("/api/room-services/:id", RoomServicesController.update); - - app.get("/api/service-type/list", ServiceTypeController.list); - app.post("/api/service-type/create", ServiceTypeController.create); - app.get("/api/service-type/detail/:id", ServiceTypeController.detail); - app.put("/api/service-type/update/:id", ServiceTypeController.update); - app.delete("/api/service-type/delete/:id/:hard", ServiceTypeController.delete); - app.put("/api/service-type/restore/:id", ServiceTypeController.restore); - - app.get("/api/service-class/list", ServiceClassController.list); - app.post("/api/service-class/create", ServiceClassController.create); - app.get("/api/service-class/detail/:id", ServiceClassController.detail); - app.put("/api/service-class/update/:id", ServiceClassController.update); - app.delete("/api/service-class/delete/:id/:hard", ServiceClassController.delete); - app.put("/api/service-class/restore/:id", ServiceClassController.restore); - - app.get("/api/service/list", ServiceController.list); - app.post("/api/service/create", ServiceController.create); - app.get("/api/service/detail/:id", ServiceController.detail); - app.put("/api/service/update/:id", ServiceController.update); - app.delete("/api/service/delete/:id/:hard", ServiceController.delete); - app.put("/api/service/restore/:id", ServiceController.restore); - - app.get("/api/service-fare/list", ServiceFareController.list); - app.get("/api/service-fare/option", ServiceFareController.option); - app.post("/api/service-fare/create", ServiceFareController.create); - app.get("/api/service-fare/detail/:id", ServiceFareController.detail); - app.put("/api/service-fare/update/:id", ServiceFareController.update); - app.delete("/api/service-fare/delete/:id/:hard", ServiceFareController.delete); - app.put("/api/service-fare/restore/:id", ServiceFareController.restore); - - app.get("/api/service-package/list", ServicePackageController.list); - app.post("/api/service-package/create", ServicePackageController.create); - app.get("/api/service-package/detail/:id", ServicePackageController.detail); - app.put("/api/service-package/update/:id", ServicePackageController.update); - app.delete("/api/service-package/delete/:id/:hard", ServicePackageController.delete); - app.put("/api/service-package/restore/:id", ServicePackageController.restore); - - app.get("/api/department/list", DepartmentController.list); - app.post("/api/department/create", DepartmentController.create); - app.get("/api/department/detail/:id", DepartmentController.detail); - app.put("/api/department/update/:id", DepartmentController.update); - app.delete("/api/department/delete/:id/:hard", DepartmentController.delete); - app.put("/api/department/restore/:id", DepartmentController.restore); - - app.get("/api/doctor-schedule/list", DoctorScheduleController.list); - app.post("/api/doctor-schedule/create", DoctorScheduleController.create); - app.get("/api/doctor-schedule/detail/:id", DoctorScheduleController.detail); - app.put("/api/doctor-schedule/update/:id", DoctorScheduleController.update); - app.delete("/api/doctor-schedule/delete/:id/:hard", DoctorScheduleController.delete); - app.put("/api/doctor-schedule/restore/:id", DoctorScheduleController.restore); - - app.get("/api/schedule/list", ScheduleController.list); - app.post("/api/schedule/create", ScheduleController.create); - app.get("/api/schedule/detail/:id", ScheduleController.detail); - app.put("/api/schedule/update/:id", ScheduleController.update); - app.get("/api/schedule/options", ScheduleController.options); - app.get("/api/schedule/calendar", ScheduleController.calendar); - app.post("/api/schedule/:id/create-exception", ScheduleController.createException); - app.delete("/api/schedule/delete/:id/:hard", ScheduleController.delete); - - app.get("/api/doctor-item/list", DoctorItemController.listAll); - app.get("/api/doctor-item/list-fav", DoctorItemController.listFav); - app.post("/api/doctor-item/select-fav", DoctorItemController.selectFav); - app.delete("/api/doctor-item/remove-fav/:fav_id", DoctorItemController.removeFav); - - app.get("/api/doctor-item-package/list", DoctorItemPackageController.list); - app.post("/api/doctor-item-package/create", DoctorItemPackageController.create); - app.get("/api/doctor-item-package/detail/:id", DoctorItemPackageController.detail); - app.put("/api/doctor-item-package/update/:id", DoctorItemPackageController.update); - app.delete("/api/doctor-item-package/delete/:id", DoctorItemPackageController.delete); - - app.get("/api/measurement-unit/list", MeasurementUnitController.list); - app.post("/api/measurement-unit/create", MeasurementUnitController.create); - app.get("/api/measurement-unit/detail/:id", MeasurementUnitController.detail); - app.put("/api/measurement-unit/update/:id", MeasurementUnitController.update); - app.delete("/api/measurement-unit/delete/:id/:hard", MeasurementUnitController.delete); - app.put("/api/measurement-unit/restore/:id", MeasurementUnitController.restore); - - app.get("/api/medical-form/list", MedicalFormController.list); - app.post("/api/medical-form/create", MedicalFormController.create); - app.get("/api/medical-form/detail/:id", MedicalFormController.detail); - app.put("/api/medical-form/update/:id", MedicalFormController.update); - app.delete("/api/medical-form/delete/:id/:hard", MedicalFormController.delete); - app.put("/api/medical-form/restore/:id", MedicalFormController.restore); - - app.get("/api/reference-range/list", ReferenceRangeController.list); - app.post("/api/reference-range/create", ReferenceRangeController.create); - app.get("/api/reference-range/detail/:id", ReferenceRangeController.detail); - app.put("/api/reference-range/update/:id", ReferenceRangeController.update); - app.delete("/api/reference-range/delete/:id/:hard", ReferenceRangeController.delete); - app.put("/api/reference-range/restore/:id", ReferenceRangeController.restore); - - app.get("/api/queue-monitoring/list", QueueMonitoringController.list); - app.post("/api/queue-monitoring/create", QueueMonitoringController.create); - app.get("/api/queue-monitoring/detail/:id", QueueMonitoringController.detail); - app.get("/api/queue-monitoring/:slug", QueueMonitoringController.detailBySlug); - app.put("/api/queue-monitoring/update/:id", QueueMonitoringController.update); - app.delete("/api/queue-monitoring/delete/:id/:hard", QueueMonitoringController.delete); - app.put("/api/queue-monitoring/restore/:id", QueueMonitoringController.restore); - - app.get("/api/examination-detail/list", ExaminationDetailController.list); - app.post("/api/examination-detail/create", ExaminationDetailController.create); - app.get("/api/examination-detail/detail/:id", ExaminationDetailController.detail); - app.put("/api/examination-detail/update/:id", ExaminationDetailController.update); - app.delete("/api/examination-detail/delete/:id/:hard", ExaminationDetailController.delete); - app.put("/api/examination-detail/restore/:id", ExaminationDetailController.restore); - - app.get("/api/examination-type/list", ExaminationTypeController.list); - app.post("/api/examination-type/create", ExaminationTypeController.create); - app.get("/api/examination-type/detail/:id", ExaminationTypeController.detail); - app.put("/api/examination-type/update/:id", ExaminationTypeController.update); - app.delete("/api/examination-type/delete/:id/:hard", ExaminationTypeController.delete); - app.put("/api/examination-type/restore/:id", ExaminationTypeController.restore); - - app.get("/api/service-examination/list", ServiceExaminationController.list); - app.post("/api/service-examination/create", ServiceExaminationController.create); - app.put("/api/service-examination/:id", ServiceExaminationController.update); - - app.get("/api/hospital-information/view", HospitalInformationController.view); - app.post("/api/hospital-information/create", HospitalInformationController.create); - app.post("/api/hospital-information/upload-logo", HospitalInformationController.uploadlogo); - app.delete("/api/hospital-information/delete-logo", HospitalInformationController.deletelogo); - - app.get("/api/pharmacy/item-group/list", ItemGroupController.list); - app.get("/api/pharmacy/item-group/export", ItemGroupController.export); - app.post("/api/pharmacy/item-group/create", ItemGroupController.create); - app.put("/api/pharmacy/item-group/update/:id", ItemGroupController.update); - app.delete("/api/pharmacy/item-group/delete/:id/:hard", ItemGroupController.delete); - app.put("/api/pharmacy/item-group/restore/:id", ItemGroupController.restore); - - app.get("/api/pharmacy/item-origin/list", ItemOriginController.list); - app.get("/api/pharmacy/item-origin/option", ItemOriginController.option); - app.get("/api/pharmacy/item-origin/export", ItemOriginController.export); - app.post("/api/pharmacy/item-origin/create", ItemOriginController.create); - app.put("/api/pharmacy/item-origin/update/:id", ItemOriginController.update); - app.delete("/api/pharmacy/item-origin/delete/:id/:hard", ItemOriginController.delete); - app.put("/api/pharmacy/item-origin/restore/:id", ItemOriginController.restore); - - app.get("/api/pharmacy/item-type/list", ItemTypeController.list); - app.get("/api/pharmacy/item-type/export", ItemTypeController.export); - app.post("/api/pharmacy/item-type/create", ItemTypeController.create); - app.put("/api/pharmacy/item-type/update/:id", ItemTypeController.update); - app.delete("/api/pharmacy/item-type/delete/:id/:hard", ItemTypeController.delete); - app.put("/api/pharmacy/item-type/restore/:id", ItemTypeController.restore); - - app.get("/api/pharmacy/item-type-detail/list", ItemTypeDetailController.list); - app.get("/api/pharmacy/item-type-detail/export", ItemTypeDetailController.export); - app.post("/api/pharmacy/item-type-detail/create", ItemTypeDetailController.create); - app.put("/api/pharmacy/item-type-detail/update/:id", ItemTypeDetailController.update); - app.delete("/api/pharmacy/item-type-detail/delete/:id/:hard", ItemTypeDetailController.delete); - app.put("/api/pharmacy/item-type-detail/restore/:id", ItemTypeDetailController.restore); - - app.get("/api/pharmacy/unit/list", UnitController.list); - app.get("/api/pharmacy/unit/export", UnitController.export); - app.post("/api/pharmacy/unit/create", UnitController.create); - app.put("/api/pharmacy/unit/update/:id", UnitController.update); - app.delete("/api/pharmacy/unit/delete/:id/:hard", UnitController.delete); - app.put("/api/pharmacy/unit/restore/:id", UnitController.restore); - - app.get("/api/currency/list", CurrencyController.list); - app.post("/api/currency/create", CurrencyController.create); - app.put("/api/currency/update/:id", CurrencyController.update); - app.delete("/api/currency/delete/:id/:hard", CurrencyController.delete); - - app.get("/api/inpatient-room/list", InpatientRoomController.list); - app.post("/api/inpatient-room/create", InpatientRoomController.create); - app.get("/api/inpatient-room/detail/:id", InpatientRoomController.detail); - app.put("/api/inpatient-room/update/:id", InpatientRoomController.update); - app.delete("/api/inpatient-room/delete/:id/:hard", InpatientRoomController.delete); - - app.get("/api/surgery-room/list", SurgeryRoomController.list); - app.post("/api/surgery-room/create", SurgeryRoomController.create); - app.get("/api/surgery-room/detail/:id", SurgeryRoomController.detail); - app.put("/api/surgery-room/update/:id", SurgeryRoomController.update); - app.delete("/api/surgery-room/delete/:id/:hard", SurgeryRoomController.delete); - - app.get("/api/surgery-type/list", SurgeryTypeController.list); - app.post("/api/surgery-type/create", SurgeryTypeController.create); - app.get("/api/surgery-type/detail/:id", SurgeryTypeController.detail); - app.put("/api/surgery-type/update/:id", SurgeryTypeController.update); - app.delete("/api/surgery-type/delete/:id/:hard", SurgeryTypeController.delete); - - app.get("/api/pharmacy/item-category/list", ItemCategoryController.list); - app.get("/api/pharmacy/item-category/export", ItemCategoryController.export); - app.post("/api/pharmacy/item-category/create", ItemCategoryController.create); - app.put("/api/pharmacy/item-category/update/:id", ItemCategoryController.update); - app.delete("/api/pharmacy/item-category/delete/:id/:hard", ItemCategoryController.delete); - app.put("/api/pharmacy/item-category/restore/:id", ItemCategoryController.restore); - - app.get("/api/pharmacy/item-status/list", ItemStatusController.list); - app.get("/api/pharmacy/item-status/export", ItemStatusController.export); - app.post("/api/pharmacy/item-status/create", ItemStatusController.create); - app.put("/api/pharmacy/item-status/update/:id", ItemStatusController.update); - app.delete("/api/pharmacy/item-status/delete/:id/:hard", ItemStatusController.delete); - app.put("/api/pharmacy/item-status/restore/:id", ItemStatusController.restore); - - app.get("/api/pharmacy/usage-instructions/list", UsageInstructionsController.list); - app.get("/api/pharmacy/usage-instructions/export", UsageInstructionsController.export); - app.post("/api/pharmacy/usage-instructions/create", UsageInstructionsController.create); - app.put("/api/pharmacy/usage-instructions/update/:id", UsageInstructionsController.update); - app.delete("/api/pharmacy/usage-instructions/delete/:id/:hard", UsageInstructionsController.delete); - app.put("/api/pharmacy/usage-instructions/restore/:id", UsageInstructionsController.restore); - - app.get("/api/pharmacy/usage-time/list", UsageTimeController.list); - app.get("/api/pharmacy/usage-time/export", UsageTimeController.export); - app.post("/api/pharmacy/usage-time/create", UsageTimeController.create); - app.put("/api/pharmacy/usage-time/update/:id", UsageTimeController.update); - app.delete("/api/pharmacy/usage-time/delete/:id/:hard", UsageTimeController.delete); - app.put("/api/pharmacy/usage-time/restore/:id", UsageTimeController.restore); - - app.get("/api/pharmacy/item-class/list", ItemClassController.list); - app.get("/api/pharmacy/item-class/export", ItemClassController.export); - app.post("/api/pharmacy/item-class/create", ItemClassController.create); - app.put("/api/pharmacy/item-class/update/:id", ItemClassController.update); - app.delete("/api/pharmacy/item-class/delete/:id/:hard", ItemClassController.delete); - app.put("/api/pharmacy/item-class/restore/:id", ItemClassController.restore); - - app.get("/api/pharmacy/item-class-detail/list", ItemClassDetailController.list); - app.get("/api/pharmacy/item-class-detail/export", ItemClassDetailController.export); - app.post("/api/pharmacy/item-class-detail/create", ItemClassDetailController.create); - app.put("/api/pharmacy/item-class-detail/update/:id", ItemClassDetailController.update); - app.delete("/api/pharmacy/item-class-detail/delete/:id/:hard", ItemClassDetailController.delete); - app.put("/api/pharmacy/item-class-detail/restore/:id", ItemClassDetailController.restore); - - app.get("/api/pharmacy/generic-name/list", GenericNameController.list); - app.get("/api/pharmacy/generic-name/export", GenericNameController.export); - app.post("/api/pharmacy/generic-name/create", GenericNameController.create); - app.put("/api/pharmacy/generic-name/update/:id", GenericNameController.update); - app.delete("/api/pharmacy/generic-name/delete/:id/:hard", GenericNameController.delete); - app.put("/api/pharmacy/generic-name/restore/:id", GenericNameController.restore); - - app.get("/api/pharmacy/factory/list", FactoryController.list); - app.get("/api/pharmacy/factory/export", FactoryController.export); - app.post("/api/pharmacy/factory/create", FactoryController.create); - app.put("/api/pharmacy/factory/update/:id", FactoryController.update); - app.delete("/api/pharmacy/factory/delete/:id/:hard", FactoryController.delete); - app.put("/api/pharmacy/factory/restore/:id", FactoryController.restore); - - app.get("/api/pharmacy/supplier/list", SupplierController.list); - app.get("/api/pharmacy/supplier/option", SupplierController.option); - app.get("/api/pharmacy/supplier/export", SupplierController.export); - app.post("/api/pharmacy/supplier/create", SupplierController.create); - app.put("/api/pharmacy/supplier/update/:id", SupplierController.update); - app.delete("/api/pharmacy/supplier/delete/:id/:hard", SupplierController.delete); - app.put("/api/pharmacy/supplier/restore/:id", SupplierController.restore); - - app.get("/api/pharmacy/factory-to-supplier/list", FactorytoSupplierController.list); - app.get("/api/pharmacy/factory-to-supplier/export", FactorytoSupplierController.export); - app.post("/api/pharmacy/factory-to-supplier/create", FactorytoSupplierController.create); - // app.put('/api/pharmacy/factory-to-supplier/update/:supplier_id', FactorytoSupplierController.update) - // app.delete('/api/pharmacy/factory-to-supplier/delete/:supplier_id/:hard', FactorytoSupplierController.delete) - // app.put('/api/pharmacy/factory-to-supplier/restore/:supplier_id', FactorytoSupplierController.restore) - - app.get("/api/pharmacy/item-master/list", ItemMasterController.list); - app.get("/api/pharmacy/item-master/option", ItemMasterController.option); - app.get("/api/pharmacy/item-master/export", ItemMasterController.export); - app.post("/api/pharmacy/item-master/create", ItemMasterController.create); - app.put("/api/pharmacy/item-master/update/:id", ItemMasterController.update); - app.delete("/api/pharmacy/item-master/delete/:id/:hard", ItemMasterController.delete); - app.put("/api/pharmacy/item-master/restore/:id", ItemMasterController.restore); - - app.get("/api/pharmacy/pharmacy-info/list", PharmacyInfoController.list); - app.get("/api/pharmacy/pharmacy-info/export", PharmacyInfoController.export); - app.post("/api/pharmacy/pharmacy-info/create", PharmacyInfoController.create); - app.put("/api/pharmacy/pharmacy-info/update/:id", PharmacyInfoController.update); - app.delete("/api/pharmacy/pharmacy-info/delete/:id/:hard", PharmacyInfoController.delete); - app.put("/api/pharmacy/pharmacy-info/restore/:id", PharmacyInfoController.restore); - app.post("/api/pharmacy/pharmacy-info/upload-logo", PharmacyInfoController.uploadlogo); - app.delete("/api/pharmacy/pharmacy-info/delete-logo", PharmacyInfoController.deletelogo); - app.get("/api/pharmacy/pharmacy-info/view/:id", PharmacyInfoController.detail); - - app.get("/api/pharmacy/item-price/list", ItemPriceController.list); - app.get("/api/pharmacy/item-price/export", ItemPriceController.export); - app.post("/api/pharmacy/item-price/create", ItemPriceController.create); - app.put("/api/pharmacy/item-price/update/:id", ItemPriceController.update); - app.delete("/api/pharmacy/item-price/delete/:id/:hard", ItemPriceController.delete); - app.put("/api/pharmacy/item-price/restore/:id", ItemPriceController.restore); - - app.get("/api/pharmacy/selling-price-percentage/list", SellingPricePercentageController.list); - app.get("/api/pharmacy/selling-price-percentage/export", SellingPricePercentageController.export); - app.post("/api/pharmacy/selling-price-percentage/create", SellingPricePercentageController.create); - app.put("/api/pharmacy/selling-price-percentage/update/:id", SellingPricePercentageController.update); - app.delete("/api/pharmacy/selling-price-percentage/delete/:id/:hard", SellingPricePercentageController.delete); - app.put("/api/pharmacy/selling-price-percentage/restore/:id", SellingPricePercentageController.restore); - - app.get("/api/patient-group/list", PatientGroupController.list); - app.get("/api/patient-group/export", PatientGroupController.export); - app.post("/api/patient-group/create", PatientGroupController.create); - app.put("/api/patient-group/update/:id", PatientGroupController.update); - app.delete("/api/patient-group/delete/:id/:hard", PatientGroupController.delete); - app.put("/api/patient-group/restore/:id", PatientGroupController.restore); - app.get("/api/patient-group/view/:id", PatientGroupController.detail); - - app.get("/api/patient-guarantor/list", PatientGuarantorController.list); - app.get("/api/patient-guarantor/export", PatientGuarantorController.export); - app.post("/api/patient-guarantor/create", PatientGuarantorController.create); - app.put("/api/patient-guarantor/update/:id", PatientGuarantorController.update); - app.delete("/api/patient-guarantor/delete/:id/:hard", PatientGuarantorController.delete); - app.put("/api/patient-guarantor/restore/:id", PatientGuarantorController.restore); - app.get("/api/patient-guarantor/view/:id", PatientGuarantorController.detail); - - app.get("/api/refferal-hospital/list", RefferalHospitalController.list); - app.get("/api/refferal-hospital/option", RefferalHospitalController.option); - app.get("/api/refferal-hospital/export", RefferalHospitalController.export); - app.post("/api/refferal-hospital/create", RefferalHospitalController.create); - app.put("/api/refferal-hospital/update/:id", RefferalHospitalController.update); - app.delete("/api/refferal-hospital/delete/:id/:hard", RefferalHospitalController.delete); - app.put("/api/refferal-hospital/restore/:id", RefferalHospitalController.restore); - - app.get("/api/initial-stock/list", InitialStockController.list); - app.post("/api/initial-stock/create", InitialStockController.create); - - app.get("/api/user-to-room/list", UserToRoomController.list); - app.get("/api/user-to-room/export", UserToRoomController.export); - app.put("/api/user-to-room/update/:user_id", UserToRoomController.update); - app.get("/api/user-to-room/view/:id", UserToRoomController.detail); - app.get("/api/user-to-room/list-room", UserToRoomController.listRoom); - app.get("/api/user-to-room/list-room/:user_id", UserToRoomController.listRoomByUser); - - app.get("/api/room-to-pharmacy/list", RoomToPharmacyController.list); - app.get("/api/room-to-pharmacy/export", RoomToPharmacyController.export); - // app.post('/api/room-to-pharmacy/create', RoomToPharmacyController.create) - app.put("/api/room-to-pharmacy/update/:room_id", RoomToPharmacyController.update); - app.get("/api/room-to-pharmacy/view/:id", RoomToPharmacyController.detail); - - app.get("/api/pharmacy/planning-verificator/list", PlanningVerificatorController.list); - app.get("/api/pharmacy/planning-verificator/export", PlanningVerificatorController.export); - app.post("/api/pharmacy/planning-verificator/create", PlanningVerificatorController.create); - app.delete("/api/pharmacy/planning-verificator/delete/:id/:hard", PlanningVerificatorController.delete); - app.put("/api/pharmacy/planning-verificator/restore/:id", PlanningVerificatorController.restore); - - app.get("/api/fare-type/list", FareTypeController.list); - app.get("/api/fare-type/option", FareTypeController.option); - app.get("/api/fare-type/detail/:id", FareTypeController.detail); - app.post("/api/fare-type/create", FareTypeController.create); - app.put("/api/fare-type/update/:id", FareTypeController.update); - app.delete("/api/fare-type/delete/:id/:hard", FareTypeController.delete); - app.put("/api/fare-type/restore/:id", FareTypeController.restore); - - app.get("/api/card-type/list", CardTypeController.list); - app.post("/api/card-type/create", CardTypeController.create); - app.get("/api/card-type/detail/:id", CardTypeController.detail); - app.put("/api/card-type/update/:id", CardTypeController.update); - app.delete("/api/card-type/delete/:id/:hard", CardTypeController.delete); - app.put("/api/card-type/restore/:id", CardTypeController.restore); - - app.get("/api/card-print-queue/list", CardPrintQueueController.list); - app.post("/api/card-print-queue/create", CardPrintQueueController.create); - app.post("/api/card-print-queue/create/provision", CardPrintQueueController.createProvision); - app.post("/api/card-print-queue/create/print", CardPrintQueueController.createPrint); - app.get("/api/card-print-queue/detail/:id", CardPrintQueueController.detail); - - app.get("/api/payment-method/list", PaymentMethodController.list); - app.post("/api/payment-method/create", PaymentMethodController.create); - app.get("/api/payment-method/detail/:id", PaymentMethodController.detail); - app.put("/api/payment-method/update/:id", PaymentMethodController.update); - app.delete("/api/payment-method/delete/:id/:hard", PaymentMethodController.delete); - app.put("/api/payment-method/restore/:id", PaymentMethodController.restore); - - app.get("/api/registration-fee/detail", RegistrationFeeController.detail); - app.post("/api/registration-fee/create", RegistrationFeeController.create); - app.put("/api/registration-fee/update/:id", RegistrationFeeController.update); - - app.get("/api/region/province", RegionController.province); - app.get("/api/region/city/:province_code", RegionController.city); - app.get("/api/region/subdistrict/:city_code", RegionController.subdistrict); - app.get("/api/region/ward/:subdistric_code", RegionController.ward); - - app.get("/api/responsible-party-consent/body", ResponsiblePartyConsentController.body); - app.post("/api/responsible-party-consent/create", ResponsiblePartyConsentController.create); - app.put("/api/responsible-party-consent/update/:id", ResponsiblePartyConsentController.update); - - app.get("/api/foster-care-history/list", FosterCareHistoryController.list); - app.post("/api/foster-care-history/create", FosterCareHistoryController.create); - app.get("/api/foster-care-history/detail/:id", FosterCareHistoryController.detail); - app.put("/api/foster-care-history/update/:id", FosterCareHistoryController.update); - app.delete("/api/foster-care-history/delete/:id/:hard", FosterCareHistoryController.delete); - app.put("/api/foster-care-history/restore/:id", FosterCareHistoryController.restore); + app.get("/api/site-points/list", SitePointsController.list); + app.get("/api/site-points/all-data", SitePointsController.alldatas); + app.get("/api/site-points/export", SitePointsController.export); + app.post("/api/site-points/create", SitePointsController.create); + app.put("/api/site-points/update/:id", SitePointsController.update); + app.delete("/api/site-points/delete/:id/:hard", SitePointsController.delete); + app.put("/api/site-points/restore/:id", SitePointsController.restore); } } diff --git a/src/scripts/seed-diagnoses-data.ts b/src/scripts/seed-diagnoses-data.ts deleted file mode 100644 index efa07d3..0000000 --- a/src/scripts/seed-diagnoses-data.ts +++ /dev/null @@ -1,155 +0,0 @@ -/** - * Usage: - * ts-node src/scripts/seed-diagnoses-data.ts - * npm run seeder - */ - -import { ILogObj, Logger } from "tslog"; -import { Diagnosis, DiagnosticProcedure, Department, Status } from "entity"; -import { OrmHelper } from "../helpers/orm"; -import fs from "fs"; -import path from "path"; - -const log: Logger = new Logger({ - name: "[seed-diagnoses-data]", - type: "pretty", -}); - -function sleep(ms: number) { - return new Promise((resolve) => setTimeout(resolve, ms)); -} - -async function waitForDbInitialized(timeoutMs: number = 15000) { - const start = Date.now(); - while (!OrmHelper.DB || !OrmHelper.DB.isInitialized) { - if (Date.now() - start > timeoutMs) { - throw new Error("Database initialization timeout"); - } - await sleep(100); - } -} - -async function ensureMasterDataSchemaReady() { - const qr = OrmHelper.DB.createQueryRunner(); - try { - const hasDiagnoses = await qr.hasTable("diagnoses"); - const hasDiagnosticProcedures = await qr.hasTable("diagnostic_procedures"); - const hasDepartments = await qr.hasTable("departments"); - - if (!hasDiagnoses) throw new Error('Table "diagnoses" not found'); - if (!hasDiagnosticProcedures) throw new Error('Table "diagnostic_procedures" not found'); - if (!hasDepartments) throw new Error('Table "departments" not found'); - } finally { - await qr.release(); - } -} - -function parseStatus(value: any): Status { - if (value === "Y") return Status.Active; - if (value === "N") return Status["Not Active"]; - return Status.Active; -} - -function parseNullableString(value: any) { - if (value === undefined || value === null) return null; - const s = String(value).trim(); - return s === "" ? null : s; -} - -function parseNullableDate(value: any): Date | null { - if (!value) return null; - const d = new Date(value); - return Number.isNaN(d.getTime()) ? null : d; -} - -async function upsertDepartment(data: any) { - const repo = OrmHelper.DB.getRepository(Department); - - let row = await repo.findOne({ where: { id: data.id } }); - - if (!row) { - row = new Department(); - row.id = data.id; - } - - row.name = data.name; - row.status = parseStatus(data.status); - - row.created_at = parseNullableDate(data.created_at) ?? row.created_at; - row.updated_at = parseNullableDate(data.updated_at) ?? row.updated_at; - row.deleted_at = parseNullableDate(data.deleted_at) ?? row.deleted_at; - return await repo.save(row); -} - -async function main() { - OrmHelper.setup(); - await waitForDbInitialized(); - - try { - log.info("Starting seed diagnoses data..."); - await ensureMasterDataSchemaReady(); - - const seedDir = path.resolve(process.cwd(), "seed", "diagnoses"); - - const filesByPrefix = { - diagnoses_: fs.readdirSync(seedDir).filter(f => f.startsWith("diagnoses_")), - diagnostic_procedures_: fs.readdirSync(seedDir).filter(f => f.startsWith("diagnostic_procedures_")), - departments_: fs.readdirSync(seedDir).filter(f => f.startsWith("departments_")), - }; - - // ====================== - // EXISTING LOGIC (UNCHANGED) - // ====================== - // diagnoses & procedures tetap jalan seperti sebelumnya - // (tidak diubah sesuai permintaan kamu) - - // ====================== - // ✅ NEW: DEPARTMENTS - // ====================== - let departmentsTotal = 0; - - for (const file of filesByPrefix.departments_) { - const filePath = path.join(seedDir, file); - const raw = await fs.promises.readFile(filePath, "utf8"); - const json = JSON.parse(raw); - - const rows = - json["select * from public.departments d "] || []; - - if (!Array.isArray(rows)) { - throw new Error(`Invalid JSON structure: ${file}`); - } - - let processed = 0; - - for (const row of rows) { - if (!row.id) { - throw new Error(`Missing department id in ${file}`); - } - - await upsertDepartment(row); - processed++; - } - - departmentsTotal += processed; - - log.info("Seeded departments file", { - file, - rows: processed, - }); - } - - log.info("Seed summary", { - departments: departmentsTotal, - }); - - log.info("✅ Seeder completed"); - process.exit(0); - - } catch (error) { - log.error("Fatal error:", error); - process.exit(1); - } -} - -main(); \ No newline at end of file diff --git a/src/scripts/seed-site-points.ts b/src/scripts/seed-site-points.ts new file mode 100644 index 0000000..ea3c2b5 --- /dev/null +++ b/src/scripts/seed-site-points.ts @@ -0,0 +1,43 @@ +import { OrmHelper } from "../helpers/orm" +import { SitePoints } from "entity" +import { sitePoints } from "../sitePointsData" + +async function seed() { + console.log(`Memulai import ${sitePoints.length} data site points...`) + + try { + await OrmHelper.setup() // sekarang bisa di-await dengan benar + + const entities: SitePoints[] = sitePoints.map((row) => { + const data = new SitePoints() + data.cell = row.cell + data.sector = row.sector + data.site = row.site + data.lat = row.lat + data.lng = row.lng + data.location = row.location + return data + }) + + const batchSize = 100 + let savedCount = 0 + + for (let i = 0; i < entities.length; i += batchSize) { + const batch = entities.slice(i, i + batchSize) + await OrmHelper.DB.manager.save(SitePoints, batch) + savedCount += batch.length + console.log(`Progress: ${savedCount}/${entities.length}`) + } + + console.log(`✅ Berhasil import ${savedCount} data!`) + } catch (error) { + console.error("❌ Gagal import:", error) + } finally { + if (OrmHelper.DB?.isInitialized) { + await OrmHelper.DB.destroy() + } + process.exit(0) + } +} + +seed() \ No newline at end of file diff --git a/src/server.ts b/src/server.ts index 8f97f0d..2870fd8 100644 --- a/src/server.ts +++ b/src/server.ts @@ -11,7 +11,6 @@ import { RoutePrivate } from './routes/private'; import { RoutePublic } from './routes/public'; import { Language } from './langs/lang'; import { SwaggerHelper } from './helpers/express/swagger'; -import { UploadHelper } from './helpers/express/upload'; const app = express(); app.use( @@ -20,7 +19,6 @@ app.use( ); -UploadHelper.setup(app) CorsHelper.setup(app); CompressionHelper.setup(app); MorganHelper.setup(app); diff --git a/src/sitePointsData.ts b/src/sitePointsData.ts new file mode 100644 index 0000000..85a5fea --- /dev/null +++ b/src/sitePointsData.ts @@ -0,0 +1,1161 @@ +// Auto-generated from Sites_Coordinates_untuk_CC.xlsm (sheet: site coordinates 4G) +// 1 entry per Cell/Sector row, as provided in the source Excel file. +export interface SitePoint { + cell: string; + sector: string; + site: string; + lat: number; + lng: number; + location: string; +} + +export const sitePoints: SitePoint[] = [ + { cell: 'ACAD1E', sector: 'ACAD#1', site: 'ACADIRUHUN', lat: -8.55465, lng: 125.588254, location: 'Dili' }, + { cell: 'ACAD1F', sector: 'ACAD#1F', site: 'ACADIRUHUN', lat: -8.55465, lng: 125.588254, location: 'Dili' }, + { cell: 'ACAD2E', sector: 'ACAD#2', site: 'ACADIRUHUN', lat: -8.55465, lng: 125.588254, location: 'Dili' }, + { cell: 'ACAD2F', sector: 'ACAD#2F', site: 'ACADIRUHUN', lat: -8.55465, lng: 125.588254, location: 'Dili' }, + { cell: 'ACAD3E', sector: 'ACAD#3', site: 'ACADIRUHUN', lat: -8.55465, lng: 125.588254, location: 'Dili' }, + { cell: 'ACAD3F', sector: 'ACAD#3F', site: 'ACADIRUHUN', lat: -8.55465, lng: 125.588254, location: 'Dili' }, + { cell: 'ACAD4E', sector: 'ACAD#4', site: 'ACADIRUHUN', lat: -8.55465, lng: 125.588254, location: 'Dili' }, + { cell: 'ACAD4F', sector: 'ACAD#4F', site: 'ACADIRUHUN', lat: -8.55465, lng: 125.588254, location: 'Dili' }, + { cell: 'ACAD5E', sector: 'ACAD#5', site: 'ACADIRUHUN', lat: -8.55465, lng: 125.588254, location: 'Dili' }, + { cell: 'ACAD5F', sector: 'ACAD#5F', site: 'ACADIRUHUN', lat: -8.55465, lng: 125.588254, location: 'Dili' }, + { cell: 'ACAD6E', sector: 'ACAD#6', site: 'ACADIRUHUN', lat: -8.55465, lng: 125.588254, location: 'Dili' }, + { cell: 'ACAD6F', sector: 'ACAD#6F', site: 'ACADIRUHUN', lat: -8.55465, lng: 125.588254, location: 'Dili' }, + { cell: 'AERP1E', sector: 'AERP#1', site: 'DILI AEROPORTO', lat: -8.550135, lng: 125.522269, location: 'Dili' }, + { cell: 'AERP1F', sector: 'AERP#1F', site: 'DILI AEROPORTO', lat: -8.550135, lng: 125.522269, location: 'Dili' }, + { cell: 'AERP2E', sector: 'AERP#2', site: 'DILI AEROPORTO', lat: -8.550135, lng: 125.522269, location: 'Dili' }, + { cell: 'AERP2F', sector: 'AERP#2F', site: 'DILI AEROPORTO', lat: -8.550135, lng: 125.522269, location: 'Dili' }, + { cell: 'AERP3E', sector: 'AERP#3', site: 'DILI AEROPORTO', lat: -8.550135, lng: 125.522269, location: 'Dili' }, + { cell: 'AERP3F', sector: 'AERP#3F', site: 'DILI AEROPORTO', lat: -8.550135, lng: 125.522269, location: 'Dili' }, + { cell: 'AERP4E', sector: 'AERP#4E', site: 'DILI AEROPORTO', lat: -8.550135, lng: 125.522269, location: 'Dili' }, + { cell: 'AERP4F', sector: 'AERP#4F', site: 'DILI AEROPORTO', lat: -8.550135, lng: 125.522269, location: 'Dili' }, + { cell: 'AERP5E', sector: 'AERP#5E', site: 'DILI AEROPORTO', lat: -8.550135, lng: 125.522269, location: 'Dili' }, + { cell: 'AERP5F', sector: 'AERP#5F', site: 'DILI AEROPORTO', lat: -8.550135, lng: 125.522269, location: 'Dili' }, + { cell: 'AERP6E', sector: 'AERP#6E', site: 'DILI AEROPORTO', lat: -8.550135, lng: 125.522269, location: 'Dili' }, + { cell: 'AERP6F', sector: 'AERP#6F', site: 'DILI AEROPORTO', lat: -8.550135, lng: 125.522269, location: 'Dili' }, + { cell: 'AHUN1E', sector: 'AHUN#1', site: 'AINITAS HUN', lat: -8.57605, lng: 125.583067, location: 'Dili' }, + { cell: 'AHUN1F', sector: 'AHUN#1F', site: 'AINITAS HUN', lat: -8.57605, lng: 125.583067, location: 'Dili' }, + { cell: 'AHUN2E', sector: 'AHUN#2', site: 'AINITAS HUN', lat: -8.57605, lng: 125.583067, location: 'Dili' }, + { cell: 'AHUN2F', sector: 'AHUN#2F', site: 'AINITAS HUN', lat: -8.57605, lng: 125.583067, location: 'Dili' }, + { cell: 'AHUN3E', sector: 'AHUN#3', site: 'AINITAS HUN', lat: -8.57605, lng: 125.583067, location: 'Dili' }, + { cell: 'AHUN3F', sector: 'AHUN#3F', site: 'AINITAS HUN', lat: -8.57605, lng: 125.583067, location: 'Dili' }, + { cell: 'AHUN4E', sector: 'AHUN4E', site: 'AINITAS HUN', lat: -8.57605, lng: 125.583067, location: 'Dili' }, + { cell: 'AHUN4F', sector: 'AHUN4F', site: 'AINITAS HUN', lat: -8.57605, lng: 125.583067, location: 'Dili' }, + { cell: 'AHUN5E', sector: 'AHUN5E', site: 'AINITAS HUN', lat: -8.57605, lng: 125.583067, location: 'Dili' }, + { cell: 'AHUN5F', sector: 'AHUN5F', site: 'AINITAS HUN', lat: -8.57605, lng: 125.583067, location: 'Dili' }, + { cell: 'AHUN6E', sector: 'AHUN6E', site: 'AINITAS HUN', lat: -8.57605, lng: 125.583067, location: 'Dili' }, + { cell: 'AHUN6F', sector: 'AHUN6F', site: 'AINITAS HUN', lat: -8.57605, lng: 125.583067, location: 'Dili' }, + { cell: 'AIMU1E', sector: 'AIMU#1', site: 'AIMUTIN', lat: -8.559, lng: 125.5512, location: 'Dili' }, + { cell: 'AIMU1F', sector: 'AIMU#1F', site: 'AIMUTIN', lat: -8.559, lng: 125.5512, location: 'Dili' }, + { cell: 'AIMU2E', sector: 'AIMU#2', site: 'AIMUTIN', lat: -8.559, lng: 125.5512, location: 'Dili' }, + { cell: 'AIMU2F', sector: 'AIMU#2F', site: 'AIMUTIN', lat: -8.559, lng: 125.5512, location: 'Dili' }, + { cell: 'AIMU3E', sector: 'AIMU#3', site: 'AIMUTIN', lat: -8.559, lng: 125.5512, location: 'Dili' }, + { cell: 'AIMU3F', sector: 'AIMU#3F', site: 'AIMUTIN', lat: -8.559, lng: 125.5512, location: 'Dili' }, + { cell: 'AIMU4E', sector: 'AIMU4', site: 'AIMUTIN', lat: -8.559, lng: 125.5512, location: 'Dili' }, + { cell: 'AIMU4F', sector: 'AIMU#4F', site: 'AIMUTIN', lat: -8.559, lng: 125.5512, location: 'Dili' }, + { cell: 'AIMU5E', sector: 'AIMU5', site: 'AIMUTIN', lat: -8.559, lng: 125.5512, location: 'Dili' }, + { cell: 'AIMU5F', sector: 'AIMU#5F', site: 'AIMUTIN', lat: -8.559, lng: 125.5512, location: 'Dili' }, + { cell: 'AIMU6E', sector: 'AIMU6', site: 'AIMUTIN', lat: -8.559, lng: 125.5512, location: 'Dili' }, + { cell: 'AIMU6F', sector: 'AIMU#6F', site: 'AIMUTIN', lat: -8.559, lng: 125.5512, location: 'Dili' }, + { cell: 'AITE1E', sector: 'AITE#1', site: 'AIMUTIN TELEMOR', lat: -8.556629, lng: 125.545951, location: 'Dili' }, + { cell: 'AITE1F', sector: 'AITE#1F', site: 'AIMUTIN TELEMOR', lat: -8.556629, lng: 125.545951, location: 'Dili' }, + { cell: 'AITE2E', sector: 'AITE#2', site: 'AIMUTIN TELEMOR', lat: -8.556629, lng: 125.545951, location: 'Dili' }, + { cell: 'AITE2F', sector: 'AITE#2F', site: 'AIMUTIN TELEMOR', lat: -8.556629, lng: 125.545951, location: 'Dili' }, + { cell: 'AITE3E', sector: 'AITE#3', site: 'AIMUTIN TELEMOR', lat: -8.556629, lng: 125.545951, location: 'Dili' }, + { cell: 'AITE3F', sector: 'AITE#3F', site: 'AIMUTIN TELEMOR', lat: -8.556629, lng: 125.545951, location: 'Dili' }, + { cell: 'AITE4E', sector: 'AITE#4', site: 'AIMUTIN TELEMOR', lat: -8.556629, lng: 125.545951, location: 'Dili' }, + { cell: 'AITE4F', sector: 'AITE#4F', site: 'AIMUTIN TELEMOR', lat: -8.556629, lng: 125.545951, location: 'Dili' }, + { cell: 'AITE5E', sector: 'AITE#5', site: 'AIMUTIN TELEMOR', lat: -8.556629, lng: 125.545951, location: 'Dili' }, + { cell: 'AITE5F', sector: 'AITE#5F', site: 'AIMUTIN TELEMOR', lat: -8.556629, lng: 125.545951, location: 'Dili' }, + { cell: 'AITE6E', sector: 'AITE#6', site: 'AIMUTIN TELEMOR', lat: -8.556629, lng: 125.545951, location: 'Dili' }, + { cell: 'AITE6F', sector: 'AITE#6F', site: 'AIMUTIN TELEMOR', lat: -8.556629, lng: 125.545951, location: 'Dili' }, + { cell: 'AITL1E', sector: 'AITL#1', site: 'AITARAK LARAN', lat: -8.555907, lng: 125.563896, location: 'Dili' }, + { cell: 'AITL1F', sector: 'AITL#1F', site: 'AITARAK LARAN', lat: -8.555907, lng: 125.563896, location: 'Dili' }, + { cell: 'AITL2E', sector: 'AITL#2', site: 'AITARAK LARAN', lat: -8.555907, lng: 125.563896, location: 'Dili' }, + { cell: 'AITL2F', sector: 'AITL#2F', site: 'AITARAK LARAN', lat: -8.555907, lng: 125.563896, location: 'Dili' }, + { cell: 'AITL3E', sector: 'AITL#3', site: 'AITARAK LARAN', lat: -8.555907, lng: 125.563896, location: 'Dili' }, + { cell: 'AITL3F', sector: 'AITL#F', site: 'AITARAK LARAN', lat: -8.555907, lng: 125.563896, location: 'Dili' }, + { cell: 'AITL4E', sector: 'AITL#4', site: 'AITARAK LARAN', lat: -8.555907, lng: 125.563896, location: 'Dili' }, + { cell: 'AITL4F', sector: 'AITL#4F', site: 'AITARAK LARAN', lat: -8.555907, lng: 125.563896, location: 'Dili' }, + { cell: 'AITL5E', sector: 'AITL#5', site: 'AITARAK LARAN', lat: -8.555907, lng: 125.563896, location: 'Dili' }, + { cell: 'AITL5F', sector: 'AITL#5F', site: 'AITARAK LARAN', lat: -8.555907, lng: 125.563896, location: 'Dili' }, + { cell: 'AITL6E', sector: 'AITL#6', site: 'AITARAK LARAN', lat: -8.555907, lng: 125.563896, location: 'Dili' }, + { cell: 'AITL6F', sector: 'AITL#6F', site: 'AITARAK LARAN', lat: -8.555907, lng: 125.563896, location: 'Dili' }, + { cell: 'AITU1E', sector: 'AITU#1', site: 'AITURI LARAN', lat: -8.578361, lng: 125.595252, location: 'DILI' }, + { cell: 'AITU2E', sector: 'AITU#2', site: 'AITURI LARAN', lat: -8.578361, lng: 125.595252, location: 'DILI' }, + { cell: 'AITU3E', sector: 'AITU#2', site: 'AITURI LARAN', lat: -8.578361, lng: 125.595252, location: 'DILI' }, + { cell: 'ARBC1E', sector: 'ARBC#1', site: 'AREA BRANCA', lat: -8.530737, lng: 125.61606, location: 'Dili' }, + { cell: 'ARBC1F', sector: 'ARBC#1F', site: 'AREA BRANCA', lat: -8.530737, lng: 125.61606, location: 'Dili' }, + { cell: 'ARBC2E', sector: 'ARBC#2', site: 'AREA BRANCA', lat: -8.530737, lng: 125.61606, location: 'Dili' }, + { cell: 'ARBC2F', sector: 'ARBC#F', site: 'AREA BRANCA', lat: -8.530737, lng: 125.61606, location: 'Dili' }, + { cell: 'ARBC3E', sector: 'ARBC#3', site: 'AREA BRANCA', lat: -8.525296, lng: 125.609824, location: 'Dili' }, + { cell: 'ARBC3F', sector: 'ARBC#3F', site: 'AREA BRANCA', lat: -8.525296, lng: 125.609824, location: 'Dili' }, + { cell: 'ARBC4E', sector: 'ARBC#4', site: 'AREA BRANCA', lat: -8.530737, lng: 125.61606, location: 'Dili' }, + { cell: 'ARBC4F', sector: 'ARBC#4F', site: 'AREA BRANCA', lat: -8.530737, lng: 125.61606, location: 'Dili' }, + { cell: 'ARBC5E', sector: 'ARBC#5', site: 'AREA BRANCA', lat: -8.530737, lng: 125.61606, location: 'Dili' }, + { cell: 'ARBC5F', sector: 'ARBC#5F', site: 'AREA BRANCA', lat: -8.530737, lng: 125.61606, location: 'Dili' }, + { cell: 'ARBC6E', sector: 'ARBC#6', site: 'AREA BRANCA', lat: -8.525296, lng: 125.609824, location: 'Dili' }, + { cell: 'ARBC6F', sector: 'ARBC#6F', site: 'AREA BRANCA', lat: -8.525296, lng: 125.609824, location: 'Dili' }, + { cell: 'ARBI1E', sector: 'ARBI#1', site: 'HOTEL ARBIRU', lat: -8.540316, lng: 125.538277, location: 'Dili' }, + { cell: 'ARBI1F', sector: 'ARBI1F', site: 'HOTEL ARBIRU', lat: -8.540316, lng: 125.538277, location: 'Dili' }, + { cell: 'ARBI2E', sector: 'ARBI#2', site: 'HOTEL ARBIRU', lat: -8.540316, lng: 125.538277, location: 'Dili' }, + { cell: 'ARBI2F', sector: 'ARBI2F', site: 'HOTEL ARBIRU', lat: -8.540316, lng: 125.538277, location: 'Dili' }, + { cell: 'ARBI4E', sector: 'ARBI4E', site: 'HOTEL ARBIRU', lat: -8.540316, lng: 125.538277, location: 'Dili' }, + { cell: 'ARBI4F', sector: 'ARBI4F', site: 'HOTEL ARBIRU', lat: -8.540316, lng: 125.538277, location: 'Dili' }, + { cell: 'ARBI5E', sector: 'ARBI5E', site: 'HOTEL ARBIRU', lat: -8.540316, lng: 125.538277, location: 'Dili' }, + { cell: 'ARBI5F', sector: 'ARBI5F', site: 'HOTEL ARBIRU', lat: -8.540316, lng: 125.538277, location: 'Dili' }, + { cell: 'ARNA1E', sector: 'ARNA#1', site: 'AILOKLARAN RUINNAKLEKAR', lat: -8.572797, lng: 125.564997, location: 'Dili' }, + { cell: 'ARNA1F', sector: 'ARNA#1F', site: 'AILOKLARAN RUINNAKLEKAR', lat: -8.572797, lng: 125.564997, location: 'Dili' }, + { cell: 'ARNA2E', sector: 'ARNA#2', site: 'AILOKLARAN RUINNAKLEKAR', lat: -8.572797, lng: 125.564997, location: 'Dili' }, + { cell: 'ARNA2F', sector: 'ARNA#2F', site: 'AILOKLARAN RUINNAKLEKAR', lat: -8.572797, lng: 125.564997, location: 'Dili' }, + { cell: 'ARNA3E', sector: 'ARNA#3', site: 'AILOKLARAN RUINNAKLEKAR', lat: -8.572797, lng: 125.564997, location: 'Dili' }, + { cell: 'ARNA3F', sector: 'ARNA#3F', site: 'AILOKLARAN RUINNAKLEKAR', lat: -8.572797, lng: 125.564997, location: 'Dili' }, + { cell: 'ARNA4E', sector: 'ARNA#4', site: 'AILOKLARAN RUINNAKLEKAR', lat: -8.572797, lng: 125.564997, location: 'Dili' }, + { cell: 'ARNA4F', sector: 'ARNA#4F', site: 'AILOKLARAN RUINNAKLEKAR', lat: -8.572797, lng: 125.564997, location: 'Dili' }, + { cell: 'ARNA5E', sector: 'ARNA#5', site: 'AILOKLARAN RUINNAKLEKAR', lat: -8.572797, lng: 125.564997, location: 'Dili' }, + { cell: 'ARNA5F', sector: 'ARNA#5F', site: 'AILOKLARAN RUINNAKLEKAR', lat: -8.572797, lng: 125.564997, location: 'Dili' }, + { cell: 'ARNA6E', sector: 'ARNA#6', site: 'AILOKLARAN RUINNAKLEKAR', lat: -8.572797, lng: 125.564997, location: 'Dili' }, + { cell: 'ARNA6F', sector: 'ARNA#6F', site: 'AILOKLARAN RUINNAKLEKAR', lat: -8.572797, lng: 125.564997, location: 'Dili' }, + { cell: 'ATAU1E', sector: 'ATAU#1', site: 'ATAURO', lat: -8.272224, lng: 125.600594, location: 'Dili (District)' }, + { cell: 'BAMA1E', sector: 'BAMA#1', site: 'BIDAU STA. ANA MANUMATA', lat: -8.551831, lng: 125.594124, location: 'Dili' }, + { cell: 'BAMA1F', sector: 'BAMA#1F', site: 'BIDAU STA. ANA MANUMATA', lat: -8.551831, lng: 125.594124, location: 'Dili' }, + { cell: 'BAMA2E', sector: 'BAMA#2', site: 'BIDAU STA. ANA MANUMATA', lat: -8.551831, lng: 125.594124, location: 'Dili' }, + { cell: 'BAMA2F', sector: 'BAMA#2F', site: 'BIDAU STA. ANA MANUMATA', lat: -8.551831, lng: 125.594124, location: 'Dili' }, + { cell: 'BAMA3E', sector: 'BAMA#3', site: 'BIDAU STA. ANA MANUMATA', lat: -8.551831, lng: 125.594124, location: 'Dili' }, + { cell: 'BAMA3F', sector: 'BAMA#3F', site: 'BIDAU STA. ANA MANUMATA', lat: -8.551831, lng: 125.594124, location: 'Dili' }, + { cell: 'BAMA4E', sector: 'BAMA#4', site: 'BIDAU STA. ANA MANUMATA', lat: -8.551831, lng: 125.594124, location: 'Dili' }, + { cell: 'BAMA4F', sector: 'BAMA#4F', site: 'BIDAU STA. ANA MANUMATA', lat: -8.551831, lng: 125.594124, location: 'Dili' }, + { cell: 'BAMA5E', sector: 'BAMA#5', site: 'BIDAU STA. ANA MANUMATA', lat: -8.551831, lng: 125.594124, location: 'Dili' }, + { cell: 'BAMA5F', sector: 'BAMA#5F', site: 'BIDAU STA. ANA MANUMATA', lat: -8.551831, lng: 125.594124, location: 'Dili' }, + { cell: 'BAMA6E', sector: 'BAMA#6', site: 'BIDAU STA. ANA MANUMATA', lat: -8.551831, lng: 125.594124, location: 'Dili' }, + { cell: 'BAMA6F', sector: 'BAMA#6F', site: 'BIDAU STA. ANA MANUMATA', lat: -8.551831, lng: 125.594124, location: 'Dili' }, + { cell: 'BALA1E', sector: 'BALA#1', site: 'BAIRRO PITE AILOK LARAN', lat: -8.5663, lng: 125.5647, location: 'Dili' }, + { cell: 'BALA1F', sector: 'BALA#1F', site: 'BAIRRO PITE AILOK LARAN', lat: -8.5663, lng: 125.5647, location: 'Dili' }, + { cell: 'BALA2E', sector: 'BALA#2', site: 'BAIRRO PITE AILOK LARAN', lat: -8.5663, lng: 125.5647, location: 'Dili' }, + { cell: 'BALA2F', sector: 'BALA#2F', site: 'BAIRRO PITE AILOK LARAN', lat: -8.5663, lng: 125.5647, location: 'Dili' }, + { cell: 'BALA3E', sector: 'BALA#3', site: 'BAIRRO PITE AILOK LARAN', lat: -8.5663, lng: 125.5647, location: 'Dili' }, + { cell: 'BALA3F', sector: 'BALA#3F', site: 'BAIRRO PITE AILOK LARAN', lat: -8.5663, lng: 125.5647, location: 'Dili' }, + { cell: 'BALA4E', sector: 'BALA#4', site: 'BAIRRO PITE AILOK LARAN', lat: -8.5663, lng: 125.5647, location: 'Dili' }, + { cell: 'BALA4F', sector: 'BALA#4F', site: 'BAIRRO PITE AILOK LARAN', lat: -8.5663, lng: 125.5647, location: 'Dili' }, + { cell: 'BALA5E', sector: 'BALA#5', site: 'BAIRRO PITE AILOK LARAN', lat: -8.5663, lng: 125.5647, location: 'Dili' }, + { cell: 'BALA5F', sector: 'BALA#5F', site: 'BAIRRO PITE AILOK LARAN', lat: -8.5663, lng: 125.5647, location: 'Dili' }, + { cell: 'BALA6E', sector: 'BALA#6', site: 'BAIRRO PITE AILOK LARAN', lat: -8.5663, lng: 125.5647, location: 'Dili' }, + { cell: 'BALA6F', sector: 'BALA#6F', site: 'BAIRRO PITE AILOK LARAN', lat: -8.5663, lng: 125.5647, location: 'Dili' }, + { cell: 'BALD1E', sector: 'BALD#1', site: 'BALIDE', lat: -8.564396, lng: 125.582151, location: 'Dili' }, + { cell: 'BALD1F', sector: 'BALD#1F', site: 'BALIDE', lat: -8.564396, lng: 125.582151, location: 'Dili' }, + { cell: 'BALD2E', sector: 'BALD#2', site: 'BALIDE', lat: -8.564396, lng: 125.582151, location: 'Dili' }, + { cell: 'BALD2F', sector: 'BALD#2F', site: 'BALIDE', lat: -8.564396, lng: 125.582151, location: 'Dili' }, + { cell: 'BALD3E', sector: 'BALD#3', site: 'BALIDE', lat: -8.564396, lng: 125.582151, location: 'Dili' }, + { cell: 'BALD3F', sector: 'BALD#3F', site: 'BALIDE', lat: -8.564396, lng: 125.582151, location: 'Dili' }, + { cell: 'BALD4E', sector: 'BALD#4', site: 'BALIDE', lat: -8.564396, lng: 125.582151, location: 'Dili' }, + { cell: 'BALD4F', sector: 'BALD#4F', site: 'BALIDE', lat: -8.564396, lng: 125.582151, location: 'Dili' }, + { cell: 'BALD5E', sector: 'BALD#5', site: 'BALIDE', lat: -8.564396, lng: 125.582151, location: 'Dili' }, + { cell: 'BALD5F', sector: 'BALD#5F', site: 'BALIDE', lat: -8.564396, lng: 125.582151, location: 'Dili' }, + { cell: 'BALD6E', sector: 'BALD#6', site: 'BALIDE', lat: -8.564396, lng: 125.582151, location: 'Dili' }, + { cell: 'BALD6F', sector: 'BALD#6F', site: 'BALIDE', lat: -8.564396, lng: 125.582151, location: 'Dili' }, + { cell: 'BAUN1E', sector: 'BAUN#1', site: 'BECORA AUHUN', lat: -8.560255, lng: 125.599532, location: 'Dili' }, + { cell: 'BAUN1F', sector: 'BAUN#1F', site: 'BECORA AUHUN', lat: -8.560255, lng: 125.599532, location: 'Dili' }, + { cell: 'BAUN2E', sector: 'BAUN#2', site: 'BECORA AUHUN', lat: -8.560255, lng: 125.599532, location: 'Dili' }, + { cell: 'BAUN2F', sector: 'BAUN#F', site: 'BECORA AUHUN', lat: -8.560255, lng: 125.599532, location: 'Dili' }, + { cell: 'BAUN3E', sector: 'BAUN#3', site: 'BECORA AUHUN', lat: -8.560255, lng: 125.599532, location: 'Dili' }, + { cell: 'BAUN3F', sector: 'BAUN#3F', site: 'BECORA AUHUN', lat: -8.560255, lng: 125.599532, location: 'Dili' }, + { cell: 'BAUN4E', sector: 'BAUN#4', site: 'BECORA AUHUN', lat: -8.560255, lng: 125.599532, location: 'Dili' }, + { cell: 'BAUN4F', sector: 'BAUN#4F', site: 'BECORA AUHUN', lat: -8.560255, lng: 125.599532, location: 'Dili' }, + { cell: 'BAUN5E', sector: 'BAUN#5', site: 'BECORA AUHUN', lat: -8.560255, lng: 125.599532, location: 'Dili' }, + { cell: 'BAUN5F', sector: 'BAUN#5F', site: 'BECORA AUHUN', lat: -8.560255, lng: 125.599532, location: 'Dili' }, + { cell: 'BAUN6E', sector: 'BAUN#6', site: 'BECORA AUHUN', lat: -8.560255, lng: 125.599532, location: 'Dili' }, + { cell: 'BAUN6F', sector: 'BAUN#6F', site: 'BECORA AUHUN', lat: -8.560255, lng: 125.599532, location: 'Dili' }, + { cell: 'BEBK1E', sector: 'BEBK#1', site: 'BEBONUK', lat: -8.547527, lng: 125.54828, location: 'Dili' }, + { cell: 'BEBK1F', sector: 'BEBK#1F', site: 'BEBONUK', lat: -8.547527, lng: 125.54828, location: 'Dili' }, + { cell: 'BEBK2E', sector: 'BEBK#2', site: 'BEBONUK', lat: -8.547527, lng: 125.54828, location: 'Dili' }, + { cell: 'BEBK2F', sector: 'BEBK#2F', site: 'BEBONUK', lat: -8.547527, lng: 125.54828, location: 'Dili' }, + { cell: 'BEBK3E', sector: 'BEBK#3', site: 'BEBONUK', lat: -8.547527, lng: 125.54828, location: 'Dili' }, + { cell: 'BEBK3F', sector: 'BEBK#33', site: 'BEBONUK', lat: -8.547527, lng: 125.54828, location: 'Dili' }, + { cell: 'BEBK4E', sector: 'BEBK#4', site: 'BEBONUK', lat: -8.547527, lng: 125.54828, location: 'Dili' }, + { cell: 'BEBK4F', sector: 'BEBK#4F', site: 'BEBONUK', lat: -8.547527, lng: 125.54828, location: 'Dili' }, + { cell: 'BEBK5E', sector: 'BEBK#5', site: 'BEBONUK', lat: -8.547527, lng: 125.54828, location: 'Dili' }, + { cell: 'BEBK5F', sector: 'BEBK#5F', site: 'BEBONUK', lat: -8.547527, lng: 125.54828, location: 'Dili' }, + { cell: 'BEBK6E', sector: 'BEBK#6', site: 'BEBONUK', lat: -8.547527, lng: 125.54828, location: 'Dili' }, + { cell: 'BEBK6F', sector: 'BEBK#66', site: 'BEBONUK', lat: -8.547527, lng: 125.54828, location: 'Dili' }, + { cell: 'BECA1E', sector: 'BECA#1', site: 'BECARIL', lat: -8.54088, lng: 125.61633, location: 'Dili' }, + { cell: 'BECA1F', sector: 'BECA#1F', site: 'BECARIL', lat: -8.54088, lng: 125.61633, location: 'Dili' }, + { cell: 'BECA2E', sector: 'BECA#2', site: 'BECARIL', lat: -8.54088, lng: 125.61633, location: 'Dili' }, + { cell: 'BECA2F', sector: 'BECA#2F', site: 'BECARIL', lat: -8.54088, lng: 125.61633, location: 'Dili' }, + { cell: 'BECA4E', sector: 'BECA#4', site: 'BECARIL', lat: -8.54088, lng: 125.61633, location: 'Dili' }, + { cell: 'BECA4F', sector: 'BECA#4F', site: 'BECARIL', lat: -8.54088, lng: 125.61633, location: 'Dili' }, + { cell: 'BECA5E', sector: 'BECA#5', site: 'BECARIL', lat: -8.54088, lng: 125.61633, location: 'Dili' }, + { cell: 'BECA5F', sector: 'BECA#5F', site: 'BECARIL', lat: -8.54088, lng: 125.61633, location: 'Dili' }, + { cell: 'BECA3E', sector: 'BECA#3', site: 'BECARIL', lat: -8.543625, lng: 125.61096, location: 'Dili' }, + { cell: 'BECE1E', sector: 'BECE#1', site: 'BECUSSE CENTRO', lat: -8.563579, lng: 125.603619, location: 'Dili' }, + { cell: 'BECE1F', sector: 'BECE#1F', site: 'BECUSSE CENTRO', lat: -8.563579, lng: 125.603619, location: 'Dili' }, + { cell: 'BECE2E', sector: 'BECE#2', site: 'BECUSSE CENTRO', lat: -8.563579, lng: 125.603619, location: 'Dili' }, + { cell: 'BECE2F', sector: 'BECE#2F', site: 'BECUSSE CENTRO', lat: -8.563579, lng: 125.603619, location: 'Dili' }, + { cell: 'BECE3E', sector: 'BECE#3', site: 'BECUSSE CENTRO', lat: -8.563579, lng: 125.603619, location: 'Dili' }, + { cell: 'BECE3F', sector: 'BECE#3F', site: 'BECUSSE CENTRO', lat: -8.563579, lng: 125.603619, location: 'Dili' }, + { cell: 'BECE4E', sector: 'BECE4E', site: 'BECUSSE CENTRO', lat: -8.563579, lng: 125.603619, location: 'Dili' }, + { cell: 'BECE4F', sector: 'BECE4F', site: 'BECUSSE CENTRO', lat: -8.563579, lng: 125.603619, location: 'Dili' }, + { cell: 'BECE5E', sector: 'BECE5E', site: 'BECUSSE CENTRO', lat: -8.563579, lng: 125.603619, location: 'Dili' }, + { cell: 'BECE5F', sector: 'BECE5F', site: 'BECUSSE CENTRO', lat: -8.563579, lng: 125.603619, location: 'Dili' }, + { cell: 'BECE6E', sector: 'BECE6E', site: 'BECUSSE CENTRO', lat: -8.563579, lng: 125.603619, location: 'Dili' }, + { cell: 'BECE6F', sector: 'BECE6F', site: 'BECUSSE CENTRO', lat: -8.563579, lng: 125.603619, location: 'Dili' }, + { cell: 'BECR1E', sector: 'BECR#1', site: 'BECORA', lat: -8.566137, lng: 125.611287, location: 'Dili' }, + { cell: 'BECR1F', sector: 'BECR#1F', site: 'BECORA', lat: -8.566137, lng: 125.611287, location: 'Dili' }, + { cell: 'BECR2E', sector: 'BECR#2', site: 'BECORA', lat: -8.566137, lng: 125.611287, location: 'Dili' }, + { cell: 'BECR2F', sector: 'BECR#2F', site: 'BECORA', lat: -8.566137, lng: 125.611287, location: 'Dili' }, + { cell: 'BECR3E', sector: 'BECR#3', site: 'BECORA', lat: -8.566137, lng: 125.611287, location: 'Dili' }, + { cell: 'BECR3F', sector: 'BECR#3F', site: 'BECORA', lat: -8.566137, lng: 125.611287, location: 'Dili' }, + { cell: 'BECR4E', sector: 'BECR#4', site: 'BECORA', lat: -8.566137, lng: 125.611287, location: 'Dili' }, + { cell: 'BECR4F', sector: 'BECR#4F', site: 'BECORA', lat: -8.566137, lng: 125.611287, location: 'Dili' }, + { cell: 'BECR5E', sector: 'BECR#5', site: 'BECORA', lat: -8.566137, lng: 125.611287, location: 'Dili' }, + { cell: 'BECR5F', sector: 'BECR#5F', site: 'BECORA', lat: -8.566137, lng: 125.611287, location: 'Dili' }, + { cell: 'BECR6E', sector: 'BECR#6', site: 'BECORA', lat: -8.566137, lng: 125.611287, location: 'Dili' }, + { cell: 'BECR6F', sector: 'BECR#6F', site: 'BECORA', lat: -8.566137, lng: 125.611287, location: 'Dili' }, + { cell: 'BEDO1E', sector: 'BEDO#1', site: 'BEDOIS', lat: -8.567502, lng: 125.617224, location: 'Dili' }, + { cell: 'BEDO1F', sector: 'BEDO#1F', site: 'BEDOIS', lat: -8.567502, lng: 125.617224, location: 'Dili' }, + { cell: 'BEDO2E', sector: 'BEDO#2', site: 'BEDOIS', lat: -8.567502, lng: 125.617224, location: 'Dili' }, + { cell: 'BEDO2F', sector: 'BEDO#2F', site: 'BEDOIS', lat: -8.567502, lng: 125.617224, location: 'Dili' }, + { cell: 'BEDO3E', sector: 'BEDO#3', site: 'BEDOIS', lat: -8.567502, lng: 125.617224, location: 'Dili' }, + { cell: 'BEDO3F', sector: 'BEDO#3F', site: 'BEDOIS', lat: -8.567502, lng: 125.617224, location: 'Dili' }, + { cell: 'BEDO4E', sector: 'BEDO#4', site: 'BEDOIS', lat: -8.567502, lng: 125.617224, location: 'Dili' }, + { cell: 'BEDO4F', sector: 'BEDO#4F', site: 'BEDOIS', lat: -8.567502, lng: 125.617224, location: 'Dili' }, + { cell: 'BEDO5E', sector: 'BEDO#5', site: 'BEDOIS', lat: -8.567502, lng: 125.617224, location: 'Dili' }, + { cell: 'BEDO5F', sector: 'BEDO#5F', site: 'BEDOIS', lat: -8.567502, lng: 125.617224, location: 'Dili' }, + { cell: 'BEDO6E', sector: 'BEDO#6', site: 'BEDOIS', lat: -8.567502, lng: 125.617224, location: 'Dili' }, + { cell: 'BEDO6F', sector: 'BEDO#6F', site: 'BEDOIS', lat: -8.567502, lng: 125.617224, location: 'Dili' }, + { cell: 'BEIK1E', sector: 'BEIK#1', site: 'BECUSSE KRAIK', lat: -8.564282, lng: 125.597544, location: 'Dili' }, + { cell: 'BEIK1F', sector: 'BEIK#1F', site: 'BECUSSE KRAIK', lat: -8.564282, lng: 125.597544, location: 'Dili' }, + { cell: 'BEIK2E', sector: 'BEIK#2', site: 'BECUSSE KRAIK', lat: -8.564282, lng: 125.597544, location: 'Dili' }, + { cell: 'BEIK2F', sector: 'BEIK#2F', site: 'BECUSSE KRAIK', lat: -8.564282, lng: 125.597544, location: 'Dili' }, + { cell: 'BEIK3E', sector: 'BEIK#3', site: 'BECUSSE KRAIK', lat: -8.564282, lng: 125.597544, location: 'Dili' }, + { cell: 'BEIK3F', sector: 'BEIK#3F', site: 'BECUSSE KRAIK', lat: -8.564282, lng: 125.597544, location: 'Dili' }, + { cell: 'BEIK4E', sector: 'BEIK#4', site: 'BECUSSE KRAIK', lat: -8.564282, lng: 125.597544, location: 'Dili' }, + { cell: 'BEIK4F', sector: 'BEIK#4F', site: 'BECUSSE KRAIK', lat: -8.564282, lng: 125.597544, location: 'Dili' }, + { cell: 'BEIK5E', sector: 'BEIK#5', site: 'BECUSSE KRAIK', lat: -8.564282, lng: 125.597544, location: 'Dili' }, + { cell: 'BEIK5F', sector: 'BEIK#5F', site: 'BECUSSE KRAIK', lat: -8.564282, lng: 125.597544, location: 'Dili' }, + { cell: 'BEIK6E', sector: 'BEIK#6', site: 'BECUSSE KRAIK', lat: -8.564282, lng: 125.597544, location: 'Dili' }, + { cell: 'BEIK6F', sector: 'BEIK#6F', site: 'BECUSSE KRAIK', lat: -8.564282, lng: 125.597544, location: 'Dili' }, + { cell: 'BEMG1E', sector: 'BEMG#1', site: 'BETO DNMG', lat: -8.548623, lng: 125.527678, location: 'Dili' }, + { cell: 'BEMG1F', sector: 'BEMG#1F', site: 'BETO DNMG', lat: -8.548623, lng: 125.527678, location: 'Dili' }, + { cell: 'BEMG2E', sector: 'BEMG#2', site: 'BETO DNMG', lat: -8.548623, lng: 125.527678, location: 'Dili' }, + { cell: 'BEMG2F', sector: 'BEMG#F', site: 'BETO DNMG', lat: -8.548623, lng: 125.527678, location: 'Dili' }, + { cell: 'BEMG3E', sector: 'BEMG#3', site: 'BETO DNMG', lat: -8.548623, lng: 125.527678, location: 'Dili' }, + { cell: 'BEMG3F', sector: 'BEMG#3F', site: 'BETO DNMG', lat: -8.548623, lng: 125.527678, location: 'Dili' }, + { cell: 'BEMG4E', sector: 'BEMG#4', site: 'BETO DNMG', lat: -8.548623, lng: 125.527678, location: 'Dili' }, + { cell: 'BEMG4F', sector: 'BEMG#4F', site: 'BETO DNMG', lat: -8.548623, lng: 125.527678, location: 'Dili' }, + { cell: 'BEMG5E', sector: 'BEMG#5', site: 'BETO DNMG', lat: -8.548623, lng: 125.527678, location: 'Dili' }, + { cell: 'BEMG5F', sector: 'BEMG#5F', site: 'BETO DNMG', lat: -8.548623, lng: 125.527678, location: 'Dili' }, + { cell: 'BEMG6E', sector: 'BEMG#6', site: 'BETO DNMG', lat: -8.548623, lng: 125.527678, location: 'Dili' }, + { cell: 'BEMG6F', sector: 'BEMG#6F', site: 'BETO DNMG', lat: -8.548623, lng: 125.527678, location: 'Dili' }, + { cell: 'BENA1E', sector: 'BENA#1', site: 'BETO NAROMAN', lat: -8.548906, lng: 125.534374, location: 'Dili' }, + { cell: 'BENA1F', sector: 'BENA#1F', site: 'BETO NAROMAN', lat: -8.548906, lng: 125.534374, location: 'Dili' }, + { cell: 'BENA2E', sector: 'BENA#2', site: 'BETO NAROMAN', lat: -8.548906, lng: 125.534374, location: 'Dili' }, + { cell: 'BENA2F', sector: 'BENA#2F', site: 'BETO NAROMAN', lat: -8.548906, lng: 125.534374, location: 'Dili' }, + { cell: 'BENA3E', sector: 'BENA#3', site: 'BETO NAROMAN', lat: -8.548906, lng: 125.534374, location: 'Dili' }, + { cell: 'BENA3F', sector: 'BENA#3F', site: 'BETO NAROMAN', lat: -8.548906, lng: 125.534374, location: 'Dili' }, + { cell: 'BENA4E', sector: 'BENA#4', site: 'BETO NAROMAN', lat: -8.548906, lng: 125.534374, location: 'Dili' }, + { cell: 'BENA4F', sector: 'BENA#4F', site: 'BETO NAROMAN', lat: -8.548906, lng: 125.534374, location: 'Dili' }, + { cell: 'BENA5E', sector: 'BENA#5', site: 'BETO NAROMAN', lat: -8.548906, lng: 125.534374, location: 'Dili' }, + { cell: 'BENA5F', sector: 'BENA#5F', site: 'BETO NAROMAN', lat: -8.548906, lng: 125.534374, location: 'Dili' }, + { cell: 'BENA6E', sector: 'BENA#6', site: 'BETO NAROMAN', lat: -8.548906, lng: 125.534374, location: 'Dili' }, + { cell: 'BENA6F', sector: 'BENA#6F', site: 'BETO NAROMAN', lat: -8.548906, lng: 125.534374, location: 'Dili' }, + { cell: 'BETO1E', sector: 'BETO#1', site: 'BETO', lat: -8.553311, lng: 125.532549, location: 'Dili' }, + { cell: 'BETO2E', sector: 'BETO#2', site: 'BETO', lat: -8.553311, lng: 125.532549, location: 'Dili' }, + { cell: 'BETO3E', sector: 'BETO#3', site: 'BETO', lat: -8.553311, lng: 125.532549, location: 'Dili' }, + { cell: 'BETO4E', sector: 'BETO#4', site: 'BETO', lat: -8.553311, lng: 125.532549, location: 'Dili' }, + { cell: 'BETO5E', sector: 'BETO#5', site: 'BETO', lat: -8.553311, lng: 125.532549, location: 'Dili' }, + { cell: 'BETO6E', sector: 'BETO#6', site: 'BETO', lat: -8.553311, lng: 125.532549, location: 'Dili' }, + { cell: 'BETO2F', sector: 'BETO#8', site: 'BETO (iMacro)', lat: -8.552891, lng: 125.527198, location: 'Dili' }, + { cell: 'BETO5F', sector: 'BETO#11', site: 'BETO (iMacro)', lat: -8.552891, lng: 125.527198, location: 'Dili' }, + { cell: 'BETO3F', sector: 'BETO#9', site: 'BETO (iMacro)', lat: -8.552891, lng: 125.527198, location: 'Dili' }, + { cell: 'BETO6F', sector: 'BETO#12', site: 'BETO (iMacro)', lat: -8.552891, lng: 125.527198, location: 'Dili' }, + { cell: 'BIDA1E', sector: 'BIDA#1', site: 'BIDAU', lat: -8.557187, lng: 125.594275, location: 'Dili' }, + { cell: 'BIDA1F', sector: 'BIDA#1F', site: 'BIDAU', lat: -8.557187, lng: 125.594275, location: 'Dili' }, + { cell: 'BIDA2E', sector: 'BIDA#2', site: 'BIDAU', lat: -8.557187, lng: 125.594275, location: 'Dili' }, + { cell: 'BIDA2F', sector: 'BIDA#2F', site: 'BIDAU', lat: -8.557187, lng: 125.594275, location: 'Dili' }, + { cell: 'BIDA3E', sector: 'BIDA#3', site: 'BIDAU', lat: -8.557187, lng: 125.594275, location: 'Dili' }, + { cell: 'BIDA3F', sector: 'BIDA#3F', site: 'BIDAU', lat: -8.557187, lng: 125.594275, location: 'Dili' }, + { cell: 'BIDA4E', sector: 'BIDA#4', site: 'BIDAU', lat: -8.557187, lng: 125.594275, location: 'Dili' }, + { cell: 'BIDA4F', sector: 'BIDA#4F', site: 'BIDAU', lat: -8.557187, lng: 125.594275, location: 'Dili' }, + { cell: 'BIDA5E', sector: 'BIDA#5', site: 'BIDAU', lat: -8.557187, lng: 125.594275, location: 'Dili' }, + { cell: 'BIDA5F', sector: 'BIDA#5F', site: 'BIDAU', lat: -8.557187, lng: 125.594275, location: 'Dili' }, + { cell: 'BIDA6E', sector: 'BIDA#6', site: 'BIDAU', lat: -8.557187, lng: 125.594275, location: 'Dili' }, + { cell: 'BIDA6F', sector: 'BIDA#6F', site: 'BIDAU', lat: -8.557187, lng: 125.594275, location: 'Dili' }, + { cell: 'BMOR1E', sector: 'BMOR#1', site: 'BEMORI', lat: -8.559669, lng: 125.588966, location: 'Dili' }, + { cell: 'BMOR1F', sector: 'BMOR#1F', site: 'BEMORI', lat: -8.559669, lng: 125.588966, location: 'Dili' }, + { cell: 'BMOR2E', sector: 'BMOR#2', site: 'BEMORI', lat: -8.559669, lng: 125.588966, location: 'Dili' }, + { cell: 'BMOR2F', sector: 'BMOR#2F', site: 'BEMORI', lat: -8.559669, lng: 125.588966, location: 'Dili' }, + { cell: 'BMOR3E', sector: 'BMOR#3', site: 'BEMORI', lat: -8.559669, lng: 125.588966, location: 'Dili' }, + { cell: 'BMOR3F', sector: 'BMOR#3F', site: 'BEMORI', lat: -8.559669, lng: 125.588966, location: 'Dili' }, + { cell: 'BMOR4E', sector: 'BMOR#4', site: 'BEMORI', lat: -8.559669, lng: 125.588966, location: 'Dili' }, + { cell: 'BMOR4F', sector: 'BMOR#4F', site: 'BEMORI', lat: -8.559669, lng: 125.588966, location: 'Dili' }, + { cell: 'BMOR5E', sector: 'BMOR#5', site: 'BEMORI', lat: -8.559669, lng: 125.588966, location: 'Dili' }, + { cell: 'BMOR5F', sector: 'BMOR#5F', site: 'BEMORI', lat: -8.559669, lng: 125.588966, location: 'Dili' }, + { cell: 'BMOR6E', sector: 'BMOR#6', site: 'BEMORI', lat: -8.559669, lng: 125.588966, location: 'Dili' }, + { cell: 'BMOR6F', sector: 'BMOR#6F', site: 'BEMORI', lat: -8.559669, lng: 125.588966, location: 'Dili' }, + { cell: 'BILE1E', sector: 'BILE#1', site: 'BIDAU LECIDERE', lat: -8.549599, lng: 125.589457, location: 'Dili' }, + { cell: 'BILE1F', sector: 'BILE#1F', site: 'BIDAU LECIDERE', lat: -8.549599, lng: 125.589457, location: 'Dili' }, + { cell: 'BILE2E', sector: 'BILE#2', site: 'BIDAU LECIDERE', lat: -8.549599, lng: 125.589457, location: 'Dili' }, + { cell: 'BILE2F', sector: 'BILE#2F', site: 'BIDAU LECIDERE', lat: -8.549599, lng: 125.589457, location: 'Dili' }, + { cell: 'BILE3E', sector: 'BILE#3', site: 'BIDAU LECIDERE', lat: -8.549599, lng: 125.589457, location: 'Dili' }, + { cell: 'BILE3F', sector: 'BILE#3F', site: 'BIDAU LECIDERE', lat: -8.549599, lng: 125.589457, location: 'Dili' }, + { cell: 'BILE4E', sector: 'BILE#4', site: 'BIDAU LECIDERE', lat: -8.549599, lng: 125.589457, location: 'Dili' }, + { cell: 'BILE4F', sector: 'BILE#4F', site: 'BIDAU LECIDERE', lat: -8.549599, lng: 125.589457, location: 'Dili' }, + { cell: 'BILE5E', sector: 'BILE#5', site: 'BIDAU LECIDERE', lat: -8.549599, lng: 125.589457, location: 'Dili' }, + { cell: 'BILE5F', sector: 'BILE#5F', site: 'BIDAU LECIDERE', lat: -8.549599, lng: 125.589457, location: 'Dili' }, + { cell: 'BILE6E', sector: 'BILE#6', site: 'BIDAU LECIDERE', lat: -8.549599, lng: 125.589457, location: 'Dili' }, + { cell: 'BILE6F', sector: 'BILE#6F', site: 'BIDAU LECIDERE', lat: -8.549599, lng: 125.589457, location: 'Dili' }, + { cell: 'BIMA1E', sector: 'BIMA#1', site: 'BIDAU MASSAUR', lat: -8.554339, lng: 125.596989, location: 'Dili' }, + { cell: 'BIMA1F', sector: 'BIMA#1F', site: 'BIDAU MASSAUR', lat: -8.554339, lng: 125.596989, location: 'Dili' }, + { cell: 'BIMA2E', sector: 'BIMA#2', site: 'BIDAU MASSAUR', lat: -8.554339, lng: 125.596989, location: 'Dili' }, + { cell: 'BIMA2F', sector: 'BIMA#F', site: 'BIDAU MASSAUR', lat: -8.554339, lng: 125.596989, location: 'Dili' }, + { cell: 'BIMA3E', sector: 'BIMA#3', site: 'BIDAU MASSAUR', lat: -8.554339, lng: 125.596989, location: 'Dili' }, + { cell: 'BIMA3F', sector: 'BIMA#3F', site: 'BIDAU MASSAUR', lat: -8.554339, lng: 125.596989, location: 'Dili' }, + { cell: 'BIMA4E', sector: 'BIMA#4', site: 'BIMAU MASSAUR', lat: -8.554339, lng: 125.596989, location: 'Dili' }, + { cell: 'BIMA4F', sector: 'BIMA#4F', site: 'BIMAU MASSAUR', lat: -8.554339, lng: 125.596989, location: 'Dili' }, + { cell: 'BIMA5E', sector: 'BIMA#5', site: 'BIMAU MASSAUR', lat: -8.554339, lng: 125.596989, location: 'Dili' }, + { cell: 'BIMA5F', sector: 'BIMA#5F', site: 'BIMAU MASSAUR', lat: -8.554339, lng: 125.596989, location: 'Dili' }, + { cell: 'BIMA6E', sector: 'BIMA#6', site: 'BIMAU MASSAUR', lat: -8.554339, lng: 125.596989, location: 'Dili' }, + { cell: 'BIMA6F', sector: 'BIMA#6F', site: 'BIMAU MASSAUR', lat: -8.554339, lng: 125.596989, location: 'Dili' }, + { cell: 'BITT1E', sector: 'BITT#1', site: 'BITERLAUN', lat: -8.548328, lng: 125.623808, location: 'DILI' }, + { cell: 'BITT2E', sector: 'BITT#2', site: 'BITERLAUN', lat: -8.548328, lng: 125.623808, location: 'DILI' }, + { cell: 'BNU1E', sector: 'BNU1E', site: 'BNU', lat: -8.555103, lng: 125.576137, location: 'Dili' }, + { cell: 'BNU1F', sector: 'BNU1F', site: 'BNU', lat: -8.555103, lng: 125.576137, location: 'Dili' }, + { cell: 'BNU2E', sector: 'BNU2E', site: 'BNU', lat: -8.555103, lng: 125.576137, location: 'Dili' }, + { cell: 'BNU2F', sector: 'BNU2F', site: 'BNU', lat: -8.555103, lng: 125.576137, location: 'Dili' }, + { cell: 'BNU3E', sector: 'BNU3E', site: 'BNU', lat: -8.555103, lng: 125.576137, location: 'Dili' }, + { cell: 'BNU3F', sector: 'BNU3F', site: 'BNU', lat: -8.555103, lng: 125.576137, location: 'Dili' }, + { cell: 'BNU4E', sector: 'BNU4E', site: 'BNU', lat: -8.555103, lng: 125.576137, location: 'Dili' }, + { cell: 'BNU4F', sector: 'BNU4F', site: 'BNU', lat: -8.555103, lng: 125.576137, location: 'Dili' }, + { cell: 'BNU5E', sector: 'BNU5E', site: 'BNU', lat: -8.555103, lng: 125.576137, location: 'Dili' }, + { cell: 'BNU5F', sector: 'BNU5F', site: 'BNU', lat: -8.555103, lng: 125.576137, location: 'Dili' }, + { cell: 'BNU6E', sector: 'BNU6E', site: 'BNU', lat: -8.555103, lng: 125.576137, location: 'Dili' }, + { cell: 'BNU6F', sector: 'BNU6F', site: 'BNU', lat: -8.555103, lng: 125.576137, location: 'Dili' }, + { cell: 'BNUL1E', sector: 'BNUL#1', site: 'BECORA NU\'U LARAN', lat: -8.573319, lng: 125.617161, location: 'Dili' }, + { cell: 'BNUL1F', sector: 'BNUL#1F', site: 'BECORA NU\'U LARAN', lat: -8.573319, lng: 125.617161, location: 'Dili' }, + { cell: 'BNUL2E', sector: 'BNUL#2', site: 'BECORA NU\'U LARAN', lat: -8.573319, lng: 125.617161, location: 'Dili' }, + { cell: 'BNUL2F', sector: 'BNUL#2F', site: 'BECORA NU\'U LARAN', lat: -8.573319, lng: 125.617161, location: 'Dili' }, + { cell: 'BNUL3E', sector: 'BNUL#3', site: 'BECORA NU\'U LARAN', lat: -8.573319, lng: 125.617161, location: 'Dili' }, + { cell: 'BNUL3F', sector: 'BNUL#3F', site: 'BECORA NU\'U LARAN', lat: -8.573319, lng: 125.617161, location: 'Dili' }, + { cell: 'BNUL4E', sector: 'BNUL#4', site: 'BECORA NU\'U LARAN', lat: -8.573319, lng: 125.617161, location: 'Dili' }, + { cell: 'BNUL4F', sector: 'BNUL#4F', site: 'BECORA NU\'U LARAN', lat: -8.573319, lng: 125.617161, location: 'Dili' }, + { cell: 'BNUL5E', sector: 'BNUL#5', site: 'BECORA NU\'U LARAN', lat: -8.573319, lng: 125.617161, location: 'Dili' }, + { cell: 'BNUL5F', sector: 'BNUL#5F', site: 'BECORA NU\'U LARAN', lat: -8.573319, lng: 125.617161, location: 'Dili' }, + { cell: 'BNUL6E', sector: 'BNUL#6', site: 'BECORA NU\'U LARAN', lat: -8.573319, lng: 125.617161, location: 'Dili' }, + { cell: 'BNUL6F', sector: 'BNUL#6F', site: 'BECORA NU\'U LARAN', lat: -8.573319, lng: 125.617161, location: 'Dili' }, + { cell: 'BORA1E', sector: 'BORA#1', site: 'BEBORA', lat: -8.55652, lng: 125.567234, location: 'Dili' }, + { cell: 'BORA1F', sector: 'BORA#1F', site: 'BEBORA', lat: -8.55652, lng: 125.567234, location: 'Dili' }, + { cell: 'BORA2E', sector: 'BORA#2', site: 'BEBORA', lat: -8.55652, lng: 125.567234, location: 'Dili' }, + { cell: 'BORA2F', sector: 'BORA#2F', site: 'BEBORA', lat: -8.55652, lng: 125.567234, location: 'Dili' }, + { cell: 'BORA3E', sector: 'BORA#3', site: 'BEBORA', lat: -8.55652, lng: 125.567234, location: 'Dili' }, + { cell: 'BORA3F', sector: 'BORA#3F', site: 'BEBORA', lat: -8.55652, lng: 125.567234, location: 'Dili' }, + { cell: 'BORA4E', sector: 'BORA#4E', site: 'BEBORA', lat: -8.55652, lng: 125.567234, location: 'Dili' }, + { cell: 'BORA4F', sector: 'BORA#4F', site: 'BEBORA', lat: -8.55652, lng: 125.567234, location: 'Dili' }, + { cell: 'BORA5E', sector: 'BORA#5E', site: 'BEBORA', lat: -8.55652, lng: 125.567234, location: 'Dili' }, + { cell: 'BORA5F', sector: 'BORA#5F', site: 'BEBORA', lat: -8.55652, lng: 125.567234, location: 'Dili' }, + { cell: 'BORA6E', sector: 'BORA#6E', site: 'BEBORA', lat: -8.55652, lng: 125.567234, location: 'Dili' }, + { cell: 'BORA6F', sector: 'BORA#6F', site: 'BEBORA', lat: -8.55652, lng: 125.567234, location: 'Dili' }, + { cell: 'BTAT1E', sector: 'BTAT#1', site: 'BAIROPITE TAT', lat: -8.558858, lng: 125.561385, location: 'Dili' }, + { cell: 'BTAT1F', sector: 'BTAT#1F', site: 'BAIROPITE TAT', lat: -8.558858, lng: 125.561385, location: 'Dili' }, + { cell: 'BTAT2E', sector: 'BTAT#2', site: 'BAIROPITE TAT', lat: -8.558858, lng: 125.561385, location: 'Dili' }, + { cell: 'BTAT2F', sector: 'BTAT#2F', site: 'BAIROPITE TAT', lat: -8.558858, lng: 125.561385, location: 'Dili' }, + { cell: 'BTAT3E', sector: 'BTAT#3', site: 'BAIROPITE TAT', lat: -8.558858, lng: 125.561385, location: 'Dili' }, + { cell: 'BTAT3F', sector: 'BTAT#3F', site: 'BAIROPITE TAT', lat: -8.558858, lng: 125.561385, location: 'Dili' }, + { cell: 'BTAT4E', sector: 'BTAT#4', site: 'BAIROPITE TAT', lat: -8.558858, lng: 125.561385, location: 'Dili' }, + { cell: 'BTAT4F', sector: 'BTAT#4F', site: 'BAIROPITE TAT', lat: -8.558858, lng: 125.561385, location: 'Dili' }, + { cell: 'BTAT5E', sector: 'BTAT#5', site: 'BAIROPITE TAT', lat: -8.558858, lng: 125.561385, location: 'Dili' }, + { cell: 'BTAT5F', sector: 'BTAT#5F', site: 'BAIROPITE TAT', lat: -8.558858, lng: 125.561385, location: 'Dili' }, + { cell: 'BTAT6E', sector: 'BTAT#6', site: 'BAIROPITE TAT', lat: -8.558858, lng: 125.561385, location: 'Dili' }, + { cell: 'BTAT6F', sector: 'BTAT#6F', site: 'BAIROPITE TAT', lat: -8.558858, lng: 125.561385, location: 'Dili' }, + { cell: 'CACU1E', sector: 'CACU#1', site: 'CACAULIDUM', lat: -8.566511, lng: 125.558621, location: 'Dili' }, + { cell: 'CACU1F', sector: 'CACU#1F', site: 'CACAULIDUM', lat: -8.566511, lng: 125.558621, location: 'Dili' }, + { cell: 'CACU2E', sector: 'CACU#2', site: 'CACAULIDUM', lat: -8.566511, lng: 125.558621, location: 'Dili' }, + { cell: 'CACU2F', sector: 'CACU#2F', site: 'CACAULIDUM', lat: -8.566511, lng: 125.558621, location: 'Dili' }, + { cell: 'CACU3E', sector: 'CACU#3', site: 'CACAULIDUM', lat: -8.566511, lng: 125.558621, location: 'Dili' }, + { cell: 'CACU3F', sector: 'CACU#3F', site: 'CACAULIDUM', lat: -8.566511, lng: 125.558621, location: 'Dili' }, + { cell: 'CACU4E', sector: 'CACU#4', site: 'CACAULIDUM', lat: -8.566511, lng: 125.558621, location: 'Dili' }, + { cell: 'CACU4F', sector: 'CACU#4F', site: 'CACAULIDUM', lat: -8.566511, lng: 125.558621, location: 'Dili' }, + { cell: 'CACU5E', sector: 'CACU#5', site: 'CACAULIDUM', lat: -8.566511, lng: 125.558621, location: 'Dili' }, + { cell: 'CACU5F', sector: 'CACU#5F', site: 'CACAULIDUM', lat: -8.566511, lng: 125.558621, location: 'Dili' }, + { cell: 'CACU6E', sector: 'CACU#6', site: 'CACAULIDUM', lat: -8.566511, lng: 125.558621, location: 'Dili' }, + { cell: 'CACU6F', sector: 'CACU#6F', site: 'CACAULIDUM', lat: -8.566511, lng: 125.558621, location: 'Dili' }, + { cell: 'CAIC1E', sector: 'CAIC#1', site: 'CAICOLI', lat: -8.562981, lng: 125.575436, location: 'Dili' }, + { cell: 'CAIC1F', sector: 'CAIC#1f', site: 'CAICOLI', lat: -8.562981, lng: 125.575436, location: 'Dili' }, + { cell: 'CAIC2E', sector: 'CAIC#2', site: 'CAICOLI', lat: -8.562981, lng: 125.575436, location: 'Dili' }, + { cell: 'CAIC2F', sector: 'CAIC#2F', site: 'CAICOLI', lat: -8.562981, lng: 125.575436, location: 'Dili' }, + { cell: 'CAIC3E', sector: 'CAIC#3', site: 'CAICOLI', lat: -8.562981, lng: 125.575436, location: 'Dili' }, + { cell: 'CAIC3F', sector: 'CAIC#F', site: 'CAICOLI', lat: -8.562981, lng: 125.575436, location: 'Dili' }, + { cell: 'CAIC4E', sector: 'CAIC#4', site: 'CAICOLI', lat: -8.562981, lng: 125.575436, location: 'Dili' }, + { cell: 'CAIC4F', sector: 'CAIC#4F', site: 'CAICOLI', lat: -8.562981, lng: 125.575436, location: 'Dili' }, + { cell: 'CAIC5E', sector: 'CAIC#5', site: 'CAICOLI', lat: -8.562981, lng: 125.575436, location: 'Dili' }, + { cell: 'CAIC5F', sector: 'CAIC#5F', site: 'CAICOLI', lat: -8.562981, lng: 125.575436, location: 'Dili' }, + { cell: 'CAIC6E', sector: 'CAIC#6', site: 'CAICOLI', lat: -8.562981, lng: 125.575436, location: 'Dili' }, + { cell: 'CAIC6F', sector: 'CAIC#6F', site: 'CAICOLI', lat: -8.562981, lng: 125.575436, location: 'Dili' }, + { cell: 'CALI1E', sector: 'CALI#1', site: 'HOTEL CALIFORNIA', lat: -8.543625, lng: 125.61096, location: 'Dili' }, + { cell: 'CALI2E', sector: 'CALI#2', site: 'HOTEL CALIFORNIA', lat: -8.543625, lng: 125.61096, location: 'Dili' }, + { cell: 'CALA1E', sector: 'CALA#1', site: 'CAMEA AILOKLARAN', lat: -8.561831, lng: 125.612114, location: 'Dili' }, + { cell: 'CALA1F', sector: 'CALA#1F', site: 'CAMEA AILOKLARAN', lat: -8.561831, lng: 125.612114, location: 'Dili' }, + { cell: 'CALA2E', sector: 'CALA#2', site: 'CAMEA AILOKLARAN', lat: -8.561831, lng: 125.612114, location: 'Dili' }, + { cell: 'CALA2F', sector: 'CALA#2F', site: 'CAMEA AILOKLARAN', lat: -8.561831, lng: 125.612114, location: 'Dili' }, + { cell: 'CALA3E', sector: 'CALA#3', site: 'CAMEA AILOKLARAN', lat: -8.561831, lng: 125.612114, location: 'Dili' }, + { cell: 'CALA3F', sector: 'CALA#3F', site: 'CAMEA AILOKLARAN', lat: -8.561831, lng: 125.612114, location: 'Dili' }, + { cell: 'CALA4E', sector: 'CALA#4', site: 'CAMEA AILOKLARAN', lat: -8.561831, lng: 125.612114, location: 'Dili' }, + { cell: 'CALA4F', sector: 'CALA#4F', site: 'CAMEA AILOKLARAN', lat: -8.561831, lng: 125.612114, location: 'Dili' }, + { cell: 'CALA5E', sector: 'CALA#5', site: 'CAMEA AILOKLARAN', lat: -8.561831, lng: 125.612114, location: 'Dili' }, + { cell: 'CALA5F', sector: 'CALA#5F', site: 'CAMEA AILOKLARAN', lat: -8.561831, lng: 125.612114, location: 'Dili' }, + { cell: 'CALA6E', sector: 'CALA#6', site: 'CAMEA AILOKLARAN', lat: -8.561831, lng: 125.612114, location: 'Dili' }, + { cell: 'CALA6F', sector: 'CALA#6F', site: 'CAMEA AILOKLARAN', lat: -8.561831, lng: 125.612114, location: 'Dili' }, + { cell: 'CMEA1E', sector: 'CMEA#1', site: 'CAMEA BEDOIS', lat: -8.564444, lng: 125.617789, location: 'Dili' }, + { cell: 'CMEA1F', sector: 'CMEA#1F', site: 'CAMEA BEDOIS', lat: -8.564444, lng: 125.617789, location: 'Dili' }, + { cell: 'CMEA2E', sector: 'CMEA#2', site: 'CAMEA BEDOIS', lat: -8.564444, lng: 125.617789, location: 'Dili' }, + { cell: 'CMEA2F', sector: 'CMEA#2F', site: 'CAMEA BEDOIS', lat: -8.564444, lng: 125.617789, location: 'Dili' }, + { cell: 'CMEA3E', sector: 'CMEA#3', site: 'CAMEA BEDOIS', lat: -8.564444, lng: 125.617789, location: 'Dili' }, + { cell: 'CMEA3F', sector: 'CMEA#3F', site: 'CAMEA BEDOIS', lat: -8.564444, lng: 125.617789, location: 'Dili' }, + { cell: 'CMEA4E', sector: 'CMEA#4', site: 'CAMEA BEDOIS', lat: -8.564444, lng: 125.617789, location: 'Dili' }, + { cell: 'CMEA4F', sector: 'CMEA#4F', site: 'CAMEA BEDOIS', lat: -8.564444, lng: 125.617789, location: 'Dili' }, + { cell: 'CMEA5E', sector: 'CMEA#5', site: 'CAMEA BEDOIS', lat: -8.564444, lng: 125.617789, location: 'Dili' }, + { cell: 'CMEA5F', sector: 'CMEA#5F', site: 'CAMEA BEDOIS', lat: -8.564444, lng: 125.617789, location: 'Dili' }, + { cell: 'CMEA6E', sector: 'CMEA#6', site: 'CAMEA BEDOIS', lat: -8.564444, lng: 125.617789, location: 'Dili' }, + { cell: 'CMEA6F', sector: 'CMEA#6F', site: 'CAMEA BEDOIS', lat: -8.564444, lng: 125.617789, location: 'Dili' }, + { cell: 'CBDT1E', sector: 'CBDT#1', site: 'TIMOR PLAZA CBD2', lat: -8.552789, lng: 125.542079, location: 'Dili' }, + { cell: 'CBDT2E', sector: 'CBDT#2', site: 'TIMOR PLAZA CBD2', lat: -8.552789, lng: 125.542079, location: 'Dili' }, + { cell: 'CBDT3E (Split CGR)', sector: 'CBDT#3', site: 'TIMOR PLAZA CBD2', lat: -8.548729, lng: 125.542886, location: 'Dili' }, + { cell: 'CBDT4E', sector: 'CBDT#4', site: 'TIMOR PLAZA CBD2', lat: -8.552789, lng: 125.542079, location: 'Dili' }, + { cell: 'CBDT5E', sector: 'CBDT#5', site: 'TIMOR PLAZA CBD2', lat: -8.552789, lng: 125.542079, location: 'Dili' }, + { cell: 'CBDT6E (Split CGR)', sector: 'CBDT#6', site: 'TIMOR PLAZA CBD2', lat: -8.548729, lng: 125.542886, location: 'Dili' }, + { cell: 'CDTR1E', sector: 'CDTR#1', site: 'CAREIRA DE TIRRO', lat: -8.564653, lng: 125.595349, location: 'Dili' }, + { cell: 'CDTR2E', sector: 'CDTR#2', site: 'CAREIRA DE TIRRO', lat: -8.564653, lng: 125.595349, location: 'Dili' }, + { cell: 'CDTR3E', sector: 'CDTR#3', site: 'CAREIRA DE TIRRO', lat: -8.564653, lng: 125.595349, location: 'Dili' }, + { cell: 'CFJJ1E', sector: 'CFJJ#1', site: 'CENTRO FORMAÇÃO JURÍDICO E JURICIÁRIO', lat: -8.559916, lng: 125.575097, location: 'Dili' }, + { cell: 'CFJJ1F', sector: 'CFJJ#1F', site: 'CENTRO FORMAÇÃO JURÍDICO E JURICIÁRIO', lat: -8.559916, lng: 125.575097, location: 'Dili' }, + { cell: 'CFJJ2E', sector: 'CFJJ#2', site: 'CENTRO FORMAÇÃO JURÍDICO E JURICIÁRIO', lat: -8.559916, lng: 125.575097, location: 'Dili' }, + { cell: 'CFJJ2F', sector: 'CFJJ#2F', site: 'CENTRO FORMAÇÃO JURÍDICO E JURICIÁRIO', lat: -8.559916, lng: 125.575097, location: 'Dili' }, + { cell: 'CFJJ3E', sector: 'CFJJ#3', site: 'CENTRO FORMAÇÃO JURÍDICO E JURICIÁRIO', lat: -8.559916, lng: 125.575097, location: 'Dili' }, + { cell: 'CFJJ3F', sector: 'CFJJ#3F', site: 'CENTRO FORMAÇÃO JURÍDICO E JURICIÁRIO', lat: -8.559916, lng: 125.575097, location: 'Dili' }, + { cell: 'CFJJ4E', sector: 'CFJJ#4', site: 'CENTRO FORMAÇÃO JURÍDICO E JURICIÁRIO', lat: -8.559916, lng: 125.575097, location: 'Dili' }, + { cell: 'CFJJ4F', sector: 'CFJJ#4F', site: 'CENTRO FORMAÇÃO JURÍDICO E JURICIÁRIO', lat: -8.559916, lng: 125.575097, location: 'Dili' }, + { cell: 'CFJJ5E', sector: 'CFJJ#5', site: 'CENTRO FORMAÇÃO JURÍDICO E JURICIÁRIO', lat: -8.559916, lng: 125.575097, location: 'Dili' }, + { cell: 'CFJJ5F', sector: 'CFJJ#5F', site: 'CENTRO FORMAÇÃO JURÍDICO E JURICIÁRIO', lat: -8.559916, lng: 125.575097, location: 'Dili' }, + { cell: 'CFJJ6E', sector: 'CFJJ#6', site: 'CENTRO FORMAÇÃO JURÍDICO E JURICIÁRIO', lat: -8.559916, lng: 125.575097, location: 'Dili' }, + { cell: 'CFJJ6F', sector: 'CFJJ#6F', site: 'CENTRO FORMAÇÃO JURÍDICO E JURICIÁRIO', lat: -8.559916, lng: 125.575097, location: 'Dili' }, + { cell: 'COLM1E', sector: 'COLM#1', site: 'COLMERA', lat: -8.557754, lng: 125.57179, location: 'Dili' }, + { cell: 'COLM2E', sector: 'COLM#2', site: 'COLMERA', lat: -8.557754, lng: 125.57179, location: 'Dili' }, + { cell: 'COLM3E', sector: 'COLM#3', site: 'COLMERA', lat: -8.557754, lng: 125.57179, location: 'Dili' }, + { cell: 'COLM4E', sector: 'COLM#4', site: 'COLMERA', lat: -8.557754, lng: 125.57179, location: 'Dili' }, + { cell: 'COLM5E', sector: 'COLM#5', site: 'COLMERA', lat: -8.557754, lng: 125.57179, location: 'Dili' }, + { cell: 'COLM6E', sector: 'COLM#6', site: 'COLMERA', lat: -8.557754, lng: 125.57179, location: 'Dili' }, + { cell: 'COMR1E', sector: 'COMR#1', site: 'COMORO', lat: -8.556842, lng: 125.537612, location: 'Dili' }, + { cell: 'COMR1F', sector: 'COMR#1F', site: 'COMORO', lat: -8.556842, lng: 125.537612, location: 'Dili' }, + { cell: 'COMR2E', sector: 'COMR#2', site: 'COMORO', lat: -8.556842, lng: 125.537612, location: 'Dili' }, + { cell: 'COMR2F', sector: 'COMR#2F', site: 'COMORO', lat: -8.556842, lng: 125.537612, location: 'Dili' }, + { cell: 'COMR3E', sector: 'COMR#3', site: 'COMORO', lat: -8.556842, lng: 125.537612, location: 'Dili' }, + { cell: 'COMR3F', sector: 'COMR#3F', site: 'COMORO', lat: -8.556842, lng: 125.537612, location: 'Dili' }, + { cell: 'COMR4E', sector: 'COMR#4', site: 'COMORO', lat: -8.556842, lng: 125.537612, location: 'Dili' }, + { cell: 'COMR4F', sector: 'COMR4F', site: 'COMORO', lat: -8.556842, lng: 125.537612, location: 'Dili' }, + { cell: 'COMR5E', sector: 'COMR#5', site: 'COMORO', lat: -8.556842, lng: 125.537612, location: 'Dili' }, + { cell: 'COMR5F', sector: 'COMR5F', site: 'COMORO', lat: -8.556842, lng: 125.537612, location: 'Dili' }, + { cell: 'COMR6E', sector: 'COMR#6', site: 'COMORO', lat: -8.556842, lng: 125.537612, location: 'Dili' }, + { cell: 'COMR6F', sector: 'COMR6F', site: 'COMORO', lat: -8.556842, lng: 125.537612, location: 'Dili' }, + { cell: 'CRUZ1E', sector: 'CRUZ#1', site: 'SANTA CRUZ', lat: -8.559771, lng: 125.586388, location: 'Dili' }, + { cell: 'CRUZ1F', sector: 'CRUZ#1F', site: 'SANTA CRUZ', lat: -8.559771, lng: 125.586388, location: 'Dili' }, + { cell: 'CRUZ2E', sector: 'CRUZ#2', site: 'SANTA CRUZ', lat: -8.559771, lng: 125.586388, location: 'Dili' }, + { cell: 'CRUZ2F', sector: 'CRUZ#2F', site: 'SANTA CRUZ', lat: -8.559771, lng: 125.586388, location: 'Dili' }, + { cell: 'CRUZ3E', sector: 'CRUZ#3', site: 'SANTA CRUZ', lat: -8.559771, lng: 125.586388, location: 'Dili' }, + { cell: 'CRUZ3F', sector: 'CRUZ#3F', site: 'SANTA CRUZ', lat: -8.559771, lng: 125.586388, location: 'Dili' }, + { cell: 'CRUZ4E', sector: 'CRUZ#4', site: 'SANTA CRUZ', lat: -8.559771, lng: 125.586388, location: 'Dili' }, + { cell: 'CRUZ4F', sector: 'CRUZ#4F', site: 'SANTA CRUZ', lat: -8.559771, lng: 125.586388, location: 'Dili' }, + { cell: 'CRUZ5E', sector: 'CRUZ#5', site: 'SANTA CRUZ', lat: -8.559771, lng: 125.586388, location: 'Dili' }, + { cell: 'CRUZ5F', sector: 'CRUZ#5F', site: 'SANTA CRUZ', lat: -8.559771, lng: 125.586388, location: 'Dili' }, + { cell: 'CRUZ6E', sector: 'CRUZ#6', site: 'SANTA CRUZ', lat: -8.559771, lng: 125.586388, location: 'Dili' }, + { cell: 'CRUZ6F', sector: 'CRUZ#6F', site: 'SANTA CRUZ', lat: -8.559771, lng: 125.586388, location: 'Dili' }, + { cell: 'CUCA1E', sector: 'CUCA#1', site: 'CUCAHUN CALIFORNIA', lat: -8.560121, lng: 125.593541, location: 'Dili' }, + { cell: 'CUCA1F', sector: 'CUCA#1F', site: 'CUCAHUN CALIFORNIA', lat: -8.560121, lng: 125.593541, location: 'Dili' }, + { cell: 'CUCA2E', sector: 'CUCA#2', site: 'CUCAHUN CALIFORNIA', lat: -8.560121, lng: 125.593541, location: 'Dili' }, + { cell: 'CUCA2F', sector: 'CUCA#2F', site: 'CUCAHUN CALIFORNIA', lat: -8.560121, lng: 125.593541, location: 'Dili' }, + { cell: 'CUCA3E', sector: 'CUCA#3', site: 'CUCAHUN CALIFORNIA', lat: -8.560121, lng: 125.593541, location: 'Dili' }, + { cell: 'CUCA3F', sector: 'CUCA#3F', site: 'CUCAHUN CALIFORNIA', lat: -8.560121, lng: 125.593541, location: 'Dili' }, + { cell: 'CUCA4E', sector: 'CUCA#4', site: 'CULUHUN CALIFORNIA', lat: -8.560121, lng: 125.593541, location: 'Dili' }, + { cell: 'CUCA4F', sector: 'CUCA#4F', site: 'CULUHUN CALIFORNIA', lat: -8.560121, lng: 125.593541, location: 'Dili' }, + { cell: 'CUCA5E', sector: 'CUCA#5', site: 'CULUHUN CALIFORNIA', lat: -8.560121, lng: 125.593541, location: 'Dili' }, + { cell: 'CUCA5F', sector: 'CUCA#5F', site: 'CULUHUN CALIFORNIA', lat: -8.560121, lng: 125.593541, location: 'Dili' }, + { cell: 'CUCA6E', sector: 'CUCA#6', site: 'CULUHUN CALIFORNIA', lat: -8.560121, lng: 125.593541, location: 'Dili' }, + { cell: 'CUCA6F', sector: 'CUCA#6F', site: 'CULUHUN CALIFORNIA', lat: -8.560121, lng: 125.593541, location: 'Dili' }, + { cell: 'CVAR1E', sector: 'CVAR#1', site: 'CASNAVAR', lat: -8.600231, lng: 125.530978, location: 'DILI' }, + { cell: 'CVAR2E', sector: 'CVAR#2', site: 'CASNAVAR', lat: -8.600231, lng: 125.530978, location: 'DILI' }, + { cell: 'CVAR3E', sector: 'CVAR#3', site: 'CASNAVAR', lat: -8.600231, lng: 125.530978, location: 'DILI' }, + { cell: 'DLTA1E', sector: 'DLTA#1', site: 'DELTA', lat: -8.559742, lng: 125.543133, location: 'Dili' }, + { cell: 'DLTA4E', sector: 'DLTA#4E', site: 'DELTA', lat: -8.559742, lng: 125.543133, location: 'Dili' }, + { cell: 'DLTA2E', sector: 'DLTA#2', site: 'DELTA', lat: -8.559742, lng: 125.543133, location: 'Dili' }, + { cell: 'DLTA5E', sector: 'DLTA#5E', site: 'DELTA', lat: -8.559742, lng: 125.543133, location: 'Dili' }, + { cell: 'DLTA3E', sector: 'DLTA#3', site: 'DELTA', lat: -8.559742, lng: 125.543133, location: 'Dili' }, + { cell: 'DLTA6E', sector: 'DLTA#6E', site: 'DELTA', lat: -8.559742, lng: 125.543133, location: 'Dili' }, + { cell: 'DUYU1E', sector: 'DUYU#1', site: 'DUYUNG', lat: -8.53132, lng: 125.75596, location: 'Dili (District)' }, + { cell: 'DUYU2E', sector: 'DUYU#2', site: 'DUYUNG', lat: -8.53132, lng: 125.75596, location: 'Dili (District)' }, + { cell: 'ETO1E', sector: 'ETO#1', site: 'ETO', lat: -8.553875, lng: 125.570303, location: 'Dili' }, + { cell: 'ETO1F', sector: 'ETO#1F', site: 'ETO', lat: -8.553875, lng: 125.570303, location: 'Dili' }, + { cell: 'ETO2E', sector: 'ETO#2', site: 'ETO', lat: -8.553875, lng: 125.570303, location: 'Dili' }, + { cell: 'ETO2F', sector: 'ETO#2F', site: 'ETO', lat: -8.553875, lng: 125.570303, location: 'Dili' }, + { cell: 'ETO3E', sector: 'ETO#3', site: 'ETO', lat: -8.553875, lng: 125.570303, location: 'Dili' }, + { cell: 'ETO3F', sector: 'ETO#F', site: 'ETO', lat: -8.553875, lng: 125.570303, location: 'Dili' }, + { cell: 'ETO4E', sector: 'ETO#4', site: 'ETO', lat: -8.553875, lng: 125.570303, location: 'Dili' }, + { cell: 'ETO4F', sector: 'ETO#4F', site: 'ETO', lat: -8.553875, lng: 125.570303, location: 'Dili' }, + { cell: 'ETO5E', sector: 'ETO#5', site: 'ETO', lat: -8.553875, lng: 125.570303, location: 'Dili' }, + { cell: 'ETO5E', sector: 'ETO#5F', site: 'ETO', lat: -8.553875, lng: 125.570303, location: 'Dili' }, + { cell: 'ETO6E', sector: 'ETO#6', site: 'ETO', lat: -8.553875, lng: 125.570303, location: 'Dili' }, + { cell: 'ETO6F', sector: 'ETO#6F', site: 'ETO', lat: -8.553875, lng: 125.570303, location: 'Dili' }, + { cell: 'EWSD1E', sector: 'EWSD#1', site: 'EWSD', lat: -8.55893, lng: 125.579062, location: 'Dili' }, + { cell: 'EWSD1F', sector: 'EWSD#1F', site: 'EWSD', lat: -8.55893, lng: 125.579062, location: 'Dili' }, + { cell: 'EWSD2E', sector: 'EWSD#2', site: 'EWSD', lat: -8.55893, lng: 125.579062, location: 'Dili' }, + { cell: 'EWSD2F', sector: 'EWSD#2F', site: 'EWSD', lat: -8.55893, lng: 125.579062, location: 'Dili' }, + { cell: 'EWSD3E', sector: 'EWSD#3', site: 'EWSD', lat: -8.55893, lng: 125.579062, location: 'Dili' }, + { cell: 'EWSD3F', sector: 'EWSD#3F', site: 'EWSD', lat: -8.55893, lng: 125.579062, location: 'Dili' }, + { cell: 'EWSD4E', sector: 'EWSD4E', site: 'EWSD', lat: -8.55893, lng: 125.579062, location: 'Dili' }, + { cell: 'EWSD4F', sector: 'EWSD4F', site: 'EWSD', lat: -8.55893, lng: 125.579062, location: 'Dili' }, + { cell: 'EWSD5E', sector: 'EWSD5E', site: 'EWSD', lat: -8.55893, lng: 125.579062, location: 'Dili' }, + { cell: 'EWSD5F', sector: 'EWSD5F', site: 'EWSD', lat: -8.55893, lng: 125.579062, location: 'Dili' }, + { cell: 'EWSD6E', sector: 'EWSD6E', site: 'EWSD', lat: -8.55893, lng: 125.579062, location: 'Dili' }, + { cell: 'EWSD6F', sector: 'EWSD6F', site: 'EWSD', lat: -8.55893, lng: 125.579062, location: 'Dili' }, + { cell: 'FATA1E', sector: 'FATA#1', site: 'FATUMETA', lat: -8.564751, lng: 125.553508, location: 'Dili' }, + { cell: 'FATA1F', sector: 'FATA#1F', site: 'FATUMETA', lat: -8.564751, lng: 125.553508, location: 'Dili' }, + { cell: 'FATA2E', sector: 'FATA#2', site: 'FATUMETA', lat: -8.564751, lng: 125.553508, location: 'Dili' }, + { cell: 'FATA2F', sector: 'FATA#2F', site: 'FATUMETA', lat: -8.564751, lng: 125.553508, location: 'Dili' }, + { cell: 'FATA3E', sector: 'FATA#3', site: 'FATUMETA', lat: -8.564751, lng: 125.553508, location: 'Dili' }, + { cell: 'FATA3F', sector: 'FATA#3F', site: 'FATUMETA', lat: -8.564751, lng: 125.553508, location: 'Dili' }, + { cell: 'FATA4E', sector: 'FATA#4', site: 'FATUMETA', lat: -8.564751, lng: 125.553508, location: 'Dili' }, + { cell: 'FATA4F', sector: 'FATA#4F', site: 'FATUMETA', lat: -8.564751, lng: 125.553508, location: 'Dili' }, + { cell: 'FATA5E', sector: 'FATA#5', site: 'FATUMETA', lat: -8.564751, lng: 125.553508, location: 'Dili' }, + { cell: 'FATA5F', sector: 'FATA#5F', site: 'FATUMETA', lat: -8.564751, lng: 125.553508, location: 'Dili' }, + { cell: 'FATA6E', sector: 'FATA#6', site: 'FATUMETA', lat: -8.564751, lng: 125.553508, location: 'Dili' }, + { cell: 'FATA6F', sector: 'FATA#6F', site: 'FATUMETA', lat: -8.564751, lng: 125.553508, location: 'Dili' }, + { cell: 'FATU1E', sector: 'FATU#1', site: 'FATUHADA', lat: -8.556222, lng: 125.553624, location: 'Dili' }, + { cell: 'FATU1F', sector: 'FATU#1', site: 'FATUHADA', lat: -8.556222, lng: 125.553624, location: 'Dili' }, + { cell: 'FATU2E', sector: 'FATU#2', site: 'FATUHADA', lat: -8.556222, lng: 125.553624, location: 'Dili' }, + { cell: 'FATU2F', sector: 'FATU#2F', site: 'FATUHADA', lat: -8.556222, lng: 125.553624, location: 'Dili' }, + { cell: 'FATU3E', sector: 'FATU#3', site: 'FATUHADA', lat: -8.556222, lng: 125.553624, location: 'Dili' }, + { cell: 'FATU3F', sector: 'FATU#3F', site: 'FATUHADA', lat: -8.556222, lng: 125.553624, location: 'Dili' }, + { cell: 'FATU4E', sector: 'FATU#3', site: 'FATUHADA', lat: -8.556222, lng: 125.553624, location: 'Dili' }, + { cell: 'FATU4F', sector: 'FATU#3F', site: 'FATUHADA', lat: -8.556222, lng: 125.553624, location: 'Dili' }, + { cell: 'FATU5E', sector: 'FATU#5', site: 'FATUHADA', lat: -8.556222, lng: 125.553624, location: 'Dili' }, + { cell: 'FATU5F', sector: 'FATU#5F', site: 'FATUHADA', lat: -8.556222, lng: 125.553624, location: 'Dili' }, + { cell: 'FATU6E', sector: 'FATU#6', site: 'FATUHADA', lat: -8.556222, lng: 125.553624, location: 'Dili' }, + { cell: 'FATU6F', sector: 'FATU#6F', site: 'FATUHADA', lat: -8.556222, lng: 125.553624, location: 'Dili' }, + { cell: 'FAMA1E', sector: 'FAMA#7', site: 'FATUHADA (iMacro)', lat: -8.554103, lng: 125.555887, location: 'Dili' }, + { cell: 'FAMA4E', sector: 'FAMA#17', site: 'FATUHADA (iMacro)', lat: -8.554103, lng: 125.555887, location: 'Dili' }, + { cell: 'FAMA2E', sector: 'FAMA#8', site: 'FATUHADA (iMacro)', lat: -8.554103, lng: 125.555887, location: 'Dili' }, + { cell: 'FAMA5E', sector: 'FAMA#18', site: 'FATUHADA (iMacro)', lat: -8.554103, lng: 125.555887, location: 'Dili' }, + { cell: 'FOME1E', sector: 'FOME#1', site: 'FOMENTO', lat: -8.56461, lng: 125.534242, location: 'Dili' }, + { cell: 'FOME1F', sector: 'FOME#1F', site: 'FOMENTO', lat: -8.56461, lng: 125.534242, location: 'Dili' }, + { cell: 'FOME2E', sector: 'FOME#2', site: 'FOMENTO', lat: -8.56461, lng: 125.534242, location: 'Dili' }, + { cell: 'FOME2F', sector: 'FOME#2F', site: 'FOMENTO', lat: -8.56461, lng: 125.534242, location: 'Dili' }, + { cell: 'FOME3E', sector: 'FOME#3', site: 'FOMENTO', lat: -8.56461, lng: 125.534242, location: 'Dili' }, + { cell: 'FOME3F', sector: 'FOME#3F', site: 'FOMENTO', lat: -8.56461, lng: 125.534242, location: 'Dili' }, + { cell: 'FOME4E', sector: 'FOME#4', site: 'FOMENTO', lat: -8.56461, lng: 125.534242, location: 'Dili' }, + { cell: 'FOME4F', sector: 'FOME#4F', site: 'FOMENTO', lat: -8.56461, lng: 125.534242, location: 'Dili' }, + { cell: 'FOME5E', sector: 'FOME#5', site: 'FOMENTO', lat: -8.56461, lng: 125.534242, location: 'Dili' }, + { cell: 'FOME5F', sector: 'FOME#5F', site: 'FOMENTO', lat: -8.56461, lng: 125.534242, location: 'Dili' }, + { cell: 'FOME6E', sector: 'FOME#6', site: 'FOMENTO', lat: -8.56461, lng: 125.534242, location: 'Dili' }, + { cell: 'FOME6F', sector: 'FOME#6F', site: 'FOMENTO', lat: -8.56461, lng: 125.534242, location: 'Dili' }, + { cell: 'FOTE1E', sector: 'FOTE#1', site: 'FOMENTO III', lat: -8.5621, lng: 125.5384, location: 'Dili' }, + { cell: 'FOTE1F', sector: 'FOTE#1F', site: 'FOMENTO III', lat: -8.5621, lng: 125.5384, location: 'Dili' }, + { cell: 'FOTE2E', sector: 'FOTE#2', site: 'FOMENTO III', lat: -8.5621, lng: 125.5384, location: 'Dili' }, + { cell: 'FOTE2F', sector: 'FOTE#2F', site: 'FOMENTO III', lat: -8.5621, lng: 125.5384, location: 'Dili' }, + { cell: 'FOTE3E', sector: 'FOTE#3', site: 'FOMENTO III', lat: -8.5621, lng: 125.5384, location: 'Dili' }, + { cell: 'FOTE3F', sector: 'FOTE#3F', site: 'FOMENTO III', lat: -8.5621, lng: 125.5384, location: 'Dili' }, + { cell: 'FOTE4E', sector: 'FOTE#4', site: 'FOMENTO III', lat: -8.5621, lng: 125.5384, location: 'Dili' }, + { cell: 'FOTE4F', sector: 'FOTE#4F', site: 'FOMENTO III', lat: -8.5621, lng: 125.5384, location: 'Dili' }, + { cell: 'FOTE5E', sector: 'FOTE#5', site: 'FOMENTO III', lat: -8.5621, lng: 125.5384, location: 'Dili' }, + { cell: 'FOTE5F', sector: 'FOTE#5F', site: 'FOMENTO III', lat: -8.5621, lng: 125.5384, location: 'Dili' }, + { cell: 'FOTE6E', sector: 'FOTE#6', site: 'FOMENTO III', lat: -8.5621, lng: 125.5384, location: 'Dili' }, + { cell: 'FOTE6F', sector: 'FOTE#6F', site: 'FOMENTO III', lat: -8.5621, lng: 125.5384, location: 'Dili' }, + { cell: 'GFOR1E', sector: 'GFOR#1', site: 'GRICENFOR', lat: -8.554321, lng: 125.582925, location: 'Dili' }, + { cell: 'GFOR1F', sector: 'GFOR#1F', site: 'GRICENFOR', lat: -8.554321, lng: 125.582925, location: 'Dili' }, + { cell: 'GFOR2E', sector: 'GFOR#2', site: 'GRICENFOR', lat: -8.554321, lng: 125.582925, location: 'Dili' }, + { cell: 'GFOR2F', sector: 'GFOR#2F', site: 'GRICENFOR', lat: -8.554321, lng: 125.582925, location: 'Dili' }, + { cell: 'GFOR3E', sector: 'GFOR#3', site: 'GRICENFOR', lat: -8.554321, lng: 125.582925, location: 'Dili' }, + { cell: 'GFOR3F', sector: 'GFOR#3F', site: 'GRICENFOR', lat: -8.554321, lng: 125.582925, location: 'Dili' }, + { cell: 'GFOR4E', sector: 'GFOR#4', site: 'GRICENFOR', lat: -8.554321, lng: 125.582925, location: 'Dili' }, + { cell: 'GFOR4F', sector: 'GFOR#4F', site: 'GRICENFOR', lat: -8.554321, lng: 125.582925, location: 'Dili' }, + { cell: 'GFOR5E', sector: 'GFOR#5', site: 'GRICENFOR', lat: -8.554321, lng: 125.582925, location: 'Dili' }, + { cell: 'GFOR5F', sector: 'GFOR#5F', site: 'GRICENFOR', lat: -8.554321, lng: 125.582925, location: 'Dili' }, + { cell: 'GFOR6E', sector: 'GFOR#6', site: 'GRICENFOR', lat: -8.554321, lng: 125.582925, location: 'Dili' }, + { cell: 'GFOR6F', sector: 'GFOR#6F', site: 'GRICENFOR', lat: -8.554321, lng: 125.582925, location: 'Dili' }, + { cell: 'GMOR1E', sector: 'GMOR#1', site: 'GARDAMOR', lat: -8.553605, lng: 125.550514, location: 'Dili' }, + { cell: 'GMOR1F', sector: 'GMOR#1F', site: 'GARDAMOR', lat: -8.553605, lng: 125.550514, location: 'Dili' }, + { cell: 'GMOR2E', sector: 'GMOR#2', site: 'GARDAMOR', lat: -8.553605, lng: 125.550514, location: 'Dili' }, + { cell: 'GMOR2F', sector: 'GMOR#2F', site: 'GARDAMOR', lat: -8.553605, lng: 125.550514, location: 'Dili' }, + { cell: 'GMOR3E', sector: 'GMOR#3', site: 'GARDAMOR', lat: -8.553605, lng: 125.550514, location: 'Dili' }, + { cell: 'GMOR3F', sector: 'GMOR#3F', site: 'GARDAMOR', lat: -8.553605, lng: 125.550514, location: 'Dili' }, + { cell: 'GMOR4E', sector: 'GMOR#4', site: 'GARDAMOR', lat: -8.553605, lng: 125.550514, location: 'Dili' }, + { cell: 'GMOR4F', sector: 'GMOR#4F', site: 'GARDAMOR', lat: -8.553605, lng: 125.550514, location: 'Dili' }, + { cell: 'GMOR5E', sector: 'GMOR#5', site: 'GARDAMOR', lat: -8.553605, lng: 125.550514, location: 'Dili' }, + { cell: 'GMOR5F', sector: 'GMOR#5F', site: 'GARDAMOR', lat: -8.553605, lng: 125.550514, location: 'Dili' }, + { cell: 'GMOR6E', sector: 'GMOR#6', site: 'GARDAMOR', lat: -8.553605, lng: 125.550514, location: 'Dili' }, + { cell: 'GMOR6F', sector: 'GMOR#6F', site: 'GARDAMOR', lat: -8.553605, lng: 125.550514, location: 'Dili' }, + { cell: 'GOTA1E', sector: 'GOTA#1', site: 'GOLGOTA', lat: -8.555048, lng: 125.518629, location: 'Dili' }, + { cell: 'GOTA1F', sector: 'GOTA#1F', site: 'GOLGOTA', lat: -8.555048, lng: 125.518629, location: 'Dili' }, + { cell: 'GOTA2E', sector: 'GOTA#2', site: 'GOLGOTA', lat: -8.555048, lng: 125.518629, location: 'Dili' }, + { cell: 'GOTA2F', sector: 'GOTA#2F', site: 'GOLGOTA', lat: -8.555048, lng: 125.518629, location: 'Dili' }, + { cell: 'GOTA3E', sector: 'GOTA#3', site: 'GOLGOTA', lat: -8.555048, lng: 125.518629, location: 'Dili' }, + { cell: 'GOTA3F', sector: 'GOTA#3F', site: 'GOLGOTA', lat: -8.555048, lng: 125.518629, location: 'Dili' }, + { cell: 'GOTA4E', sector: 'GOTA#4', site: 'GOLGOTA', lat: -8.555048, lng: 125.518629, location: 'Dili' }, + { cell: 'GOTA4F', sector: 'GOTA#4F', site: 'GOLGOTA', lat: -8.555048, lng: 125.518629, location: 'Dili' }, + { cell: 'GOTA5E', sector: 'GOTA#5', site: 'GOLGOTA', lat: -8.555048, lng: 125.518629, location: 'Dili' }, + { cell: 'GOTA5F', sector: 'GOTA#5F', site: 'GOLGOTA', lat: -8.555048, lng: 125.518629, location: 'Dili' }, + { cell: 'GOTA6E', sector: 'GOTA#6', site: 'GOLGOTA', lat: -8.555048, lng: 125.518629, location: 'Dili' }, + { cell: 'GOTA6F', sector: 'GOTA#6F', site: 'GOLGOTA', lat: -8.555048, lng: 125.518629, location: 'Dili' }, + { cell: 'HACA1E', sector: 'HACA#1', site: 'HERA ACANUNO', lat: -8.554865, lng: 125.652393, location: 'Dili (District)' }, + { cell: 'HACA1F', sector: 'HACA1F', site: 'HERA ACANUNO', lat: -8.554865, lng: 125.652393, location: 'Dili (District)' }, + { cell: 'HACA2E', sector: 'HACA#2', site: 'HERA ACANUNO', lat: -8.554865, lng: 125.652393, location: 'Dili (District)' }, + { cell: 'HACA2F', sector: 'HACA2F', site: 'HERA ACANUNO', lat: -8.554865, lng: 125.652393, location: 'Dili (District)' }, + { cell: 'HACA3E', sector: 'HACA#3', site: 'HERA ACANUNO', lat: -8.554865, lng: 125.652393, location: 'Dili (District)' }, + { cell: 'HACA3F', sector: 'HACA3F', site: 'HERA ACANUNO', lat: -8.554865, lng: 125.652393, location: 'Dili (District)' }, + { cell: 'HACA4E', sector: 'HACA4E', site: 'HERA ACANUNO', lat: -8.554865, lng: 125.652393, location: 'Dili (District)' }, + { cell: 'HACA4F', sector: 'HACA4F', site: 'HERA ACANUNO', lat: -8.554865, lng: 125.652393, location: 'Dili (District)' }, + { cell: 'HACA5E', sector: 'HACA5E', site: 'HERA ACANUNO', lat: -8.554865, lng: 125.652393, location: 'Dili (District)' }, + { cell: 'HACA5F', sector: 'HACA5F', site: 'HERA ACANUNO', lat: -8.554865, lng: 125.652393, location: 'Dili (District)' }, + { cell: 'HACA6E', sector: 'HACA6E', site: 'HERA ACANUNO', lat: -8.554865, lng: 125.652393, location: 'Dili (District)' }, + { cell: 'HACA6F', sector: 'HACA6F', site: 'HERA ACANUNO', lat: -8.554865, lng: 125.652393, location: 'Dili (District)' }, + { cell: 'HALA4E', sector: 'HALA#4', site: 'HERA AILOKLARAN', lat: -8.5301, lng: 125.665, location: 'DILI (Distric)' }, + { cell: 'HALA5E', sector: 'HALA#5', site: 'HERA AILOKLARAN', lat: -8.5301, lng: 125.665, location: 'DILI (Distric)' }, + { cell: 'HALA6E', sector: 'HALA#6', site: 'HERA AILOKLARAN', lat: -8.5301, lng: 125.665, location: 'DILI (Distric)' }, + { cell: 'HERA1E', sector: 'HERA#1', site: 'HERA', lat: -8.545247, lng: 125.673123, location: 'Dili (District)' }, + { cell: 'HERA2E ', sector: 'HERA#2', site: 'HERA', lat: -8.545247, lng: 125.673123, location: 'Dili (District)' }, + { cell: 'HERA3E', sector: 'HERA#3', site: 'HERA', lat: -8.545247, lng: 125.673123, location: 'Dili (District)' }, + { cell: 'HETE1E', sector: 'HETE1E', site: 'HERA TEMPORARIO', lat: -8.559034, lng: 125.645948, location: 'Dili' }, + { cell: 'HETE1F', sector: 'HETE1F', site: 'HERA TEMPORARIO', lat: -8.559034, lng: 125.645948, location: 'Dili' }, + { cell: 'HETE2E', sector: 'HETE2E', site: 'HERA TEMPORARIO', lat: -8.559034, lng: 125.645948, location: 'Dili' }, + { cell: 'HETE2F', sector: 'HETE2F', site: 'HERA TEMPORARIO', lat: -8.559034, lng: 125.645948, location: 'Dili' }, + { cell: 'HETE3E', sector: 'HETE3E', site: 'HERA TEMPORARIO', lat: -8.559034, lng: 125.645948, location: 'Dili' }, + { cell: 'HETE3F', sector: 'HETE3F', site: 'HERA TEMPORARIO', lat: -8.559034, lng: 125.645948, location: 'Dili' }, + { cell: 'HETE4E', sector: 'HETE4E', site: 'HERA TEMPORARIO', lat: -8.559034, lng: 125.645948, location: 'Dili' }, + { cell: 'HETE4F', sector: 'HETE4F', site: 'HERA TEMPORARIO', lat: -8.559034, lng: 125.645948, location: 'Dili' }, + { cell: 'HETE5E', sector: 'HETE5E', site: 'HERA TEMPORARIO', lat: -8.559034, lng: 125.645948, location: 'Dili' }, + { cell: 'HETE5F', sector: 'HETE5F', site: 'HERA TEMPORARIO', lat: -8.559034, lng: 125.645948, location: 'Dili' }, + { cell: 'HETE6E', sector: 'HETE6E', site: 'HERA TEMPORARIO', lat: -8.559034, lng: 125.645948, location: 'Dili' }, + { cell: 'HETE6F', sector: 'HETE6F', site: 'HERA TEMPORARIO', lat: -8.559034, lng: 125.645948, location: 'Dili' }, + { cell: 'HRAM1E', sector: 'HRAM#1', site: 'HOTEL RAMELAU', lat: -8.555201, lng: 125.54862, location: 'Dili' }, + { cell: 'HRAM1F', sector: 'HRAM#1F', site: 'HOTEL RAMELAU', lat: -8.555201, lng: 125.54862, location: 'Dili' }, + { cell: 'HRAM2E', sector: 'HRAM#2', site: 'HOTEL RAMELAU', lat: -8.555201, lng: 125.54862, location: 'Dili' }, + { cell: 'HRAM2F', sector: 'HRAM#2F', site: 'HOTEL RAMELAU', lat: -8.555201, lng: 125.54862, location: 'Dili' }, + { cell: 'HRAM3E', sector: 'HRAM#3', site: 'HOTEL RAMELAU', lat: -8.555201, lng: 125.54862, location: 'Dili' }, + { cell: 'HRAM3F', sector: 'HRAM#3F', site: 'HOTEL RAMELAU', lat: -8.555201, lng: 125.54862, location: 'Dili' }, + { cell: 'HRAM4E', sector: 'HRAM#4E', site: 'HOTEL RAMELAU', lat: -8.555201, lng: 125.54862, location: 'Dili' }, + { cell: 'HRAM4F', sector: 'HRAM#4F', site: 'HOTEL RAMELAU', lat: -8.555201, lng: 125.54862, location: 'Dili' }, + { cell: 'HRAM5E', sector: 'HRAM#5E', site: 'HOTEL RAMELAU', lat: -8.555201, lng: 125.54862, location: 'Dili' }, + { cell: 'HRAM5F', sector: 'HRAM#5F', site: 'HOTEL RAMELAU', lat: -8.555201, lng: 125.54862, location: 'Dili' }, + { cell: 'HRAM6E', sector: 'HRAM#6E', site: 'HOTEL RAMELAU', lat: -8.555201, lng: 125.54862, location: 'Dili' }, + { cell: 'HRAM6F', sector: 'HRAM#6F', site: 'HOTEL RAMELAU', lat: -8.555201, lng: 125.54862, location: 'Dili' }, + { cell: 'HTIM1E', sector: 'HTIM#1', site: 'HOTEL TIMOR', lat: -8.554222, lng: 125.573653, location: 'Dili' }, + { cell: 'HTIM1F', sector: 'HTIM#1F', site: 'HOTEL TIMOR', lat: -8.554222, lng: 125.573653, location: 'Dili' }, + { cell: 'HTIM2E', sector: 'HTIM#2', site: 'HOTEL TIMOR', lat: -8.554222, lng: 125.573653, location: 'Dili' }, + { cell: 'HTIM2F', sector: 'HTIM#2F', site: 'HOTEL TIMOR', lat: -8.554222, lng: 125.573653, location: 'Dili' }, + { cell: 'HTIM3E', sector: 'HTIM#3', site: 'HOTEL TIMOR', lat: -8.554222, lng: 125.573653, location: 'Dili' }, + { cell: 'HTIM3F', sector: 'HTIM#3F', site: 'HOTEL TIMOR', lat: -8.554222, lng: 125.573653, location: 'Dili' }, + { cell: 'HTIM4E', sector: 'HTIM#4', site: 'HOTEL TIMOR', lat: -8.554222, lng: 125.573653, location: 'Dili' }, + { cell: 'HTIM4F', sector: 'HTIM#4F', site: 'HOTEL TIMOR', lat: -8.554222, lng: 125.573653, location: 'Dili' }, + { cell: 'HTIM5E', sector: 'HTIM#5', site: 'HOTEL TIMOR', lat: -8.554222, lng: 125.573653, location: 'Dili' }, + { cell: 'HTIM5F', sector: 'HTIM#5F', site: 'HOTEL TIMOR', lat: -8.554222, lng: 125.573653, location: 'Dili' }, + { cell: 'HTIM6E', sector: 'HTIM#6', site: 'HOTEL TIMOR', lat: -8.554222, lng: 125.573653, location: 'Dili' }, + { cell: 'HTIM6F', sector: 'HTIM#6F', site: 'HOTEL TIMOR', lat: -8.554222, lng: 125.573653, location: 'Dili' }, + { cell: 'HUSK1E', sector: 'HUSK#1', site: 'HUSBUK', lat: -8.559698, lng: 125.487105, location: 'Dili' }, + { cell: 'HUSK1F', sector: 'HUSK#1F', site: 'HUSBUK', lat: -8.559698, lng: 125.487105, location: 'Dili' }, + { cell: 'HUSK4E', sector: 'HUSK#4', site: 'HUSBUK', lat: -8.559698, lng: 125.487105, location: 'Dili' }, + { cell: 'HUSK4F', sector: 'HUSK#4F', site: 'HUSBUK', lat: -8.559698, lng: 125.487105, location: 'Dili' }, + { cell: 'HULA1E', sector: 'HULA#1', site: 'HUDILARAN', lat: -8.556, lng: 125.5589, location: 'Dili' }, + { cell: 'HULA1F', sector: 'HULA#1F', site: 'HUDILARAN', lat: -8.556, lng: 125.5589, location: 'Dili' }, + { cell: 'HULA2E', sector: 'HULA#2', site: 'HUDILARAN', lat: -8.556, lng: 125.5589, location: 'Dili' }, + { cell: 'HULA2F', sector: 'HULA#2F', site: 'HUDILARAN', lat: -8.556, lng: 125.5589, location: 'Dili' }, + { cell: 'HULA3E', sector: 'HULA#3', site: 'HUDILARAN', lat: -8.556, lng: 125.5589, location: 'Dili' }, + { cell: 'HULA3F', sector: 'HULA#3F', site: 'HUDILARAN', lat: -8.556, lng: 125.5589, location: 'Dili' }, + { cell: 'HULA4E', sector: 'HULA#4', site: 'HUDILARAN', lat: -8.556, lng: 125.5589, location: 'Dili' }, + { cell: 'HULA4F', sector: 'HULA#4F', site: 'HUDILARAN', lat: -8.556, lng: 125.5589, location: 'Dili' }, + { cell: 'HULA5E', sector: 'HULA#5', site: 'HUDILARAN', lat: -8.556, lng: 125.5589, location: 'Dili' }, + { cell: 'HULA5F', sector: 'HULA#5F', site: 'HUDILARAN', lat: -8.556, lng: 125.5589, location: 'Dili' }, + { cell: 'HULA6E', sector: 'HULA#6', site: 'HUDILARAN', lat: -8.556, lng: 125.5589, location: 'Dili' }, + { cell: 'HULA6F', sector: 'HULA#6F', site: 'HUDILARAN', lat: -8.556, lng: 125.5589, location: 'Dili' }, + { cell: 'KAME1E', sector: 'KAME#1', site: 'KAMPUNG MERDEKA', lat: -8.558557, lng: 125.531874, location: 'Dili' }, + { cell: 'KAME2E', sector: 'KAME#2', site: 'KAMPUNG MERDEKA', lat: -8.558557, lng: 125.531874, location: 'Dili' }, + { cell: 'KAME3E', sector: 'KAME#3', site: 'KAMPUNG MERDEKA', lat: -8.558557, lng: 125.531874, location: 'Dili' }, + { cell: 'KAME4E', sector: 'KAME#4', site: 'KAMPUNG MERDEKA', lat: -8.558557, lng: 125.531874, location: 'Dili' }, + { cell: 'KAME5E', sector: 'KAME#5', site: 'KAMPUNG MERDEKA', lat: -8.558557, lng: 125.531874, location: 'Dili' }, + { cell: 'KAME6E', sector: 'KAME#6', site: 'KAMPUNG MERDEKA', lat: -8.558557, lng: 125.531874, location: 'Dili' }, + { cell: 'KBAR1E', sector: 'KBAR#1', site: 'KAMPUNG BARU', lat: -8.565125, lng: 125.526904, location: 'Dili' }, + { cell: 'KBAR11E', sector: 'KBAR#11', site: 'KAMPUNG BARU', lat: -8.565125, lng: 125.526904, location: 'Dili' }, + { cell: 'KBAR2E', sector: 'KBAR#2', site: 'KAMPUNG BARU', lat: -8.565125, lng: 125.526904, location: 'Dili' }, + { cell: 'KBAR12E', sector: 'KBAR#12', site: 'KAMPUNG BARU', lat: -8.565125, lng: 125.526904, location: 'Dili' }, + { cell: 'KBAR3E', sector: 'KBAR#3', site: 'KAMPUNG BARU', lat: -8.565125, lng: 125.526904, location: 'Dili' }, + { cell: 'KBAR13E', sector: 'KBAR#13', site: 'KAMPUNG BARU', lat: -8.565125, lng: 125.526904, location: 'Dili' }, + { cell: 'KBAR4E', sector: 'KBAR#4', site: 'KAMPUNG BARU', lat: -8.565125, lng: 125.526904, location: 'Dili' }, + { cell: 'KBAR14E', sector: 'KBAR#14', site: 'KAMPUNG BARU', lat: -8.565125, lng: 125.526904, location: 'Dili' }, + { cell: 'KBAR5E', sector: 'KBAR#5', site: 'KAMPUNG BARU', lat: -8.565125, lng: 125.526904, location: 'Dili' }, + { cell: 'KBAR15E', sector: 'KBAR#15', site: 'KAMPUNG BARU', lat: -8.565125, lng: 125.526904, location: 'Dili' }, + { cell: 'KBAR6E', sector: 'KBAR#6', site: 'KAMPUNG BARU', lat: -8.565125, lng: 125.526904, location: 'Dili' }, + { cell: 'KBAR16E', sector: 'KBAR#16', site: 'KAMPUNG BARU', lat: -8.565125, lng: 125.526904, location: 'Dili' }, + { cell: 'KLOR1E', sector: 'KLOR#1', site: 'KAMPUNG ALOR', lat: -8.55109, lng: 125.55968, location: 'Dili' }, + { cell: 'KLOR1F', sector: 'KLOR#1F', site: 'KAMPUNG ALOR', lat: -8.55109, lng: 125.55968, location: 'Dili' }, + { cell: 'KLOR2E', sector: 'KLOR#2', site: 'KAMPUNG ALOR', lat: -8.55109, lng: 125.55968, location: 'Dili' }, + { cell: 'KLOR2F', sector: 'KLOR#2F', site: 'KAMPUNG ALOR', lat: -8.55109, lng: 125.55968, location: 'Dili' }, + { cell: 'KLOR3E', sector: 'KLOR#3', site: 'KAMPUNG ALOR', lat: -8.55109, lng: 125.55968, location: 'Dili' }, + { cell: 'KLOR3F', sector: 'KLOR#3F', site: 'KAMPUNG ALOR', lat: -8.55109, lng: 125.55968, location: 'Dili' }, + { cell: 'KLOR4E', sector: 'KLOR#4', site: 'KAMPUNG ALOR', lat: -8.55109, lng: 125.55968, location: 'Dili' }, + { cell: 'KLOR4F', sector: 'KLOR#4F', site: 'KAMPUNG ALOR', lat: -8.55109, lng: 125.55968, location: 'Dili' }, + { cell: 'KLOR5E', sector: 'KLOR#5', site: 'KAMPUNG ALOR', lat: -8.55109, lng: 125.55968, location: 'Dili' }, + { cell: 'KLOR5F', sector: 'KLOR#5F', site: 'KAMPUNG ALOR', lat: -8.55109, lng: 125.55968, location: 'Dili' }, + { cell: 'KLOR6F', sector: 'KLOR#6F', site: 'KAMPUNG ALOR', lat: -8.55109, lng: 125.55968, location: 'Dili' }, + { cell: 'KLOR6F', sector: 'KLOR#6F', site: 'KAMPUNG ALOR', lat: -8.55109, lng: 125.55968, location: 'Dili' }, + { cell: 'LAHO1E', sector: 'LAHO#1', site: 'LAHANE ORIENTAL', lat: -8.56691, lng: 125.58464, location: 'Dili' }, + { cell: 'LAHO1F', sector: 'LAHO#1F', site: 'LAHANE ORIENTAL', lat: -8.56691, lng: 125.58464, location: 'Dili' }, + { cell: 'LAHO2E', sector: 'LAHO#2', site: 'LAHANE ORIENTAL', lat: -8.56691, lng: 125.58464, location: 'Dili' }, + { cell: 'LAHO2F', sector: 'LAHO#2F', site: 'LAHANE ORIENTAL', lat: -8.56691, lng: 125.58464, location: 'Dili' }, + { cell: 'LAHO3E', sector: 'LAHO#3', site: 'LAHANE ORIENTAL', lat: -8.56691, lng: 125.58464, location: 'Dili' }, + { cell: 'LAHO3F', sector: 'LAHO#3F', site: 'LAHANE ORIENTAL', lat: -8.56691, lng: 125.58464, location: 'Dili' }, + { cell: 'LAHO4E', sector: 'LAHO#4', site: 'LAHANE ORIENTAL', lat: -8.56691, lng: 125.58464, location: 'Dili' }, + { cell: 'LAHO4F', sector: 'LAHO#4F', site: 'LAHANE ORIENTAL', lat: -8.56691, lng: 125.58464, location: 'Dili' }, + { cell: 'LAHO5E', sector: 'LAHO#5', site: 'LAHANE ORIENTAL', lat: -8.56691, lng: 125.58464, location: 'Dili' }, + { cell: 'LAHO5F', sector: 'LAHO#5F', site: 'LAHANE ORIENTAL', lat: -8.56691, lng: 125.58464, location: 'Dili' }, + { cell: 'LAHO6E', sector: 'LAHO#6', site: 'LAHANE ORIENTAL', lat: -8.56691, lng: 125.58464, location: 'Dili' }, + { cell: 'LAHO6F', sector: 'LAHO#6F', site: 'LAHANE ORIENTAL', lat: -8.56691, lng: 125.58464, location: 'Dili' }, + { cell: 'LECI1E', sector: 'LECI#1', site: 'LECIDERE', lat: -8.551937, lng: 125.583601, location: 'Dili' }, + { cell: 'LECI1F', sector: 'LECI#1F', site: 'LECIDERE', lat: -8.551937, lng: 125.583601, location: 'Dili' }, + { cell: 'LECI2E', sector: 'LECI#2', site: 'LECIDERE', lat: -8.551937, lng: 125.583601, location: 'Dili' }, + { cell: 'LECI2F', sector: 'LECI#2F', site: 'LECIDERE', lat: -8.551937, lng: 125.583601, location: 'Dili' }, + { cell: 'LECI3E', sector: 'LECI#3', site: 'LECIDERE', lat: -8.551937, lng: 125.583601, location: 'Dili' }, + { cell: 'LECI3F', sector: 'LECI#3F', site: 'LECIDERE', lat: -8.551937, lng: 125.583601, location: 'Dili' }, + { cell: 'LECI4E', sector: 'LECI#4', site: 'LECIDERE', lat: -8.551937, lng: 125.583601, location: 'Dili' }, + { cell: 'LECI4F', sector: 'LECI#4F', site: 'LECIDERE', lat: -8.551937, lng: 125.583601, location: 'Dili' }, + { cell: 'LECI5E', sector: 'LECI#5', site: 'LECIDERE', lat: -8.551937, lng: 125.583601, location: 'Dili' }, + { cell: 'LECI5F', sector: 'LECI#5F', site: 'LECIDERE', lat: -8.551937, lng: 125.583601, location: 'Dili' }, + { cell: 'LECI6E', sector: 'LECI#6', site: 'LECIDERE', lat: -8.551937, lng: 125.583601, location: 'Dili' }, + { cell: 'LECI6F', sector: 'LECI#6F', site: 'LECIDERE', lat: -8.551937, lng: 125.583601, location: 'Dili' }, + { cell: 'LEMK1E', sector: 'LEMK#1', site: 'LEMOKARI', lat: -8.571833, lng: 125.535189, location: 'Dili' }, + { cell: 'LEMK1F', sector: 'LEMK#1F', site: 'LEMOKARI', lat: -8.571833, lng: 125.535189, location: 'Dili' }, + { cell: 'LEMK2E', sector: 'LEMK#2', site: 'LEMOKARI', lat: -8.571833, lng: 125.535189, location: 'Dili' }, + { cell: 'LEMK2F', sector: 'LEMK#2F', site: 'LEMOKARI', lat: -8.571833, lng: 125.535189, location: 'Dili' }, + { cell: 'LEMK3E', sector: 'LEMK#3', site: 'LEMOKARI', lat: -8.571833, lng: 125.535189, location: 'Dili' }, + { cell: 'LEMK3F', sector: 'LEMK#3F', site: 'LEMOKARI', lat: -8.571833, lng: 125.535189, location: 'Dili' }, + { cell: 'LEMK4E', sector: 'LEMK#4', site: 'LEMOKARI', lat: -8.571833, lng: 125.535189, location: 'Dili' }, + { cell: 'LEMK4F', sector: 'LEMK#4F', site: 'LEMOKARI', lat: -8.571833, lng: 125.535189, location: 'Dili' }, + { cell: 'LEMK5E', sector: 'LEMK#5', site: 'LEMOKARI', lat: -8.571833, lng: 125.535189, location: 'Dili' }, + { cell: 'LEMK5F', sector: 'LEMK#5F', site: 'LEMOKARI', lat: -8.571833, lng: 125.535189, location: 'Dili' }, + { cell: 'LEMK6E', sector: 'LEMK#6', site: 'LEMOKARI', lat: -8.571833, lng: 125.535189, location: 'Dili' }, + { cell: 'LEMK6F', sector: 'LEMK#6F', site: 'LEMOKARI', lat: -8.571833, lng: 125.535189, location: 'Dili' }, + { cell: 'LIDU1E', sector: 'LIDU#1E', site: 'LIDUN', lat: -8.574247, lng: 125.542276, location: 'Dili' }, + { cell: 'LIDU1F', sector: 'LIDU#1F', site: 'LIDUN', lat: -8.574247, lng: 125.542276, location: 'Dili' }, + { cell: 'LIDU2E', sector: 'LIDU#2E', site: 'LIDUN', lat: -8.574247, lng: 125.542276, location: 'Dili' }, + { cell: 'LIDU2F', sector: 'LIDU#2F', site: 'LIDUN', lat: -8.574247, lng: 125.542276, location: 'Dili' }, + { cell: 'LIDU3E', sector: 'LIDU#3E', site: 'LIDUN', lat: -8.574247, lng: 125.542276, location: 'Dili' }, + { cell: 'LIDU3F', sector: 'LIDU#3F', site: 'LIDUN', lat: -8.574247, lng: 125.542276, location: 'Dili' }, + { cell: 'LIDU4E', sector: 'LIDU#4E', site: 'LIDUN', lat: -8.574247, lng: 125.542276, location: 'Dili' }, + { cell: 'LIDU4F', sector: 'LIDU#4F', site: 'LIDUN', lat: -8.574247, lng: 125.542276, location: 'Dili' }, + { cell: 'LIDU5E', sector: 'LIDU#5E', site: 'LIDUN', lat: -8.574247, lng: 125.542276, location: 'Dili' }, + { cell: 'LIDU5F', sector: 'LIDU#5F', site: 'LIDUN', lat: -8.574247, lng: 125.542276, location: 'Dili' }, + { cell: 'LIDU6E', sector: 'LIDU#6E', site: 'LIDUN', lat: -8.574247, lng: 125.542276, location: 'Dili' }, + { cell: 'LIDU6F', sector: 'LIDU#6F', site: 'LIDUN', lat: -8.574247, lng: 125.542276, location: 'Dili' }, + { cell: 'LISB1E', sector: 'LISB#1', site: 'LISBUTAK', lat: -8.576319, lng: 125.532329, location: 'Dili' }, + { cell: 'LISB1F', sector: 'LISB#1F', site: 'LISBUTAK', lat: -8.576319, lng: 125.532329, location: 'Dili' }, + { cell: 'LISB2E', sector: 'LISB#2', site: 'LISBUTAK', lat: -8.576319, lng: 125.532329, location: 'Dili' }, + { cell: 'LISB2F', sector: 'LISB#2F', site: 'LISBUTAK', lat: -8.576319, lng: 125.532329, location: 'Dili' }, + { cell: 'LISB3E', sector: 'LISB#3', site: 'LISBUTAK', lat: -8.576319, lng: 125.532329, location: 'Dili' }, + { cell: 'LISB3F', sector: 'LISB#3F', site: 'LISBUTAK', lat: -8.576319, lng: 125.532329, location: 'Dili' }, + { cell: 'LISB4E', sector: 'LISB#4', site: 'LISBUTAK', lat: -8.576319, lng: 125.532329, location: 'Dili' }, + { cell: 'LISB4F', sector: 'LISB#4F', site: 'LISBUTAK', lat: -8.576319, lng: 125.532329, location: 'Dili' }, + { cell: 'LISB5E', sector: 'LISB#5', site: 'LISBUTAK', lat: -8.576319, lng: 125.532329, location: 'Dili' }, + { cell: 'LISB5F', sector: 'LISB#5F', site: 'LISBUTAK', lat: -8.576319, lng: 125.532329, location: 'Dili' }, + { cell: 'LISB6E', sector: 'LISB#6', site: 'LISBUTAK', lat: -8.576319, lng: 125.532329, location: 'Dili' }, + { cell: 'LISB6F', sector: 'LISB#6F', site: 'LISBUTAK', lat: -8.576319, lng: 125.532329, location: 'Dili' }, + { cell: 'LOCE1E', sector: 'LOCE#1', site: 'LOCENEON', lat: -8.559331, lng: 125.582984, location: 'Dili' }, + { cell: 'LOCE1F', sector: 'LOCE#1F', site: 'LOCENEON', lat: -8.559331, lng: 125.582984, location: 'Dili' }, + { cell: 'LOCE2E', sector: 'LOCE#2', site: 'LOCENEON', lat: -8.559331, lng: 125.582984, location: 'Dili' }, + { cell: 'LOCE2F', sector: 'LOCE#2F', site: 'LOCENEON', lat: -8.559331, lng: 125.582984, location: 'Dili' }, + { cell: 'LOCE3E', sector: 'LOCE#3', site: 'LOCENEON', lat: -8.559331, lng: 125.582984, location: 'Dili' }, + { cell: 'LOCE3F', sector: 'LOCE#3F', site: 'LOCENEON', lat: -8.559331, lng: 125.582984, location: 'Dili' }, + { cell: 'LOCE4E', sector: 'LOCE#4', site: 'LOCENEON', lat: -8.559331, lng: 125.582984, location: 'Dili' }, + { cell: 'LOCE4F', sector: 'LOCE#4F', site: 'LOCENEON', lat: -8.559331, lng: 125.582984, location: 'Dili' }, + { cell: 'LOCE5E', sector: 'LOCE#5', site: 'LOCENEON', lat: -8.559331, lng: 125.582984, location: 'Dili' }, + { cell: 'LOCE5F', sector: 'LOCE#5F', site: 'LOCENEON', lat: -8.559331, lng: 125.582984, location: 'Dili' }, + { cell: 'LOCE6E', sector: 'LOCE#6', site: 'LOCENEON', lat: -8.559331, lng: 125.582984, location: 'Dili' }, + { cell: 'LOCE6F', sector: 'LOCE#6F', site: 'LOCENEON', lat: -8.559331, lng: 125.582984, location: 'Dili' }, + { cell: 'LUMA1E', sector: 'LUMA#1', site: 'LUROMATA', lat: -8.551274, lng: 125.554004, location: 'Dili' }, + { cell: 'LUMA1F', sector: 'LUMA#1F', site: 'LUROMATA', lat: -8.551274, lng: 125.554004, location: 'Dili' }, + { cell: 'LUMA2E', sector: 'LUMA#2', site: 'LUROMATA', lat: -8.551274, lng: 125.554004, location: 'Dili' }, + { cell: 'LUMA2F', sector: 'LUMA#2F', site: 'LUROMATA', lat: -8.551274, lng: 125.554004, location: 'Dili' }, + { cell: 'LUMA3E', sector: 'LUMA#3', site: 'LUROMATA', lat: -8.551274, lng: 125.554004, location: 'Dili' }, + { cell: 'LUMA3F', sector: 'LUMA#3F', site: 'LUROMATA', lat: -8.551274, lng: 125.554004, location: 'Dili' }, + { cell: 'LUMA4E', sector: 'LUMA#4', site: 'LUROMATA', lat: -8.551274, lng: 125.554004, location: 'Dili' }, + { cell: 'LUMA4F', sector: 'LUMA#4F', site: 'LUROMATA', lat: -8.551274, lng: 125.554004, location: 'Dili' }, + { cell: 'LUMA5E', sector: 'LUMA#5', site: 'LUROMATA', lat: -8.551274, lng: 125.554004, location: 'Dili' }, + { cell: 'LUMA5F', sector: 'LUMA#5F', site: 'LUROMATA', lat: -8.551274, lng: 125.554004, location: 'Dili' }, + { cell: 'LUMA6E', sector: 'LUMA#6', site: 'LUROMATA', lat: -8.551274, lng: 125.554004, location: 'Dili' }, + { cell: 'LUMA6F', sector: 'LUMA#6F', site: 'LUROMATA', lat: -8.551274, lng: 125.554004, location: 'Dili' }, + { cell: 'MADU1E', sector: 'MADU#1', site: ' MASLIDUN', lat: -8.568757, lng: 125.514704, location: 'Dili' }, + { cell: 'MADU1F', sector: 'MADU#1F', site: ' MASLIDUN', lat: -8.568757, lng: 125.514704, location: 'Dili' }, + { cell: 'MADU2E', sector: 'MADU#2', site: ' MASLIDUN', lat: -8.568757, lng: 125.514704, location: 'Dili' }, + { cell: 'MADU2F', sector: 'MADU#F', site: ' MASLIDUN', lat: -8.568757, lng: 125.514704, location: 'Dili' }, + { cell: 'MADU3E', sector: 'MADU#3', site: ' MASLIDUN', lat: -8.568757, lng: 125.514704, location: 'Dili' }, + { cell: 'MADU3F', sector: 'MADU#3F', site: ' MASLIDUN', lat: -8.568757, lng: 125.514704, location: 'Dili' }, + { cell: 'MADU4E', sector: 'MADU#4', site: ' MASLIDUN', lat: -8.568757, lng: 125.514704, location: 'Dili' }, + { cell: 'MADU4F', sector: 'MADU#4F', site: ' MASLIDUN', lat: -8.568757, lng: 125.514704, location: 'Dili' }, + { cell: 'MADU5E', sector: 'MADU#5', site: ' MASLIDUN', lat: -8.568757, lng: 125.514704, location: 'Dili' }, + { cell: 'MADU5F', sector: 'MADU#5F', site: ' MASLIDUN', lat: -8.568757, lng: 125.514704, location: 'Dili' }, + { cell: 'MADU6E', sector: 'MADU#6', site: ' MASLIDUN', lat: -8.568757, lng: 125.514704, location: 'Dili' }, + { cell: 'MADU6F', sector: 'MADU#6F', site: ' MASLIDUN', lat: -8.568757, lng: 125.514704, location: 'Dili' }, + { cell: 'MANA1E', sector: 'MANA#1', site: 'MANLEUANA', lat: -8.5749, lng: 125.5383, location: 'Dili' }, + { cell: 'MANA1F', sector: 'MANA#1F', site: 'MANLEUANA', lat: -8.5749, lng: 125.5383, location: 'Dili' }, + { cell: 'MANA2E', sector: 'MANA#2', site: 'MANLEUANA', lat: -8.5749, lng: 125.5383, location: 'Dili' }, + { cell: 'MANA2F', sector: 'MANA#2F', site: 'MANLEUANA', lat: -8.5749, lng: 125.5383, location: 'Dili' }, + { cell: 'MANA3E', sector: 'MANA#3', site: 'MANLEUANA', lat: -8.5749, lng: 125.5383, location: 'Dili' }, + { cell: 'MANA3F', sector: 'MANA#3F', site: 'MANLEUANA', lat: -8.5749, lng: 125.5383, location: 'Dili' }, + { cell: 'MANA4E', sector: 'MANA#4', site: 'MANLEUANA', lat: -8.5749, lng: 125.5383, location: 'Dili' }, + { cell: 'MANA4F', sector: 'MANA#4F', site: 'MANLEUANA', lat: -8.5749, lng: 125.5383, location: 'Dili' }, + { cell: 'MANA5E', sector: 'MANA#5', site: 'MANLEUANA', lat: -8.5749, lng: 125.5383, location: 'Dili' }, + { cell: 'MANA5F', sector: 'MANA#5F', site: 'MANLEUANA', lat: -8.5749, lng: 125.5383, location: 'Dili' }, + { cell: 'MANA6E', sector: 'MANA#6', site: 'MANLEUANA', lat: -8.5749, lng: 125.5383, location: 'Dili' }, + { cell: 'MANA6F', sector: 'MANA#6F', site: 'MANLEUANA', lat: -8.5749, lng: 125.5383, location: 'Dili' }, + { cell: 'MANE1E', sector: 'MANE#1', site: 'MANELEU', lat: -8.564059, lng: 125.544706, location: 'Dili' }, + { cell: 'MANE1F', sector: 'MANE#1F', site: 'MANELEU', lat: -8.564059, lng: 125.544706, location: 'Dili' }, + { cell: 'MANE2E', sector: 'MANE#2', site: 'MANELEU', lat: -8.564059, lng: 125.544706, location: 'Dili' }, + { cell: 'MANE2F', sector: 'MANE#2F', site: 'MANELEU', lat: -8.564059, lng: 125.544706, location: 'Dili' }, + { cell: 'MANE3E', sector: 'MANE#3', site: 'MANELEU', lat: -8.564059, lng: 125.544706, location: 'Dili' }, + { cell: 'MANE3F', sector: 'MANE#3F', site: 'MANELEU', lat: -8.564059, lng: 125.544706, location: 'Dili' }, + { cell: 'MANE4E', sector: 'MANE#4', site: 'MANELEU', lat: -8.564059, lng: 125.544706, location: 'Dili' }, + { cell: 'MANE4F', sector: 'MANE#4F', site: 'MANELEU', lat: -8.564059, lng: 125.544706, location: 'Dili' }, + { cell: 'MANE5E', sector: 'MANE#5', site: 'MANELEU', lat: -8.564059, lng: 125.544706, location: 'Dili' }, + { cell: 'MANE5F', sector: 'MANE#5F', site: 'MANELEU', lat: -8.564059, lng: 125.544706, location: 'Dili' }, + { cell: 'MANE6E', sector: 'MANE#6', site: 'MANELEU', lat: -8.564059, lng: 125.544706, location: 'Dili' }, + { cell: 'MANE6F', sector: 'MANE#6F', site: 'MANELEU', lat: -8.564059, lng: 125.544706, location: 'Dili' }, + { cell: 'MARA1E', sector: 'MARA#1', site: 'Marabia', lat: -8.579707, lng: 125.575098, location: 'Dili' }, + { cell: 'MARA2E', sector: 'MARA#2', site: 'Marabia', lat: -8.579707, lng: 125.575098, location: 'Dili' }, + { cell: 'MARA3E', sector: 'MARA#3', site: 'Marabia', lat: -8.579707, lng: 125.575098, location: 'Dili' }, + { cell: 'MASC1E', sector: 'MASC#1', site: 'MASCARENHAS', lat: -8.565056, lng: 125.577416, location: 'Dili' }, + { cell: 'MASC1F', sector: 'MASC#1F', site: 'MASCARENHAS', lat: -8.565056, lng: 125.577416, location: 'Dili' }, + { cell: 'MASC2E', sector: 'MASC#2', site: 'MASCARENHAS', lat: -8.565056, lng: 125.577416, location: 'Dili' }, + { cell: 'MASC2F', sector: 'MASC#2F', site: 'MASCARENHAS', lat: -8.565056, lng: 125.577416, location: 'Dili' }, + { cell: 'MASC3E', sector: 'MASC#3', site: 'MASCARENHAS', lat: -8.565056, lng: 125.577416, location: 'Dili' }, + { cell: 'MASC3F', sector: 'MASC#3F', site: 'MASCARENHAS', lat: -8.565056, lng: 125.577416, location: 'Dili' }, + { cell: 'MASC4E', sector: 'MASC#4', site: 'MASCARENHAS', lat: -8.565056, lng: 125.577416, location: 'Dili' }, + { cell: 'MASC4F', sector: 'MASC#4F', site: 'MASCARENHAS', lat: -8.565056, lng: 125.577416, location: 'Dili' }, + { cell: 'MASC5E', sector: 'MASC#5', site: 'MASCARENHAS', lat: -8.565056, lng: 125.577416, location: 'Dili' }, + { cell: 'MASC5F', sector: 'MASC#5F', site: 'MASCARENHAS', lat: -8.565056, lng: 125.577416, location: 'Dili' }, + { cell: 'MASC6E', sector: 'MASC#6', site: 'MASCARENHAS', lat: -8.565056, lng: 125.577416, location: 'Dili' }, + { cell: 'MASC6F', sector: 'MASC#6F', site: 'MASCARENHAS', lat: -8.565056, lng: 125.577416, location: 'Dili' }, + { cell: 'METI1E', sector: 'METI#1', site: 'METIAUT', lat: -8.5481, lng: 125.600977, location: 'Dili' }, + { cell: 'METI1F', sector: 'METI1F', site: 'METIAUT', lat: -8.5481, lng: 125.600977, location: 'Dili' }, + { cell: 'METI2E', sector: 'METI#2', site: 'METIAUT', lat: -8.5481, lng: 125.600977, location: 'Dili' }, + { cell: 'METI2F', sector: 'METI2F', site: 'METIAUT', lat: -8.5481, lng: 125.600977, location: 'Dili' }, + { cell: 'METI4E', sector: 'METI4E', site: 'METIAUT', lat: -8.5481, lng: 125.600977, location: 'Dili' }, + { cell: 'METI4F', sector: 'METI4F', site: 'METIAUT', lat: -8.5481, lng: 125.600977, location: 'Dili' }, + { cell: 'METI5E', sector: 'METI5E', site: 'METIAUT', lat: -8.5481, lng: 125.600977, location: 'Dili' }, + { cell: 'METI5F', sector: 'METI5F', site: 'METIAUT', lat: -8.5481, lng: 125.600977, location: 'Dili' }, + { cell: 'MLMO1E', sector: 'MLMO#1', site: 'MALINAMOK', lat: -8.55743, lng: 125.526083, location: 'Dili' }, + { cell: 'MLMO1F', sector: 'MLMO#1F', site: 'MALINAMOK', lat: -8.55743, lng: 125.526083, location: 'Dili' }, + { cell: 'MLMO2E', sector: 'MLMO#2', site: 'MALINAMOK', lat: -8.55743, lng: 125.526083, location: 'Dili' }, + { cell: 'MLMO2F', sector: 'MLMO#2F', site: 'MALINAMOK', lat: -8.55743, lng: 125.526083, location: 'Dili' }, + { cell: 'MLMO3E', sector: 'MLMO#3', site: 'MALINAMOK', lat: -8.55743, lng: 125.526083, location: 'Dili' }, + { cell: 'MLMO3F', sector: 'MLMO#3F', site: 'MALINAMOK', lat: -8.55743, lng: 125.526083, location: 'Dili' }, + { cell: 'MLMO4E', sector: 'MLMO#4', site: 'MALINAMOK', lat: -8.55743, lng: 125.526083, location: 'Dili' }, + { cell: 'MLMO4F', sector: 'MLMO#4F', site: 'MALINAMOK', lat: -8.55743, lng: 125.526083, location: 'Dili' }, + { cell: 'MLMO5E', sector: 'MLMO#5', site: 'MALINAMOK', lat: -8.55743, lng: 125.526083, location: 'Dili' }, + { cell: 'MLMO5F', sector: 'MLMO#5F', site: 'MALINAMOK', lat: -8.55743, lng: 125.526083, location: 'Dili' }, + { cell: 'MLMO6E', sector: 'MLMO#6', site: 'MALINAMOK', lat: -8.55743, lng: 125.526083, location: 'Dili' }, + { cell: 'MLMO6F', sector: 'MLMO#6F', site: 'MALINAMOK', lat: -8.55743, lng: 125.526083, location: 'Dili' }, + { cell: 'MNEC1E', sector: 'MNEC#1', site: 'MNEC', lat: -8.548266, lng: 125.557369, location: 'Dili' }, + { cell: 'MNEC2E', sector: 'MNEC#2', site: 'MNEC', lat: -8.548266, lng: 125.557369, location: 'Dili' }, + { cell: 'MNEC3E', sector: 'MNEC#3', site: 'MNEC', lat: -8.548266, lng: 125.557369, location: 'Dili' }, + { cell: 'MNEC4E', sector: 'MNEC#4', site: 'MNEC', lat: -8.548266, lng: 125.557369, location: 'Dili' }, + { cell: 'MNEC5E', sector: 'MNEC#5', site: 'MNEC', lat: -8.548266, lng: 125.557369, location: 'Dili' }, + { cell: 'MNEC6E', sector: 'MNEC#6', site: 'MNEC', lat: -8.548266, lng: 125.557369, location: 'Dili' }, + { cell: 'MOTE1E', sector: 'MOTE#1', site: 'MOTAEL TEMPORARIO', lat: -8.551134, lng: 125.571302, location: 'Dili' }, + { cell: 'MOTE2E', sector: 'MOTE#2', site: 'MOTAEL TEMPORARIO', lat: -8.551134, lng: 125.571302, location: 'Dili' }, + { cell: 'MTNR1E', sector: 'MTNR#1', site: 'METINARO', lat: -8.517556, lng: 125.779543, location: 'Dili (District)' }, + { cell: 'MTNR2E', sector: 'MTNR#2', site: 'METINARO', lat: -8.517556, lng: 125.779543, location: 'Dili (District)' }, + { cell: 'MTNR3E (Split DUYU#2)', sector: 'MTNR#3', site: 'METINARO (splittagem Duyu#2)', lat: -8.53132, lng: 125.75596, location: 'Dili (District)' }, + { cell: 'MUPE1E', sector: 'MUPE#1', site: 'LISBUTAK MUNDO PERDIDO ', lat: -8.579338, lng: 125.53699, location: 'Dili' }, + { cell: 'MUPE1F', sector: 'MUPE#1F', site: 'LISBUTAK MUNDO PERDIDO ', lat: -8.579338, lng: 125.53699, location: 'Dili' }, + { cell: 'MUPE2E', sector: 'MUPE#2', site: 'LISBUTAK MUNDO PERDIDO ', lat: -8.579338, lng: 125.53699, location: 'Dili' }, + { cell: 'MUPE2F', sector: 'MUPE#2F', site: 'LISBUTAK MUNDO PERDIDO ', lat: -8.579338, lng: 125.53699, location: 'Dili' }, + { cell: 'MUPE3E', sector: 'MUPE#3', site: 'LISBUTAK MUNDO PERDIDO ', lat: -8.579338, lng: 125.53699, location: 'Dili' }, + { cell: 'MUPE3F', sector: 'MUPE#3F', site: 'LISBUTAK MUNDO PERDIDO ', lat: -8.579338, lng: 125.53699, location: 'Dili' }, + { cell: 'MUPE4E', sector: 'MUPE#4', site: 'LISBUTAK MUNDO PERDIDO ', lat: -8.579338, lng: 125.53699, location: 'Dili' }, + { cell: 'MUPE4F', sector: 'MUPE#4F', site: 'LISBUTAK MUNDO PERDIDO ', lat: -8.579338, lng: 125.53699, location: 'Dili' }, + { cell: 'MUPE5E', sector: 'MUPE#5', site: 'LISBUTAK MUNDO PERDIDO ', lat: -8.579338, lng: 125.53699, location: 'Dili' }, + { cell: 'MUPE5F', sector: 'MUPE#5F', site: 'LISBUTAK MUNDO PERDIDO ', lat: -8.579338, lng: 125.53699, location: 'Dili' }, + { cell: 'MUPE6E', sector: 'MUPE#6', site: 'LISBUTAK MUNDO PERDIDO ', lat: -8.579338, lng: 125.53699, location: 'Dili' }, + { cell: 'MUPE6F', sector: 'MUPE#6F', site: 'LISBUTAK MUNDO PERDIDO ', lat: -8.579338, lng: 125.53699, location: 'Dili' }, + { cell: 'NOPE1E', sector: 'NOPE#1', site: 'NOPENG', lat: -8.561, lng: 125.5698, location: 'Dili' }, + { cell: 'NOPE1F', sector: 'NOPE#1F', site: 'NOPENG', lat: -8.561, lng: 125.5698, location: 'Dili' }, + { cell: 'NOPE2E', sector: 'NOPE#2', site: 'NOPENG', lat: -8.561, lng: 125.5698, location: 'Dili' }, + { cell: 'NOPE2F', sector: 'NOPE#2F', site: 'NOPENG', lat: -8.561, lng: 125.5698, location: 'Dili' }, + { cell: 'NOPE3E', sector: 'NOPE#3', site: 'NOPENG', lat: -8.561, lng: 125.5698, location: 'Dili' }, + { cell: 'NOPE3F', sector: 'NOPE#3F', site: 'NOPENG', lat: -8.561, lng: 125.5698, location: 'Dili' }, + { cell: 'NOPE4E', sector: 'NOPE#4E', site: 'NOPENG', lat: -8.561, lng: 125.5698, location: 'Dili' }, + { cell: 'NOPE4F', sector: 'NOPE#4F', site: 'NOPENG', lat: -8.561, lng: 125.5698, location: 'Dili' }, + { cell: 'NOPE5E', sector: 'NOPE#5E', site: 'NOPENG', lat: -8.561, lng: 125.5698, location: 'Dili' }, + { cell: 'NOPE5F', sector: 'NOPE#5F', site: 'NOPENG', lat: -8.561, lng: 125.5698, location: 'Dili' }, + { cell: 'NOPE6E', sector: 'NOPE#6E', site: 'NOPENG', lat: -8.561, lng: 125.5698, location: 'Dili' }, + { cell: 'NOPE6F', sector: 'NOPE#6F', site: 'NOPENG', lat: -8.561, lng: 125.5698, location: 'Dili' }, + { cell: 'PALA1E', sector: 'PALA#1', site: 'PALAPACO', lat: -8.552033, lng: 125.566838, location: 'Dili' }, + { cell: 'PALA2E', sector: 'PALA#2', site: 'PALAPACO', lat: -8.552033, lng: 125.566838, location: 'Dili' }, + { cell: 'PALA3E', sector: 'PALA#3', site: 'PALAPACO', lat: -8.552033, lng: 125.566838, location: 'Dili' }, + { cell: 'PALA4E', sector: 'PALA#4', site: 'PALAPAÇO', lat: -8.552033, lng: 125.566838, location: 'Dili' }, + { cell: 'PALA5E', sector: 'PALA#5', site: 'PALAPAÇO', lat: -8.552033, lng: 125.566838, location: 'Dili' }, + { cell: 'PALA6E', sector: 'PALA#6', site: 'PALAPAÇO', lat: -8.552033, lng: 125.566838, location: 'Dili' }, + { cell: 'PALA1F', sector: 'PALA#7', site: 'PALAPASO (iMacro)', lat: -8.548391, lng: 125.565259, location: 'Dili' }, + { cell: 'PALA4F', sector: 'PALA#11', site: 'PALAPASO (iMacro)', lat: -8.548391, lng: 125.565259, location: 'Dili' }, + { cell: 'PALA3F', sector: 'PALA#9', site: 'PALAPASO (iMacro)', lat: -8.548391, lng: 125.565259, location: 'Dili' }, + { cell: 'PALA6F', sector: 'PALA#12', site: 'PALAPASO (iMacro)', lat: -8.548391, lng: 125.565259, location: 'Dili' }, + { cell: 'PANA1E', sector: 'PANA#1', site: 'PARLAMENTO NACIONAL', lat: -8.554402, lng: 125.57883, location: 'Dili' }, + { cell: 'PANA1F', sector: 'PANA#1F', site: 'PARLAMENTO NACIONAL', lat: -8.554402, lng: 125.57883, location: 'Dili' }, + { cell: 'PANA2E', sector: 'PANA#2', site: 'PARLAMENTO NACIONAL', lat: -8.554402, lng: 125.57883, location: 'Dili' }, + { cell: 'PANA2F', sector: 'PANA#2F', site: 'PARLAMENTO NACIONAL', lat: -8.554402, lng: 125.57883, location: 'Dili' }, + { cell: 'PANA3E', sector: 'PANA#3', site: 'PARLAMENTO NACIONAL', lat: -8.554402, lng: 125.57883, location: 'Dili' }, + { cell: 'PANA3F', sector: 'PANA#3F', site: 'PARLAMENTO NACIONAL', lat: -8.554402, lng: 125.57883, location: 'Dili' }, + { cell: 'PANA4E', sector: 'PANA4E', site: 'PARLAMENTO NACIONAL', lat: -8.554402, lng: 125.57883, location: 'Dili' }, + { cell: 'PANA4F', sector: 'PANA4F', site: 'PARLAMENTO NACIONAL', lat: -8.554402, lng: 125.57883, location: 'Dili' }, + { cell: 'PANA5E', sector: 'PANA5E', site: 'PARLAMENTO NACIONAL', lat: -8.554402, lng: 125.57883, location: 'Dili' }, + { cell: 'PANA5F', sector: 'PANA5F', site: 'PARLAMENTO NACIONAL', lat: -8.554402, lng: 125.57883, location: 'Dili' }, + { cell: 'PANA6E', sector: 'PANA6E', site: 'PARLAMENTO NACIONAL', lat: -8.554402, lng: 125.57883, location: 'Dili' }, + { cell: 'PANA6F', sector: 'PANA6F', site: 'PARLAMENTO NACIONAL', lat: -8.554402, lng: 125.57883, location: 'Dili' }, + { cell: 'PITE1E', sector: 'PITE#1', site: 'BAIRRO PITE', lat: -8.56241, lng: 125.562484, location: 'Dili' }, + { cell: 'PITE1F', sector: 'PITE#1F', site: 'BAIRRO PITE', lat: -8.56241, lng: 125.562484, location: 'Dili' }, + { cell: 'PITE2E', sector: 'PITE#2', site: 'BAIRRO PITE', lat: -8.56241, lng: 125.562484, location: 'Dili' }, + { cell: 'PITE2F', sector: 'PITE#2F', site: 'BAIRRO PITE', lat: -8.56241, lng: 125.562484, location: 'Dili' }, + { cell: 'PITE3E', sector: 'PITE#3', site: 'BAIRRO PITE', lat: -8.56241, lng: 125.562484, location: 'Dili' }, + { cell: 'PITE3F', sector: 'PITE#3F', site: 'BAIRRO PITE', lat: -8.56241, lng: 125.562484, location: 'Dili' }, + { cell: 'PITE4E', sector: 'PITE4E', site: 'BAIRRO PITE', lat: -8.56241, lng: 125.562484, location: 'Dili' }, + { cell: 'PITE4F', sector: 'PITE4F', site: 'BAIRRO PITE', lat: -8.56241, lng: 125.562484, location: 'Dili' }, + { cell: 'PITE5E', sector: 'PITE5E', site: 'BAIRRO PITE', lat: -8.56241, lng: 125.562484, location: 'Dili' }, + { cell: 'PITE5F', sector: 'PITE5F', site: 'BAIRRO PITE', lat: -8.56241, lng: 125.562484, location: 'Dili' }, + { cell: 'PITE6E', sector: 'PITE6E', site: 'BAIRRO PITE', lat: -8.56241, lng: 125.562484, location: 'Dili' }, + { cell: 'PITE6F', sector: 'PITE6F', site: 'BAIRRO PITE', lat: -8.56241, lng: 125.562484, location: 'Dili' }, + { cell: 'RAKA1E', sector: 'RAKA#1', site: 'BERAKA', lat: -8.534815, lng: 125.706246, location: 'Dili Distrito' }, + { cell: 'RAKA2E', sector: 'RAKA#2', site: 'BERAKA', lat: -8.534815, lng: 125.706246, location: 'Dili Distrito' }, + { cell: 'RAKA3E', sector: 'RAKA#3', site: 'BERAKA', lat: -8.534815, lng: 125.706246, location: 'Dili Distrito' }, + { cell: 'RAIN1E', sector: 'RAIN#1', site: 'RAINAIN', lat: -8.562049, lng: 125.556946, location: 'Dili' }, + { cell: 'RAIN1F', sector: 'RAIN#1F', site: 'RAINAIN', lat: -8.562049, lng: 125.556946, location: 'Dili' }, + { cell: 'RAIN2E', sector: 'RAIN#2', site: 'RAINAIN', lat: -8.562049, lng: 125.556946, location: 'Dili' }, + { cell: 'RAIN2F', sector: 'RAIN#2F', site: 'RAINAIN', lat: -8.562049, lng: 125.556946, location: 'Dili' }, + { cell: 'RAIN3E', sector: 'RAIN#3', site: 'RAINAIN', lat: -8.562049, lng: 125.556946, location: 'Dili' }, + { cell: 'RAIN3F', sector: 'RAIN#3F', site: 'RAINAIN', lat: -8.562049, lng: 125.556946, location: 'Dili' }, + { cell: 'RAIN4E', sector: 'RAIN#4', site: 'RAI NAIN', lat: -8.562049, lng: 125.556946, location: 'Dili' }, + { cell: 'RAIN4F', sector: 'RAIN#4F', site: 'RAI NAIN', lat: -8.562049, lng: 125.556946, location: 'Dili' }, + { cell: 'RAIN5E', sector: 'RAIN#5', site: 'RAI NAIN', lat: -8.562049, lng: 125.556946, location: 'Dili' }, + { cell: 'RAIN5F', sector: 'RAIN#5F', site: 'RAI NAIN', lat: -8.562049, lng: 125.556946, location: 'Dili' }, + { cell: 'RAIN6E', sector: 'RAIN#6', site: 'RAI NAIN', lat: -8.562049, lng: 125.556946, location: 'Dili' }, + { cell: 'RAIN6F', sector: 'RAIN#6F', site: 'RAI NAIN', lat: -8.562049, lng: 125.556946, location: 'Dili' }, + { cell: 'REMA1E', sector: 'REMA#1', site: 'REMACK', lat: -8.561853, lng: 125.605291, location: 'Dili' }, + { cell: 'REMA1F', sector: 'REMA#1F', site: 'REMACK', lat: -8.561853, lng: 125.605291, location: 'Dili' }, + { cell: 'REMA2E', sector: 'REMA#2', site: 'REMACK', lat: -8.561853, lng: 125.605291, location: 'Dili' }, + { cell: 'REMA2F', sector: 'REMA#2F', site: 'REMACK', lat: -8.561853, lng: 125.605291, location: 'Dili' }, + { cell: 'REMA3E', sector: 'REMA#3', site: 'REMACK', lat: -8.561853, lng: 125.605291, location: 'Dili' }, + { cell: 'REMA3F', sector: 'REMA#3F', site: 'REMACK', lat: -8.561853, lng: 125.605291, location: 'Dili' }, + { cell: 'REMA4E', sector: 'REMA#4', site: 'REMACK', lat: -8.561853, lng: 125.605291, location: 'Dili' }, + { cell: 'REMA4F', sector: 'REMA#4F', site: 'REMACK', lat: -8.561853, lng: 125.605291, location: 'Dili' }, + { cell: 'REMA5E', sector: 'REMA#5', site: 'REMACK', lat: -8.561853, lng: 125.605291, location: 'Dili' }, + { cell: 'REMA5F', sector: 'REMA#5F', site: 'REMACK', lat: -8.561853, lng: 125.605291, location: 'Dili' }, + { cell: 'REMA6E', sector: 'REMA#6', site: 'REMACK', lat: -8.561853, lng: 125.605291, location: 'Dili' }, + { cell: 'REMA6F', sector: 'REMA#6F', site: 'REMACK', lat: -8.561853, lng: 125.605291, location: 'Dili' }, + { cell: 'RUAK1E', sector: 'RUAK#1', site: 'MATAN RUAK', lat: -8.5476, lng: 125.5534, location: 'Dili' }, + { cell: 'RUAK1F', sector: 'RUAK#1F', site: 'MATAN RUAK', lat: -8.5476, lng: 125.5534, location: 'Dili' }, + { cell: 'RUAK2E', sector: 'RUAK#2', site: 'MATAN RUAK', lat: -8.5476, lng: 125.5534, location: 'Dili' }, + { cell: 'RUAK2F', sector: 'RUAK#2F', site: 'MATAN RUAK', lat: -8.5476, lng: 125.5534, location: 'Dili' }, + { cell: 'RUAK3E', sector: 'RUAK#3', site: 'MATAN RUAK', lat: -8.5476, lng: 125.5534, location: 'Dili' }, + { cell: 'RUAK3F', sector: 'RUAK#3F', site: 'MATAN RUAK', lat: -8.5476, lng: 125.5534, location: 'Dili' }, + { cell: 'RUAK4E', sector: 'RUAK#4', site: 'MATAN RUAK', lat: -8.5476, lng: 125.5534, location: 'Dili' }, + { cell: 'RUAK4F', sector: 'RUAK#4F', site: 'MATAN RUAK', lat: -8.5476, lng: 125.5534, location: 'Dili' }, + { cell: 'RUAK5E', sector: 'RUAK#5', site: 'MATAN RUAK', lat: -8.5476, lng: 125.5534, location: 'Dili' }, + { cell: 'RUAK5F', sector: 'RUAK#5F', site: 'MATAN RUAK', lat: -8.5476, lng: 125.5534, location: 'Dili' }, + { cell: 'RUAK6E', sector: 'RUAK#6', site: 'MATAN RUAK', lat: -8.5476, lng: 125.5534, location: 'Dili' }, + { cell: 'RUAK6F', sector: 'RUAK#6F', site: 'MATAN RUAK', lat: -8.5476, lng: 125.5534, location: 'Dili' }, + { cell: 'SUKA4E', sector: 'SUKA#4', site: 'Sukaer Laran', lat: -8.53891, lng: 125.68461, location: 'Dili (District)' }, + { cell: 'SUKA5E', sector: 'SUKA#5', site: 'Sukaer Laran', lat: -8.53891, lng: 125.68461, location: 'Dili (District)' }, + { cell: 'SUKA6E', sector: 'SUKA#6', site: 'Sukaer Laran', lat: -8.53891, lng: 125.68461, location: 'Dili (District)' }, + { cell: 'SUKA2E (Spllitagem to Beraka#3)', sector: 'SUKA#3', site: 'Sukaer Laran', lat: -8.534815, lng: 125.706246, location: 'Dili (District)' }, + { cell: 'SURI1E', sector: 'SURI#1', site: 'SURIKMAS', lat: -8.562456, lng: 125.55039, location: 'Dili' }, + { cell: 'SURI1F', sector: 'SURI#1F', site: 'SURIKMAS', lat: -8.562456, lng: 125.55039, location: 'Dili' }, + { cell: 'SURI2E', sector: 'SURI#2', site: 'SURIKMAS', lat: -8.562456, lng: 125.55039, location: 'Dili' }, + { cell: 'SURI2F', sector: 'SURI#2F', site: 'SURIKMAS', lat: -8.562456, lng: 125.55039, location: 'Dili' }, + { cell: 'SURI3E', sector: 'SURI#3', site: 'SURIKMAS', lat: -8.562456, lng: 125.55039, location: 'Dili' }, + { cell: 'SURI3F', sector: 'SURI#3F', site: 'SURIKMAS', lat: -8.562456, lng: 125.55039, location: 'Dili' }, + { cell: 'SURI4E', sector: 'SURI4', site: 'SURIKMAS', lat: -8.562456, lng: 125.55039, location: 'Dili' }, + { cell: 'SURI4F', sector: 'SURI#4F', site: 'SURIKMAS', lat: -8.562456, lng: 125.55039, location: 'Dili' }, + { cell: 'SURI5E', sector: 'SURI5', site: 'SURIKMAS', lat: -8.562456, lng: 125.55039, location: 'Dili' }, + { cell: 'SURI5F', sector: 'SURI#5F', site: 'SURIKMAS', lat: -8.562456, lng: 125.55039, location: 'Dili' }, + { cell: 'SURI6E', sector: 'SURI6', site: 'SURIKMAS', lat: -8.562456, lng: 125.55039, location: 'Dili' }, + { cell: 'SURI6F', sector: 'SURI#6F', site: 'SURIKMAS', lat: -8.562456, lng: 125.55039, location: 'Dili' }, + { cell: 'TAIN1E', sector: 'TAIN#1', site: 'TASITOLU INUR', lat: -8.563604, lng: 125.502143, location: 'Dili' }, + { cell: 'TAIN1F', sector: 'TAIN#1f', site: 'TASITOLU INUR', lat: -8.563604, lng: 125.502143, location: 'Dili' }, + { cell: 'TAIN2E', sector: 'TAIN#2', site: 'TASITOLU INUR', lat: -8.563604, lng: 125.502143, location: 'Dili' }, + { cell: 'TAIN2F', sector: 'TAIN#2F', site: 'TASITOLU INUR', lat: -8.563604, lng: 125.502143, location: 'Dili' }, + { cell: 'TAIN3E', sector: 'TAIN#3', site: 'TASITOLU INUR', lat: -8.563604, lng: 125.502143, location: 'Dili' }, + { cell: 'TAIN3F', sector: 'TAIN#F', site: 'TASITOLU INUR', lat: -8.563604, lng: 125.502143, location: 'Dili' }, + { cell: 'TAIN4E', sector: 'TAIN#4', site: 'TASITOLU INUR', lat: -8.563604, lng: 125.502143, location: 'Dili' }, + { cell: 'TAIN4F', sector: 'TAIN#4F', site: 'TASITOLU INUR', lat: -8.563604, lng: 125.502143, location: 'Dili' }, + { cell: 'TAIN5E', sector: 'TAIN#5', site: 'TASITOLU INUR', lat: -8.563604, lng: 125.502143, location: 'Dili' }, + { cell: 'TAIN5E', sector: 'TAIN#5F', site: 'TASITOLU INUR', lat: -8.563604, lng: 125.502143, location: 'Dili' }, + { cell: 'TAIN6E', sector: 'TAIN#6', site: 'TASITOLU INUR', lat: -8.563604, lng: 125.502143, location: 'Dili' }, + { cell: 'TAIN6F', sector: 'TAIN#6F', site: 'TASITOLU INUR', lat: -8.563604, lng: 125.502143, location: 'Dili' }, + { cell: 'TAPT1E', sector: 'TAPT1E', site: 'TASITOLU TEMPORARIO PELICAN', lat: -8.557709, lng: 125.492723, location: 'Dili' }, + { cell: 'TAPT2E', sector: 'TAPT2E', site: 'TASITOLU TEMPORARIO PELICAN', lat: -8.557709, lng: 125.492723, location: 'Dili' }, + { cell: 'TAPT3E', sector: 'TAPT3E', site: 'TASITOLU TEMPORARIO PELICAN', lat: -8.557709, lng: 125.492723, location: 'Dili' }, + { cell: 'TATE1E', sector: 'TATE#1', site: 'TASITOLUTEMPORARIO', lat: -8.559535, lng: 125.505449, location: 'Dili' }, + { cell: 'TATE2E', sector: 'TATE#2', site: 'TASITOLUTEMPORARIO', lat: -8.559535, lng: 125.505449, location: 'Dili' }, + { cell: 'TATE4E', sector: 'TATE#4', site: 'TASITOLUTEMPORARIO', lat: -8.559535, lng: 125.505449, location: 'Dili' }, + { cell: 'TATE5E', sector: 'TATE#5', site: 'TASITOLUTEMPORARIO', lat: -8.559535, lng: 125.505449, location: 'Dili' }, + { cell: 'TASI1E', sector: 'TASI#1', site: 'TASITOLU', lat: -8.558093, lng: 125.50949, location: 'Dili' }, + { cell: 'TASI1F', sector: 'TASI#1F', site: 'TASITOLU', lat: -8.558093, lng: 125.50949, location: 'Dili' }, + { cell: 'TASI2E', sector: 'TASI#2', site: 'TASITOLU', lat: -8.558093, lng: 125.50949, location: 'Dili' }, + { cell: 'TASI2F', sector: 'TASI#2F', site: 'TASITOLU', lat: -8.558093, lng: 125.50949, location: 'Dili' }, + { cell: 'TASI3E', sector: 'TASI#3', site: 'TASITOLU', lat: -8.558093, lng: 125.50949, location: 'Dili' }, + { cell: 'TASI3F', sector: 'TASI#3F', site: 'TASITOLU', lat: -8.558093, lng: 125.50949, location: 'Dili' }, + { cell: 'TASI4E', sector: 'TASI#4', site: 'TASITOLU', lat: -8.558093, lng: 125.50949, location: 'Dili' }, + { cell: 'TASI4F', sector: 'TASI#4F', site: 'TASITOLU', lat: -8.558093, lng: 125.50949, location: 'Dili' }, + { cell: 'TASI5E', sector: 'TASI#5', site: 'TASITOLU', lat: -8.558093, lng: 125.50949, location: 'Dili' }, + { cell: 'TASI5F', sector: 'TASI#5F', site: 'TASITOLU', lat: -8.558093, lng: 125.50949, location: 'Dili' }, + { cell: 'TASI6E', sector: 'TASI#6', site: 'TASITOLU', lat: -8.558093, lng: 125.50949, location: 'Dili' }, + { cell: 'TASI6F', sector: 'TASI#6F', site: 'TASITOLU', lat: -8.558093, lng: 125.50949, location: 'Dili' }, + { cell: 'TATE1E', sector: 'TATE#7', site: 'TASITOLU (iMacro)', lat: -8.559479, lng: 125.505493, location: 'Dili' }, + { cell: 'TATE1F', sector: 'TATE#17', site: 'TASITOLU (iMacro)', lat: -8.559479, lng: 125.505493, location: 'Dili' }, + { cell: 'TATE2E', sector: 'TATE#8', site: 'TASITOLU (iMacro)', lat: -8.559479, lng: 125.505493, location: 'Dili' }, + { cell: 'TATE2F', sector: 'TATE#18', site: 'TASITOLU (iMacro)', lat: -8.559479, lng: 125.505493, location: 'Dili' }, + { cell: 'TATD1E', sector: 'TATD1E', site: 'TASITOLU TEMPORARIO2', lat: -8.560451, lng: 125.503787, location: 'Dili' }, + { cell: 'TATD1F', sector: 'TATD1F', site: 'TASITOLU TEMPORARIO2', lat: -8.560451, lng: 125.503787, location: 'Dili' }, + { cell: 'TATD2E', sector: 'TATD2E', site: 'TASITOLU TEMPORARIO2', lat: -8.560451, lng: 125.503787, location: 'Dili' }, + { cell: 'TATD2F', sector: 'TATD2F', site: 'TASITOLU TEMPORARIO2', lat: -8.560451, lng: 125.503787, location: 'Dili' }, + { cell: 'TATD3E', sector: 'TATD3E', site: 'TASITOLU TEMPORARIO2', lat: -8.560451, lng: 125.503787, location: 'Dili' }, + { cell: 'TATD3F', sector: 'TATD3F', site: 'TASITOLU TEMPORARIO2', lat: -8.560451, lng: 125.503787, location: 'Dili' }, + { cell: 'TATD4E', sector: 'TATD4E', site: 'TASITOLU TEMPORARIO2', lat: -8.560451, lng: 125.503787, location: 'Dili' }, + { cell: 'TATD4F', sector: 'TATD4F', site: 'TASITOLU TEMPORARIO2', lat: -8.560451, lng: 125.503787, location: 'Dili' }, + { cell: 'TATD5E', sector: 'TATD5E', site: 'TASITOLU TEMPORARIO2', lat: -8.560451, lng: 125.503787, location: 'Dili' }, + { cell: 'TATD5F', sector: 'TATD5F', site: 'TASITOLU TEMPORARIO2', lat: -8.560451, lng: 125.503787, location: 'Dili' }, + { cell: 'TATD6E', sector: 'TATD6E', site: 'TASITOLU TEMPORARIO2', lat: -8.560451, lng: 125.503787, location: 'Dili' }, + { cell: 'TATD6F', sector: 'TATD6F', site: 'TASITOLU TEMPORARIO2', lat: -8.560451, lng: 125.503787, location: 'Dili' }, + { cell: 'TATT1E', sector: 'TATT1E', site: 'TASITOLU TEMPORARIO3', lat: -8.556031, lng: 125.511544, location: 'Dili' }, + { cell: 'TATT1F', sector: 'TATT1F', site: 'TASITOLU TEMPORARIO3', lat: -8.556031, lng: 125.511544, location: 'Dili' }, + { cell: 'TATT2E', sector: 'TATT2E', site: 'TASITOLU TEMPORARIO3', lat: -8.556031, lng: 125.511544, location: 'Dili' }, + { cell: 'TATT2F', sector: 'TATT2F', site: 'TASITOLU TEMPORARIO3', lat: -8.556031, lng: 125.511544, location: 'Dili' }, + { cell: 'TATT3E', sector: 'TATT3E', site: 'TASITOLU TEMPORARIO3', lat: -8.558093, lng: 125.50949, location: 'Dili' }, + { cell: 'TATT3F', sector: 'TATT3F', site: 'TASITOLU TEMPORARIO3', lat: -8.558093, lng: 125.50949, location: 'Dili' }, + { cell: 'TATT4E', sector: 'TATT4E', site: 'TASITOLU TEMPORARIO3', lat: -8.556031, lng: 125.511544, location: 'Dili' }, + { cell: 'TATT4F', sector: 'TATT4F', site: 'TASITOLU TEMPORARIO3', lat: -8.556031, lng: 125.511544, location: 'Dili' }, + { cell: 'TATT5E', sector: 'TATT5E', site: 'TASITOLU TEMPORARIO3', lat: -8.556031, lng: 125.511544, location: 'Dili' }, + { cell: 'TATT5F', sector: 'TATT5F', site: 'TASITOLU TEMPORARIO3', lat: -8.556031, lng: 125.511544, location: 'Dili' }, + { cell: 'TATT6E', sector: 'TATT6E', site: 'TASITOLU TEMPORARIO3', lat: -8.558093, lng: 125.50949, location: 'Dili' }, + { cell: 'TATT6F', sector: 'TATT6F', site: 'TASITOLU TEMPORARIO3', lat: -8.558093, lng: 125.50949, location: 'Dili' }, + { cell: 'TATU1E', sector: 'TATU1E', site: 'TASITOLU TEMPORARIO1', lat: -8.559476, lng: 125.505488, location: 'Dili' }, + { cell: 'TATU1F', sector: 'TATU1F', site: 'TASITOLU TEMPORARIO1', lat: -8.559476, lng: 125.505488, location: 'Dili' }, + { cell: 'TATU2E', sector: 'TATU2E', site: 'TASITOLU TEMPORARIO1', lat: -8.559476, lng: 125.505488, location: 'Dili' }, + { cell: 'TATU2F', sector: 'TATU2F', site: 'TASITOLU TEMPORARIO1', lat: -8.559476, lng: 125.505488, location: 'Dili' }, + { cell: 'TATU3E', sector: 'TATU3E', site: 'TASITOLU TEMPORARIO1', lat: -8.559476, lng: 125.505488, location: 'Dili' }, + { cell: 'TATU3F', sector: 'TATU3F', site: 'TASITOLU TEMPORARIO1', lat: -8.559476, lng: 125.505488, location: 'Dili' }, + { cell: 'TATU4E', sector: 'TATU4E', site: 'TASITOLU TEMPORARIO1', lat: -8.559476, lng: 125.505488, location: 'Dili' }, + { cell: 'TATU4F', sector: 'TATU4F', site: 'TASITOLU TEMPORARIO1', lat: -8.559476, lng: 125.505488, location: 'Dili' }, + { cell: 'TATU5E', sector: 'TATU5E', site: 'TASITOLU TEMPORARIO1', lat: -8.559476, lng: 125.505488, location: 'Dili' }, + { cell: 'TATU5F', sector: 'TATU5F', site: 'TASITOLU TEMPORARIO1', lat: -8.559476, lng: 125.505488, location: 'Dili' }, + { cell: 'TATU6E', sector: 'TATU6E', site: 'TASITOLU TEMPORARIO1', lat: -8.559476, lng: 125.505488, location: 'Dili' }, + { cell: 'TATU6F', sector: 'TATU6F', site: 'TASITOLU TEMPORARIO1', lat: -8.559476, lng: 125.505488, location: 'Dili' }, + { cell: 'TAVC1E', sector: 'TAVC#1', site: 'TAIBESSI VILLA CARDIM', lat: -8.56577, lng: 125.590753, location: 'Dili' }, + { cell: 'TAVC1F', sector: 'TAVC#1F', site: 'TAIBESSI VILLA CARDIM', lat: -8.56577, lng: 125.590753, location: 'Dili' }, + { cell: 'TAVC2E', sector: 'TAVC#2', site: 'TAIBESSI VILLA CARDIM', lat: -8.56577, lng: 125.590753, location: 'Dili' }, + { cell: 'TAVC2F', sector: 'TAVC#2F', site: 'TAIBESSI VILLA CARDIM', lat: -8.56577, lng: 125.590753, location: 'Dili' }, + { cell: 'TAVC3E', sector: 'TAVC#3', site: 'TAIBESSI VILLA CARDIM', lat: -8.56577, lng: 125.590753, location: 'Dili' }, + { cell: 'TAVC3F', sector: 'TAVC#3F', site: 'TAIBESSI VILLA CARDIM', lat: -8.56577, lng: 125.590753, location: 'Dili' }, + { cell: 'TAVC4E', sector: 'TAVC#4', site: 'TAIBESSI VILLA CARDIM', lat: -8.56577, lng: 125.590753, location: 'Dili' }, + { cell: 'TAVC4F', sector: 'TAVC#4F', site: 'TAIBESSI VILLA CARDIM', lat: -8.56577, lng: 125.590753, location: 'Dili' }, + { cell: 'TAVC5E', sector: 'TAVC#5', site: 'TAIBESSI VILLA CARDIM', lat: -8.56577, lng: 125.590753, location: 'Dili' }, + { cell: 'TAVC5F', sector: 'TAVC#5F', site: 'TAIBESSI VILLA CARDIM', lat: -8.56577, lng: 125.590753, location: 'Dili' }, + { cell: 'TAVC6E', sector: 'TAVC#6', site: 'TAIBESSI VILLA CARDIM', lat: -8.56577, lng: 125.590753, location: 'Dili' }, + { cell: 'TAVC6F', sector: 'TAVC#6F', site: 'TAIBESSI VILLA CARDIM', lat: -8.56577, lng: 125.590753, location: 'Dili' }, + { cell: 'TBES1E', sector: 'TBES#1', site: 'TAIBESSI', lat: -8.562955, lng: 125.588688, location: 'Dili' }, + { cell: 'TBES1F', sector: 'TBES#1F', site: 'TAIBESSI', lat: -8.562955, lng: 125.588688, location: 'Dili' }, + { cell: 'TBES2E', sector: 'TBES#2', site: 'TAIBESSI', lat: -8.562955, lng: 125.588688, location: 'Dili' }, + { cell: 'TBES2F', sector: 'TBES#2F', site: 'TAIBESSI', lat: -8.562955, lng: 125.588688, location: 'Dili' }, + { cell: 'TBES3E', sector: 'TBES#3', site: 'TAIBESSI', lat: -8.562955, lng: 125.588688, location: 'Dili' }, + { cell: 'TBES3F', sector: 'TBES#3F', site: 'TAIBESSI', lat: -8.562955, lng: 125.588688, location: 'Dili' }, + { cell: 'TBES4E', sector: 'TBES#4E', site: 'TAIBESSI', lat: -8.562955, lng: 125.588688, location: 'Dili' }, + { cell: 'TBES4F', sector: 'TBES#4F', site: 'TAIBESSI', lat: -8.562955, lng: 125.588688, location: 'Dili' }, + { cell: 'TBES5E', sector: 'TBES#5E', site: 'TAIBESSI', lat: -8.562955, lng: 125.588688, location: 'Dili' }, + { cell: 'TBES5F', sector: 'TBES#5F', site: 'TAIBESSI', lat: -8.562955, lng: 125.588688, location: 'Dili' }, + { cell: 'TBES6E', sector: 'TBES#6E', site: 'TAIBESSI', lat: -8.562955, lng: 125.588688, location: 'Dili' }, + { cell: 'TBES6F', sector: 'TBES#6F', site: 'TAIBESSI', lat: -8.562955, lng: 125.588688, location: 'Dili' }, + { cell: 'TERA1E', sector: 'TERA#1', site: 'TERRAMOTO', lat: -8.546358, lng: 125.541319, location: 'Dili' }, + { cell: 'TERA1F', sector: 'TERA#1F', site: 'TERRAMOTO', lat: -8.546358, lng: 125.541319, location: 'Dili' }, + { cell: 'TERA2E', sector: 'TERA#2', site: 'TERRAMOTO', lat: -8.546358, lng: 125.541319, location: 'Dili' }, + { cell: 'TERA2F', sector: 'TERA#2F', site: 'TERRAMOTO', lat: -8.546358, lng: 125.541319, location: 'Dili' }, + { cell: 'TERA3E', sector: 'TERA#3', site: 'TERRAMOTO', lat: -8.546358, lng: 125.541319, location: 'Dili' }, + { cell: 'TERA3F', sector: 'TERA#3F', site: 'TERRAMOTO', lat: -8.546358, lng: 125.541319, location: 'Dili' }, + { cell: 'TERA4E', sector: 'TERA#4', site: 'TERRAMOTO', lat: -8.546358, lng: 125.541319, location: 'Dili' }, + { cell: 'TERA4F', sector: 'TERA#4F', site: 'TERRAMOTO', lat: -8.546358, lng: 125.541319, location: 'Dili' }, + { cell: 'TERA5E', sector: 'TERA#5', site: 'TERRAMOTO', lat: -8.546358, lng: 125.541319, location: 'Dili' }, + { cell: 'TERA5F', sector: 'TERA#5F', site: 'TERRAMOTO', lat: -8.546358, lng: 125.541319, location: 'Dili' }, + { cell: 'TERA6E', sector: 'TERA#6', site: 'TERRAMOTO', lat: -8.546358, lng: 125.541319, location: 'Dili' }, + { cell: 'TERA6F', sector: 'TERA#6F', site: 'TERRAMOTO', lat: -8.546358, lng: 125.541319, location: 'Dili' }, + { cell: 'THAL1E', sector: 'THAL#1', site: 'TAIBESSI HAS LARAN', lat: -8.5638, lng: 125.5912, location: 'Dili' }, + { cell: 'THAL2E', sector: 'THAL#2', site: 'TAIBESSI HAS LARAN', lat: -8.5638, lng: 125.5912, location: 'Dili' }, + { cell: 'THAL3E', sector: 'THAL#3', site: 'TAIBESSI HAS LARAN', lat: -8.5638, lng: 125.5912, location: 'Dili' }, + { cell: 'THAL4E', sector: 'THAL#4', site: 'TAIBESSI HAS LARAN', lat: -8.5638, lng: 125.5912, location: 'Dili' }, + { cell: 'THAL5E', sector: 'THAL#5', site: 'TAIBESSI HAS LARAN', lat: -8.5638, lng: 125.5912, location: 'Dili' }, + { cell: 'THAL6E', sector: 'THAL#6', site: 'TAIBESSI HAS LARAN', lat: -8.5638, lng: 125.5912, location: 'Dili' }, + { cell: 'TITE1E', sector: 'TITE1E', site: 'TIBAR TEMPORARIO', lat: -8.567375, lng: 125.490274, location: 'Dili' }, + { cell: 'TITE1F', sector: 'TITE1F', site: 'TIBAR TEMPORARIO', lat: -8.567375, lng: 125.490274, location: 'Dili' }, + { cell: 'TITE2E', sector: 'TITE2E', site: 'TIBAR TEMPORARIO', lat: -8.567375, lng: 125.490274, location: 'Dili' }, + { cell: 'TITE2F', sector: 'TITE2F', site: 'TIBAR TEMPORARIO', lat: -8.567375, lng: 125.490274, location: 'Dili' }, + { cell: 'TITE3E', sector: 'TITE3E', site: 'TIBAR TEMPORARIO', lat: -8.567375, lng: 125.490274, location: 'Dili' }, + { cell: 'TITE3F', sector: 'TITE3F', site: 'TIBAR TEMPORARIO', lat: -8.567375, lng: 125.490274, location: 'Dili' }, + { cell: 'TITE4E', sector: 'TITE4E', site: 'TIBAR TEMPORARIO', lat: -8.567375, lng: 125.490274, location: 'Dili' }, + { cell: 'TITE4F', sector: 'TITE4F', site: 'TIBAR TEMPORARIO', lat: -8.567375, lng: 125.490274, location: 'Dili' }, + { cell: 'TITE5E', sector: 'TITE5E', site: 'TIBAR TEMPORARIO', lat: -8.567375, lng: 125.490274, location: 'Dili' }, + { cell: 'TITE5F', sector: 'TITE5F', site: 'TIBAR TEMPORARIO', lat: -8.567375, lng: 125.490274, location: 'Dili' }, + { cell: 'TITE6E', sector: 'TITE6E', site: 'TIBAR TEMPORARIO', lat: -8.567375, lng: 125.490274, location: 'Dili' }, + { cell: 'TITE6F', sector: 'TITE6F', site: 'TIBAR TEMPORARIO', lat: -8.567375, lng: 125.490274, location: 'Dili' }, + { cell: 'TPIN1E', sector: 'TPIN#1', site: 'TIMOR PLAZA INDOOR', lat: -8.553847, lng: 125.54154, location: 'Dili' }, + { cell: 'TPOD1E', sector: 'TPOD#1', site: 'TIMOR PLAZA OUTDOOR', lat: -8.553878, lng: 125.541972, location: 'Dili' }, + { cell: 'TPOD1F', sector: 'TPOD#1F', site: 'TIMOR PLAZA OUTDOOR', lat: -8.553878, lng: 125.541972, location: 'Dili' }, + { cell: 'TPOD2E', sector: 'TPOD#2', site: 'TIMOR PLAZA OUTDOOR', lat: -8.553878, lng: 125.541972, location: 'Dili' }, + { cell: 'TPOD2F', sector: 'TPOD#2F', site: 'TIMOR PLAZA OUTDOOR', lat: -8.553878, lng: 125.541972, location: 'Dili' }, + { cell: 'TPOD3E', sector: 'TPOD#3', site: 'TIMOR PLAZA OUTDOOR', lat: -8.553677, lng: 125.541174, location: 'Dili' }, + { cell: 'TPOD3F', sector: 'TPOD#3F', site: 'TIMOR PLAZA OUTDOOR', lat: -8.553878, lng: 125.541972, location: 'Dili' }, + { cell: 'TPOD4E', sector: 'TPOD#4', site: 'TIMOR PLAZA OUTDOOR', lat: -8.553878, lng: 125.541972, location: 'Dili' }, + { cell: 'TPOD4F', sector: 'TPOD#4F', site: 'TIMOR PLAZA OUTDOOR', lat: -8.553878, lng: 125.541972, location: 'Dili' }, + { cell: 'TPOD5E', sector: 'TPOD#5', site: 'TIMOR PLAZA OUTDOOR', lat: -8.553878, lng: 125.541972, location: 'Dili' }, + { cell: 'TPOD5F', sector: 'TPOD#5F', site: 'TIMOR PLAZA OUTDOOR', lat: -8.553878, lng: 125.541972, location: 'Dili' }, + { cell: 'TPOD6E', sector: 'TPOD#6', site: 'TIMOR PLAZA OUTDOOR', lat: -8.553878, lng: 125.541972, location: 'Dili' }, + { cell: 'TPOD6F', sector: 'TPOD#6F', site: 'TIMOR PLAZA OUTDOOR', lat: -8.553878, lng: 125.541972, location: 'Dili' }, + { cell: 'TUBA1E', sector: 'TUBA#1', site: 'TUBARAI', lat: -8.56849, lng: 125.59189, location: 'Dili' }, + { cell: 'TUBA1F', sector: 'TUBA1F', site: 'TUBARAI', lat: -8.56849, lng: 125.59189, location: 'Dili' }, + { cell: 'TUBA2E', sector: 'TUBA#2', site: 'TUBARAI', lat: -8.56849, lng: 125.59189, location: 'Dili' }, + { cell: 'TUBA2F', sector: 'TUBA2F', site: 'TUBARAI', lat: -8.56849, lng: 125.59189, location: 'Dili' }, + { cell: 'TUBA3E', sector: 'TUBA#3', site: 'TUBARAI', lat: -8.56849, lng: 125.59189, location: 'Dili' }, + { cell: 'TUBA3F', sector: 'TUBA3F', site: 'TUBARAI', lat: -8.56849, lng: 125.59189, location: 'Dili' }, + { cell: 'TUBA4E', sector: 'TUBA4E', site: 'TUBARAI', lat: -8.56849, lng: 125.59189, location: 'Dili' }, + { cell: 'TUBA4F', sector: 'TUBA4F', site: 'TUBARAI', lat: -8.56849, lng: 125.59189, location: 'Dili' }, + { cell: 'TUBA5E', sector: 'TUBA5E', site: 'TUBARAI', lat: -8.56849, lng: 125.59189, location: 'Dili' }, + { cell: 'TUBA5F', sector: 'TUBA5F', site: 'TUBARAI', lat: -8.56849, lng: 125.59189, location: 'Dili' }, + { cell: 'TUBA6E', sector: 'TUBA6E', site: 'TUBARAI', lat: -8.56849, lng: 125.59189, location: 'Dili' }, + { cell: 'TUBA6F', sector: 'TUBA6F', site: 'TUBARAI', lat: -8.56849, lng: 125.59189, location: 'Dili' }, + { cell: 'TUTI1E', sector: 'TUTI#1', site: 'TUTI', lat: -8.550753, lng: 125.538265, location: 'Dili' }, + { cell: 'TUTI1F', sector: 'TUTI#1F', site: 'TUTI', lat: -8.550753, lng: 125.538265, location: 'Dili' }, + { cell: 'TUTI2E', sector: 'TUTI#2', site: 'TUTI', lat: -8.550753, lng: 125.538265, location: 'Dili' }, + { cell: 'TUTI2F', sector: 'TUTI#2F', site: 'TUTI', lat: -8.550753, lng: 125.538265, location: 'Dili' }, + { cell: 'TUTI3E', sector: 'TUTI#3', site: 'TUTI', lat: -8.550753, lng: 125.538265, location: 'Dili' }, + { cell: 'TUTI3F', sector: 'TUTI#3F', site: 'TUTI', lat: -8.550753, lng: 125.538265, location: 'Dili' }, + { cell: 'TUTI4E', sector: 'TUTI#4', site: 'TUTI', lat: -8.550753, lng: 125.538265, location: 'Dili' }, + { cell: 'TUTI4F', sector: 'TUTI#4F', site: 'TUTI', lat: -8.550753, lng: 125.538265, location: 'Dili' }, + { cell: 'TUTI5E', sector: 'TUTI#5', site: 'TUTI', lat: -8.550753, lng: 125.538265, location: 'Dili' }, + { cell: 'TUTI5F', sector: 'TUTI#5F', site: 'TUTI', lat: -8.550753, lng: 125.538265, location: 'Dili' }, + { cell: 'TUTI6E', sector: 'TUTI#6', site: 'TUTI', lat: -8.550753, lng: 125.538265, location: 'Dili' }, + { cell: 'TUTI6F', sector: 'TUTI#6F', site: 'TUTI', lat: -8.550753, lng: 125.538265, location: 'Dili' }, + { cell: 'VERD1E', sector: 'VERD#1', site: 'VILA VERDE', lat: -8.562632, lng: 125.567864, location: 'Dili' }, + { cell: 'VERD1F', sector: 'VERD#1F', site: 'VILA VERDE', lat: -8.562632, lng: 125.567864, location: 'Dili' }, + { cell: 'VERD2E', sector: 'VERD#2', site: 'VILA VERDE', lat: -8.562632, lng: 125.567864, location: 'Dili' }, + { cell: 'VERD2F', sector: 'VERD#2F', site: 'VILA VERDE', lat: -8.562632, lng: 125.567864, location: 'Dili' }, + { cell: 'VERD3E', sector: 'VERD#3', site: 'VILA VERDE', lat: -8.562632, lng: 125.567864, location: 'Dili' }, + { cell: 'VERD3F', sector: 'VERD#3F', site: 'VILA VERDE', lat: -8.562632, lng: 125.567864, location: 'Dili' }, + { cell: 'VERD4E', sector: 'VERD#4', site: 'VILA VERDE', lat: -8.562632, lng: 125.567864, location: 'Dili' }, + { cell: 'VERD4F', sector: 'VERD#4F', site: 'VILA VERDE', lat: -8.562632, lng: 125.567864, location: 'Dili' }, + { cell: 'VERD5E', sector: 'VERD#5', site: 'VILA VERDE', lat: -8.562632, lng: 125.567864, location: 'Dili' }, + { cell: 'VERD5F', sector: 'VERD#5F', site: 'VILA VERDE', lat: -8.562632, lng: 125.567864, location: 'Dili' }, + { cell: 'VERD6E', sector: 'VERD#6', site: 'VILA VERDE', lat: -8.562632, lng: 125.567864, location: 'Dili' }, + { cell: 'VERD6F', sector: 'VERD#6F', site: 'VILA VERDE', lat: -8.562632, lng: 125.567864, location: 'Dili' }, + { cell: 'BBAR1E', sector: 'BBAR#1', site: 'BALIBAR', lat: -8.598, lng: 125.6035, location: 'Dili (District)' }, + { cell: 'BBAR3E', sector: 'BBAR#3', site: 'BALIBAR', lat: -8.598, lng: 125.6035, location: 'Dili (District)' }, +]; \ No newline at end of file diff --git a/src/swagger/builder.js b/src/swagger/builder.js index b68311a..7a09297 100644 --- a/src/swagger/builder.js +++ b/src/swagger/builder.js @@ -15,696 +15,14 @@ const doc = { ], components: { schemas: { - product: { - $code: "123456", - $name: "Product name", - $description: "Product description", - $source: "trialBalanceBranch / cifAccount / lnkolek", - $status: "Y", - }, - branch: { - $code: "123456", - $name: "Branch name", - $status: "Y", - }, - currency: { - $name: "Dolar", - $symbol: "$", - $status: "Y", - }, - inpatient_room: { - $room_id: "34fdda87-9b42-44d3-8cab-2f2032481d42", - $name: "Name", - $number_of_bed: 1, - }, - surgery_room: { - $room_id: "34fdda87-9b42-44d3-8cab-2f2032481d42", - $name: "Name", - }, - surgery_type: { - $name: "Elective", - }, - menu: { - $module: "Dashboard", - $name: "Dashboard", - $link: "/", - $id_parent: "", - $order_number: 1, - $icon: "", - $application: "ukln", - $status: "Y", - }, - administrativu: { - $code: "123456", - $name: "Administrativu name", - $status: "Y", - $munisipo_id: "uuid-string", - }, - application: { - $id: "ukln", - $name: "Dashboard Performance Business", - $reset_password_url: "https://brilianapps.britimorleste.tl/ukln/auth/reset-password/", - $status: "Y", - }, - aldeia: { - $code: "123456", - $name: "Aldeia name", - $status: "Y", - $suco_id: "uuid-string", - }, - class_economi: { - $code: "123456", - $name: "Class economi name", - $status: "Y", - }, - district: { - $code: "123456", - $name: "District name", - $status: "Y", - }, - income_tier: { - $code: "123456", - $name: "Income tier name", - $status: "Y", - }, - munisipo: { - $code: "123456", - $name: "Munisipo name", - $status: "Y", - }, - suco: { - $code: "123456", - $name: "Suco name", - $status: "Y", - $administrativu_id: "uuid-string", - }, - nationality: { - $code: "123456", - $name: "Nationality name", - $status: "Y", - }, - classEconomi: { - $code: "123456", - $name: "Class Economi name", - $status: "Y", - }, - incomeTier: { - $code: "123456", - $name: "Income Tier name", - $status: "Y", - }, - diagnosis: { - $diagnosis: "Diagnosis name English (ICD-11)", - $diagnosis_ind: "Diagnosis name Indonesian", - $diagnosis_pt: "Diagnosis name Portuguese", - $diagnosis_tet: "Diagnosis name Tetum", - $code: "ABC123", - $status: "Y", - }, - diagnostic_procedure: { - $diagnosticProcedure: "Procedure name (ICD-9)", - $code: "XYZ789", - $status: "Y", - }, - room: { - $room: "Room name", - $code: "R001", - number: "101", - $description: "Optional description", - $department_id: "uuid-string", - $serviceclass: "uuid-string", - $status: "Y", - $location: "Room location", - $picture: "Room picture name", - specialist_form: { "@enum": ["dental", "cardiology", "dermatology", "gynecology", "orthopedics", "neurology", "ear-nose-throat", "pulmonology", "urology"] }, - }, - room_number: { - $number: "101", - }, - laboratory: { - $room: "Room name", - $code: "R001", - $description: "Optional description", - $department_id: "uuid-string", - $status: "Y", - }, - // pharmacy: { - // $room: "Room name", - // $code: "R001", - // $description: "Optional description", - // $department_id: "uuid-string", - // $status: "Y" - // }, - serviceType: { - $name: "Registration & Tickets", - $status: { "@enum": ["Y", "N"] }, - }, - serviceClass: { - $name: "Class name", - }, - service: { - $name: "e.g. ER Registration", - $service_type_id: "uuid-string", - $status: { "@enum": ["Y", "N"] }, - }, - roomServices: { - $service_type_ids: ["uuid-string"], - }, - serviceFare: { - $service_id: "uuid-string", - $faretype: [ - { - $faretype_id: "uuid-string", - $service_class: [ - { - $service_class_id: "uuid-string", - $fare: 100000, - }, - ], - }, - ], - }, - servicePackage: { - $name: "Package name", - $service_class_id: "uuid-string", - $fare: 500000, - $service_ids: ["uuid-string"], - }, - department: { - $name: "igd", - $status: { "@enum": ["Y", "N"] }, - }, - doctorSchedule: { - $day: "Senin", - $start_time: "08:00", - $end_time: "12:00", - $doctor_id: "uuid-string", - $room_id: "uuid-string", - $quota: "20", - $status: { "@enum": ["Y", "N"] }, - }, - doctorItem: { - $doctor_id: "uuid-string", - $item_master_id: "uuid-string", - }, - doctorItemPackage: { - $doctor_id: "uuid-string", - $name: "Paket Obat Harian", - $description: "Optional description", - $item_master_ids: ["uuid-string"], - $active: true, - }, - measurementUnit: { - $unit: "Milligram", - $status: { "@enum": ["Y", "N"] }, - }, - medical_form: { - $title: "Form title", - $name: "Form name", - $description: "Form description", - picture: "Form picture path", - $status: "Y", - }, - referenceRange: { - $gender: { "@enum": ["male", "female"] }, - $age_range_min: "0 | (days)", - $age_range_max: "20 | (days)", - $value_min: "13.7", - $value_max: "17.5", - $status: { "@enum": ["Y", "N"] }, - }, - queueMonitoring: { - $name: "Ground Floor Queue", - $slug: "ground-floor-queue", - $room_ids: ["uuid-string"], - $status: { "@enum": ["Y", "N"] }, - }, - examinationType: { - $name: "Examination Type name", - $status: { "@enum": ["Y", "N"] }, - $service_ids: ["uuid-string"], - }, - examinationDetail: { - $name: "Examination Detail name", - $order_no: "Order number", - $measurement_unit_id: "uuid-string", - $reference_range_ids: "[] array uuid-string", - $status: { "@enum": ["Y", "N"] }, - }, - serviceExamination: { - $examination_detail_ids: ["uuid-string"], - }, - serviceExaminationCreate: { - $examination_detail_ids: ["uuid-string"], - $service_id: "uuid-string", - }, - hospitalinformation: { - $name: "Hospital Name", - $address: "Hospital Address", - $phone: "Hospital Phone", - $logo: "Hospital Logo", - // $province: "province code", - // $city: "city code", - // $subdistrict: "subdistrict code", - // $ward: "ward code", - $munisipo: "Munisipo ID", - $administrativu: "Administrativu ID", - $aldeia: "Aldeia ID", - $suco: "Suco ID", - }, - files: { - $file_name: "File Name", - }, - item_group: { - $group_name: "ItemGroup name", - }, - item_origin: { - $origin_name: "ItemOrigin name", - $origin_description: "ItemOrigin Desc", - $department: "Department name", - $account: "Account name", - }, - item_type: { - $type_name: "ItemType name", - $item_group_id: "ItemGroup Id", - }, - item_type_detail: { - $type_detail_name: "ItemTypeDetail name", - $item_type_id: "ItemType Id", - }, - unit: { - $unit_name: "Unit name", - $small_unit: "Small unit name", - $large_unit: "Large unit name", - }, - item_category: { - $category_name: "ItemCategory name", - }, - item_status: { - $status_name: "Itemstatus name", - }, - item_class: { - $item_class_name: "ItemClass name", - }, - item_class_detail: { - $class_detail_name: "ItemClassDetail name", - }, - usage_instructions: { - $usage_instructions_name: "UsageInstructions name", - $usage_instructions_abbreviation: "UsageInstructions Abbreviation", - }, - usage_time: { - $usage_time_name: "UsageInstructions name", - $usage_time_abbreviation: "UsageInstructions Abbreviation", - }, - generic_name: { - $generic_name: "Generic name", - }, - factory: { - $factory_name: "factory name", - $address: "Factory address", - $web: "Factory url web", - $phone: "Factory phone", - $email: "Factory email", - }, - supplier: { - $supplier_name: "supplier name", - $address: "supplier address", - $phone: "supplier phone", - $email: "supplier email", - }, - factory_to_supplier: { - $supplier_id: "Supplier ID (required, UUID)", - $factory_ids: "Array [factory-uuid-1, factory-uuid-2]", - }, - item_master: { - $item_name: "Item name", - $generic_name_id: "Generic name ID (UUID)", - $item_type_detail_id: "Item type detail ID (UUID)", - $item_category_id: "Item category ID (UUID)", - $item_class_id: "Item class ID (UUID)", - $item_class_detail_id: "Item class Detail ID (UUID)", - $item_status_id: "Item status ID (UUID)", - $factory_id: "Factory ID (UUID)", - // $unit_id: "Unit ID (UUID)", - $smallunit: "string", - $largeunit: "string", - $pack_size: "Pack size (integer, minimum 0)", - $minimum_quantity: "Minimum quantity (integer, minimum 0)", - $minimum_sales_quantity: "Minimum sales quantity (integer, minimum 0)", - $strength: "Strength value (number, minimum 0)", - $active: "Active status (boolean)", - }, - pharmacy_info: { - $logo: "Logo (string, max 256)", - $name: "Name (string, max 256)", - $address: "Address (string, max 500)", - $munisipiu: "Munisipiu ID (UUID)", - $postu_admin: "Postu Admin ID (UUID)", - $suco: "Suco ID (UUID)", - $aldeia: "Aldeia ID (UUID)", - $phone: "Phone (string, max 30, optional)", - $default_room_id: "Default Room ID (UUID)", - // $province: "Province Code", - // $city: "City Code", - // $subdistrict: "Subdistrict Code", - // $ward: "Ward Code", - }, - item_price: { - $item_master_id: "Item Master ID (required, UUID)", - $purchase_price: "Purchase Price (required, number, minimum 0)", - $selling_price: "Selling Price (required, number, minimum 0)", - }, - initial_stock: { - $itemmaster: "Item Master uuid", - $room: "Room uuid", - $itemorigin: "Item Origin uuid", - $batch: "Batch", - $exp_date: "Exp Date", - $stock: "Stock", - }, - selling_price_percentage: { - $item_master_id: "Item Master ID (required, UUID)", - $item_origin_id: "Item Origin ID (required, UUID)", - $percentage: "Percentage (required, number, min 0, max 999.99, 2 decimal places)", - }, - patient_group: { - $patient_group_name: "PatientGroup name", - }, - patient_guarantor: { - $guarantor_name: "PatientGuarantor name", - $phone: "08123456789", // Nomor telepon - // $province: "West Java", // Provinsi - // $city: "Bandung", // Kota - $munisipo: "2e1a1b33-bbb2-4f33-b2c4-cff5976f3f95", // Munisipo (UUID) - $administrativu: "2e1a1b33-bbb2-4f33-b2c4-cff5976f3f95", // Administrativu (UUID) - $aldeia: "2e1a1b33-bbb2-4f33-b2c4-cff5976f3f95", // Aldeia (UUID) - $suco: "2e1a1b33-bbb2-4f33-b2c4-cff5976f3f95", // Suco (UUID) - // $zip_code: "40123", // Kode Pos - $agreement_no: "AG123456789", // Nomor Perjanjian - $agreement_desc: "Health Insurance Agreement", // Deskripsi Perjanjian (opsional) - $patient_group_id: "2e1a1b33-bbb2-4f33-b2c4-cff5976f3f95", // Patient Group (UUID) - $faretype: "3f1a1b33-bbb2-4f33-b2c4-cff5976f3f95", // Fare Type (UUID) - $maximalliability: 1000000, // Maximal Liability (opsional) - is_default: false, // Is Default (opsional) - is_full_paid: false, // Is Full Paid (opsional) - }, - refferal_hospital: { - $refferal_hospital_name: "RefferalHospital name", - }, - user_to_room: { - $user_id: "user ID (required, UUID)", - $room_id: "Room ID (required, UUID)", - }, - user_to_room_update: { - $user_id: "user ID (required, UUID)", - $room_ids: "Array [room-uuid-1, room-uuid-2]", - }, - room_to_pharmacy: { - $room_id: "room ID (required, UUID)", - $pharmacy_room_id: "Pharmacy Room ID (required, UUID)", - }, - planning_verificator: { - $user_id: "User ID (required, UUID)", - }, - scheduleRecurrence: { - $type: { "@enum": ["daily", "weekly", "monthly"] }, - $interval: 1, - $daysOfWeek: ["MO", "WE", "FR"], - }, - scheduleSeriesCreate: { - $roomId: "uuid-string", - $doctorId: "uuid-string", - $title: "Practice Schedule", - $quota: 20, - $startDate: "2026-03-20", - $untilDate: "2026-06-30", - $startTime: "09:00:00", - $endTime: "12:00:00", - $recurrence: { $ref: "#/components/schemas/scheduleRecurrence" }, - }, - scheduleSeriesUpdate: { - $roomId: "uuid-string", - $doctorId: "uuid-string", - $title: "Practice Schedule Updated", - $quota: 25, - $startDate: "2026-03-20", - $untilDate: "2026-07-31", - $startTime: "10:00:00", - $endTime: "13:00:00", - $recurrence: { $ref: "#/components/schemas/scheduleRecurrence" }, - }, - scheduleSeriesDetail: { - $id: "uuid-string", - $room_id: "uuid-string", - $doctor_id: "uuid-string", - $title: "Practice Schedule", - $quota: 20, - $start_date: "2026-03-20", - $until_date: "2026-06-30", - $start_time: "09:00:00", - $end_time: "12:00:00", - $recurrence: { $ref: "#/components/schemas/scheduleRecurrence" }, - $status: "Active", - $room: { id: "uuid-string", room: "Room 1" }, - $doctor: { id: "uuid-string", name: "Dr A" }, - }, - scheduleExceptionCreate: { - $occurrenceDate: "2026-03-24", - $isCancelled: false, - $overrideRoomId: "uuid-string", - $overrideDoctorId: "uuid-string", - $overrideTitle: "Override Practice", - $overrideStartAt: "2026-03-24T10:00:00.000Z", - $overrideEndAt: "2026-03-24T12:30:00.000Z", - }, - scheduleCalendarResource: { - $id: "room-1:doctor-1", - $roomId: "room-1", - $roomName: "Room 1", - $doctorId: "doctor-1", - $doctorName: "Dr A", - }, - scheduleCalendarEvent: { - $id: "occ:series-101:2026-03-20", - $seriesId: "series-101", - $resourceId: "room-1:doctor-1", - $title: "Practice", - $startAt: "2026-03-20T09:00:00+07:00", - $endAt: "2026-03-20T12:00:00+07:00", - $quota: 20, - $usedQuota: 7, - $leftQuota: 13, - $isRecurring: true, - $isException: false, - $status: "confirmed", - }, - scheduleCalendarMeta: { - $total_count: 24, - $page: 1, - $limit: 20, - }, - faretype: { - $name: "Name (string)", - }, - card_type: { - $name: "Name (string)", - }, - card_print_queue: { - mrn: "123456", - municipiu_code: "code", - posto_adm_code: "code", - name: "Patient Name", - address: "Address text", - municipiu: "Municipiu name", - posto_adm: "Posto adm name", - suco: "Suco name", - aldeia: "Aldeia name", - sexo: "M", - birthdate: "2026-06-10", - patient_id: "patient-uuid", - facility_code: "0001", - status: { "@enum": ["pending", "in_progress", "completed", "failed", "blocked"] }, - }, - card_key_set: { - $key_set_id: "Key Set ID (string)", - app_master_key: "App Master Key (string, optional)", - read_basic_key: "Read Basic Key (string, optional)", - write_update_key: "Write Update Key (string, optional)", - read_sensitive_key: "Read Sensitive Key (string, optional)", - }, - payment_method: { - $name: "Name (string)", - }, - registration_fee: { - type: "emergency | outpatient", - service: ["uuid-string-1", "uuid-string-2"], - }, - serviceFareUpdate: { - $fare: 100000, - }, - responsiblepartyconsent: { - $bodytext: "string", - $type: "responsible-party-consent | patient-education | inpatient-admission-consent | provision-of-information | ward-class-upgrade-entitlement", - }, - fostercarehistory: { - type: "object", - properties: { - diagnosis: { - type: "string", - maxLength: 256, - example: "Gangguan Pertukaran Gas" - }, - code: { - type: "string", - maxLength: 128, - example: "D.0003" - }, - status: { - type: "string", - example: "active" - }, - category: { - type: "string", - maxLength: 128, - nullable: true, - example: "Fisiologis" - }, - subcategory: { - type: "string", - maxLength: 128, - nullable: true, - example: "Respirasi" - }, - definition: { - type: "string", - maxLength: 128, - nullable: true, - example: "Kelebihan atau kekurangan oksigenasi" - }, - objective: { - type: "string", - maxLength: 128, - nullable: true, - example: "Meningkatkan pertukaran gas" - }, - result_criteria: { - type: "array", - nullable: true, - items: { - type: "object", - properties: { - group: { type: "number", example: 1 }, - name: { type: "string", example: "Saturasi oksigen membaik" } - } - } - }, - causes: { - type: "array", - nullable: true, - items: { - type: "object", - properties: { - group: { type: "string", example: "Fisiologis" }, - name: { type: "string", example: "Ketidakseimbangan ventilasi-perfusi" } - } - } - }, - related_clinical_condition: { - type: "array", - nullable: true, - items: { - type: "object", - properties: { - name: { type: "string", example: "Penyakit Paru Obstruktif Kronis (PPOK)" } - } - } - }, - subjective_major: { - type: "array", - nullable: true, - items: { - type: "object", - properties: { - group: { type: "string", example: "Mayor" }, - name: { type: "string", example: "Dispnea" } - } - } - }, - objectitve_major: { - type: "array", - nullable: true, - items: { - type: "object", - properties: { - group: { type: "string", example: "Mayor" }, - name: { type: "string", example: "PCO2 meningkat/menurun" } - } - } - }, - subjective_minor: { - type: "array", - nullable: true, - items: { - type: "object", - properties: { - group: { type: "string", example: "Minor" }, - name: { type: "string", example: "Pusing" } - } - } - }, - objective_minor: { - type: "array", - nullable: true, - items: { - type: "object", - properties: { - group: { type: "string", example: "Minor" }, - name: { type: "string", example: "Napas cuping hidung" } - } - } - }, - observation: { - type: "array", - nullable: true, - items: { - type: "object", - properties: { - name: { type: "string", example: "Monitor frekuensi, irama, kedalaman napas" } - } - } - }, - therapeutic: { - type: "array", - nullable: true, - items: { - type: "object", - properties: { - name: { type: "string", example: "Berikan posisi semi-Fowler" } - } - } - }, - education: { - type: "array", - nullable: true, - items: { - type: "object", - properties: { - name: { type: "string", example: "Anjurkan teknik batuk efektif" } - } - } - }, - colaboration: { - type: "array", - nullable: true, - items: { - type: "object", - properties: { - name: { type: "string", example: "Kolaborasi pemberian bronkodilator" } - } - } - }, - } + + site_points: { + $cell: "Cell", + $sector: "Sector", + $site: "Site", + $lat: "Latitude", + $lng: "Longitude", + $location: "Location", }, }, parameters: {},