diff --git a/cmd/main-migration/migrations/20251120005512.sql b/cmd/main-migration/migrations/20251120005512.sql new file mode 100644 index 00000000..8fd4b6af --- /dev/null +++ b/cmd/main-migration/migrations/20251120005512.sql @@ -0,0 +1,2 @@ +-- Modify "McuOrderItem" table +ALTER TABLE "public"."McuOrderItem" ADD COLUMN "Note" character varying(1024) NULL; diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index e4ce72b0..64a7c3f4 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:8gw1BB9DWz+cNATJjG1oMXA+QAF1HrIw47xjbI33aC4= +h1:4ab+A8iOO9wdTsRlY3sxe8ge29VhYaHMyq+qQCEN2UE= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -123,5 +123,6 @@ h1:8gw1BB9DWz+cNATJjG1oMXA+QAF1HrIw47xjbI33aC4= 20251118074929.sql h1:p1KsWqCuR1JXA/jVO5BmOhCcaQ8clT7t0YRszAhPFbg= 20251119063438.sql h1:NVGM0X/LHD37EaPl8SNzkNiZDJ7AB1QR+LLwLh6WRdg= 20251119065730.sql h1:U5lzk1WvMB0bw3kwckou7jkEt4bwdYItwHr2Vxqe7w4= -20251119072302.sql h1:8L+NsXPFXGZDQZIOhShvuBM9aLwU3h95tXnz6jxHhlA= -20251119072450.sql h1:ksTc8ljaHFrBo1/HiHtcnT+iJ7kPS93KgetFTf3p4Qc= +20251119072302.sql h1:qCuI2WMEMF/XNbjV+RXPjBnuCKLu1Fia+mR9HiLWBIs= +20251119072450.sql h1:Xg+bTwqGyKPNFEQhJylvpz1wifdfmDJvcAq6vmNf0Ng= +20251120005512.sql h1:Ek6qpacAI/qVuTYxKno+uJyzn7s5z9pf3t7VA8gTzm4= diff --git a/internal/domain/main-entities/device-order-item/dto.go b/internal/domain/main-entities/device-order-item/dto.go index 4464c91d..3d31c66d 100644 --- a/internal/domain/main-entities/device-order-item/dto.go +++ b/internal/domain/main-entities/device-order-item/dto.go @@ -15,6 +15,7 @@ type CreateDto struct { type ReadListDto struct { FilterDto Includes string `json:"includes"` + Sort string `json:"sort"` Pagination ecore.Pagination } diff --git a/internal/domain/main-entities/employee/dto.go b/internal/domain/main-entities/employee/dto.go index 85b7008a..5b2c674d 100644 --- a/internal/domain/main-entities/employee/dto.go +++ b/internal/domain/main-entities/employee/dto.go @@ -4,6 +4,7 @@ import ( ecore "simrs-vx/internal/domain/base-entities/core" ep "simrs-vx/internal/domain/main-entities/person" eu "simrs-vx/internal/domain/main-entities/user" + "time" erc "simrs-vx/internal/domain/references/common" erg "simrs-vx/internal/domain/references/organization" @@ -55,22 +56,26 @@ type MetaDto struct { type ResponseDto struct { ecore.Main - User_Id *uint `json:"user_id"` - User *eu.User `json:"user,omitempty"` - Person_Id *uint `json:"person_id"` - Person *ep.Person `json:"person,omitempty"` - Number *string `json:"number"` - Status_Code erc.ActiveStatusCode `json:"status_code"` + User_Id *uint `json:"user_id"` + User *eu.User `json:"user,omitempty"` + Person_Id *uint `json:"person_id"` + Person *ep.Person `json:"person,omitempty"` + Number *string `json:"number"` + Position_Code *erg.EmployeePositionCode `json:"position_code"` + Contract_ExpiredDate *time.Time `json:"contract_expiredDate"` + Status_Code erc.ActiveStatusCode `json:"status_code"` } func (d Employee) ToResponse() ResponseDto { resp := ResponseDto{ - User_Id: d.User_Id, - User: d.User, - Person_Id: d.Person_Id, - Person: d.Person, - Number: d.Number, - Status_Code: d.Status_Code, + User_Id: d.User_Id, + User: d.User, + Person_Id: d.Person_Id, + Person: d.Person, + Number: d.Number, + Position_Code: d.Position_Code, + Contract_ExpiredDate: d.Contract_ExpiredDate, + Status_Code: d.Status_Code, } resp.Main = d.Main return resp diff --git a/internal/domain/main-entities/mcu-order-item/base/entity.go b/internal/domain/main-entities/mcu-order-item/base/entity.go new file mode 100644 index 00000000..dcfb0625 --- /dev/null +++ b/internal/domain/main-entities/mcu-order-item/base/entity.go @@ -0,0 +1,20 @@ +package mcuorderitem + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + ems "simrs-vx/internal/domain/main-entities/mcu-src" + "time" + + erc "simrs-vx/internal/domain/references/common" +) + +type McuOrderItem struct { + ecore.Main // adjust this according to the needs + McuOrder_Id *uint `json:"mcuOrder_id" gorm:"uniqueIndex:idx_order_src"` + McuSrc_Code *string `json:"mcuSrc_code" gorm:"uniqueIndex:idx_order_src"` + McuSrc *ems.McuSrc `json:"mcuSrc,omitempty" gorm:"foreignKey:McuSrc_Code;references:Code"` + ExaminationDate *time.Time `json:"examinationDate"` + Note *string `json:"note" gorm:"size:1024"` + Result *string `json:"result"` + Status_Code erc.DataStatusCode `json:"status_code"` +} diff --git a/internal/domain/main-entities/mcu-order-item/entity.go b/internal/domain/main-entities/mcu-order-item/entity.go index 97384243..48a57bac 100644 --- a/internal/domain/main-entities/mcu-order-item/entity.go +++ b/internal/domain/main-entities/mcu-order-item/entity.go @@ -1,23 +1,15 @@ package mcuorderitem import ( - ecore "simrs-vx/internal/domain/base-entities/core" emo "simrs-vx/internal/domain/main-entities/mcu-order" - ems "simrs-vx/internal/domain/main-entities/mcu-src" - "time" + emoib "simrs-vx/internal/domain/main-entities/mcu-order-item/base" erc "simrs-vx/internal/domain/references/common" ) type McuOrderItem struct { - ecore.Main // adjust this according to the needs - McuOrder_Id *uint `json:"mcuOrder_id" gorm:"uniqueIndex:idx_order_src"` - McuOrder *emo.McuOrder `json:"mcuOrder,omitempty" gorm:"foreignKey:McuOrder_Id;references:Id"` - McuSrc_Code *string `json:"mcuSrc_code" gorm:"uniqueIndex:idx_order_src"` - McuSrc *ems.McuSrc `json:"mcuSrc,omitempty" gorm:"foreignKey:McuSrc_Code;references:Code"` - ExaminationDate *time.Time `json:"examinationDate"` - Result *string `json:"result"` - Status_Code erc.DataStatusCode `json:"status_code"` + emoib.McuOrderItem + McuOrder *emo.McuOrder `json:"mcuOrder,omitempty" gorm:"foreignKey:McuOrder_Id;references:Id"` } func (d McuOrderItem) IsCompleted() bool { diff --git a/internal/domain/main-entities/mcu-order/dto.go b/internal/domain/main-entities/mcu-order/dto.go index 594f72d7..2835ce2c 100644 --- a/internal/domain/main-entities/mcu-order/dto.go +++ b/internal/domain/main-entities/mcu-order/dto.go @@ -17,6 +17,7 @@ import ( // internal - domain - main-entities ed "simrs-vx/internal/domain/main-entities/doctor" ee "simrs-vx/internal/domain/main-entities/encounter" + emoib "simrs-vx/internal/domain/main-entities/mcu-order-item/base" ) type CreateDto struct { @@ -85,7 +86,8 @@ type ResponseDto struct { ExaminationDate *time.Time `json:"examinationDate"` Number uint8 `json:"number"` Temperature float64 `json:"temperature"` - UrgencyLevel_Code ercl.McuUrgencyLevelCode `json:"urgencyLevel_code""` + UrgencyLevel_Code ercl.McuUrgencyLevelCode `json:"urgencyLevel_code"` + Items []*emoib.McuOrderItem `json:"items"` } func (d McuOrder) ToResponse() ResponseDto { @@ -100,6 +102,7 @@ func (d McuOrder) ToResponse() ResponseDto { Number: d.Number, Temperature: d.Temperature, UrgencyLevel_Code: d.UrgencyLevel_Code, + Items: d.Items, } resp.Main = d.Main return resp diff --git a/internal/domain/main-entities/mcu-order/entity.go b/internal/domain/main-entities/mcu-order/entity.go index b9e5d0d7..81fb7495 100644 --- a/internal/domain/main-entities/mcu-order/entity.go +++ b/internal/domain/main-entities/mcu-order/entity.go @@ -4,6 +4,7 @@ import ( ecore "simrs-vx/internal/domain/base-entities/core" ed "simrs-vx/internal/domain/main-entities/doctor" ee "simrs-vx/internal/domain/main-entities/encounter" + emoib "simrs-vx/internal/domain/main-entities/mcu-order-item/base" "time" ercl "simrs-vx/internal/domain/references/clinical" @@ -23,6 +24,11 @@ type McuOrder struct { Temperature float64 `json:"temperature"` UrgencyLevel_Code ercl.McuUrgencyLevelCode `json:"urgencyLevel_code" gorm:"not null;size:15"` Scope_Code ercl.McuScopeCode `json:"scope_code" gorm:"index;size:10"` + Items []*emoib.McuOrderItem `json:"items" gorm:"foreignKey:McuOrder_Id;references:Id"` +} + +func (d McuOrder) IsNotNew() bool { + return d.Status_Code != erc.DSCNew } func (d McuOrder) IsCompleted() bool { diff --git a/internal/domain/main-entities/person-address/base/entity.go b/internal/domain/main-entities/person-address/base/entity.go new file mode 100644 index 00000000..65d71912 --- /dev/null +++ b/internal/domain/main-entities/person-address/base/entity.go @@ -0,0 +1,22 @@ +package personaddress + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + epr "simrs-vx/internal/domain/main-entities/postal-region" + ev "simrs-vx/internal/domain/main-entities/village" + + erp "simrs-vx/internal/domain/references/person" +) + +type PersonAddress struct { + ecore.Main // adjust this according to the needs + Person_Id uint `json:"person_id"` + Address string `json:"address" gorm:"size:150"` + LocationType_Code erp.AddressLocationTypeCode `json:"locationType_code" gorm:"size:10"` + Rt string `json:"rt" gorm:"size:2"` + Rw string `json:"rw" gorm:"size:2"` + PostalRegion_Code *string `json:"postalRegion_code" gorm:"size:6"` + PostalRegion *epr.PostalRegion `json:"postalRegion,omitempty" gorm:"foreignKey:PostalRegion_Code;references:Code"` + Village_Code *string `json:"village_code" gorm:"size:10"` + Village *ev.Village `json:"village,omitempty" gorm:"foreignKey:Village_Code;references:Code"` +} diff --git a/internal/domain/main-entities/person-address/entity.go b/internal/domain/main-entities/person-address/entity.go index 65d71912..f53e2859 100644 --- a/internal/domain/main-entities/person-address/entity.go +++ b/internal/domain/main-entities/person-address/entity.go @@ -1,22 +1,9 @@ package personaddress import ( - ecore "simrs-vx/internal/domain/base-entities/core" - epr "simrs-vx/internal/domain/main-entities/postal-region" - ev "simrs-vx/internal/domain/main-entities/village" - - erp "simrs-vx/internal/domain/references/person" + eb "simrs-vx/internal/domain/main-entities/person-address/base" ) type PersonAddress struct { - ecore.Main // adjust this according to the needs - Person_Id uint `json:"person_id"` - Address string `json:"address" gorm:"size:150"` - LocationType_Code erp.AddressLocationTypeCode `json:"locationType_code" gorm:"size:10"` - Rt string `json:"rt" gorm:"size:2"` - Rw string `json:"rw" gorm:"size:2"` - PostalRegion_Code *string `json:"postalRegion_code" gorm:"size:6"` - PostalRegion *epr.PostalRegion `json:"postalRegion,omitempty" gorm:"foreignKey:PostalRegion_Code;references:Code"` - Village_Code *string `json:"village_code" gorm:"size:10"` - Village *ev.Village `json:"village,omitempty" gorm:"foreignKey:Village_Code;references:Code"` + eb.PersonAddress } diff --git a/internal/domain/main-entities/person-contact/base/entity.go b/internal/domain/main-entities/person-contact/base/entity.go new file mode 100644 index 00000000..b39aa53e --- /dev/null +++ b/internal/domain/main-entities/person-contact/base/entity.go @@ -0,0 +1,13 @@ +package personcontact + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + erp "simrs-vx/internal/domain/references/person" +) + +type PersonContact struct { + ecore.Main // adjust this according to the needs + Person_Id uint `json:"person_id"` + Type_Code erp.ContactTypeCode `json:"type_code" gorm:"size:15"` + Value string `json:"value" gorm:"size:100"` +} diff --git a/internal/domain/main-entities/person-contact/entity.go b/internal/domain/main-entities/person-contact/entity.go index b39aa53e..3ba257c4 100644 --- a/internal/domain/main-entities/person-contact/entity.go +++ b/internal/domain/main-entities/person-contact/entity.go @@ -1,13 +1,9 @@ package personcontact import ( - ecore "simrs-vx/internal/domain/base-entities/core" - erp "simrs-vx/internal/domain/references/person" + eb "simrs-vx/internal/domain/main-entities/person-contact/base" ) type PersonContact struct { - ecore.Main // adjust this according to the needs - Person_Id uint `json:"person_id"` - Type_Code erp.ContactTypeCode `json:"type_code" gorm:"size:15"` - Value string `json:"value" gorm:"size:100"` + eb.PersonContact } diff --git a/internal/domain/main-entities/soapi/dto.go b/internal/domain/main-entities/soapi/dto.go index b8f1b827..3edc18e3 100644 --- a/internal/domain/main-entities/soapi/dto.go +++ b/internal/domain/main-entities/soapi/dto.go @@ -32,7 +32,7 @@ type FilterDto struct { Encounter_Id *uint `json:"encounter-id"` Employee_Id *uint `json:"employee-id"` Time *time.Time `json:"time"` - TypeCode erc.SoapiTypeCode `json:"typeCode"` + TypeCode erc.SoapiTypeCode `json:"type-code"` Value *string `json:"value"` } diff --git a/internal/domain/references/organization/organization.go b/internal/domain/references/organization/organization.go index 09b19dce..e12531cd 100644 --- a/internal/domain/references/organization/organization.go +++ b/internal/domain/references/organization/organization.go @@ -18,14 +18,16 @@ const ( EPCReg EmployeePositionCode = "reg" // Admisi/Pendaftaran EPCNur EmployeePositionCode = "nur" // Perawat EPCDoc EmployeePositionCode = "doc" // Dokter - EPCNut EmployeePositionCode = "nut" // Ahli gizi EPCMwi EmployeePositionCode = "miw" // Bidan + EPCThr EmployeePositionCode = "thr" // Terapis + EPCNut EmployeePositionCode = "nut" // Ahli gizi EPCLab EmployeePositionCode = "lab" // Laboran EPCPha EmployeePositionCode = "pha" // Farmasi - EPCPay EmployeePositionCode = "pay" // Pembayaran - EPCHur EmployeePositionCode = "hue" // Sumber Daya Manusia - EPCGea EmployeePositionCode = "gea" // Bagian Umum - EPCMan EmployeePositionCode = "man" // Manajemen + EPCNom EmployeePositionCode = "nom" // Non Medic + // EPCPay EmployeePositionCode = "pay" // Pembayaran + // EPCHur EmployeePositionCode = "hue" // Sumber Daya Manusia + // EPCGea EmployeePositionCode = "gea" // Bagian Umum + // EPCMan EmployeePositionCode = "man" // Manajemen IPCSpecialist = "specialist-intern" IPCNurse = "nurse-intern" diff --git a/internal/interface/main-handler/main-handler.go b/internal/interface/main-handler/main-handler.go index b63bc834..56811194 100644 --- a/internal/interface/main-handler/main-handler.go +++ b/internal/interface/main-handler/main-handler.go @@ -182,6 +182,7 @@ func SetRoutes() http.Handler { "POST /": mcuorder.O.Create, "PATCH /{id}": mcuorder.O.Update, "DELETE /{id}": mcuorder.O.Delete, + "PATCH /{id}/submit": mcuorder.O.Submit, "PATCH /{id}/complete": mcuorder.O.Complete, "PATCH /{id}/set-schedule": mcuorder.O.SetSchedule, }) diff --git a/internal/interface/main-handler/mcu-order/handler.go b/internal/interface/main-handler/mcu-order/handler.go index ac4aca9f..bbbd1c56 100644 --- a/internal/interface/main-handler/mcu-order/handler.go +++ b/internal/interface/main-handler/mcu-order/handler.go @@ -85,6 +85,18 @@ func (obj myBase) Delete(w http.ResponseWriter, r *http.Request) { rw.DataResponse(w, res, err) } +func (obj myBase) Submit(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + + dto := e.ReadDetailDto{} + dto.Id = uint(id) + res, err := u.Submit(dto) + rw.DataResponse(w, res, err) +} + func (obj myBase) Complete(w http.ResponseWriter, r *http.Request) { id := rw.ValidateInt(w, "id", r.PathValue("id")) if id <= 0 { diff --git a/internal/lib/auth/tycovar.go b/internal/lib/auth/tycovar.go index 70a6fec2..117d0c73 100644 --- a/internal/lib/auth/tycovar.go +++ b/internal/lib/auth/tycovar.go @@ -65,19 +65,19 @@ func (a AuthInfo) IsPharmacist() bool { return *a.Employee_Position_Code == string(ero.EPCPha) } -func (a AuthInfo) IsPayment() bool { - if a.Employee_Position_Code == nil { - return false - } - return *a.Employee_Position_Code == string(ero.EPCPay) -} +// func (a AuthInfo) IsPayment() bool { +// if a.Employee_Position_Code == nil { +// return false +// } +// return *a.Employee_Position_Code == string(ero.EPCPay) +// } -func (a AuthInfo) IsManagement() bool { - if a.Employee_Position_Code == nil { - return false - } - return *a.Employee_Position_Code == string(ero.EPCMan) -} +// func (a AuthInfo) IsManagement() bool { +// if a.Employee_Position_Code == nil { +// return false +// } +// return *a.Employee_Position_Code == string(ero.EPCMan) +// } func (a AuthInfo) IsSpecialistIntern() bool { if a.Intern_Position_Code == nil { diff --git a/internal/use-case/main-use-case/authentication/helper.go b/internal/use-case/main-use-case/authentication/helper.go index c0a3bd0f..7af3afa5 100644 --- a/internal/use-case/main-use-case/authentication/helper.go +++ b/internal/use-case/main-use-case/authentication/helper.go @@ -226,6 +226,10 @@ func populateRoles(user *eu.User, input eu.LoginDto, atClaims jwt.MapClaims, out outputData["doctor_code"] = doctor.Code // specialist + if doctor.Unit_Code != nil { + atClaims["unit_code"] = doctor.Unit_Code + outputData["unit_code"] = doctor.Unit_Code + } if doctor.Specialist_Code != nil { atClaims["specialist_code"] = doctor.Specialist_Code outputData["specialist_code"] = doctor.Specialist_Code diff --git a/internal/use-case/main-use-case/device-order-item/lib.go b/internal/use-case/main-use-case/device-order-item/lib.go index 70ccc5d7..84838096 100644 --- a/internal/use-case/main-use-case/device-order-item/lib.go +++ b/internal/use-case/main-use-case/device-order-item/lib.go @@ -52,8 +52,8 @@ func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.De Scopes(gh.Preload(input.Includes)). Scopes(gh.Filter(input.FilterDto)). Count(&count). - Scopes(gh.Paginate(input, &pagination)). - Order("\"CreatedAt\" DESC") + Scopes(gh.Sort(input.Sort)). + Scopes(gh.Paginate(input, &pagination)) if err := tx.Find(&data).Error; err != nil { if err == gorm.ErrRecordNotFound { diff --git a/internal/use-case/main-use-case/mcu-order/case.go b/internal/use-case/main-use-case/mcu-order/case.go index 38f13088..6d7c4fed 100644 --- a/internal/use-case/main-use-case/mcu-order/case.go +++ b/internal/use-case/main-use-case/mcu-order/case.go @@ -324,6 +324,65 @@ func Delete(input e.DeleteDto) (*d.Data, error) { } +func Submit(input e.ReadDetailDto) (*d.Data, error) { + var data *e.McuOrder + var err error + + event := pl.Event{ + Feature: "Process", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "process") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + data, err = ReadDetailData(input, &event, tx) + if err != nil { + return err + } + + if data.IsNotNew() { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-state-mismatch", + Detail: "prescription is not in new state", + Raw: errors.New("prescription is not in new state"), + } + return pl.SetLogError(&event, input) + } + + data.Status_Code = erc.DSCSubmited + if err := tx.Save(&data).Error; err != nil { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-update-fail", + Detail: "Database update failed", + Raw: err, + } + return pl.SetLogError(&event, input) + } + + pl.SetLogInfo(&event, nil, "complete") + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "submited", + }, + Data: data.ToResponse(), + }, nil + +} + func Complete(input e.ReadDetailDto) (*d.Data, error) { var data *e.McuOrder var err error