diff --git a/.vscode/launch.json b/.vscode/launch.json index fddb0d29..6969b05e 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -14,6 +14,20 @@ "mode": "auto", "program": "${workspaceFolder}/cmd/bpjs-api" }, + { + "name": "Launch Package simgos sync API", + "type": "go", + "request": "launch", + "mode": "auto", + "program": "${workspaceFolder}/cmd/simgos-sync-api" + }, + { + "name": "Launch Package main sync API", + "type": "go", + "request": "launch", + "mode": "auto", + "program": "${workspaceFolder}/cmd/main-sync-api" + }, { "name": "Launch Package migratioon", "type": "go", diff --git a/README-APP.md b/README-APP.md index 4da56232..4a63384d 100644 --- a/README-APP.md +++ b/README-APP.md @@ -1,4 +1,16 @@ # APP DESIGN CONVENTION +## Intro +Uses Go Programming Language, with no framework. +- Why no framework? Go's std libs are already powerfull which aligns with the philosophy of "do one thing well" +- It's common in the Go community that "No framework is the best framework" + +Uses community standard layout for the project layout, can be viewed here:
+https://github.com/golang-standards/project-layout + +Uses Clean Architecture (later writen as CA) approach, can be viewed here:
+https://www.freecodecamp.org/news/a-quick-introduction-to-clean-architecture-990c014448d2 + +Uses kebab-case for the directory naming ## Implementing Clean Architecture (later called CA) in the layout 1. The CA can be implemented simply by using directory structures to represent the layers diff --git a/cmd/main-sync-api/config.yml-example b/cmd/main-sync-api/config.yml-example new file mode 100644 index 00000000..edb5c84b --- /dev/null +++ b/cmd/main-sync-api/config.yml-example @@ -0,0 +1,41 @@ +appCfg: + fullName: SIMRS Sync + codeName: simrs-sync + version: 0.1.0 + env: development + lang: en + +dbCfg: + dsn: + maxOpenConns: 5 + maxIdleConns: 5 + maxIdleTime: 100 + +multiDbCfg: + dbs : + - name: simrs_sync + dsn: + maxOpenConns: 5 + maxIdleConns: 5 + maxIdleTime: 100 + +httpCfg: + host: 127.0.0.1 + port: 8003 + +loggerCfg: + hideTime: true + hideLevel: true + +langCfg: + active: en + path: ../../assets/language/en + fileName: data.json + +corsCfg: + allowedOrigin: + allowedMethod: GET, POST, PUT, PATCH, DELETE, OPTIONS + +syncUrlCfg: + target: + host: \ No newline at end of file diff --git a/cmd/main-sync-api/main.go b/cmd/main-sync-api/main.go new file mode 100644 index 00000000..5bfdd36b --- /dev/null +++ b/cmd/main-sync-api/main.go @@ -0,0 +1,15 @@ +package main + +import ( + a "github.com/karincake/apem" + + h "simrs-vx/internal/interface/main-sync-handler" + + d "github.com/karincake/apem/db-gorm-pg" + + l "github.com/karincake/apem/logger-zerolog" +) + +func main() { + a.Run(h.SetRoutes(), &l.O, &d.O) +} diff --git a/cmd/simgos-sync-api/config.yml-example b/cmd/simgos-sync-api/config.yml-example new file mode 100644 index 00000000..153be50e --- /dev/null +++ b/cmd/simgos-sync-api/config.yml-example @@ -0,0 +1,41 @@ +appCfg: + fullName: SIMRS Sync + codeName: simrs-sync + version: 0.1.0 + env: development + lang: en + +dbCfg: + dsn: + maxOpenConns: 5 + maxIdleConns: 5 + maxIdleTime: 100 + +multiDbCfg: + dbs : + - name: simrs_sync + dsn: + maxOpenConns: 5 + maxIdleConns: 5 + maxIdleTime: 100 + +httpCfg: + host: 127.0.0.1 + port: 8002 + +loggerCfg: + hideTime: true + hideLevel: true + +langCfg: + active: en + path: ../../assets/language/en + fileName: data.json + +corsCfg: + allowedOrigin: + allowedMethod: GET, POST, PUT, PATCH, DELETE, OPTIONS + +syncUrlCfg: + target: + host: \ No newline at end of file diff --git a/cmd/simgos-sync-api/main.go b/cmd/simgos-sync-api/main.go new file mode 100644 index 00000000..ddb3897d --- /dev/null +++ b/cmd/simgos-sync-api/main.go @@ -0,0 +1,15 @@ +package main + +import ( + a "github.com/karincake/apem" + + h "simrs-vx/internal/interface/simgos-sync-handler" + + d "github.com/karincake/apem/db-gorm-pg" + + l "github.com/karincake/apem/logger-zerolog" +) + +func main() { + a.Run(h.SetRoutes(), &l.O, &d.O) +} diff --git a/internal/domain/main-entities/doctor/dto.go b/internal/domain/main-entities/doctor/dto.go index 62d5f5b4..0abcd99b 100644 --- a/internal/domain/main-entities/doctor/dto.go +++ b/internal/domain/main-entities/doctor/dto.go @@ -9,6 +9,7 @@ import ( ) type CreateDto struct { + Code *string `json:"code" validate:"maxLength=20"` Employee_Id *uint `json:"employee_id"` IHS_Number *string `json:"ihs_number"` SIP_Number *string `json:"sip_number"` @@ -24,6 +25,7 @@ type ReadListDto struct { } type FilterDto struct { + Code *string `json:"code"` Employee_Id *uint `json:"employee-id"` IHS_Number *string `json:"ihs-number" validate:"maxLength=20"` SIP_Number *string `json:"sip-number" validate:"maxLength=20"` @@ -34,6 +36,7 @@ type FilterDto struct { type ReadDetailDto struct { Id uint16 `json:"id"` + Code *string `json:"code"` Employee_Id *uint `json:"employee_id"` IHS_Number *string `json:"ihs_number"` SIP_Number *string `json:"sip_number"` @@ -56,6 +59,7 @@ type MetaDto struct { type ResponseDto struct { ecore.Main + Code *string `json:"code"` Employee_Id *uint `json:"employee_id"` Employee *ee.Employee `json:"employee,omitempty"` IHS_Number *string `json:"ihs_number"` @@ -70,6 +74,7 @@ type ResponseDto struct { func (d Doctor) ToResponse() ResponseDto { resp := ResponseDto{ + Code: d.Code, Employee_Id: d.Employee_Id, Employee: d.Employee, IHS_Number: d.IHS_Number, diff --git a/internal/domain/main-entities/laborant/dto.go b/internal/domain/main-entities/laborant/dto.go index 4397d2f1..e5fdb550 100644 --- a/internal/domain/main-entities/laborant/dto.go +++ b/internal/domain/main-entities/laborant/dto.go @@ -6,6 +6,7 @@ import ( ) type CreateDto struct { + Code *string `json:"code" validate:"maxLength=20"` Employee_Id *uint `json:"employee_id"` IHS_Number *string `json:"ihs_number" validate:"maxLength=20"` } @@ -17,12 +18,14 @@ type ReadListDto struct { } type FilterDto struct { + Code *string `json:"code"` Employee_Id *uint `json:"employee-id"` IHS_Number *string `json:"ihs-number"` } type ReadDetailDto struct { Id uint16 `json:"id"` + Code *string `json:"code"` Employee_Id *uint `json:"employee_id"` IHS_Number *string `json:"ihs_number"` } @@ -44,6 +47,7 @@ type MetaDto struct { type ResponseDto struct { ecore.Main + Code *string `json:"code"` Employee_Id *uint `json:"employee_id"` Employee *ee.Employee `json:"employee,omitempty"` IHS_Number *string `json:"ihs_number"` @@ -51,6 +55,7 @@ type ResponseDto struct { func (d Laborant) ToResponse() ResponseDto { resp := ResponseDto{ + Code: d.Code, Employee_Id: d.Employee_Id, Employee: d.Employee, IHS_Number: d.IHS_Number, diff --git a/internal/domain/main-entities/midwife/dto.go b/internal/domain/main-entities/midwife/dto.go index d1adfdaf..ed01a36b 100644 --- a/internal/domain/main-entities/midwife/dto.go +++ b/internal/domain/main-entities/midwife/dto.go @@ -6,6 +6,7 @@ import ( ) type CreateDto struct { + Code *string `json:"code" validate:"maxLength=20"` Employee_Id *uint `json:"employee_id"` IHS_Number *string `json:"ihs_number" validate:"maxLength=20"` } @@ -17,12 +18,14 @@ type ReadListDto struct { } type FilterDto struct { + Code *string `json:"code"` Employee_Id *uint `json:"employee_id"` IHS_Number *string `json:"ihs_number"` } type ReadDetailDto struct { Id uint16 `json:"id"` + Code *string `json:"code"` Employee_Id *uint `json:"employee_id"` IHS_Number *string `json:"ihs_number"` } @@ -44,6 +47,7 @@ type MetaDto struct { type ResponseDto struct { ecore.Main + Code *string `json:"code"` Employee_Id *uint `json:"employee_id"` Employee *ee.Employee `json:"employee,omitempty"` IHS_Number *string `json:"ihs_number"` @@ -51,6 +55,7 @@ type ResponseDto struct { func (d Midwife) ToResponse() ResponseDto { resp := ResponseDto{ + Code: d.Code, Employee_Id: d.Employee_Id, Employee: d.Employee, IHS_Number: d.IHS_Number, diff --git a/internal/domain/main-entities/nurse/dto.go b/internal/domain/main-entities/nurse/dto.go index 1707f212..7b7b283c 100644 --- a/internal/domain/main-entities/nurse/dto.go +++ b/internal/domain/main-entities/nurse/dto.go @@ -8,6 +8,7 @@ import ( ) type CreateDto struct { + Code *string `json:"code" validate:"maxLength=20"` Employee_Id *uint `json:"employee_id"` IHS_Number *string `json:"ihs_number" validate:"maxLength=20"` Unit_Id *uint16 `json:"unit_id"` @@ -21,6 +22,7 @@ type ReadListDto struct { } type FilterDto struct { + Code *string `json:"code"` Employee_Id *uint `json:"employee-id"` IHS_Number *string `json:"ihs-number"` Unit_Id *uint16 `json:"unit-id"` @@ -28,6 +30,7 @@ type FilterDto struct { } type ReadDetailDto struct { Id uint16 `json:"id"` + Code *string `json:"code"` Employee_Id *uint `json:"employee_id"` IHS_Number *string `json:"ihs_number"` } @@ -49,6 +52,7 @@ type MetaDto struct { type ResponseDto struct { ecore.Main + Code *string `json:"code"` Employee_Id *uint `json:"employee_id"` Employee *ee.Employee `json:"employee,omitempty"` IHS_Number *string `json:"ihs_number"` @@ -60,6 +64,7 @@ type ResponseDto struct { func (d Nurse) ToResponse() ResponseDto { resp := ResponseDto{ + Code: d.Code, Employee_Id: d.Employee_Id, Employee: d.Employee, IHS_Number: d.IHS_Number, diff --git a/internal/domain/main-entities/nutritionist/dto.go b/internal/domain/main-entities/nutritionist/dto.go index df6365bf..832d6873 100644 --- a/internal/domain/main-entities/nutritionist/dto.go +++ b/internal/domain/main-entities/nutritionist/dto.go @@ -6,6 +6,7 @@ import ( ) type CreateDto struct { + Code *string `json:"code" validate:"maxLength=20"` Employee_Id *uint `json:"employee_id"` IHS_Number *string `json:"ihs_number" validate:"maxLength=20"` } @@ -17,12 +18,14 @@ type ReadListDto struct { } type FilterDto struct { + Code *string `json:"code"` Employee_Id *uint `json:"employee-id"` IHS_Number *string `json:"ihs-number"` } type ReadDetailDto struct { Id uint16 `json:"id"` + Code *string `json:"code"` Employee_Id *uint `json:"employee_id"` IHS_Number *string `json:"ihs_number"` } @@ -44,6 +47,7 @@ type MetaDto struct { type ResponseDto struct { ecore.Main + Code *string `json:"code"` Employee_Id *uint `json:"employee_id"` Employee *ee.Employee `json:"employee,omitempty"` IHS_Number *string `json:"ihs_number"` @@ -51,6 +55,7 @@ type ResponseDto struct { func (d Nutritionist) ToResponse() ResponseDto { resp := ResponseDto{ + Code: d.Code, Employee_Id: d.Employee_Id, Employee: d.Employee, IHS_Number: d.IHS_Number, diff --git a/internal/domain/main-entities/patient/dto.go b/internal/domain/main-entities/patient/dto.go index 00134b6e..4927a50e 100644 --- a/internal/domain/main-entities/patient/dto.go +++ b/internal/domain/main-entities/patient/dto.go @@ -57,8 +57,8 @@ type DeleteDto struct { } type SearchDto struct { - Search string `json:"search"` - Mode SearchMode `json:"mode"` + Search string `json:"search"` + Pagination ecore.Pagination } type UploadDto struct { diff --git a/internal/domain/main-entities/pharmacist/dto.go b/internal/domain/main-entities/pharmacist/dto.go index 4a04f8d2..ded53ac8 100644 --- a/internal/domain/main-entities/pharmacist/dto.go +++ b/internal/domain/main-entities/pharmacist/dto.go @@ -6,6 +6,7 @@ import ( ) type CreateDto struct { + Code *string `json:"code" validate:"maxLength=20"` Employee_Id *uint `json:"employee_id"` IHS_Number *string `json:"ihs_number" validate:"maxLength=20"` } @@ -17,12 +18,14 @@ type ReadListDto struct { } type FilterDto struct { + Code *string `json:"code"` Employee_Id *uint `json:"employee-id"` IHS_Number *string `json:"ihs-number"` } type ReadDetailDto struct { Id uint16 `json:"id"` + Code *string `json:"code"` Employee_Id *uint `json:"employee_id"` IHS_Number *string `json:"ihs_number"` } @@ -44,6 +47,7 @@ type MetaDto struct { type ResponseDto struct { ecore.Main + Code *string `json:"code"` Employee_Id *uint `json:"employee_id"` Employee *ee.Employee `json:"employee,omitempty"` IHS_Number *string `json:"ihs_number"` @@ -51,6 +55,7 @@ type ResponseDto struct { func (d Pharmacist) ToResponse() ResponseDto { resp := ResponseDto{ + Code: d.Code, Employee_Id: d.Employee_Id, Employee: d.Employee, IHS_Number: d.IHS_Number, diff --git a/internal/domain/main-entities/user/dto.go b/internal/domain/main-entities/user/dto.go index b06a4bb0..c3a84737 100644 --- a/internal/domain/main-entities/user/dto.go +++ b/internal/domain/main-entities/user/dto.go @@ -20,6 +20,7 @@ type CreateDto struct { Person *ep.UpdateDto `json:"person"` PersonAddresses []epa.UpdateDto `json:"personAddresses"` PersonContacts []epc.UpdateDto `json:"personContacts"` + Code *string `json:"code" validate:"maxLength=20"` Employee *EmployeUpdateDto `json:"employee"` IHS_Number *string `json:"ihs_number" validate:"maxLength=20"` SIP_Number *string `json:"sip_number" validate:"maxLength=20"` diff --git a/internal/domain/simgos-sync-entities/.keep b/internal/domain/simgos-sync-entities/.keep new file mode 100644 index 00000000..e69de29b diff --git a/internal/infra/sync-cfg/sync-cfg.go b/internal/infra/sync-cfg/sync-cfg.go new file mode 100644 index 00000000..0368a7c4 --- /dev/null +++ b/internal/infra/sync-cfg/sync-cfg.go @@ -0,0 +1,14 @@ +package synccfg + +import ( + a "github.com/karincake/apem" + lo "github.com/karincake/apem/loggero" +) + +func SetConfig() { + a.ParseSingleCfg(&O) + if O.Host == "" || O.Target == "" { + panic("sync url config host or target empty") + } + lo.I.Println("sync url config loaded, status: DONE!!") +} diff --git a/internal/infra/sync-cfg/tycovar.go b/internal/infra/sync-cfg/tycovar.go new file mode 100644 index 00000000..9bb59f3d --- /dev/null +++ b/internal/infra/sync-cfg/tycovar.go @@ -0,0 +1,8 @@ +package synccfg + +var O SyncUrlCfg = SyncUrlCfg{} + +type SyncUrlCfg struct { + Target string `yaml:"target"` + Host string `yaml:"host"` +} diff --git a/internal/interface/main-handler/main-handler.go b/internal/interface/main-handler/main-handler.go index 690a830a..6a98487f 100644 --- a/internal/interface/main-handler/main-handler.go +++ b/internal/interface/main-handler/main-handler.go @@ -274,7 +274,7 @@ func SetRoutes() http.Handler { "PATCH /{id}": patient.O.Update, "DELETE /{id}": patient.O.Delete, "GET /search/{keyword}": patient.O.Search, - "GET /by-resident-identity": patient.O.SearchByResidentIdentity, + "GET /by-resident-identity": patient.O.SearchByResidentIdentityNumber, "POST /{id}/upload": patient.O.Upload, }) diff --git a/internal/interface/main-handler/patient/handler.go b/internal/interface/main-handler/patient/handler.go index 2c5fcb5b..1d02d8d7 100644 --- a/internal/interface/main-handler/patient/handler.go +++ b/internal/interface/main-handler/patient/handler.go @@ -76,21 +76,22 @@ func (obj myBase) Delete(w http.ResponseWriter, r *http.Request) { func (obj myBase) Search(w http.ResponseWriter, r *http.Request) { dto := e.SearchDto{} + + sf.UrlQueryParam(&dto, *r.URL) keyword := rw.ValidateString(w, "keyword", r.PathValue("keyword")) if keyword == "" { rw.WriteJSON(w, http.StatusUnauthorized, d.IS{"message": "keyword is required"}, nil) } - dto.Mode = e.SMIdent + dto.Search = keyword res, err := u.Search(dto) rw.DataResponse(w, res, err) } -func (obj myBase) SearchByResidentIdentity(w http.ResponseWriter, r *http.Request) { +func (obj myBase) SearchByResidentIdentityNumber(w http.ResponseWriter, r *http.Request) { dto := e.SearchDto{} sf.UrlQueryParam(&dto, *r.URL) - dto.Mode = e.SMNik - res, err := u.Search(dto) + res, err := u.SearchByResidentIdentityNumber(dto) rw.DataResponse(w, res, err) } diff --git a/internal/interface/main-sync-handler/main-sync-handler.go b/internal/interface/main-sync-handler/main-sync-handler.go new file mode 100644 index 00000000..c8ba5144 --- /dev/null +++ b/internal/interface/main-sync-handler/main-sync-handler.go @@ -0,0 +1,36 @@ +package mainsynchandler + +import ( + "net/http" + + /******************** infra ********************/ + gs "simrs-vx/internal/infra/gorm-setting" + synccfg "simrs-vx/internal/infra/sync-cfg" + + /******************** pkg ********************/ + cmw "simrs-vx/pkg/cors-manager-mw" + lh "simrs-vx/pkg/lang-helper" + handlerlogger "simrs-vx/pkg/middleware/handler-logger" + zlc "simrs-vx/pkg/zerolog-ctx" + + /******************** external ********************/ + a "github.com/karincake/apem" + + /******************** internal ********************/ + "simrs-vx/internal/interface/main-handler/home" +) + +func SetRoutes() http.Handler { + /// + a.RegisterExtCall(gs.Adjust) + a.RegisterExtCall(zlc.Adjust) + a.RegisterExtCall(lh.Populate) + a.RegisterExtCall(synccfg.SetConfig) + + r := http.NewServeMux() + + /******************** Main ********************/ + r.HandleFunc("/", home.Home) + + return cmw.SetCors(handlerlogger.SetLog(r)) +} diff --git a/internal/interface/simgos-sync-handler/simgos-sync-handler.go b/internal/interface/simgos-sync-handler/simgos-sync-handler.go new file mode 100644 index 00000000..f51106a9 --- /dev/null +++ b/internal/interface/simgos-sync-handler/simgos-sync-handler.go @@ -0,0 +1,36 @@ +package simgossynchandler + +import ( + "net/http" + + /******************** infra ********************/ + gs "simrs-vx/internal/infra/gorm-setting" + synccfg "simrs-vx/internal/infra/sync-cfg" + + /******************** pkg ********************/ + cmw "simrs-vx/pkg/cors-manager-mw" + lh "simrs-vx/pkg/lang-helper" + handlerlogger "simrs-vx/pkg/middleware/handler-logger" + zlc "simrs-vx/pkg/zerolog-ctx" + + /******************** external ********************/ + a "github.com/karincake/apem" + + /******************** internal ********************/ + "simrs-vx/internal/interface/main-handler/home" +) + +func SetRoutes() http.Handler { + /// + a.RegisterExtCall(gs.Adjust) + a.RegisterExtCall(zlc.Adjust) + a.RegisterExtCall(lh.Populate) + a.RegisterExtCall(synccfg.SetConfig) + + r := http.NewServeMux() + + /******************** Main ********************/ + r.HandleFunc("/", home.Home) + + return cmw.SetCors(handlerlogger.SetLog(r)) +} diff --git a/internal/use-case/main-sync-case/.keep b/internal/use-case/main-sync-case/.keep new file mode 100644 index 00000000..e69de29b diff --git a/internal/use-case/main-use-case/doctor/helper.go b/internal/use-case/main-use-case/doctor/helper.go index 8077b92f..b62045c7 100644 --- a/internal/use-case/main-use-case/doctor/helper.go +++ b/internal/use-case/main-use-case/doctor/helper.go @@ -17,6 +17,7 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Doctor) { inputSrc = &inputTemp.CreateDto } + data.Code = inputSrc.Code data.Employee_Id = inputSrc.Employee_Id data.IHS_Number = inputSrc.IHS_Number data.SIP_Number = inputSrc.SIP_Number diff --git a/internal/use-case/main-use-case/laborant/helper.go b/internal/use-case/main-use-case/laborant/helper.go index 8619f7e6..8a053b90 100644 --- a/internal/use-case/main-use-case/laborant/helper.go +++ b/internal/use-case/main-use-case/laborant/helper.go @@ -17,6 +17,7 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Laborant) { inputSrc = &inputTemp.CreateDto } + data.Code = inputSrc.Code data.Employee_Id = inputSrc.Employee_Id data.IHS_Number = inputSrc.IHS_Number } diff --git a/internal/use-case/main-use-case/midwife/helper.go b/internal/use-case/main-use-case/midwife/helper.go index 5be74b86..e63f0e6f 100644 --- a/internal/use-case/main-use-case/midwife/helper.go +++ b/internal/use-case/main-use-case/midwife/helper.go @@ -17,6 +17,7 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Midwife) { inputSrc = &inputTemp.CreateDto } + data.Code = inputSrc.Code data.Employee_Id = inputSrc.Employee_Id data.IHS_Number = inputSrc.IHS_Number } diff --git a/internal/use-case/main-use-case/nurse/helper.go b/internal/use-case/main-use-case/nurse/helper.go index 5ecb6f20..003230b3 100644 --- a/internal/use-case/main-use-case/nurse/helper.go +++ b/internal/use-case/main-use-case/nurse/helper.go @@ -17,6 +17,7 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Nurse) { inputSrc = &inputTemp.CreateDto } + data.Code = inputSrc.Code data.Employee_Id = inputSrc.Employee_Id data.IHS_Number = inputSrc.IHS_Number data.Unit_Id = inputSrc.Unit_Id diff --git a/internal/use-case/main-use-case/nutritionist/helper.go b/internal/use-case/main-use-case/nutritionist/helper.go index 4ff20809..028b2dc3 100644 --- a/internal/use-case/main-use-case/nutritionist/helper.go +++ b/internal/use-case/main-use-case/nutritionist/helper.go @@ -17,6 +17,7 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Nutritionist) { inputSrc = &inputTemp.CreateDto } + data.Code = inputSrc.Code data.Employee_Id = inputSrc.Employee_Id data.IHS_Number = inputSrc.IHS_Number } diff --git a/internal/use-case/main-use-case/patient/case.go b/internal/use-case/main-use-case/patient/case.go index fd17d7fb..b52215ac 100644 --- a/internal/use-case/main-use-case/patient/case.go +++ b/internal/use-case/main-use-case/patient/case.go @@ -352,18 +352,18 @@ func Delete(input e.DeleteDto) (*d.Data, error) { } -func Search(input e.SearchDto) (*d.Data, error) { +func SearchByResidentIdentityNumber(input e.SearchDto) (*d.Data, error) { var data *e.Patient var err error event := pl.Event{ - Feature: "Search", + Feature: "Search By Resident Identity Number", Source: source, } // Start log pl.SetLogInfo(&event, input, "started", "search") - if data, err = SearchData(input, &event); err != nil { + if data, err = SearchDataByRIN(input, &event); err != nil { return nil, err } @@ -377,6 +377,46 @@ func Search(input e.SearchDto) (*d.Data, error) { }, nil } +func Search(input e.SearchDto) (*d.Data, error) { + var dataList []e.Patient + var metaList *e.MetaDto + var err error + + event := pl.Event{ + Feature: "Search", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "readList") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + + if dataList, metaList, err = SearchData(input, &event, tx); err != nil { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "list-data", + "status": "fetched", + "page_number": strconv.Itoa(metaList.PageNumber), + "page_size": strconv.Itoa(metaList.PageSize), + "record_totalCount": strconv.Itoa(metaList.Count), + "record_currentCount": strconv.Itoa(len(dataList)), + }, + Data: e.ToResponseList(dataList), + }, nil +} + func Upload(input e.UploadDto) (*d.Data, error) { rdDto := e.ReadDetailDto{Id: uint16(input.Id)} var data *e.Patient diff --git a/internal/use-case/main-use-case/patient/lib.go b/internal/use-case/main-use-case/patient/lib.go index f35e3853..36c9d416 100644 --- a/internal/use-case/main-use-case/patient/lib.go +++ b/internal/use-case/main-use-case/patient/lib.go @@ -154,11 +154,11 @@ func DeleteData(data *e.Patient, event *pl.Event, dbx ...*gorm.DB) error { return nil } -func SearchData(input e.SearchDto, event *pl.Event, dbx ...*gorm.DB) (*e.Patient, error) { +// Search By Resident Identity Number +func SearchDataByRIN(input e.SearchDto, event *pl.Event, dbx ...*gorm.DB) (*e.Patient, error) { pl.SetLogInfo(event, input, "started", "DBSearch") - var patient e.Patient - var err error + var data e.Patient var tx *gorm.DB if len(dbx) > 0 { @@ -174,27 +174,60 @@ func SearchData(input e.SearchDto, event *pl.Event, dbx ...*gorm.DB) (*e.Patient Preload("Person.Relatives"). Preload("Person.Insurances") - switch input.Mode { - case e.SMIdent: - // Search by patient number OR person's resident identity number (exact match) OR person's name (partial match) - err = tx.Joins("JOIN \"Person\" ON \"Patient\".\"Person_Id\" = \"Person\".\"Id\""). - Where("\"Patient\".\"Number\" = ? OR \"Person\".\"ResidentIdentityNumber\" = ? OR \"Person\".\"Name\" ILIKE ?", - input.Search, input.Search, "%"+input.Search+"%"). - First(&patient).Error - case e.SMNik: - // Search by patient person's resident identity number (exact match) - err = tx.Joins("JOIN \"Person\" ON \"Patient\".\"Person_Id\" = \"Person\".\"Id\""). - Where("\"Person\".\"ResidentIdentityNumber\" = ?", - input.Search). - First(&patient).Error - } + // Search by patient person's resident identity number (exact match) + err := tx.Joins("JOIN \"Person\" ON \"Patient\".\"Person_Id\" = \"Person\".\"Id\""). + Where("\"Person\".\"ResidentIdentityNumber\" = ?", + input.Search). + First(&data).Error if err != nil { - if processedErr := pu.HandleSearchError(err, event, source, input.Search, patient); processedErr != nil { + if processedErr := pu.HandleSearchError(err, event, source, input.Search, data); processedErr != nil { return nil, processedErr } } pl.SetLogInfo(event, nil, "complete") - return &patient, nil + return &data, nil +} + +func SearchData(input e.SearchDto, event *pl.Event, dbx ...*gorm.DB) ([]e.Patient, *e.MetaDto, error) { + pl.SetLogInfo(event, input, "started", "DBSearch") + + var data []e.Patient + pagination := gh.Pagination{} + count := int64(0) + meta := e.MetaDto{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + // Preload associations for complete data + tx = tx.Preload(clause.Associations) + tx = tx.Preload("Person.Addresses"). + Preload("Person.Contacts"). + Preload("Person.Relatives"). + Preload("Person.Insurances") + + // Search by patient number OR person's resident identity number (exact match) OR person's name (partial match) + tx = tx.Joins("JOIN \"Person\" ON \"Patient\".\"Person_Id\" = \"Person\".\"Id\""). + Where("\"Patient\".\"Number\" ILIKE ? OR \"Person\".\"ResidentIdentityNumber\" ILIKE ? OR \"Person\".\"Name\" ILIKE ?", + "%"+input.Search+"%", "%"+input.Search+"%", "%"+input.Search+"%") + err := tx.Scopes(gh.Paginate(input, &pagination)).Find(&data).Error + + if err != nil { + if processedErr := pu.HandleSearchError(err, event, source, input.Search, data); processedErr != nil { + return nil, nil, processedErr + } + } + + meta.Count = int(count) + meta.PageNumber = pagination.PageNumber + meta.PageSize = pagination.PageSize + + pl.SetLogInfo(event, nil, "complete") + return data, &meta, nil } diff --git a/internal/use-case/main-use-case/pharmacist/helper.go b/internal/use-case/main-use-case/pharmacist/helper.go index deb230cf..c17fa8a2 100644 --- a/internal/use-case/main-use-case/pharmacist/helper.go +++ b/internal/use-case/main-use-case/pharmacist/helper.go @@ -17,6 +17,7 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Pharmacist) { inputSrc = &inputTemp.CreateDto } + data.Code = inputSrc.Code data.Employee_Id = inputSrc.Employee_Id data.IHS_Number = inputSrc.IHS_Number } diff --git a/internal/use-case/main-use-case/user/case.go b/internal/use-case/main-use-case/user/case.go index 7d2053de..8e452e62 100644 --- a/internal/use-case/main-use-case/user/case.go +++ b/internal/use-case/main-use-case/user/case.go @@ -9,6 +9,7 @@ import ( ed "simrs-vx/internal/domain/main-entities/doctor" ee "simrs-vx/internal/domain/main-entities/employee" el "simrs-vx/internal/domain/main-entities/laborant" + emw "simrs-vx/internal/domain/main-entities/midwife" en "simrs-vx/internal/domain/main-entities/nurse" et "simrs-vx/internal/domain/main-entities/nutritionist" ep "simrs-vx/internal/domain/main-entities/pharmacist" @@ -18,6 +19,7 @@ import ( ud "simrs-vx/internal/use-case/main-use-case/doctor" ue "simrs-vx/internal/use-case/main-use-case/employee" ul "simrs-vx/internal/use-case/main-use-case/laborant" + umw "simrs-vx/internal/use-case/main-use-case/midwife" un "simrs-vx/internal/use-case/main-use-case/nurse" ut "simrs-vx/internal/use-case/main-use-case/nutritionist" upe "simrs-vx/internal/use-case/main-use-case/person" @@ -106,6 +108,7 @@ func Create(input e.CreateDto) (*d.Data, error) { switch input.Employee.Position_Code { case ero.EPCDoc: createDoc := ed.CreateDto{ + Code: input.Code, Employee_Id: &employeeData.Id, IHS_Number: input.IHS_Number, SIP_Number: input.SIP_Number, @@ -118,6 +121,7 @@ func Create(input e.CreateDto) (*d.Data, error) { } case ero.EPCNur: createNurse := en.CreateDto{ + Code: input.Code, Employee_Id: &employeeData.Id, IHS_Number: input.IHS_Number, Unit_Id: input.Unit_Id, @@ -128,6 +132,7 @@ func Create(input e.CreateDto) (*d.Data, error) { } case ero.EPCNut: createNutritionist := et.CreateDto{ + Code: input.Code, Employee_Id: &employeeData.Id, IHS_Number: input.IHS_Number, } @@ -136,6 +141,7 @@ func Create(input e.CreateDto) (*d.Data, error) { } case ero.EPCPha: createPharmacist := ep.CreateDto{ + Code: input.Code, Employee_Id: &employeeData.Id, IHS_Number: input.IHS_Number, } @@ -144,12 +150,22 @@ func Create(input e.CreateDto) (*d.Data, error) { } case ero.EPCLab: createLaborant := el.CreateDto{ + Code: input.Code, Employee_Id: &employeeData.Id, IHS_Number: input.IHS_Number, } if _, err := ul.CreateData(createLaborant, &event, tx); err != nil { return err } + case ero.EPCMwi: + createMidWife := emw.CreateDto{ + Code: input.Code, + Employee_Id: &employeeData.Id, + IHS_Number: input.IHS_Number, + } + if _, err := umw.CreateData(createMidWife, &event, tx); err != nil { + return err + } default: return errors.New("invalid employee position") } @@ -380,6 +396,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { return err } createDoc := ed.CreateDto{ + Code: input.Code, Employee_Id: &employeeData.Id, IHS_Number: input.IHS_Number, SIP_Number: input.SIP_Number, @@ -402,6 +419,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { return err } createNur := en.CreateDto{ + Code: input.Code, Employee_Id: &employeeData.Id, IHS_Number: input.IHS_Number, } @@ -422,6 +440,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { return err } createNut := et.CreateDto{ + Code: input.Code, Employee_Id: &employeeData.Id, IHS_Number: input.IHS_Number, } @@ -442,6 +461,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { return err } createPha := ep.CreateDto{ + Code: input.Code, Employee_Id: &employeeData.Id, IHS_Number: input.IHS_Number, } @@ -462,6 +482,7 @@ func Update(input e.UpdateDto) (*d.Data, error) { return err } createLab := el.CreateDto{ + Code: input.Code, Employee_Id: &employeeData.Id, IHS_Number: input.IHS_Number, } @@ -475,6 +496,27 @@ func Update(input e.UpdateDto) (*d.Data, error) { if _, err := ul.CreateData(createLab, &event, tx); err != nil { return err } + case ero.EPCMwi: + readMidWife := emw.ReadDetailDto{Employee_Id: &employeeData.Id} + readMidWifeData, err := umw.ReadDetailData(readMidWife, &event, tx) + if err != nil { + return err + } + createMidWife := emw.CreateDto{ + Code: input.Code, + Employee_Id: &employeeData.Id, + IHS_Number: input.IHS_Number, + } + if readMidWifeData != nil { + if err := umw.UpdateData(emw.UpdateDto{CreateDto: createMidWife}, readMidWifeData, &event, tx); err != nil { + return err + } + return nil + } + + if _, err := umw.CreateData(createMidWife, &event, tx); err != nil { + return err + } default: return errors.New("invalid employee position") } diff --git a/internal/use-case/simgos-sync-case/.keep b/internal/use-case/simgos-sync-case/.keep new file mode 100644 index 00000000..e69de29b