From 86a073164da8f828303bc59f6a78d6d62d37f3fd Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Wed, 17 Sep 2025 11:47:03 +0700 Subject: [PATCH 1/7] wip encounter + medication --- .../main-entities/medication-item/dto.go | 8 +++ .../domain/main-entities/medication/dto.go | 7 +- .../main-entities/prescription-item/dto.go | 4 ++ .../domain/main-entities/prescription/dto.go | 36 ++++++---- .../main-handler/medication/handler.go | 8 +-- .../main-handler/prescription/handler.go | 6 +- .../main-use-case/encounter/helper.go | 51 ++++++++++++++ .../use-case/main-use-case/medication/case.go | 4 ++ .../main-use-case/medication/helper.go | 69 ++++++++++--------- .../use-case/main-use-case/medication/lib.go | 10 ++- .../main-use-case/prescription-item/helper.go | 1 + .../main-use-case/prescription/helper.go | 1 + .../main-use-case/prescription/lib.go | 10 ++- pkg/use-case-helper/use-case-helper.go | 6 ++ 14 files changed, 164 insertions(+), 57 deletions(-) diff --git a/internal/domain/main-entities/medication-item/dto.go b/internal/domain/main-entities/medication-item/dto.go index 00edb045..ce2f9193 100644 --- a/internal/domain/main-entities/medication-item/dto.go +++ b/internal/domain/main-entities/medication-item/dto.go @@ -17,6 +17,8 @@ type CreateDto struct { Interval uint8 `json:"interval"` IntervalUnit_Code erc.TimeUnitCode `json:"intervalUnit_code"` IsRedeemed bool `json:"isRedeemed"` + Quantity float64 `json:"quantity"` + Note *string `json:"note" gorm:"size:1024"` } type ReadListDto struct { @@ -34,6 +36,8 @@ type FilterDto struct { Interval uint8 `json:"interval"` IntervalUnit_Code erc.TimeUnitCode `json:"intervalUnit_code"` IsRedeemed bool `json:"isRedeemed"` + Quantity float64 `json:"quantity"` + Note *string `json:"note" gorm:"size:1024"` Page int `json:"page"` PageSize int `json:"page_size"` @@ -71,6 +75,8 @@ type ResponseDto struct { Interval uint8 `json:"interval"` IntervalUnit_Code erc.TimeUnitCode `json:"intervalUnit_code"` IsRedeemed bool `json:"isRedeemed"` + Quantity float64 `json:"quantity"` + Note *string `json:"note" gorm:"size:1024"` } func (d MedicationItem) ToResponse() ResponseDto { @@ -86,6 +92,8 @@ func (d MedicationItem) ToResponse() ResponseDto { Interval: d.Interval, IntervalUnit_Code: d.IntervalUnit_Code, IsRedeemed: d.IsRedeemed, + Quantity: d.Quantity, + Note: d.Note, } resp.Main = d.Main return resp diff --git a/internal/domain/main-entities/medication/dto.go b/internal/domain/main-entities/medication/dto.go index 7242b9d5..86c77b2f 100644 --- a/internal/domain/main-entities/medication/dto.go +++ b/internal/domain/main-entities/medication/dto.go @@ -35,18 +35,19 @@ type FilterDto struct { NoPagination int `json:"no_pagination"` } type ReadDetailDto struct { - Id uint16 `json:"id"` + Id uint `json:"id"` + Encounter_Id *uint `json:"encounter_id"` pa.AuthInfo } type UpdateDto struct { - Id uint16 `json:"id"` + Id uint `json:"id"` CreateDto } type DeleteDto struct { - Id uint16 `json:"id"` + Id uint `json:"id"` } type MetaDto struct { diff --git a/internal/domain/main-entities/prescription-item/dto.go b/internal/domain/main-entities/prescription-item/dto.go index f23a6610..f46b8bc9 100644 --- a/internal/domain/main-entities/prescription-item/dto.go +++ b/internal/domain/main-entities/prescription-item/dto.go @@ -16,6 +16,7 @@ type CreateDto struct { Usage float64 `json:"usage"` Interval uint8 `json:"interval"` IntervalUnit_Code erc.TimeUnitCode `json:"intervalUnit_code"` + Quantity float64 `json:"quantity"` } type ReadListDto struct { @@ -32,6 +33,7 @@ type FilterDto struct { Usage float64 `json:"usage"` Interval uint8 `json:"interval"` IntervalUnit_Code erc.TimeUnitCode `json:"intervalUnit_code"` + Quantity float64 `json:"quantity"` Page int `json:"page"` PageSize int `json:"page_size"` @@ -68,6 +70,7 @@ type ResponseDto struct { Usage float64 `json:"usage"` Interval uint8 `json:"interval"` IntervalUnit_Code erc.TimeUnitCode `json:"intervalUnit_code"` + Quantity float64 `json:"quantity"` } func (d PrescriptionItem) ToResponse() ResponseDto { @@ -82,6 +85,7 @@ func (d PrescriptionItem) ToResponse() ResponseDto { Usage: d.Usage, Interval: d.Interval, IntervalUnit_Code: d.IntervalUnit_Code, + Quantity: d.Quantity, } resp.Main = d.Main return resp diff --git a/internal/domain/main-entities/prescription/dto.go b/internal/domain/main-entities/prescription/dto.go index b87d6f12..e693a1c2 100644 --- a/internal/domain/main-entities/prescription/dto.go +++ b/internal/domain/main-entities/prescription/dto.go @@ -4,13 +4,17 @@ 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" + "time" + + erc "simrs-vx/internal/domain/references/common" ) type CreateDto struct { - Encounter_Id *uint `json:"encounter_id"` - Doctor_Id *uint `json:"doctor_id"` - IssuedAt *time.Time `json:"issuedAt"` + Encounter_Id *uint `json:"encounter_id"` + Doctor_Id *uint `json:"doctor_id"` + IssuedAt *time.Time `json:"issuedAt"` + Status_Code *erc.DataStatusCode `json:"status_code"` } type ReadListDto struct { @@ -20,25 +24,27 @@ type ReadListDto struct { } type FilterDto struct { - Encounter_Id *uint `json:"encounter_id"` - Doctor_Id *uint `json:"doctor_id"` - IssuedAt *time.Time `json:"issuedAt"` + Encounter_Id *uint `json:"encounter_id"` + Doctor_Id *uint `json:"doctor_id"` + IssuedAt *time.Time `json:"issuedAt"` + Status_Code *erc.DataStatusCode `json:"status_code"` Page int `json:"page"` PageSize int `json:"page_size"` NoPagination int `json:"no_pagination"` } type ReadDetailDto struct { - Id uint16 `json:"id"` + Id uint `json:"id"` + Encounter_Id *uint `json:"encounter_id"` } type UpdateDto struct { - Id uint16 `json:"id"` + Id uint `json:"id"` CreateDto } type DeleteDto struct { - Id uint16 `json:"id"` + Id uint `json:"id"` } type MetaDto struct { @@ -49,11 +55,12 @@ type MetaDto struct { type ResponseDto struct { ecore.Main - Encounter_Id *uint `json:"encounter_id"` - Encounter *ee.Encounter `json:"encounter,omitempty"` - Doctor_Id *uint `json:"doctor_id"` - Doctor *ed.Doctor `json:"doctor,omitempty"` - IssuedAt *time.Time `json:"issuedAt"` + Encounter_Id *uint `json:"encounter_id"` + Encounter *ee.Encounter `json:"encounter,omitempty"` + Doctor_Id *uint `json:"doctor_id"` + Doctor *ed.Doctor `json:"doctor,omitempty"` + IssuedAt *time.Time `json:"issuedAt"` + Status_Code *erc.DataStatusCode `json:"status_code"` } func (d Prescription) ToResponse() ResponseDto { @@ -63,6 +70,7 @@ func (d Prescription) ToResponse() ResponseDto { Doctor_Id: d.Doctor_Id, Doctor: d.Doctor, IssuedAt: d.IssuedAt, + Status_Code: d.Status_Code, } resp.Main = d.Main return resp diff --git a/internal/interface/main-handler/medication/handler.go b/internal/interface/main-handler/medication/handler.go index b847eb5b..5037f2eb 100644 --- a/internal/interface/main-handler/medication/handler.go +++ b/internal/interface/main-handler/medication/handler.go @@ -40,7 +40,7 @@ func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { return } dto := e.ReadDetailDto{} - dto.Id = uint16(id) + dto.Id = uint(id) res, err := u.ReadDetail(dto) rw.DataResponse(w, res, err) } @@ -55,7 +55,7 @@ func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { return } - dto.Id = uint16(id) + dto.Id = uint(id) res, err := u.Update(dto) rw.DataResponse(w, res, err) } @@ -67,7 +67,7 @@ func (obj myBase) Delete(w http.ResponseWriter, r *http.Request) { } dto := e.DeleteDto{} - dto.Id = uint16(id) + dto.Id = uint(id) res, err := u.Delete(dto) rw.DataResponse(w, res, err) } @@ -88,7 +88,7 @@ func (obj myBase) Complete(w http.ResponseWriter, r *http.Request) { return } dto.AuthInfo = *authInfo - dto.Id = uint16(id) + dto.Id = uint(id) res, err := u.Complete(dto) rw.DataResponse(w, res, err) } diff --git a/internal/interface/main-handler/prescription/handler.go b/internal/interface/main-handler/prescription/handler.go index 25ee9469..1ac30d97 100644 --- a/internal/interface/main-handler/prescription/handler.go +++ b/internal/interface/main-handler/prescription/handler.go @@ -38,7 +38,7 @@ func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { return } dto := e.ReadDetailDto{} - dto.Id = uint16(id) + dto.Id = uint(id) res, err := u.ReadDetail(dto) rw.DataResponse(w, res, err) } @@ -53,7 +53,7 @@ func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { return } - dto.Id = uint16(id) + dto.Id = uint(id) res, err := u.Update(dto) rw.DataResponse(w, res, err) } @@ -65,7 +65,7 @@ func (obj myBase) Delete(w http.ResponseWriter, r *http.Request) { } dto := e.DeleteDto{} - dto.Id = uint16(id) + dto.Id = uint(id) res, err := u.Delete(dto) rw.DataResponse(w, res, err) } diff --git a/internal/use-case/main-use-case/encounter/helper.go b/internal/use-case/main-use-case/encounter/helper.go index b40783b7..94f196bb 100644 --- a/internal/use-case/main-use-case/encounter/helper.go +++ b/internal/use-case/main-use-case/encounter/helper.go @@ -8,7 +8,17 @@ import ( "errors" e "simrs-vx/internal/domain/main-entities/encounter" es "simrs-vx/internal/domain/main-entities/soapi" + + // ep "simrs-vx/internal/domain/main-entities/prescription" + // epi "simrs-vx/internal/domain/main-entities/prescription-item" + // em "simrs-vx/internal/domain/main-entities/medication" + + // up "simrs-vx/internal/use-case/main-use-case/prescription" + // upi "simrs-vx/internal/use-case/main-use-case/prescription-item" + // um "simrs-vx/internal/use-case/main-use-case/medication" + pl "simrs-vx/pkg/logger" + // pu "simrs-vx/pkg/use-case-helper" erc "simrs-vx/internal/domain/references/common" ero "simrs-vx/internal/domain/references/organization" @@ -98,3 +108,44 @@ func checkSoapiByDocExists(encounter_id uint, event *pl.Event, tx *gorm.DB) erro } return pl.SetLogError(event, nil) } + +// func createMedication(encounter_id uint, event *pl.Event, tx *gorm.DB) error { +// pl.SetLogInfo(event, nil, "started", "createMedication") + +// prescription, err := up.ReadDetailData(ep.ReadDetailDto{Id: encounter_id}, event, tx) +// if err != nil { +// return err +// } + +// prescriptionItem, _, err := upi.ReadListData(epi.ReadListDto{FilterDto: epi.FilterDto{Prescription_Id: &prescription.Id}}, event, tx) +// if err != nil { +// return err +// } + +// if len(prescriptionItem) == 0 { +// return nil +// } + +// medicationCreate := em.CreateDto{ +// Encounter_Id: &encounter_id, +// IssuedAt: pu.GetTimeNow(), +// } +// medication, err := um.CreateData(medicationCreate, event, tx) +// if err != nil { +// return err +// } + +// for _, prescriptionItem := range prescriptionItem { +// if prescriptionItem.IsMix { +// continue +// } +// // medication, err := um.ReadDetailData(e.ReadDetailDto{Id: prescriptionItem.Medication_Id}, event, tx) +// // if err != nil { +// // return err +// // } +// // if medication.IsCompleted() { +// // continue +// // } +// // createMedicationItemDist(medication.Id, event, tx) +// } +// } diff --git a/internal/use-case/main-use-case/medication/case.go b/internal/use-case/main-use-case/medication/case.go index ec096f29..c4a97373 100644 --- a/internal/use-case/main-use-case/medication/case.go +++ b/internal/use-case/main-use-case/medication/case.go @@ -332,6 +332,10 @@ func Complete(input e.ReadDetailDto) (*d.Data, error) { return pl.SetLogError(&event, input) } + if err := createMedicationItemDist(&data.Id, &event, tx); err != nil { + return err + } + pl.SetLogInfo(&event, nil, "complete") return nil }) diff --git a/internal/use-case/main-use-case/medication/helper.go b/internal/use-case/main-use-case/medication/helper.go index 52676431..374eaf1f 100644 --- a/internal/use-case/main-use-case/medication/helper.go +++ b/internal/use-case/main-use-case/medication/helper.go @@ -6,10 +6,17 @@ package medication import ( e "simrs-vx/internal/domain/main-entities/medication" - // emi "simrs-vx/internal/domain/main-entities/medication-item" - // emid "simrs-vx/internal/domain/main-entities/medication-item-dist" - // umi "simrs-vx/internal/use-case/main-use-case/medication-item" - // umid "simrs-vx/internal/use-case/main-use-case/medication-item-dist" + emi "simrs-vx/internal/domain/main-entities/medication-item" + emid "simrs-vx/internal/domain/main-entities/medication-item-dist" + umi "simrs-vx/internal/use-case/main-use-case/medication-item" + umid "simrs-vx/internal/use-case/main-use-case/medication-item-dist" + + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + dg "github.com/karincake/apem/db-gorm-pg" + + "gorm.io/gorm" ) func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Medication) { @@ -27,32 +34,32 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Medication) { data.Status_Code = inputSrc.Status_Code } -// func createMedicationItemDist(medication_id *uint, event *pl.Event, dbx ...*gorm.DB) error { -// pl.SetLogInfo(event, nil, "started", "createMedicationItemDist") -// var tx *gorm.DB -// if len(dbx) > 0 { -// tx = dbx[0] -// } else { -// tx = dg.I -// } +func createMedicationItemDist(medication_id *uint, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, nil, "started", "createMedicationItemDist") + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } -// filterMI := emi.ReadListDto{FilterDto: emi.FilterDto{Medication_Id: medication_id, IsRedeemed: true}} -// medicationItemList, _, err := umi.ReadListData(filterMI, event, tx) -// if err != nil { -// return err -// } -// for _, medicationItem := range medicationItemList { -// midCreate := emid.CreateDto{ -// MedicationItem_Id: &medicationItem.Id, -// DateTime: medicationItem.MedicationItem.DateTime, -// Remain: medicationItem.MedicationItem.Remain, -// Nurse_Id: medicationItem.MedicationItem.Nurse_Id, -// } -// if err := umid.Create(midCreate); err != nil { -// return err -// } -// } + filterMI := emi.ReadListDto{FilterDto: emi.FilterDto{Medication_Id: medication_id, IsRedeemed: true}} + medicationItemList, _, err := umi.ReadListData(filterMI, event, tx) + if err != nil { + return err + } + // Nurse id isn't set here because it will be set when medItemDist is consumed by the nurse who is logged in and performing the consume action, so it isn't needed here. + for _, medicationItem := range medicationItemList { + midCreate := emid.CreateDto{ + MedicationItem_Id: &medicationItem.Id, + DateTime: pu.GetTimeNow(), + Remain: medicationItem.Quantity, + } + if _, err := umid.CreateData(midCreate, event, tx); err != nil { + return err + } + } -// pl.SetLogInfo(event, nil, "complete") -// return nil -// } + pl.SetLogInfo(event, nil, "complete") + return nil +} diff --git a/internal/use-case/main-use-case/medication/lib.go b/internal/use-case/main-use-case/medication/lib.go index 95488f11..227eb27b 100644 --- a/internal/use-case/main-use-case/medication/lib.go +++ b/internal/use-case/main-use-case/medication/lib.go @@ -96,7 +96,15 @@ func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e tx = dg.I } - if err := tx.First(&data, input.Id).Error; err != nil { + if input.Encounter_Id != nil { + tx = tx.Where("\"Encounter_Id\" = ?", *input.Encounter_Id) + } + + if input.Id != 0 { + tx = tx.Where("\"Id\" = ?", input.Id) + } + + if err := tx.First(&data).Error; err != nil { if processedErr := pu.HandleReadError(err, event, source, input.Id, data); processedErr != nil { return nil, processedErr } diff --git a/internal/use-case/main-use-case/prescription-item/helper.go b/internal/use-case/main-use-case/prescription-item/helper.go index 000522d5..47efc3f9 100644 --- a/internal/use-case/main-use-case/prescription-item/helper.go +++ b/internal/use-case/main-use-case/prescription-item/helper.go @@ -24,4 +24,5 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.PrescriptionItem) { data.Usage = inputSrc.Usage data.Interval = inputSrc.Interval data.IntervalUnit_Code = inputSrc.IntervalUnit_Code + data.Quantity = inputSrc.Quantity } diff --git a/internal/use-case/main-use-case/prescription/helper.go b/internal/use-case/main-use-case/prescription/helper.go index 768d11bd..13f8f2e6 100644 --- a/internal/use-case/main-use-case/prescription/helper.go +++ b/internal/use-case/main-use-case/prescription/helper.go @@ -20,4 +20,5 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Prescription) { data.Encounter_Id = inputSrc.Encounter_Id data.Doctor_Id = inputSrc.Doctor_Id data.IssuedAt = inputSrc.IssuedAt + data.Status_Code = inputSrc.Status_Code } diff --git a/internal/use-case/main-use-case/prescription/lib.go b/internal/use-case/main-use-case/prescription/lib.go index bf1fe36b..bff59916 100644 --- a/internal/use-case/main-use-case/prescription/lib.go +++ b/internal/use-case/main-use-case/prescription/lib.go @@ -96,7 +96,15 @@ func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e tx = dg.I } - if err := tx.First(&data, input.Id).Error; err != nil { + if input.Encounter_Id != nil { + tx = tx.Where("\"Encounter_Id\" = ?", *input.Encounter_Id) + } + + if input.Id != 0 { + tx = tx.Where("\"Id\" = ?", input.Id) + } + + if err := tx.First(&data).Error; err != nil { if processedErr := pu.HandleReadError(err, event, source, input.Id, data); processedErr != nil { return nil, processedErr } diff --git a/pkg/use-case-helper/use-case-helper.go b/pkg/use-case-helper/use-case-helper.go index a16a9ba2..9fd8351d 100644 --- a/pkg/use-case-helper/use-case-helper.go +++ b/pkg/use-case-helper/use-case-helper.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" "strings" + "time" pl "simrs-vx/pkg/logger" @@ -126,3 +127,8 @@ func kebabToPascal(input string) string { } return strings.Join(parts, "") } + +func GetTimeNow() *time.Time { + tmp := time.Now() + return &tmp +} From 5a5856ccb960c00eb004e216ee06990cc708e519 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Wed, 17 Sep 2025 16:35:07 +0700 Subject: [PATCH 2/7] waiting for migration --- .../main-handler/encounter/handler.go | 5 + .../main-handler/medication/handler.go | 3 - .../use-case/main-use-case/encounter/case.go | 4 + .../main-use-case/encounter/helper.go | 140 ++++++++++++------ .../main-use-case/medication/helper.go | 3 +- .../main-use-case/medicine-mix/lib.go | 4 + internal/use-case/main-use-case/nurse/lib.go | 6 +- .../use-case/main-use-case/pharmacist/lib.go | 6 +- .../main-use-case/prescription-item/lib.go | 4 + 9 files changed, 123 insertions(+), 52 deletions(-) diff --git a/internal/interface/main-handler/encounter/handler.go b/internal/interface/main-handler/encounter/handler.go index c2634a91..7484b302 100644 --- a/internal/interface/main-handler/encounter/handler.go +++ b/internal/interface/main-handler/encounter/handler.go @@ -72,9 +72,14 @@ func (obj myBase) Delete(w http.ResponseWriter, r *http.Request) { func (obj myBase) CheckOut(w http.ResponseWriter, r *http.Request) { dto := e.DischargeDto{} + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { return } + dto.Id = uint(id) res, err := u.CheckOut(dto) rw.DataResponse(w, res, err) } diff --git a/internal/interface/main-handler/medication/handler.go b/internal/interface/main-handler/medication/handler.go index 5037f2eb..272eae56 100644 --- a/internal/interface/main-handler/medication/handler.go +++ b/internal/interface/main-handler/medication/handler.go @@ -84,9 +84,6 @@ func (obj myBase) Complete(w http.ResponseWriter, r *http.Request) { } dto := e.ReadDetailDto{} - if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { - return - } dto.AuthInfo = *authInfo dto.Id = uint(id) res, err := u.Complete(dto) diff --git a/internal/use-case/main-use-case/encounter/case.go b/internal/use-case/main-use-case/encounter/case.go index ed8fa816..437e6b55 100644 --- a/internal/use-case/main-use-case/encounter/case.go +++ b/internal/use-case/main-use-case/encounter/case.go @@ -379,6 +379,10 @@ func CheckOut(input e.DischargeDto) (*d.Data, error) { return err } + if err := createMedication(data.Id, &event, tx); err != nil { + return err + } + pl.SetLogInfo(&event, nil, "complete") return nil diff --git a/internal/use-case/main-use-case/encounter/helper.go b/internal/use-case/main-use-case/encounter/helper.go index 94f196bb..5bf73d14 100644 --- a/internal/use-case/main-use-case/encounter/helper.go +++ b/internal/use-case/main-use-case/encounter/helper.go @@ -9,16 +9,22 @@ import ( e "simrs-vx/internal/domain/main-entities/encounter" es "simrs-vx/internal/domain/main-entities/soapi" - // ep "simrs-vx/internal/domain/main-entities/prescription" - // epi "simrs-vx/internal/domain/main-entities/prescription-item" - // em "simrs-vx/internal/domain/main-entities/medication" + em "simrs-vx/internal/domain/main-entities/medication" + emei "simrs-vx/internal/domain/main-entities/medication-item" + emi "simrs-vx/internal/domain/main-entities/medicine-mix" + emmi "simrs-vx/internal/domain/main-entities/medicine-mix-item" + ep "simrs-vx/internal/domain/main-entities/prescription" + epi "simrs-vx/internal/domain/main-entities/prescription-item" - // up "simrs-vx/internal/use-case/main-use-case/prescription" - // upi "simrs-vx/internal/use-case/main-use-case/prescription-item" - // um "simrs-vx/internal/use-case/main-use-case/medication" + um "simrs-vx/internal/use-case/main-use-case/medication" + umei "simrs-vx/internal/use-case/main-use-case/medication-item" + umi "simrs-vx/internal/use-case/main-use-case/medicine-mix" + ummi "simrs-vx/internal/use-case/main-use-case/medicine-mix-item" + up "simrs-vx/internal/use-case/main-use-case/prescription" + upi "simrs-vx/internal/use-case/main-use-case/prescription-item" pl "simrs-vx/pkg/logger" - // pu "simrs-vx/pkg/use-case-helper" + pu "simrs-vx/pkg/use-case-helper" erc "simrs-vx/internal/domain/references/common" ero "simrs-vx/internal/domain/references/organization" @@ -109,43 +115,93 @@ func checkSoapiByDocExists(encounter_id uint, event *pl.Event, tx *gorm.DB) erro return pl.SetLogError(event, nil) } -// func createMedication(encounter_id uint, event *pl.Event, tx *gorm.DB) error { -// pl.SetLogInfo(event, nil, "started", "createMedication") +func createMedication(encounter_id uint, event *pl.Event, tx *gorm.DB) error { + pl.SetLogInfo(event, nil, "started", "createMedication") -// prescription, err := up.ReadDetailData(ep.ReadDetailDto{Id: encounter_id}, event, tx) -// if err != nil { -// return err -// } + prescription, err := up.ReadDetailData(ep.ReadDetailDto{Encounter_Id: &encounter_id}, event, tx) + if err != nil { + return err + } -// prescriptionItem, _, err := upi.ReadListData(epi.ReadListDto{FilterDto: epi.FilterDto{Prescription_Id: &prescription.Id}}, event, tx) -// if err != nil { -// return err -// } + prescriptionItem, _, err := upi.ReadListData(epi.ReadListDto{FilterDto: epi.FilterDto{Prescription_Id: &prescription.Id}}, event, tx) + if err != nil { + return err + } -// if len(prescriptionItem) == 0 { -// return nil -// } + if len(prescriptionItem) == 0 { + return nil + } -// medicationCreate := em.CreateDto{ -// Encounter_Id: &encounter_id, -// IssuedAt: pu.GetTimeNow(), -// } -// medication, err := um.CreateData(medicationCreate, event, tx) -// if err != nil { -// return err -// } + medicationCreate := em.CreateDto{ + Encounter_Id: &encounter_id, + IssuedAt: pu.GetTimeNow(), + } + medication, err := um.CreateData(medicationCreate, event, tx) + if err != nil { + return err + } -// for _, prescriptionItem := range prescriptionItem { -// if prescriptionItem.IsMix { -// continue -// } -// // medication, err := um.ReadDetailData(e.ReadDetailDto{Id: prescriptionItem.Medication_Id}, event, tx) -// // if err != nil { -// // return err -// // } -// // if medication.IsCompleted() { -// // continue -// // } -// // createMedicationItemDist(medication.Id, event, tx) -// } -// } + for _, prescriptionItem := range prescriptionItem { + if prescriptionItem.IsMix { + medMix_id, err := createMedicineMixAndItem(*prescriptionItem.MedicineMix, event, tx) + if err != nil { + return err + } + prescriptionItem.MedicineMix_Id = medMix_id + } + err := createMedicationItem(medication.Id, prescriptionItem, event, tx) + if err != nil { + return err + } + } + return nil +} + +func createMedicineMixAndItem(input emi.MedicineMix, event *pl.Event, tx *gorm.DB) (*uint, error) { + pl.SetLogInfo(event, nil, "started", "createMedicineMix") + + medicineMixCreate := emi.CreateDto{ + Name: input.Name, + } + medicineMix, err := umi.CreateData(medicineMixCreate, event, tx) + if err != nil { + return nil, err + } + + // recreate medicineMixItem with new medicineMix_id to keep medMixItem remain the same for prescriptionItem that is created + for _, medicineMixItem := range input.MixItems { + medicineMixItemCreate := emmi.CreateDto{ + MedicineMix_Id: &medicineMix.Id, + Medicine_Id: medicineMixItem.Medicine_Id, + Dose: medicineMixItem.Dose, + } + _, err := ummi.CreateData(medicineMixItemCreate, event, tx) + if err != nil { + return nil, err + } + + } + return &medicineMix.Id, nil +} + +func createMedicationItem(medication_id uint, input epi.PrescriptionItem, event *pl.Event, tx *gorm.DB) error { + pl.SetLogInfo(event, nil, "started", "createMedicationItem") + + medicationItemCreate := emei.CreateDto{ + Medication_Id: &medication_id, + IsMix: input.IsMix, + Medicine_Id: input.Medicine_Id, + MedicineMix_Id: input.MedicineMix_Id, + Usage: input.Usage, + Interval: input.Interval, + IntervalUnit_Code: input.IntervalUnit_Code, + Quantity: input.Quantity, + } + + _, err := umei.CreateData(medicationItemCreate, event, tx) + if err != nil { + return err + } + + return nil +} diff --git a/internal/use-case/main-use-case/medication/helper.go b/internal/use-case/main-use-case/medication/helper.go index 374eaf1f..63290cb1 100644 --- a/internal/use-case/main-use-case/medication/helper.go +++ b/internal/use-case/main-use-case/medication/helper.go @@ -43,7 +43,7 @@ func createMedicationItemDist(medication_id *uint, event *pl.Event, dbx ...*gorm tx = dg.I } - filterMI := emi.ReadListDto{FilterDto: emi.FilterDto{Medication_Id: medication_id, IsRedeemed: true}} + filterMI := emi.ReadListDto{FilterDto: emi.FilterDto{Medication_Id: medication_id, IsRedeemed: true}, Preloads: []string{"MedicineMix"}} medicationItemList, _, err := umi.ReadListData(filterMI, event, tx) if err != nil { return err @@ -58,6 +58,7 @@ func createMedicationItemDist(medication_id *uint, event *pl.Event, dbx ...*gorm if _, err := umid.CreateData(midCreate, event, tx); err != nil { return err } + } pl.SetLogInfo(event, nil, "complete") diff --git a/internal/use-case/main-use-case/medicine-mix/lib.go b/internal/use-case/main-use-case/medicine-mix/lib.go index 6a2cf257..162399db 100644 --- a/internal/use-case/main-use-case/medicine-mix/lib.go +++ b/internal/use-case/main-use-case/medicine-mix/lib.go @@ -51,6 +51,8 @@ func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.Me tx = dg.I } + tx = tx.Preload("MixItems") + tx = tx. Model(&e.MedicineMix{}). Scopes(gh.Filter(input)). @@ -90,6 +92,8 @@ func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e tx = dg.I } + tx = tx.Preload("MixItems") + if err := tx.First(&data, input.Id).Error; err != nil { if processedErr := pu.HandleReadError(err, event, source, input.Id, data); processedErr != nil { return nil, processedErr diff --git a/internal/use-case/main-use-case/nurse/lib.go b/internal/use-case/main-use-case/nurse/lib.go index 468b41c2..adbd1b76 100644 --- a/internal/use-case/main-use-case/nurse/lib.go +++ b/internal/use-case/main-use-case/nurse/lib.go @@ -172,9 +172,9 @@ func GetIdByUserId(user_id *uint, event *pl.Event, dbx ...*gorm.DB) (*uint, erro var nurse_id uint err := tx.Model(&e.Nurse{}). - Select("Nurse.Id as nurse_id"). - Joins("JOIN Employee e ON e.Id = Nurse.Employee_Id"). - Where("e.User_Id = ?", user_id). + Select("\"Nurse\".\"Id\" as nurse_id"). + Joins("JOIN \"Employee\" AS e ON e.\"Id\" = \"Nurse\".\"Employee_Id\""). + Where("e.\"User_Id\" = ?", user_id). Scan(&nurse_id).Error if err != nil { diff --git a/internal/use-case/main-use-case/pharmacist/lib.go b/internal/use-case/main-use-case/pharmacist/lib.go index e9478d70..0038591a 100644 --- a/internal/use-case/main-use-case/pharmacist/lib.go +++ b/internal/use-case/main-use-case/pharmacist/lib.go @@ -172,9 +172,9 @@ func GetIdByUserId(user_id *uint, event *pl.Event, dbx ...*gorm.DB) (*uint, erro var pharmacist_id uint err := tx.Model(&e.Pharmacist{}). - Select("Pharmacist.Id as pharmacist_id"). - Joins("JOIN Employee e ON e.Id = Pharmacist.Employee_Id"). - Where("e.User_Id = ?", user_id). + Select("\"Pharmacist\".\"Id\" as pharmacist_id"). + Joins("JOIN \"Employee\" as e ON e.\"Id\" = \"Pharmacist\".\"Employee_Id\""). + Where("e.\"User_Id\" = ?", user_id). Scan(&pharmacist_id).Error if err != nil { diff --git a/internal/use-case/main-use-case/prescription-item/lib.go b/internal/use-case/main-use-case/prescription-item/lib.go index 800096fd..70913046 100644 --- a/internal/use-case/main-use-case/prescription-item/lib.go +++ b/internal/use-case/main-use-case/prescription-item/lib.go @@ -51,6 +51,8 @@ func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.Pr tx = dg.I } + tx = tx.Preload("MedicineMix").Preload("MedicineMix.MixItems") + if len(input.Preloads) > 0 { for _, preload := range input.Preloads { tx = tx.Preload(preload) @@ -96,6 +98,8 @@ func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e tx = dg.I } + tx = tx.Preload("MedicineMix").Preload("MedicineMix.MixItems") + if err := tx.First(&data, input.Id).Error; err != nil { if processedErr := pu.HandleReadError(err, event, source, input.Id, data); processedErr != nil { return nil, processedErr From 3b753cb972461ba87b96385e76b60cb98c276e7f Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Wed, 17 Sep 2025 16:38:35 +0700 Subject: [PATCH 3/7] feat (medicine-mix-item): add note --- .../main-entities/medicine-mix-item/dto.go | 16 ++++++++++------ .../main-use-case/medicine-mix-item/helper.go | 1 + 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/internal/domain/main-entities/medicine-mix-item/dto.go b/internal/domain/main-entities/medicine-mix-item/dto.go index 1be930e1..b00114c5 100644 --- a/internal/domain/main-entities/medicine-mix-item/dto.go +++ b/internal/domain/main-entities/medicine-mix-item/dto.go @@ -6,9 +6,10 @@ import ( ) type CreateDto struct { - MedicineMix_Id *uint `json:"medicineMix_id"` - Medicine_Id *uint `json:"medicine_id"` - Dose *uint8 `json:"dose"` + MedicineMix_Id *uint `json:"medicineMix_id"` + Medicine_Id *uint `json:"medicine_id"` + Dose *uint8 `json:"dose"` + Note *string `json:"note" gom:"size:1024"` } type ReadListDto struct { @@ -18,9 +19,10 @@ type ReadListDto struct { } type FilterDto struct { - MedicineMix_Id *uint `json:"medicineMix_id"` - Medicine_Id *uint `json:"medicine_id"` - Dose *uint8 `json:"dose"` + MedicineMix_Id *uint `json:"medicineMix_id"` + Medicine_Id *uint `json:"medicine_id"` + Dose *uint8 `json:"dose"` + Note *string `json:"note" gom:"size:1024"` Page int `json:"page"` PageSize int `json:"page_size"` @@ -52,6 +54,7 @@ type ResponseDto struct { Medicine_Id *uint `json:"medicine_id"` Medicine *em.Medicine `json:"medicine,omitempty"` Dose *uint8 `json:"dose"` + Note *string `json:"note" gom:"size:1024"` } func (d MedicineMixItem) ToResponse() ResponseDto { @@ -60,6 +63,7 @@ func (d MedicineMixItem) ToResponse() ResponseDto { Medicine_Id: d.Medicine_Id, Medicine: d.Medicine, Dose: d.Dose, + Note: d.Note, } resp.Main = d.Main return resp diff --git a/internal/use-case/main-use-case/medicine-mix-item/helper.go b/internal/use-case/main-use-case/medicine-mix-item/helper.go index d4ac8020..0a64f30c 100644 --- a/internal/use-case/main-use-case/medicine-mix-item/helper.go +++ b/internal/use-case/main-use-case/medicine-mix-item/helper.go @@ -20,4 +20,5 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.MedicineMixItem) { data.MedicineMix_Id = inputSrc.MedicineMix_Id data.Medicine_Id = inputSrc.Medicine_Id data.Dose = inputSrc.Dose + data.Note = inputSrc.Note } From e666a421f45c9626e8de4478fc39bc8608e29831 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Thu, 18 Sep 2025 14:47:11 +0700 Subject: [PATCH 4/7] feat (mcu-order): adjust mcu dto and helper --- .../main-entities/mcu-order-item/dto.go | 27 +++++----- .../domain/main-entities/mcu-order/dto.go | 54 +++++++++++++------ .../main-entities/person-relative/dto.go | 15 +++++- .../use-case/main-use-case/device/helper.go | 1 + .../use-case/main-use-case/material/helper.go | 1 + .../main-use-case/mcu-order/helper.go | 5 ++ .../main-use-case/person-relative/helper.go | 1 + 7 files changed, 75 insertions(+), 29 deletions(-) diff --git a/internal/domain/main-entities/mcu-order-item/dto.go b/internal/domain/main-entities/mcu-order-item/dto.go index 91ce3bdc..e5b82cb9 100644 --- a/internal/domain/main-entities/mcu-order-item/dto.go +++ b/internal/domain/main-entities/mcu-order-item/dto.go @@ -5,6 +5,7 @@ import ( emo "simrs-vx/internal/domain/main-entities/mcu-order" ems "simrs-vx/internal/domain/main-entities/mcu-src" erc "simrs-vx/internal/domain/references/common" + "time" ) type CreateDto struct { @@ -51,22 +52,24 @@ type MetaDto struct { type ResponseDto struct { ecore.Main - McuOrder_Id *uint `json:"mcuOrder_id"` - McuOrder *emo.McuOrder `json:"mcuOrder,omitempty"` - McuSrc_Id *uint `json:"mcuSrc_id"` - McuSrc *ems.McuSrc `json:"mcuSrc,omitempty"` - Result *string `json:"result"` - Status_Code erc.DataStatusCode `json:"status_code"` + McuOrder_Id *uint `json:"mcuOrder_id"` + McuOrder *emo.McuOrder `json:"mcuOrder,omitempty"` + McuSrc_Id *uint `json:"mcuSrc_id"` + McuSrc *ems.McuSrc `json:"mcuSrc,omitempty"` + Result *string `json:"result"` + Status_Code erc.DataStatusCode `json:"status_code"` + ExaminationDate *time.Time `json:"examinationDate"` } func (d McuOrderItem) ToResponse() ResponseDto { resp := ResponseDto{ - McuOrder_Id: d.McuOrder_Id, - McuOrder: d.McuOrder, - McuSrc_Id: d.McuSrc_Id, - McuSrc: d.McuSrc, - Result: d.Result, - Status_Code: d.Status_Code, + McuOrder_Id: d.McuOrder_Id, + McuOrder: d.McuOrder, + McuSrc_Id: d.McuSrc_Id, + McuSrc: d.McuSrc, + Result: d.Result, + Status_Code: d.Status_Code, + ExaminationDate: d.ExaminationDate, } resp.Main = d.Main return resp diff --git a/internal/domain/main-entities/mcu-order/dto.go b/internal/domain/main-entities/mcu-order/dto.go index 418fb02c..dbff3fdc 100644 --- a/internal/domain/main-entities/mcu-order/dto.go +++ b/internal/domain/main-entities/mcu-order/dto.go @@ -4,13 +4,20 @@ 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" + ercl "simrs-vx/internal/domain/references/clinical" erc "simrs-vx/internal/domain/references/common" + "time" ) type CreateDto struct { - Encounter_Id *uint `json:"encounter_id"` - Status_Code erc.DataStatusCode `json:"status_code" gorm:"not null;size:10"` - Doctor_Id *uint `json:"doctor_id"` + Encounter_Id *uint `json:"encounter_id"` + Status_Code erc.DataStatusCode `json:"status_code" gorm:"not null;size:10"` + Doctor_Id *uint `json:"doctor_id"` + SpecimenPickTime *time.Time `json:"specimenPickTime"` + ExaminationDate *time.Time `json:"examinationDate"` + Number uint8 `json:"number"` + Temperature float64 `json:"temperature"` + McuUrgencyLevel_Code ercl.McuUrgencyLevelCode `json:"mcuUrgencyLevel_code""` } type ReadListDto struct { @@ -20,9 +27,14 @@ type ReadListDto struct { } type FilterDto struct { - Encounter_Id *uint `json:"encounter_id"` - Status_Code erc.DataStatusCode `json:"status_code" gorm:"not null;size:10"` - Doctor_Id *uint `json:"doctor_id"` + Encounter_Id *uint `json:"encounter_id"` + Status_Code erc.DataStatusCode `json:"status_code" gorm:"not null;size:10"` + Doctor_Id *uint `json:"doctor_id"` + SpecimenPickTime *time.Time `json:"specimenPickTime"` + ExaminationDate *time.Time `json:"examinationDate"` + Number uint8 `json:"number"` + Temperature float64 `json:"temperature"` + McuUrgencyLevel_Code ercl.McuUrgencyLevelCode `json:"mcuUrgencyLevel_code""` Page int `json:"page"` PageSize int `json:"page_size"` @@ -49,20 +61,30 @@ type MetaDto struct { type ResponseDto struct { ecore.Main - Encounter_Id *uint `json:"encounter_id"` - Encounter *ee.Encounter `json:"encounter,omitempty"` - Status_Code erc.DataStatusCode `json:"status_code" gorm:"not null;size:10"` - Doctor_Id *uint `json:"doctor_id"` - Doctor *ed.Doctor `json:"doctor,omitempty"` + Encounter_Id *uint `json:"encounter_id"` + Encounter *ee.Encounter `json:"encounter,omitempty"` + Status_Code erc.DataStatusCode `json:"status_code" gorm:"not null;size:10"` + Doctor_Id *uint `json:"doctor_id"` + Doctor *ed.Doctor `json:"doctor,omitempty"` + SpecimenPickTime *time.Time `json:"specimenPickTime"` + ExaminationDate *time.Time `json:"examinationDate"` + Number uint8 `json:"number"` + Temperature float64 `json:"temperature"` + McuUrgencyLevel_Code ercl.McuUrgencyLevelCode `json:"mcuUrgencyLevel_code""` } func (d McuOrder) ToResponse() ResponseDto { resp := ResponseDto{ - Encounter_Id: d.Encounter_Id, - Encounter: d.Encounter, - Status_Code: d.Status_Code, - Doctor_Id: d.Doctor_Id, - Doctor: d.Doctor, + Encounter_Id: d.Encounter_Id, + Encounter: d.Encounter, + Status_Code: d.Status_Code, + Doctor_Id: d.Doctor_Id, + Doctor: d.Doctor, + SpecimenPickTime: d.SpecimenPickTime, + ExaminationDate: d.ExaminationDate, + Number: d.Number, + Temperature: d.Temperature, + McuUrgencyLevel_Code: d.McuUrgencyLevel_Code, } resp.Main = d.Main return resp diff --git a/internal/domain/main-entities/person-relative/dto.go b/internal/domain/main-entities/person-relative/dto.go index 4f28cbf8..deb29886 100644 --- a/internal/domain/main-entities/person-relative/dto.go +++ b/internal/domain/main-entities/person-relative/dto.go @@ -84,7 +84,20 @@ type ResponseDto struct { } func (d *PersonRelative) ToResponse() ResponseDto { - resp := ResponseDto{} + resp := ResponseDto{ + Person_Id: d.Person_Id, + Relationship_Code: d.Relationship_Code, + Name: d.Name, + Address: d.Address, + Village_Code: d.Village_Code, + Village: d.Village, + Gender_Code: d.Gender_Code, + PhoneNumber: d.PhoneNumber, + Education_Code: d.Education_Code, + Occupation_Code: d.Occupation_Code, + Occupation_Name: d.Occupation_Name, + Responsible: d.Responsible, + } resp.Main = d.Main return resp } diff --git a/internal/use-case/main-use-case/device/helper.go b/internal/use-case/main-use-case/device/helper.go index 63d51664..08964464 100644 --- a/internal/use-case/main-use-case/device/helper.go +++ b/internal/use-case/main-use-case/device/helper.go @@ -31,6 +31,7 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Device) { data.Name = inputSrc.Name data.Uom_Code = inputSrc.Uom_Code data.Item_Id = inputSrc.Item_Id + data.Infra_Id = inputSrc.Infra_Id } func createItem(input *e.CreateDto, event *pl.Event, tx *gorm.DB) error { diff --git a/internal/use-case/main-use-case/material/helper.go b/internal/use-case/main-use-case/material/helper.go index ce0d8a2e..9cfefe27 100644 --- a/internal/use-case/main-use-case/material/helper.go +++ b/internal/use-case/main-use-case/material/helper.go @@ -31,6 +31,7 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Material) { data.Uom_Code = inputSrc.Uom_Code data.Stock = inputSrc.Stock data.Item_Id = inputSrc.Item_Id + data.Infra_Id = inputSrc.Infra_Id } func createItem(input *e.CreateDto, event *pl.Event, tx *gorm.DB) error { diff --git a/internal/use-case/main-use-case/mcu-order/helper.go b/internal/use-case/main-use-case/mcu-order/helper.go index cb0b9878..65c95bff 100644 --- a/internal/use-case/main-use-case/mcu-order/helper.go +++ b/internal/use-case/main-use-case/mcu-order/helper.go @@ -20,4 +20,9 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.McuOrder) { data.Encounter_Id = inputSrc.Encounter_Id data.Status_Code = inputSrc.Status_Code data.Doctor_Id = inputSrc.Doctor_Id + data.SpecimenPickTime = inputSrc.SpecimenPickTime + data.ExaminationDate = inputSrc.ExaminationDate + data.Number = inputSrc.Number + data.Temperature = inputSrc.Temperature + data.McuUrgencyLevel_Code = inputSrc.McuUrgencyLevel_Code } diff --git a/internal/use-case/main-use-case/person-relative/helper.go b/internal/use-case/main-use-case/person-relative/helper.go index 48883d5a..b0624521 100644 --- a/internal/use-case/main-use-case/person-relative/helper.go +++ b/internal/use-case/main-use-case/person-relative/helper.go @@ -27,4 +27,5 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.PersonRelative) { data.Education_Code = inputSrc.Education_Code data.Occupation_Code = inputSrc.Occupation_Code data.Occupation_Name = inputSrc.Occupation_Name + data.Responsible = inputSrc.Responsible } From 6304d8f02af5852e279caec5e90a830f790b88b0 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Sun, 21 Sep 2025 04:41:43 +0700 Subject: [PATCH 5/7] add mcu orders related, not tested yet --- .../main-entities/mcu-order-item/dto.go | 20 +- .../main-entities/mcu-order-item/entity.go | 4 + .../main-entities/mcu-order-sub-item/dto.go | 6 +- .../domain/main-entities/mcu-order/dto.go | 12 +- .../domain/main-entities/mcu-order/entity.go | 4 + internal/domain/main-entities/mcu-src/dto.go | 1 + .../domain/main-entities/mcu-sub-src/dto.go | 1 + .../references/organization/organization.go | 2 + .../interface/main-handler/main-handler.go | 70 +++-- .../main-handler/mcu-order-item/handler.go | 21 +- .../mcu-order-sub-item/handler.go | 71 +++++ .../main-handler/mcu-order/handler.go | 33 +- .../main-handler/mcu-sub-src/handler.go | 71 +++++ .../main-use-case/mcu-order-item/case.go | 54 ++++ .../main-use-case/mcu-order-item/helper.go | 1 + .../main-use-case/mcu-order-sub-item/case.go | 279 +++++++++++++++++ .../mcu-order-sub-item/helper.go | 24 ++ .../main-use-case/mcu-order-sub-item/lib.go | 155 ++++++++++ .../mcu-order-sub-item/middleware-runner.go | 103 +++++++ .../mcu-order-sub-item/middleware.go | 9 + .../mcu-order-sub-item/tycovar.go | 44 +++ .../use-case/main-use-case/mcu-order/case.go | 107 +++++++ .../use-case/main-use-case/mcu-src/case.go | 4 + .../use-case/main-use-case/mcu-src/helper.go | 28 ++ .../main-use-case/mcu-sub-src/case.go | 282 ++++++++++++++++++ .../main-use-case/mcu-sub-src/helper.go | 51 ++++ .../use-case/main-use-case/mcu-sub-src/lib.go | 155 ++++++++++ .../mcu-sub-src/middleware-runner.go | 103 +++++++ .../main-use-case/mcu-sub-src/middleware.go | 9 + .../main-use-case/mcu-sub-src/tycovar.go | 44 +++ 30 files changed, 1722 insertions(+), 46 deletions(-) create mode 100644 internal/interface/main-handler/mcu-order-sub-item/handler.go create mode 100644 internal/interface/main-handler/mcu-sub-src/handler.go create mode 100644 internal/use-case/main-use-case/mcu-order-sub-item/case.go create mode 100644 internal/use-case/main-use-case/mcu-order-sub-item/helper.go create mode 100644 internal/use-case/main-use-case/mcu-order-sub-item/lib.go create mode 100644 internal/use-case/main-use-case/mcu-order-sub-item/middleware-runner.go create mode 100644 internal/use-case/main-use-case/mcu-order-sub-item/middleware.go create mode 100644 internal/use-case/main-use-case/mcu-order-sub-item/tycovar.go create mode 100644 internal/use-case/main-use-case/mcu-sub-src/case.go create mode 100644 internal/use-case/main-use-case/mcu-sub-src/helper.go create mode 100644 internal/use-case/main-use-case/mcu-sub-src/lib.go create mode 100644 internal/use-case/main-use-case/mcu-sub-src/middleware-runner.go create mode 100644 internal/use-case/main-use-case/mcu-sub-src/middleware.go create mode 100644 internal/use-case/main-use-case/mcu-sub-src/tycovar.go diff --git a/internal/domain/main-entities/mcu-order-item/dto.go b/internal/domain/main-entities/mcu-order-item/dto.go index e5b82cb9..24aba1b8 100644 --- a/internal/domain/main-entities/mcu-order-item/dto.go +++ b/internal/domain/main-entities/mcu-order-item/dto.go @@ -9,10 +9,11 @@ import ( ) type CreateDto struct { - McuOrder_Id *uint `json:"mcuOrder_id"` - McuSrc_Id *uint `json:"mcuSrc_id"` - Result *string `json:"result"` - Status_Code erc.DataStatusCode `json:"status_code"` + McuOrder_Id *uint `json:"mcuOrder_id"` + McuSrc_Id *uint `json:"mcuSrc_id"` + Result *string `json:"result"` + Status_Code erc.DataStatusCode `json:"status_code"` + ExaminationDate *time.Time `json:"examinationDate"` } type ReadListDto struct { @@ -32,16 +33,21 @@ type FilterDto struct { NoPagination int `json:"no_pagination"` } type ReadDetailDto struct { - Id uint16 `json:"id"` + Id uint `json:"id"` } type UpdateDto struct { - Id uint16 `json:"id"` + Id uint `json:"id"` CreateDto } type DeleteDto struct { - Id uint16 `json:"id"` + Id uint `json:"id"` +} + +type SetScheduleDto struct { + Id uint `json:"id"` + ExaminationDate *time.Time `json:"examinationDate"` } type MetaDto struct { diff --git a/internal/domain/main-entities/mcu-order-item/entity.go b/internal/domain/main-entities/mcu-order-item/entity.go index f1ae0cc8..6a4441d0 100644 --- a/internal/domain/main-entities/mcu-order-item/entity.go +++ b/internal/domain/main-entities/mcu-order-item/entity.go @@ -19,3 +19,7 @@ type McuOrderItem struct { Result *string `json:"result"` Status_Code erc.DataStatusCode `json:"status_code"` } + +func (d McuOrderItem) IsCompleted() bool { + return d.Status_Code == erc.DSCDone +} diff --git a/internal/domain/main-entities/mcu-order-sub-item/dto.go b/internal/domain/main-entities/mcu-order-sub-item/dto.go index d59d2ccf..cb250200 100644 --- a/internal/domain/main-entities/mcu-order-sub-item/dto.go +++ b/internal/domain/main-entities/mcu-order-sub-item/dto.go @@ -31,16 +31,16 @@ type FilterDto struct { NoPagination int `json:"no_pagination"` } type ReadDetailDto struct { - Id uint16 `json:"id"` + Id uint `json:"id"` } type UpdateDto struct { - Id uint16 `json:"id"` + Id uint `json:"id"` CreateDto } type DeleteDto struct { - Id uint16 `json:"id"` + Id uint `json:"id"` } type MetaDto struct { diff --git a/internal/domain/main-entities/mcu-order/dto.go b/internal/domain/main-entities/mcu-order/dto.go index dbff3fdc..4dcabce4 100644 --- a/internal/domain/main-entities/mcu-order/dto.go +++ b/internal/domain/main-entities/mcu-order/dto.go @@ -41,16 +41,21 @@ type FilterDto struct { NoPagination int `json:"no_pagination"` } type ReadDetailDto struct { - Id uint16 `json:"id"` + Id uint `json:"id"` } type UpdateDto struct { - Id uint16 `json:"id"` + Id uint `json:"id"` CreateDto } type DeleteDto struct { - Id uint16 `json:"id"` + Id uint `json:"id"` +} + +type SetScheduleDto struct { + Id uint `json:"id"` + ExaminationDate *time.Time `json:"examinationDate"` } type MetaDto struct { @@ -58,7 +63,6 @@ type MetaDto struct { PageSize int `json:"page_size"` Count int `json:"count"` } - type ResponseDto struct { ecore.Main Encounter_Id *uint `json:"encounter_id"` diff --git a/internal/domain/main-entities/mcu-order/entity.go b/internal/domain/main-entities/mcu-order/entity.go index 134485e5..96721caf 100644 --- a/internal/domain/main-entities/mcu-order/entity.go +++ b/internal/domain/main-entities/mcu-order/entity.go @@ -23,3 +23,7 @@ type McuOrder struct { Temperature float64 `json:"temperature"` McuUrgencyLevel_Code ercl.McuUrgencyLevelCode `json:"mcuUrgencyLevel_code" gorm:"not null;size:15"` } + +func (d McuOrder) IsCompleted() bool { + return d.Status_Code == erc.DSCDone +} diff --git a/internal/domain/main-entities/mcu-src/dto.go b/internal/domain/main-entities/mcu-src/dto.go index 56ab9f57..2d0e9827 100644 --- a/internal/domain/main-entities/mcu-src/dto.go +++ b/internal/domain/main-entities/mcu-src/dto.go @@ -9,6 +9,7 @@ type CreateDto struct { Code string `json:"code" validate:"maxLength=20"` Name string `json:"name" validate:"maxLength=50"` CheckupCategory_Code *string `json:"checkupCategory_code" validate:"maxLength=20"` + Item_Id *uint `json:"item_id"` } type ReadListDto struct { diff --git a/internal/domain/main-entities/mcu-sub-src/dto.go b/internal/domain/main-entities/mcu-sub-src/dto.go index eec34ead..a6d0a804 100644 --- a/internal/domain/main-entities/mcu-sub-src/dto.go +++ b/internal/domain/main-entities/mcu-sub-src/dto.go @@ -10,6 +10,7 @@ type CreateDto struct { Code string `json:"code" validate:"maxLength=20"` Name string `json:"name" validate:"maxLength=50"` McuSrc_Id *uint `json:"mcuSrc_id"` + Item_Id *uint `json:"item_id"` } type ReadListDto struct { diff --git a/internal/domain/references/organization/organization.go b/internal/domain/references/organization/organization.go index 30aa25b5..1f655466 100644 --- a/internal/domain/references/organization/organization.go +++ b/internal/domain/references/organization/organization.go @@ -23,6 +23,8 @@ const ( ITGCMedicine ItemGroupCode = "medicine" ITGCDevice ItemGroupCode = "device" ITGCMaterial ItemGroupCode = "material" + ITGCMCU ItemGroupCode = "mcu" + ITGCMCUSub ItemGroupCode = "mcuSub" ITGCEmpFee ItemGroupCode = "employee-fee" ITGCDocFee ItemGroupCode = "doctor-fee" diff --git a/internal/interface/main-handler/main-handler.go b/internal/interface/main-handler/main-handler.go index cc14eaf1..b57ad997 100644 --- a/internal/interface/main-handler/main-handler.go +++ b/internal/interface/main-handler/main-handler.go @@ -14,6 +14,7 @@ import ( materialorderitem "simrs-vx/internal/interface/main-handler/material-order-item" mcuorder "simrs-vx/internal/interface/main-handler/mcu-order" mcuorderitem "simrs-vx/internal/interface/main-handler/mcu-order-item" + mcuordersubitem "simrs-vx/internal/interface/main-handler/mcu-order-sub-item" medication "simrs-vx/internal/interface/main-handler/medication" medicationitem "simrs-vx/internal/interface/main-handler/medication-item" medicationitemdist "simrs-vx/internal/interface/main-handler/medication-item-dist" @@ -68,6 +69,7 @@ import ( material "simrs-vx/internal/interface/main-handler/material" mcusrc "simrs-vx/internal/interface/main-handler/mcu-src" mcusrccategory "simrs-vx/internal/interface/main-handler/mcu-src-category" + mcusubsrc "simrs-vx/internal/interface/main-handler/mcu-sub-src" medicalactionsrc "simrs-vx/internal/interface/main-handler/medical-action-src" medicalactionsrcitem "simrs-vx/internal/interface/main-handler/medical-action-src-item" medicine "simrs-vx/internal/interface/main-handler/medicine" @@ -111,24 +113,30 @@ func SetRoutes() http.Handler { hc.RegCrud(r, "/v1/counter", counter.O) hc.RegCrud(r, "/v1/medicine-mix", medicicinemix.O) hc.RegCrud(r, "/v1/medicine-mix-item", medicicinemixitem.O) - - /******************** actor ********************/ - hk.GroupRoutes("/v1/user", r, hk.MapHandlerFunc{ - "GET /": user.O.GetList, - "GET /{id}": user.O.GetDetail, - "POST /": user.O.Create, - "PATCH /{id}": user.O.Update, - "DELETE /{id}": user.O.Delete, - "PATCH /{id}/block": user.O.Block, - "PATCH /{id}/active": user.O.Active, + hc.RegCrud(r, "/v1/soapi", auth.GuardMW, soapi.O) + hc.RegCrud(r, "/v1/adime", auth.GuardMW, adime.O) + hc.RegCrud(r, "/v1/sbar", auth.GuardMW, sbar.O) + hc.RegCrud(r, "/v1/prescription", prescription.O) + hc.RegCrud(r, "/v1/prescription-item", prescriptionitem.O) + hc.RegCrud(r, "/v1/device-order-item", deviceorderitem.O) + hc.RegCrud(r, "/v1/material-order-item", materialorderitem.O) + hc.RegCrud(r, "/v1/mcu-order-sub-item", mcuordersubitem.O) + hk.GroupRoutes("/v1/mcu-order", r, hk.MapHandlerFunc{ + "GET /": mcuorder.O.GetList, + "GET /{id}": mcuorder.O.GetDetail, + "POST /": mcuorder.O.Create, + "PATCH /{id}": mcuorder.O.Update, + "DELETE /{id}": mcuorder.O.Delete, + "PATCH /{id}/complete": mcuorder.O.Complete, + "PATCH /{id}/set-schedule": mcuorder.O.SetSchedule, }) - hk.GroupRoutes("/v1/patient", r, hk.MapHandlerFunc{ - "GET /": patient.O.GetList, - "GET /{id}": patient.O.GetDetail, - "POST /": patient.O.Create, - "PATCH /{id}": patient.O.Update, - "DELETE /{id}": patient.O.Delete, - "GET /by-identifier": patient.O.Search, + hk.GroupRoutes("/v1/mcu-order-item", r, hk.MapHandlerFunc{ + "GET /": mcuorderitem.O.GetList, + "GET /{id}": mcuorderitem.O.GetDetail, + "POST /": mcuorderitem.O.Create, + "PATCH /{id}": mcuorderitem.O.Update, + "DELETE /{id}": mcuorderitem.O.Delete, + "PATCH /{id}/set-schedule": mcuorderitem.O.SetSchedule, }) hk.GroupRoutes("/v1/encounter", r, hk.MapHandlerFunc{ "GET /": encounter.O.GetList, @@ -183,9 +191,7 @@ func SetRoutes() http.Handler { "PATCH /{id}/complete": materialorder.O.Complete, }) - hc.RegCrud(r, "/v1/soapi", auth.GuardMW, soapi.O) - hc.RegCrud(r, "/v1/adime", auth.GuardMW, adime.O) - hc.RegCrud(r, "/v1/sbar", auth.GuardMW, sbar.O) + /******************** actor ********************/ hc.RegCrud(r, "/v1/person", person.O) hc.RegCrud(r, "/v1/person-address", personaddress.O) hc.RegCrud(r, "/v1/person-contact", personcontact.O) @@ -194,12 +200,23 @@ func SetRoutes() http.Handler { hc.RegCrud(r, "/v1/nurse", nurse.O) hc.RegCrud(r, "/v1/nutritionist", nutritionist.O) hc.RegCrud(r, "/v1/pharmacist", pharmacist.O) - hc.RegCrud(r, "/v1/prescription", prescription.O) - hc.RegCrud(r, "/v1/prescription-item", prescriptionitem.O) - hc.RegCrud(r, "/v1/device-order-item", deviceorderitem.O) - hc.RegCrud(r, "/v1/material-order-item", materialorderitem.O) - hc.RegCrud(r, "/v1/mcu-order", mcuorder.O) - hc.RegCrud(r, "/v1/mcu-order-item", mcuorderitem.O) + hk.GroupRoutes("/v1/user", r, hk.MapHandlerFunc{ + "GET /": user.O.GetList, + "GET /{id}": user.O.GetDetail, + "POST /": user.O.Create, + "PATCH /{id}": user.O.Update, + "DELETE /{id}": user.O.Delete, + "PATCH /{id}/block": user.O.Block, + "PATCH /{id}/active": user.O.Active, + }) + hk.GroupRoutes("/v1/patient", r, hk.MapHandlerFunc{ + "GET /": patient.O.GetList, + "GET /{id}": patient.O.GetDetail, + "POST /": patient.O.Create, + "PATCH /{id}": patient.O.Update, + "DELETE /{id}": patient.O.Delete, + "GET /by-identifier": patient.O.Search, + }) /******************** sources ********************/ hc.RegCrud(r, "/v1/division", division.O) @@ -228,6 +245,7 @@ func SetRoutes() http.Handler { hc.RegCrud(r, "/v1/language", language.O) hc.RegCrud(r, "/v1/specialist", specialist.O) hc.RegCrud(r, "/v1/subspecialist", subspecialist.O) + hc.RegCrud(r, "/v1/mcu-sub-src", mcusubsrc.O) hc.RegCrud(r, "/v1/village", village.O) hc.RegCrud(r, "/v1/district", district.O) diff --git a/internal/interface/main-handler/mcu-order-item/handler.go b/internal/interface/main-handler/mcu-order-item/handler.go index a3a4bcc8..f407a044 100644 --- a/internal/interface/main-handler/mcu-order-item/handler.go +++ b/internal/interface/main-handler/mcu-order-item/handler.go @@ -38,7 +38,7 @@ func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { return } dto := e.ReadDetailDto{} - dto.Id = uint16(id) + dto.Id = uint(id) res, err := u.ReadDetail(dto) rw.DataResponse(w, res, err) } @@ -53,7 +53,7 @@ func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { return } - dto.Id = uint16(id) + dto.Id = uint(id) res, err := u.Update(dto) rw.DataResponse(w, res, err) } @@ -65,7 +65,22 @@ func (obj myBase) Delete(w http.ResponseWriter, r *http.Request) { } dto := e.DeleteDto{} - dto.Id = uint16(id) + dto.Id = uint(id) res, err := u.Delete(dto) rw.DataResponse(w, res, err) } + +func (obj myBase) SetSchedule(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + + dto := e.SetScheduleDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + dto.Id = uint(id) + res, err := u.SetSchedule(dto) + rw.DataResponse(w, res, err) +} diff --git a/internal/interface/main-handler/mcu-order-sub-item/handler.go b/internal/interface/main-handler/mcu-order-sub-item/handler.go new file mode 100644 index 00000000..e36426e0 --- /dev/null +++ b/internal/interface/main-handler/mcu-order-sub-item/handler.go @@ -0,0 +1,71 @@ +package mcuordersubitem + +import ( + "net/http" + + rw "github.com/karincake/risoles" + sf "github.com/karincake/semprit" + + // ua "github.com/karincake/tumpeng/auth/svc" + + e "simrs-vx/internal/domain/main-entities/mcu-order-sub-item" + u "simrs-vx/internal/use-case/main-use-case/mcu-order-sub-item" +) + +type myBase struct{} + +var O myBase + +func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { + dto := e.CreateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + res, err := u.Create(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { + dto := e.ReadListDto{} + sf.UrlQueryParam(&dto, *r.URL) + res, err := u.ReadList(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) GetDetail(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.ReadDetail(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + + dto := e.UpdateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + dto.Id = uint(id) + res, err := u.Update(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) Delete(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + + dto := e.DeleteDto{} + dto.Id = uint(id) + res, err := u.Delete(dto) + rw.DataResponse(w, res, err) +} diff --git a/internal/interface/main-handler/mcu-order/handler.go b/internal/interface/main-handler/mcu-order/handler.go index 77e19669..44a635a5 100644 --- a/internal/interface/main-handler/mcu-order/handler.go +++ b/internal/interface/main-handler/mcu-order/handler.go @@ -38,7 +38,7 @@ func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { return } dto := e.ReadDetailDto{} - dto.Id = uint16(id) + dto.Id = uint(id) res, err := u.ReadDetail(dto) rw.DataResponse(w, res, err) } @@ -53,7 +53,7 @@ func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { return } - dto.Id = uint16(id) + dto.Id = uint(id) res, err := u.Update(dto) rw.DataResponse(w, res, err) } @@ -65,7 +65,34 @@ func (obj myBase) Delete(w http.ResponseWriter, r *http.Request) { } dto := e.DeleteDto{} - dto.Id = uint16(id) + dto.Id = uint(id) res, err := u.Delete(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 { + return + } + + dto := e.ReadDetailDto{} + dto.Id = uint(id) + res, err := u.Complete(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) SetSchedule(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + + dto := e.SetScheduleDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + dto.Id = uint(id) + res, err := u.SetSchedule(dto) + rw.DataResponse(w, res, err) +} diff --git a/internal/interface/main-handler/mcu-sub-src/handler.go b/internal/interface/main-handler/mcu-sub-src/handler.go new file mode 100644 index 00000000..949be715 --- /dev/null +++ b/internal/interface/main-handler/mcu-sub-src/handler.go @@ -0,0 +1,71 @@ +package mcusubsrc + +import ( + "net/http" + + rw "github.com/karincake/risoles" + sf "github.com/karincake/semprit" + + // ua "github.com/karincake/tumpeng/auth/svc" + + e "simrs-vx/internal/domain/main-entities/mcu-sub-src" + u "simrs-vx/internal/use-case/main-use-case/mcu-sub-src" +) + +type myBase struct{} + +var O myBase + +func (obj myBase) Create(w http.ResponseWriter, r *http.Request) { + dto := e.CreateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + res, err := u.Create(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) GetList(w http.ResponseWriter, r *http.Request) { + dto := e.ReadListDto{} + sf.UrlQueryParam(&dto, *r.URL) + res, err := u.ReadList(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) GetDetail(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + dto := e.ReadDetailDto{} + dto.Id = uint16(id) + res, err := u.ReadDetail(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) Update(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + + dto := e.UpdateDto{} + if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res { + return + } + dto.Id = uint16(id) + res, err := u.Update(dto) + rw.DataResponse(w, res, err) +} + +func (obj myBase) Delete(w http.ResponseWriter, r *http.Request) { + id := rw.ValidateInt(w, "id", r.PathValue("id")) + if id <= 0 { + return + } + + dto := e.DeleteDto{} + dto.Id = uint16(id) + res, err := u.Delete(dto) + rw.DataResponse(w, res, err) +} diff --git a/internal/use-case/main-use-case/mcu-order-item/case.go b/internal/use-case/main-use-case/mcu-order-item/case.go index 74323143..899b8120 100644 --- a/internal/use-case/main-use-case/mcu-order-item/case.go +++ b/internal/use-case/main-use-case/mcu-order-item/case.go @@ -1,6 +1,7 @@ package mcuorderitem import ( + "errors" "strconv" e "simrs-vx/internal/domain/main-entities/mcu-order-item" @@ -277,3 +278,56 @@ func Delete(input e.DeleteDto) (*d.Data, error) { }, nil } + +func SetSchedule(input e.SetScheduleDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Id: input.Id} + var data *e.McuOrderItem + var err error + + event := pl.Event{ + Feature: "SetSchedule", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "setSchedule") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + data, err = ReadDetailData(rdDto, &event, tx) + if err != nil { + return err + } + if data.IsCompleted() { + return errors.New("data already completed") + } + + data.ExaminationDate = input.ExaminationDate + 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": "setSchedule", + }, + Data: data.ToResponse(), + }, nil +} diff --git a/internal/use-case/main-use-case/mcu-order-item/helper.go b/internal/use-case/main-use-case/mcu-order-item/helper.go index 48eaaf09..a2694ecd 100644 --- a/internal/use-case/main-use-case/mcu-order-item/helper.go +++ b/internal/use-case/main-use-case/mcu-order-item/helper.go @@ -21,4 +21,5 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.McuOrderItem) { data.McuSrc_Id = inputSrc.McuSrc_Id data.Result = inputSrc.Result data.Status_Code = inputSrc.Status_Code + data.ExaminationDate = inputSrc.ExaminationDate } diff --git a/internal/use-case/main-use-case/mcu-order-sub-item/case.go b/internal/use-case/main-use-case/mcu-order-sub-item/case.go new file mode 100644 index 00000000..bf3e4ce9 --- /dev/null +++ b/internal/use-case/main-use-case/mcu-order-sub-item/case.go @@ -0,0 +1,279 @@ +package mcuordersubitem + +import ( + "strconv" + + e "simrs-vx/internal/domain/main-entities/mcu-order-sub-item" + + dg "github.com/karincake/apem/db-gorm-pg" + d "github.com/karincake/dodol" + + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" +) + +const source = "mcu-order-sub-item" + +func Create(input e.CreateDto) (*d.Data, error) { + data := e.McuOrderSubItem{} + + event := pl.Event{ + Feature: "Create", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "create") + + err := dg.I.Transaction(func(tx *gorm.DB) error { + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunCreateMiddleware(createPreMw, &input, &data); err != nil { + return err + } + + if resData, err := CreateData(input, &event, tx); err != nil { + return err + } else { + data = *resData + } + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunCreateMiddleware(createPostMw, &input, &data); err != nil { + return err + } + + pl.SetLogInfo(&event, nil, "complete") + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.II{ + "source": source, + "structure": "single-data", + "status": "created", + }, + Data: data.ToResponse(), + }, nil +} + +func ReadList(input e.ReadListDto) (*d.Data, error) { + var data *e.McuOrderSubItem + var dataList []e.McuOrderSubItem + var metaList *e.MetaDto + var err error + + event := pl.Event{ + Feature: "ReadList", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "readList") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunReadListMiddleware(readListPreMw, &input, data); err != nil { + return err + } + + if len(input.Includes) > 0 { + input.Preloads = pu.GetPreloads(input.Includes) + } + if dataList, metaList, err = ReadListData(input, &event, tx); err != nil { + return err + } + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunReadListMiddleware(readListPostMw, &input, data); 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), + }, + Data: e.ToResponseList(dataList), + }, nil +} + +func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { + var data *e.McuOrderSubItem + var err error + + event := pl.Event{ + Feature: "ReadDetail", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "readDetail") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunReadDetailMiddleware(readDetailPreMw, &input, data); err != nil { + return err + } + + if data, err = ReadDetailData(input, &event, tx); err != nil { + return err + } + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunReadDetailMiddleware(readDetailPostMw, &input, data); err != nil { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "fetched", + }, + Data: data.ToResponse(), + }, nil +} + +func Update(input e.UpdateDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Id: input.Id} + var data *e.McuOrderSubItem + var err error + + event := pl.Event{ + Feature: "Update", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "update") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + return err + } + + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunUpdateMiddleware(readDetailPreMw, &rdDto, data); err != nil { + return err + } + + if err := UpdateData(input, data, &event, tx); err != nil { + return err + } + + pl.SetLogInfo(&event, nil, "complete") + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunUpdateMiddleware(readDetailPostMw, &rdDto, data); err != nil { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "updated", + }, + Data: data.ToResponse(), + }, nil + +} + +func Delete(input e.DeleteDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Id: input.Id} + var data *e.McuOrderSubItem + var err error + + event := pl.Event{ + Feature: "Delete", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "delete") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + return err + } + + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunDeleteMiddleware(readDetailPreMw, &rdDto, data); err != nil { + return err + } + + if err := DeleteData(data, &event, tx); err != nil { + return err + } + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunDeleteMiddleware(readDetailPostMw, &rdDto, data); err != nil { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "deleted", + }, + Data: data.ToResponse(), + }, nil + +} diff --git a/internal/use-case/main-use-case/mcu-order-sub-item/helper.go b/internal/use-case/main-use-case/mcu-order-sub-item/helper.go new file mode 100644 index 00000000..f8d9c30f --- /dev/null +++ b/internal/use-case/main-use-case/mcu-order-sub-item/helper.go @@ -0,0 +1,24 @@ +/* +DESCRIPTION: +Any functions that are used internally by the use-case +*/ +package mcuordersubitem + +import ( + e "simrs-vx/internal/domain/main-entities/mcu-order-sub-item" +) + +func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.McuOrderSubItem) { + var inputSrc *e.CreateDto + if inputT, ok := any(input).(*e.CreateDto); ok { + inputSrc = inputT + } else { + inputTemp := any(input).(*e.UpdateDto) + inputSrc = &inputTemp.CreateDto + } + + data.McuSubSrc_Id = inputSrc.McuSubSrc_Id + data.McuOrderItem_Id = inputSrc.McuOrderItem_Id + data.Result = inputSrc.Result + data.Status_Code = inputSrc.Status_Code +} diff --git a/internal/use-case/main-use-case/mcu-order-sub-item/lib.go b/internal/use-case/main-use-case/mcu-order-sub-item/lib.go new file mode 100644 index 00000000..edfee9cd --- /dev/null +++ b/internal/use-case/main-use-case/mcu-order-sub-item/lib.go @@ -0,0 +1,155 @@ +package mcuordersubitem + +import ( + e "simrs-vx/internal/domain/main-entities/mcu-order-sub-item" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + dg "github.com/karincake/apem/db-gorm-pg" + gh "github.com/karincake/getuk" + "gorm.io/gorm" +) + +func CreateData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*e.McuOrderSubItem, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + + data := e.McuOrderSubItem{} + setData(&input, &data) + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + if err := tx.Create(&data).Error; err != nil { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-create-fail", + Detail: "Database insert failed", + Raw: err, + } + return nil, pl.SetLogError(event, input) + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.McuOrderSubItem, *e.MetaDto, error) { + pl.SetLogInfo(event, input, "started", "DBReadList") + data := []e.McuOrderSubItem{} + pagination := gh.Pagination{} + count := int64(0) + meta := e.MetaDto{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + if len(input.Preloads) > 0 { + for _, preload := range input.Preloads { + tx = tx.Preload(preload) + } + } + + tx = tx. + Model(&e.McuOrderSubItem{}). + Scopes(gh.Filter(input.FilterDto)). + Count(&count). + Scopes(gh.Paginate(input, &pagination)). + Order("\"CreatedAt\" DESC") + + if err := tx.Find(&data).Error; err != nil { + if err == gorm.ErrRecordNotFound { + return nil, &meta, nil + } + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-get-fail", + Detail: "Database get failed", + Raw: err, + } + return nil, nil, pl.SetLogError(event, input) + + } + meta.Count = int(count) + meta.PageNumber = pagination.PageNumber + meta.PageSize = pagination.PageSize + + pl.SetLogInfo(event, nil, "complete") + return data, &meta, nil +} + +func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e.McuOrderSubItem, error) { + pl.SetLogInfo(event, input, "started", "DBReadDetail") + data := e.McuOrderSubItem{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + if err := tx.First(&data, input.Id).Error; err != nil { + if processedErr := pu.HandleReadError(err, event, source, input.Id, data); processedErr != nil { + return nil, processedErr + } + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func UpdateData(input e.UpdateDto, data *e.McuOrderSubItem, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, data, "started", "DBUpdate") + setData(&input, data) + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + 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 +} + +func DeleteData(data *e.McuOrderSubItem, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, data, "started", "DBDelete") + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + if err := tx.Delete(&data).Error; err != nil { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-delete-fail", + Detail: "Database delete failed", + Raw: err, + } + return pl.SetLogError(event, data) + } + + pl.SetLogInfo(event, nil, "complete") + return nil +} diff --git a/internal/use-case/main-use-case/mcu-order-sub-item/middleware-runner.go b/internal/use-case/main-use-case/mcu-order-sub-item/middleware-runner.go new file mode 100644 index 00000000..04b7323f --- /dev/null +++ b/internal/use-case/main-use-case/mcu-order-sub-item/middleware-runner.go @@ -0,0 +1,103 @@ +package mcuordersubitem + +import ( + e "simrs-vx/internal/domain/main-entities/mcu-order-sub-item" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" +) + +type middlewareRunner struct { + Event *pl.Event + Tx *gorm.DB + MwType pu.MWType +} + +// NewMiddlewareExecutor creates a new middleware executor +func newMiddlewareRunner(event *pl.Event, tx *gorm.DB) *middlewareRunner { + return &middlewareRunner{ + Event: event, + Tx: tx, + } +} + +// ExecuteCreateMiddleware executes create middleware +func (me *middlewareRunner) RunCreateMiddleware(middlewares []createMw, input *e.CreateDto, data *e.McuOrderSubItem) error { + for _, middleware := range middlewares { + logData := pu.GetLogData(input, data) + + pl.SetLogInfo(me.Event, logData, "started", middleware.Name) + + if err := middleware.Func(input, data, me.Tx); err != nil { + return pu.HandleMiddlewareError(me.Event, string(me.MwType), middleware.Name, logData, err) + } + + pl.SetLogInfo(me.Event, nil, "complete") + } + return nil +} + +func (me *middlewareRunner) RunReadListMiddleware(middlewares []readListMw, input *e.ReadListDto, data *e.McuOrderSubItem) error { + for _, middleware := range middlewares { + logData := pu.GetLogData(input, data) + + pl.SetLogInfo(me.Event, logData, "started", middleware.Name) + + if err := middleware.Func(input, data, me.Tx); err != nil { + return pu.HandleMiddlewareError(me.Event, string(me.MwType), middleware.Name, logData, err) + } + + pl.SetLogInfo(me.Event, nil, "complete") + } + return nil +} + +func (me *middlewareRunner) RunReadDetailMiddleware(middlewares []readDetailMw, input *e.ReadDetailDto, data *e.McuOrderSubItem) error { + for _, middleware := range middlewares { + logData := pu.GetLogData(input, data) + + pl.SetLogInfo(me.Event, logData, "started", middleware.Name) + + if err := middleware.Func(input, data, me.Tx); err != nil { + return pu.HandleMiddlewareError(me.Event, string(me.MwType), middleware.Name, logData, err) + } + + pl.SetLogInfo(me.Event, nil, "complete") + } + return nil +} + +func (me *middlewareRunner) RunUpdateMiddleware(middlewares []readDetailMw, input *e.ReadDetailDto, data *e.McuOrderSubItem) error { + for _, middleware := range middlewares { + logData := pu.GetLogData(input, data) + + pl.SetLogInfo(me.Event, logData, "started", middleware.Name) + + if err := middleware.Func(input, data, me.Tx); err != nil { + return pu.HandleMiddlewareError(me.Event, string(me.MwType), middleware.Name, logData, err) + } + + pl.SetLogInfo(me.Event, nil, "complete") + } + return nil +} + +func (me *middlewareRunner) RunDeleteMiddleware(middlewares []readDetailMw, input *e.ReadDetailDto, data *e.McuOrderSubItem) error { + for _, middleware := range middlewares { + logData := pu.GetLogData(input, data) + + pl.SetLogInfo(me.Event, logData, "started", middleware.Name) + + if err := middleware.Func(input, data, me.Tx); err != nil { + return pu.HandleMiddlewareError(me.Event, string(me.MwType), middleware.Name, logData, err) + } + + pl.SetLogInfo(me.Event, nil, "complete") + } + return nil +} + +func (me *middlewareRunner) setMwType(mwType pu.MWType) { + me.MwType = mwType +} diff --git a/internal/use-case/main-use-case/mcu-order-sub-item/middleware.go b/internal/use-case/main-use-case/mcu-order-sub-item/middleware.go new file mode 100644 index 00000000..8dda3302 --- /dev/null +++ b/internal/use-case/main-use-case/mcu-order-sub-item/middleware.go @@ -0,0 +1,9 @@ +package mcuordersubitem + +// example of middleware +// func init() { +// createPreMw = append(createPreMw, +// CreateMw{Name: "modif-input", Func: pm.ModifInput}, +// CreateMw{Name: "check-data", Func: pm.CheckData}, +// ) +// } diff --git a/internal/use-case/main-use-case/mcu-order-sub-item/tycovar.go b/internal/use-case/main-use-case/mcu-order-sub-item/tycovar.go new file mode 100644 index 00000000..58b67a88 --- /dev/null +++ b/internal/use-case/main-use-case/mcu-order-sub-item/tycovar.go @@ -0,0 +1,44 @@ +/* +DESCRIPTION: +A sample, part of the package that contains type, constants, and/or variables. + +In this sample it also provides type and variable regarding the needs of the +middleware to separate from main use-case which has the basic CRUD +functionality. The purpose of this is to make the code more maintainable. +*/ +package mcuordersubitem + +import ( + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/mcu-order-sub-item" +) + +type createMw struct { + Name string + Func func(input *e.CreateDto, data *e.McuOrderSubItem, tx *gorm.DB) error +} + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data *e.McuOrderSubItem, tx *gorm.DB) error +} + +type readDetailMw struct { + Name string + Func func(input *e.ReadDetailDto, data *e.McuOrderSubItem, tx *gorm.DB) error +} + +type UpdateMw = readDetailMw +type DeleteMw = readDetailMw + +var createPreMw []createMw // preprocess middleware +var createPostMw []createMw // postprocess middleware +var readListPreMw []readListMw // .. +var readListPostMw []readListMw // .. +var readDetailPreMw []readDetailMw +var readDetailPostMw []readDetailMw +var updatePreMw []readDetailMw +var updatePostMw []readDetailMw +var deletePreMw []readDetailMw +var deletePostMw []readDetailMw 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 b000ffc8..57de98fb 100644 --- a/internal/use-case/main-use-case/mcu-order/case.go +++ b/internal/use-case/main-use-case/mcu-order/case.go @@ -1,10 +1,13 @@ package mcuorder import ( + "errors" "strconv" e "simrs-vx/internal/domain/main-entities/mcu-order" + erc "simrs-vx/internal/domain/references/common" + dg "github.com/karincake/apem/db-gorm-pg" d "github.com/karincake/dodol" @@ -277,3 +280,107 @@ func Delete(input e.DeleteDto) (*d.Data, error) { }, nil } + +func Complete(input e.ReadDetailDto) (*d.Data, error) { + var data *e.McuOrder + var err error + + event := pl.Event{ + Feature: "Complete", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "complete") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + data, err = ReadDetailData(input, &event, tx) + if err != nil { + return err + } + + if data.IsCompleted() { + return errors.New("data already completed") + } + + data.Status_Code = erc.DSCDone + 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": "fetched", + }, + Data: data.ToResponse(), + }, nil +} + +func SetSchedule(input e.SetScheduleDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Id: input.Id} + var data *e.McuOrder + var err error + + event := pl.Event{ + Feature: "SetSchedule", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "setSchedule") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + data, err = ReadDetailData(rdDto, &event, tx) + if err != nil { + return err + } + if data.IsCompleted() { + return errors.New("data already completed") + } + + data.ExaminationDate = input.ExaminationDate + 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": "setSchedule", + }, + Data: data.ToResponse(), + }, nil +} diff --git a/internal/use-case/main-use-case/mcu-src/case.go b/internal/use-case/main-use-case/mcu-src/case.go index ae7a1860..f0e7589a 100644 --- a/internal/use-case/main-use-case/mcu-src/case.go +++ b/internal/use-case/main-use-case/mcu-src/case.go @@ -34,6 +34,10 @@ func Create(input e.CreateDto) (*d.Data, error) { return err } + if err := createItem(&input, &event, tx); err != nil { + return err + } + if resData, err := CreateData(input, &event, tx); err != nil { return err } else { diff --git a/internal/use-case/main-use-case/mcu-src/helper.go b/internal/use-case/main-use-case/mcu-src/helper.go index 820dbfa7..3c7dc31c 100644 --- a/internal/use-case/main-use-case/mcu-src/helper.go +++ b/internal/use-case/main-use-case/mcu-src/helper.go @@ -5,7 +5,17 @@ Any functions that are used internally by the use-case package mcusrc import ( + ei "simrs-vx/internal/domain/main-entities/item" e "simrs-vx/internal/domain/main-entities/mcu-src" + + ui "simrs-vx/internal/use-case/main-use-case/item" + + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + ero "simrs-vx/internal/domain/references/organization" + + "gorm.io/gorm" ) func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.McuSrc) { @@ -20,4 +30,22 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.McuSrc) { data.Code = inputSrc.Code data.Name = inputSrc.Name data.CheckupCategory_Code = inputSrc.CheckupCategory_Code + data.Item_Id = inputSrc.Item_Id +} + +func createItem(input *e.CreateDto, event *pl.Event, tx *gorm.DB) error { + itemCreate := ei.CreateDto{ + Code: pu.AddPrefix("mcu-", input.Code), + Name: input.Name, + ItemGroup_Code: ero.ITGCMCU, + // Uom_Code: &input.Uom_Code, + // Infra_Id: input.Infra_Id, + } + item, err := ui.CreateData(itemCreate, event, tx) + if err != nil { + return err + } + + input.Item_Id = &item.Id + return nil } diff --git a/internal/use-case/main-use-case/mcu-sub-src/case.go b/internal/use-case/main-use-case/mcu-sub-src/case.go new file mode 100644 index 00000000..e977931f --- /dev/null +++ b/internal/use-case/main-use-case/mcu-sub-src/case.go @@ -0,0 +1,282 @@ +package mcusubsrc + +import ( + e "simrs-vx/internal/domain/main-entities/mcu-sub-src" + "strconv" + + dg "github.com/karincake/apem/db-gorm-pg" + d "github.com/karincake/dodol" + + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" +) + +const source = "mcu-sub-src" + +func Create(input e.CreateDto) (*d.Data, error) { + data := e.McuSubSrc{} + + event := pl.Event{ + Feature: "Create", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "create") + + err := dg.I.Transaction(func(tx *gorm.DB) error { + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunCreateMiddleware(createPreMw, &input, &data); err != nil { + return err + } + + if err := createItem(&input, &event, tx); err != nil { + return err + } + + if resData, err := CreateData(input, &event, tx); err != nil { + return err + } else { + data = *resData + } + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunCreateMiddleware(createPostMw, &input, &data); err != nil { + return err + } + + pl.SetLogInfo(&event, nil, "complete") + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.II{ + "source": source, + "structure": "single-data", + "status": "created", + }, + Data: data.ToResponse(), + }, nil +} + +func ReadList(input e.ReadListDto) (*d.Data, error) { + var data *e.McuSubSrc + var dataList []e.McuSubSrc + var metaList *e.MetaDto + var err error + + event := pl.Event{ + Feature: "ReadList", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "readList") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunReadListMiddleware(readListPreMw, &input, data); err != nil { + return err + } + + if len(input.Includes) > 0 { + input.Preloads = pu.GetPreloads(input.Includes) + } + if dataList, metaList, err = ReadListData(input, &event, tx); err != nil { + return err + } + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunReadListMiddleware(readListPostMw, &input, data); 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), + }, + Data: e.ToResponseList(dataList), + }, nil +} + +func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { + var data *e.McuSubSrc + var err error + + event := pl.Event{ + Feature: "ReadDetail", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "readDetail") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunReadDetailMiddleware(readDetailPreMw, &input, data); err != nil { + return err + } + + if data, err = ReadDetailData(input, &event, tx); err != nil { + return err + } + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunReadDetailMiddleware(readDetailPostMw, &input, data); err != nil { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "fetched", + }, + Data: data.ToResponse(), + }, nil +} + +func Update(input e.UpdateDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Id: input.Id} + var data *e.McuSubSrc + var err error + + event := pl.Event{ + Feature: "Update", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "update") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + return err + } + + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunUpdateMiddleware(readDetailPreMw, &rdDto, data); err != nil { + return err + } + + if err := UpdateData(input, data, &event, tx); err != nil { + return err + } + + pl.SetLogInfo(&event, nil, "complete") + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunUpdateMiddleware(readDetailPostMw, &rdDto, data); err != nil { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "updated", + }, + Data: data.ToResponse(), + }, nil + +} + +func Delete(input e.DeleteDto) (*d.Data, error) { + rdDto := e.ReadDetailDto{Id: input.Id} + var data *e.McuSubSrc + var err error + + event := pl.Event{ + Feature: "Delete", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "delete") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + pl.SetLogInfo(&event, rdDto, "started", "DBReadDetail") + if data, err = ReadDetailData(rdDto, &event, tx); err != nil { + return err + } + + mwRunner := newMiddlewareRunner(&event, tx) + mwRunner.setMwType(pu.MWTPre) + // Run pre-middleware + if err := mwRunner.RunDeleteMiddleware(readDetailPreMw, &rdDto, data); err != nil { + return err + } + + if err := DeleteData(data, &event, tx); err != nil { + return err + } + + mwRunner.setMwType(pu.MWTPost) + // Run post-middleware + if err := mwRunner.RunDeleteMiddleware(readDetailPostMw, &rdDto, data); err != nil { + return err + } + + return nil + }) + + if err != nil { + return nil, err + } + + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "deleted", + }, + Data: data.ToResponse(), + }, nil + +} diff --git a/internal/use-case/main-use-case/mcu-sub-src/helper.go b/internal/use-case/main-use-case/mcu-sub-src/helper.go new file mode 100644 index 00000000..071d5f38 --- /dev/null +++ b/internal/use-case/main-use-case/mcu-sub-src/helper.go @@ -0,0 +1,51 @@ +/* +DESCRIPTION: +Any functions that are used internally by the use-case +*/ +package mcusubsrc + +import ( + ei "simrs-vx/internal/domain/main-entities/item" + e "simrs-vx/internal/domain/main-entities/mcu-sub-src" + + ui "simrs-vx/internal/use-case/main-use-case/item" + + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + ero "simrs-vx/internal/domain/references/organization" + + "gorm.io/gorm" +) + +func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.McuSubSrc) { + var inputSrc *e.CreateDto + if inputT, ok := any(input).(*e.CreateDto); ok { + inputSrc = inputT + } else { + inputTemp := any(input).(*e.UpdateDto) + inputSrc = &inputTemp.CreateDto + } + + data.Code = inputSrc.Code + data.Name = inputSrc.Name + data.McuSrc_Id = inputSrc.McuSrc_Id + data.Item_Id = inputSrc.Item_Id +} + +func createItem(input *e.CreateDto, event *pl.Event, tx *gorm.DB) error { + itemCreate := ei.CreateDto{ + Code: pu.AddPrefix("mcuSub-", input.Code), + Name: input.Name, + ItemGroup_Code: ero.ITGCMCU, + // Uom_Code: &input.Uom_Code, + // Infra_Id: input.Infra_Id, + } + item, err := ui.CreateData(itemCreate, event, tx) + if err != nil { + return err + } + + input.Item_Id = &item.Id + return nil +} diff --git a/internal/use-case/main-use-case/mcu-sub-src/lib.go b/internal/use-case/main-use-case/mcu-sub-src/lib.go new file mode 100644 index 00000000..711dabdd --- /dev/null +++ b/internal/use-case/main-use-case/mcu-sub-src/lib.go @@ -0,0 +1,155 @@ +package mcusubsrc + +import ( + e "simrs-vx/internal/domain/main-entities/mcu-sub-src" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + dg "github.com/karincake/apem/db-gorm-pg" + gh "github.com/karincake/getuk" + "gorm.io/gorm" +) + +func CreateData(input e.CreateDto, event *pl.Event, dbx ...*gorm.DB) (*e.McuSubSrc, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + + data := e.McuSubSrc{} + setData(&input, &data) + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + if err := tx.Create(&data).Error; err != nil { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-create-fail", + Detail: "Database insert failed", + Raw: err, + } + return nil, pl.SetLogError(event, input) + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.McuSubSrc, *e.MetaDto, error) { + pl.SetLogInfo(event, input, "started", "DBReadList") + data := []e.McuSubSrc{} + pagination := gh.Pagination{} + count := int64(0) + meta := e.MetaDto{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + if len(input.Preloads) > 0 { + for _, preload := range input.Preloads { + tx = tx.Preload(preload) + } + } + + tx = tx. + Model(&e.McuSubSrc{}). + Scopes(gh.Filter(input.FilterDto)). + Count(&count). + Scopes(gh.Paginate(input, &pagination)). + Order("\"CreatedAt\" DESC") + + if err := tx.Find(&data).Error; err != nil { + if err == gorm.ErrRecordNotFound { + return nil, &meta, nil + } + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-get-fail", + Detail: "Database get failed", + Raw: err, + } + return nil, nil, pl.SetLogError(event, input) + + } + meta.Count = int(count) + meta.PageNumber = pagination.PageNumber + meta.PageSize = pagination.PageSize + + pl.SetLogInfo(event, nil, "complete") + return data, &meta, nil +} + +func ReadDetailData(input e.ReadDetailDto, event *pl.Event, dbx ...*gorm.DB) (*e.McuSubSrc, error) { + pl.SetLogInfo(event, input, "started", "DBReadDetail") + data := e.McuSubSrc{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + if err := tx.First(&data, input.Id).Error; err != nil { + if processedErr := pu.HandleReadError(err, event, source, input.Id, data); processedErr != nil { + return nil, processedErr + } + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func UpdateData(input e.UpdateDto, data *e.McuSubSrc, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, data, "started", "DBUpdate") + setData(&input, data) + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + 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 +} + +func DeleteData(data *e.McuSubSrc, event *pl.Event, dbx ...*gorm.DB) error { + pl.SetLogInfo(event, data, "started", "DBDelete") + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + if err := tx.Delete(&data).Error; err != nil { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-delete-fail", + Detail: "Database delete failed", + Raw: err, + } + return pl.SetLogError(event, data) + } + + pl.SetLogInfo(event, nil, "complete") + return nil +} diff --git a/internal/use-case/main-use-case/mcu-sub-src/middleware-runner.go b/internal/use-case/main-use-case/mcu-sub-src/middleware-runner.go new file mode 100644 index 00000000..89d328ed --- /dev/null +++ b/internal/use-case/main-use-case/mcu-sub-src/middleware-runner.go @@ -0,0 +1,103 @@ +package mcusubsrc + +import ( + e "simrs-vx/internal/domain/main-entities/mcu-sub-src" + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" +) + +type middlewareRunner struct { + Event *pl.Event + Tx *gorm.DB + MwType pu.MWType +} + +// NewMiddlewareExecutor creates a new middleware executor +func newMiddlewareRunner(event *pl.Event, tx *gorm.DB) *middlewareRunner { + return &middlewareRunner{ + Event: event, + Tx: tx, + } +} + +// ExecuteCreateMiddleware executes create middleware +func (me *middlewareRunner) RunCreateMiddleware(middlewares []createMw, input *e.CreateDto, data *e.McuSubSrc) error { + for _, middleware := range middlewares { + logData := pu.GetLogData(input, data) + + pl.SetLogInfo(me.Event, logData, "started", middleware.Name) + + if err := middleware.Func(input, data, me.Tx); err != nil { + return pu.HandleMiddlewareError(me.Event, string(me.MwType), middleware.Name, logData, err) + } + + pl.SetLogInfo(me.Event, nil, "complete") + } + return nil +} + +func (me *middlewareRunner) RunReadListMiddleware(middlewares []readListMw, input *e.ReadListDto, data *e.McuSubSrc) error { + for _, middleware := range middlewares { + logData := pu.GetLogData(input, data) + + pl.SetLogInfo(me.Event, logData, "started", middleware.Name) + + if err := middleware.Func(input, data, me.Tx); err != nil { + return pu.HandleMiddlewareError(me.Event, string(me.MwType), middleware.Name, logData, err) + } + + pl.SetLogInfo(me.Event, nil, "complete") + } + return nil +} + +func (me *middlewareRunner) RunReadDetailMiddleware(middlewares []readDetailMw, input *e.ReadDetailDto, data *e.McuSubSrc) error { + for _, middleware := range middlewares { + logData := pu.GetLogData(input, data) + + pl.SetLogInfo(me.Event, logData, "started", middleware.Name) + + if err := middleware.Func(input, data, me.Tx); err != nil { + return pu.HandleMiddlewareError(me.Event, string(me.MwType), middleware.Name, logData, err) + } + + pl.SetLogInfo(me.Event, nil, "complete") + } + return nil +} + +func (me *middlewareRunner) RunUpdateMiddleware(middlewares []readDetailMw, input *e.ReadDetailDto, data *e.McuSubSrc) error { + for _, middleware := range middlewares { + logData := pu.GetLogData(input, data) + + pl.SetLogInfo(me.Event, logData, "started", middleware.Name) + + if err := middleware.Func(input, data, me.Tx); err != nil { + return pu.HandleMiddlewareError(me.Event, string(me.MwType), middleware.Name, logData, err) + } + + pl.SetLogInfo(me.Event, nil, "complete") + } + return nil +} + +func (me *middlewareRunner) RunDeleteMiddleware(middlewares []readDetailMw, input *e.ReadDetailDto, data *e.McuSubSrc) error { + for _, middleware := range middlewares { + logData := pu.GetLogData(input, data) + + pl.SetLogInfo(me.Event, logData, "started", middleware.Name) + + if err := middleware.Func(input, data, me.Tx); err != nil { + return pu.HandleMiddlewareError(me.Event, string(me.MwType), middleware.Name, logData, err) + } + + pl.SetLogInfo(me.Event, nil, "complete") + } + return nil +} + +func (me *middlewareRunner) setMwType(mwType pu.MWType) { + me.MwType = mwType +} diff --git a/internal/use-case/main-use-case/mcu-sub-src/middleware.go b/internal/use-case/main-use-case/mcu-sub-src/middleware.go new file mode 100644 index 00000000..a58ac781 --- /dev/null +++ b/internal/use-case/main-use-case/mcu-sub-src/middleware.go @@ -0,0 +1,9 @@ +package mcusubsrc + +// example of middleware +// func init() { +// createPreMw = append(createPreMw, +// CreateMw{Name: "modif-input", Func: pm.ModifInput}, +// CreateMw{Name: "check-data", Func: pm.CheckData}, +// ) +// } diff --git a/internal/use-case/main-use-case/mcu-sub-src/tycovar.go b/internal/use-case/main-use-case/mcu-sub-src/tycovar.go new file mode 100644 index 00000000..7522ada4 --- /dev/null +++ b/internal/use-case/main-use-case/mcu-sub-src/tycovar.go @@ -0,0 +1,44 @@ +/* +DESCRIPTION: +A sample, part of the package that contains type, constants, and/or variables. + +In this sample it also provides type and variable regarding the needs of the +middleware to separate from main use-case which has the basic CRUD +functionality. The purpose of this is to make the code more maintainable. +*/ +package mcusubsrc + +import ( + "gorm.io/gorm" + + e "simrs-vx/internal/domain/main-entities/mcu-sub-src" +) + +type createMw struct { + Name string + Func func(input *e.CreateDto, data *e.McuSubSrc, tx *gorm.DB) error +} + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data *e.McuSubSrc, tx *gorm.DB) error +} + +type readDetailMw struct { + Name string + Func func(input *e.ReadDetailDto, data *e.McuSubSrc, tx *gorm.DB) error +} + +type UpdateMw = readDetailMw +type DeleteMw = readDetailMw + +var createPreMw []createMw // preprocess middleware +var createPostMw []createMw // postprocess middleware +var readListPreMw []readListMw // .. +var readListPostMw []readListMw // .. +var readDetailPreMw []readDetailMw +var readDetailPostMw []readDetailMw +var updatePreMw []readDetailMw +var updatePostMw []readDetailMw +var deletePreMw []readDetailMw +var deletePostMw []readDetailMw From 37da1ee418ea8398a62ad7fc95df55688c6f1c2a Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Mon, 22 Sep 2025 13:00:23 +0700 Subject: [PATCH 6/7] feat (orders): add guard if parents are done, cant create child --- .../mcu-order-sub-item/entity.go | 4 ++ .../interface/main-handler/main-handler.go | 10 ++- .../main-handler/mcu-order-item/handler.go | 12 ++++ .../mcu-order-sub-item/handler.go | 12 ++++ .../main-use-case/device-order/case.go | 7 ++ .../use-case/main-use-case/encounter/case.go | 4 +- .../use-case/main-use-case/encounter/lib.go | 24 +++++++ .../main-use-case/material-order-item/case.go | 8 +++ .../main-use-case/material-order/case.go | 7 ++ .../main-use-case/material-order/lib.go | 24 +++++++ .../main-use-case/mcu-order-item/case.go | 66 ++++++++++++++++++ .../main-use-case/mcu-order-item/lib.go | 24 +++++++ .../main-use-case/mcu-order-sub-item/case.go | 67 +++++++++++++++++++ .../use-case/main-use-case/mcu-order/case.go | 7 ++ .../use-case/main-use-case/mcu-order/lib.go | 24 +++++++ .../main-use-case/mcu-sub-src/helper.go | 2 +- .../main-use-case/prescription/case.go | 59 ++++++++++++++++ pkg/use-case-helper/use-case-helper.go | 7 ++ 18 files changed, 365 insertions(+), 3 deletions(-) diff --git a/internal/domain/main-entities/mcu-order-sub-item/entity.go b/internal/domain/main-entities/mcu-order-sub-item/entity.go index c3f77361..83ae4d53 100644 --- a/internal/domain/main-entities/mcu-order-sub-item/entity.go +++ b/internal/domain/main-entities/mcu-order-sub-item/entity.go @@ -17,3 +17,7 @@ type McuOrderSubItem struct { Result *string `json:"result"` Status_Code erc.DataStatusCode `json:"status_code"` } + +func (d McuOrderSubItem) IsCompleted() bool { + return d.Status_Code == erc.DSCDone +} diff --git a/internal/interface/main-handler/main-handler.go b/internal/interface/main-handler/main-handler.go index b57ad997..121a2c8d 100644 --- a/internal/interface/main-handler/main-handler.go +++ b/internal/interface/main-handler/main-handler.go @@ -120,7 +120,6 @@ func SetRoutes() http.Handler { hc.RegCrud(r, "/v1/prescription-item", prescriptionitem.O) hc.RegCrud(r, "/v1/device-order-item", deviceorderitem.O) hc.RegCrud(r, "/v1/material-order-item", materialorderitem.O) - hc.RegCrud(r, "/v1/mcu-order-sub-item", mcuordersubitem.O) hk.GroupRoutes("/v1/mcu-order", r, hk.MapHandlerFunc{ "GET /": mcuorder.O.GetList, "GET /{id}": mcuorder.O.GetDetail, @@ -136,8 +135,17 @@ func SetRoutes() http.Handler { "POST /": mcuorderitem.O.Create, "PATCH /{id}": mcuorderitem.O.Update, "DELETE /{id}": mcuorderitem.O.Delete, + "PATCH /{id}/complete": mcuorderitem.O.Complete, "PATCH /{id}/set-schedule": mcuorderitem.O.SetSchedule, }) + hk.GroupRoutes("/v1/mcu-order-sub-item", r, hk.MapHandlerFunc{ + "GET /": mcuordersubitem.O.GetList, + "GET /{id}": mcuordersubitem.O.GetDetail, + "POST /": mcuordersubitem.O.Create, + "PATCH /{id}": mcuordersubitem.O.Update, + "DELETE /{id}": mcuordersubitem.O.Delete, + "PATCH /{id}/complete": mcuordersubitem.O.Complete, + }) hk.GroupRoutes("/v1/encounter", r, hk.MapHandlerFunc{ "GET /": encounter.O.GetList, "GET /{id}": encounter.O.GetDetail, diff --git a/internal/interface/main-handler/mcu-order-item/handler.go b/internal/interface/main-handler/mcu-order-item/handler.go index f407a044..75f5ad6a 100644 --- a/internal/interface/main-handler/mcu-order-item/handler.go +++ b/internal/interface/main-handler/mcu-order-item/handler.go @@ -70,6 +70,18 @@ func (obj myBase) Delete(w http.ResponseWriter, r *http.Request) { 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 { + return + } + + dto := e.ReadDetailDto{} + dto.Id = uint(id) + res, err := u.Complete(dto) + rw.DataResponse(w, res, err) +} + func (obj myBase) SetSchedule(w http.ResponseWriter, r *http.Request) { id := rw.ValidateInt(w, "id", r.PathValue("id")) if id <= 0 { diff --git a/internal/interface/main-handler/mcu-order-sub-item/handler.go b/internal/interface/main-handler/mcu-order-sub-item/handler.go index e36426e0..8e8f8c79 100644 --- a/internal/interface/main-handler/mcu-order-sub-item/handler.go +++ b/internal/interface/main-handler/mcu-order-sub-item/handler.go @@ -69,3 +69,15 @@ func (obj myBase) Delete(w http.ResponseWriter, r *http.Request) { res, err := u.Delete(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 { + return + } + + dto := e.ReadDetailDto{} + dto.Id = uint(id) + res, err := u.Complete(dto) + rw.DataResponse(w, res, err) +} diff --git a/internal/use-case/main-use-case/device-order/case.go b/internal/use-case/main-use-case/device-order/case.go index 96c510c0..66dc1949 100644 --- a/internal/use-case/main-use-case/device-order/case.go +++ b/internal/use-case/main-use-case/device-order/case.go @@ -6,6 +6,8 @@ import ( e "simrs-vx/internal/domain/main-entities/device-order" + ue "simrs-vx/internal/use-case/main-use-case/encounter" + erc "simrs-vx/internal/domain/references/common" dg "github.com/karincake/apem/db-gorm-pg" @@ -38,6 +40,11 @@ func Create(input e.CreateDto) (*d.Data, error) { return err } + // check if encounter is done + if ue.IsDone(*input.Encounter_Id, &event, tx) { + return errors.New("encounter is already done") + } + if resData, err := CreateData(input, &event, tx); err != nil { return err } else { diff --git a/internal/use-case/main-use-case/encounter/case.go b/internal/use-case/main-use-case/encounter/case.go index 437e6b55..c63579cf 100644 --- a/internal/use-case/main-use-case/encounter/case.go +++ b/internal/use-case/main-use-case/encounter/case.go @@ -380,7 +380,9 @@ func CheckOut(input e.DischargeDto) (*d.Data, error) { } if err := createMedication(data.Id, &event, tx); err != nil { - return err + if !pu.IsDataNotFoundError(err) { + return err + } } pl.SetLogInfo(&event, nil, "complete") diff --git a/internal/use-case/main-use-case/encounter/lib.go b/internal/use-case/main-use-case/encounter/lib.go index a0aaa94b..8653cdbf 100644 --- a/internal/use-case/main-use-case/encounter/lib.go +++ b/internal/use-case/main-use-case/encounter/lib.go @@ -178,3 +178,27 @@ func UpdateDischargeData(input e.DischargeDto, data *e.Encounter, event *pl.Even pl.SetLogInfo(event, nil, "complete") return nil } + +func IsDone(encounter_id uint, event *pl.Event, dbx ...*gorm.DB) bool { + pl.SetLogInfo(event, nil, "started", "DBIsDone") + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + var data e.Encounter + if err := tx.Where("\"Id\" = ?", encounter_id).First(&data).Error; err != nil { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-get-fail", + Detail: "Database get failed", + Raw: err, + } + return false + } + + pl.SetLogInfo(event, nil, "complete") + return data.IsDone() +} diff --git a/internal/use-case/main-use-case/material-order-item/case.go b/internal/use-case/main-use-case/material-order-item/case.go index 497c3b02..32d7875d 100644 --- a/internal/use-case/main-use-case/material-order-item/case.go +++ b/internal/use-case/main-use-case/material-order-item/case.go @@ -1,10 +1,13 @@ package materialorderitem import ( + "errors" "strconv" e "simrs-vx/internal/domain/main-entities/material-order-item" + umo "simrs-vx/internal/use-case/main-use-case/material-order" + dg "github.com/karincake/apem/db-gorm-pg" d "github.com/karincake/dodol" @@ -35,6 +38,11 @@ func Create(input e.CreateDto) (*d.Data, error) { return err } + // check if materialOrder is done + if umo.IsCompleted(*input.MaterialOrder_Id, &event, tx) { + return errors.New("materialOrder is already done") + } + if resData, err := CreateData(input, &event, tx); err != nil { return err } else { diff --git a/internal/use-case/main-use-case/material-order/case.go b/internal/use-case/main-use-case/material-order/case.go index 28f41704..bed63695 100644 --- a/internal/use-case/main-use-case/material-order/case.go +++ b/internal/use-case/main-use-case/material-order/case.go @@ -6,6 +6,8 @@ import ( e "simrs-vx/internal/domain/main-entities/material-order" + ue "simrs-vx/internal/use-case/main-use-case/encounter" + erc "simrs-vx/internal/domain/references/common" dg "github.com/karincake/apem/db-gorm-pg" @@ -38,6 +40,11 @@ func Create(input e.CreateDto) (*d.Data, error) { return err } + // check if encounter is done + if ue.IsDone(*input.Encounter_Id, &event, tx) { + return errors.New("encounter is already done") + } + if resData, err := CreateData(input, &event, tx); err != nil { return err } else { diff --git a/internal/use-case/main-use-case/material-order/lib.go b/internal/use-case/main-use-case/material-order/lib.go index 27b91ce1..135aaf54 100644 --- a/internal/use-case/main-use-case/material-order/lib.go +++ b/internal/use-case/main-use-case/material-order/lib.go @@ -153,3 +153,27 @@ func DeleteData(data *e.MaterialOrder, event *pl.Event, dbx ...*gorm.DB) error { pl.SetLogInfo(event, nil, "complete") return nil } + +func IsCompleted(materialOrder_id uint, event *pl.Event, dbx ...*gorm.DB) bool { + pl.SetLogInfo(event, nil, "started", "DBIsCompleted") + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + var data e.MaterialOrder + if err := tx.Where("\"Id\" = ?", materialOrder_id).First(&data).Error; err != nil { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-get-fail", + Detail: "Database get failed", + Raw: err, + } + return false + } + + pl.SetLogInfo(event, nil, "complete") + return data.IsCompleted() +} diff --git a/internal/use-case/main-use-case/mcu-order-item/case.go b/internal/use-case/main-use-case/mcu-order-item/case.go index 899b8120..2b1cacd1 100644 --- a/internal/use-case/main-use-case/mcu-order-item/case.go +++ b/internal/use-case/main-use-case/mcu-order-item/case.go @@ -6,6 +6,10 @@ import ( e "simrs-vx/internal/domain/main-entities/mcu-order-item" + umo "simrs-vx/internal/use-case/main-use-case/mcu-order" + + erc "simrs-vx/internal/domain/references/common" + dg "github.com/karincake/apem/db-gorm-pg" d "github.com/karincake/dodol" @@ -36,6 +40,11 @@ func Create(input e.CreateDto) (*d.Data, error) { return err } + // check if mcuOrder is done + if umo.IsCompleted(*input.McuOrder_Id, &event, tx) { + return errors.New("mcuOrder is already done") + } + if resData, err := CreateData(input, &event, tx); err != nil { return err } else { @@ -279,6 +288,63 @@ func Delete(input e.DeleteDto) (*d.Data, error) { } +func Complete(input e.ReadDetailDto) (*d.Data, error) { + var data *e.McuOrderItem + var err error + + event := pl.Event{ + Feature: "Complete", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "complete") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + data, err = ReadDetailData(input, &event, tx) + if err != nil { + return err + } + + if data.IsCompleted() { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-state-mismatch", + Detail: "mcuOrderItem is already completed", + Raw: errors.New("mcuOrderItem is already completed"), + } + return pl.SetLogError(&event, input) + } + + data.Status_Code = erc.DSCDone + 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": "fetched", + }, + Data: data.ToResponse(), + }, nil +} + func SetSchedule(input e.SetScheduleDto) (*d.Data, error) { rdDto := e.ReadDetailDto{Id: input.Id} var data *e.McuOrderItem diff --git a/internal/use-case/main-use-case/mcu-order-item/lib.go b/internal/use-case/main-use-case/mcu-order-item/lib.go index be5c0374..40ebf33d 100644 --- a/internal/use-case/main-use-case/mcu-order-item/lib.go +++ b/internal/use-case/main-use-case/mcu-order-item/lib.go @@ -153,3 +153,27 @@ func DeleteData(data *e.McuOrderItem, event *pl.Event, dbx ...*gorm.DB) error { pl.SetLogInfo(event, nil, "complete") return nil } + +func IsCompleted(mcuOrderItem_id uint, event *pl.Event, dbx ...*gorm.DB) bool { + pl.SetLogInfo(event, nil, "started", "DBIsCompleted") + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + var data e.McuOrderItem + if err := tx.Where("\"Id\" = ?", mcuOrderItem_id).First(&data).Error; err != nil { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-get-fail", + Detail: "Database get failed", + Raw: err, + } + return false + } + + pl.SetLogInfo(event, nil, "complete") + return data.IsCompleted() +} diff --git a/internal/use-case/main-use-case/mcu-order-sub-item/case.go b/internal/use-case/main-use-case/mcu-order-sub-item/case.go index bf3e4ce9..88684bff 100644 --- a/internal/use-case/main-use-case/mcu-order-sub-item/case.go +++ b/internal/use-case/main-use-case/mcu-order-sub-item/case.go @@ -1,10 +1,15 @@ package mcuordersubitem import ( + "errors" "strconv" e "simrs-vx/internal/domain/main-entities/mcu-order-sub-item" + umoi "simrs-vx/internal/use-case/main-use-case/mcu-order-item" + + erc "simrs-vx/internal/domain/references/common" + dg "github.com/karincake/apem/db-gorm-pg" d "github.com/karincake/dodol" @@ -35,6 +40,11 @@ func Create(input e.CreateDto) (*d.Data, error) { return err } + // check if mcuOrderItem is done + if umoi.IsCompleted(*input.McuOrderItem_Id, &event, tx) { + return errors.New("mcuOrderItem is already done") + } + if resData, err := CreateData(input, &event, tx); err != nil { return err } else { @@ -277,3 +287,60 @@ func Delete(input e.DeleteDto) (*d.Data, error) { }, nil } + +func Complete(input e.ReadDetailDto) (*d.Data, error) { + var data *e.McuOrderSubItem + var err error + + event := pl.Event{ + Feature: "Complete", + Source: source, + } + + // Start log + pl.SetLogInfo(&event, input, "started", "complete") + + err = dg.I.Transaction(func(tx *gorm.DB) error { + data, err = ReadDetailData(input, &event, tx) + if err != nil { + return err + } + + if data.IsCompleted() { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-state-mismatch", + Detail: "mcuOrderSubItem is already completed", + Raw: errors.New("mcuOrderSubItem is already completed"), + } + return pl.SetLogError(&event, input) + } + + data.Status_Code = erc.DSCDone + 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": "fetched", + }, + Data: data.ToResponse(), + }, nil +} 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 57de98fb..158a4995 100644 --- a/internal/use-case/main-use-case/mcu-order/case.go +++ b/internal/use-case/main-use-case/mcu-order/case.go @@ -6,6 +6,8 @@ import ( e "simrs-vx/internal/domain/main-entities/mcu-order" + ue "simrs-vx/internal/use-case/main-use-case/encounter" + erc "simrs-vx/internal/domain/references/common" dg "github.com/karincake/apem/db-gorm-pg" @@ -38,6 +40,11 @@ func Create(input e.CreateDto) (*d.Data, error) { return err } + // check if encounter is done + if ue.IsDone(*input.Encounter_Id, &event, tx) { + return errors.New("encounter is already done") + } + if resData, err := CreateData(input, &event, tx); err != nil { return err } else { diff --git a/internal/use-case/main-use-case/mcu-order/lib.go b/internal/use-case/main-use-case/mcu-order/lib.go index 1cfd7adc..048e6129 100644 --- a/internal/use-case/main-use-case/mcu-order/lib.go +++ b/internal/use-case/main-use-case/mcu-order/lib.go @@ -153,3 +153,27 @@ func DeleteData(data *e.McuOrder, event *pl.Event, dbx ...*gorm.DB) error { pl.SetLogInfo(event, nil, "complete") return nil } + +func IsCompleted(mcuOrder_id uint, event *pl.Event, dbx ...*gorm.DB) bool { + pl.SetLogInfo(event, nil, "started", "DBIsCompleted") + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + var data e.McuOrder + if err := tx.Where("\"Id\" = ?", mcuOrder_id).First(&data).Error; err != nil { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-get-fail", + Detail: "Database get failed", + Raw: err, + } + return false + } + + pl.SetLogInfo(event, nil, "complete") + return data.IsCompleted() +} diff --git a/internal/use-case/main-use-case/mcu-sub-src/helper.go b/internal/use-case/main-use-case/mcu-sub-src/helper.go index 071d5f38..95444d5a 100644 --- a/internal/use-case/main-use-case/mcu-sub-src/helper.go +++ b/internal/use-case/main-use-case/mcu-sub-src/helper.go @@ -37,7 +37,7 @@ func createItem(input *e.CreateDto, event *pl.Event, tx *gorm.DB) error { itemCreate := ei.CreateDto{ Code: pu.AddPrefix("mcuSub-", input.Code), Name: input.Name, - ItemGroup_Code: ero.ITGCMCU, + ItemGroup_Code: ero.ITGCMCUSub, // Uom_Code: &input.Uom_Code, // Infra_Id: input.Infra_Id, } diff --git a/internal/use-case/main-use-case/prescription/case.go b/internal/use-case/main-use-case/prescription/case.go index 9b0baeb2..43c0a9e9 100644 --- a/internal/use-case/main-use-case/prescription/case.go +++ b/internal/use-case/main-use-case/prescription/case.go @@ -277,3 +277,62 @@ func Delete(input e.DeleteDto) (*d.Data, error) { }, nil } + +// func Approve(input e.ReadDetailDto) (*d.Data, error) { +// var data *e.Prescription +// var err error + +// event := pl.Event{ +// Feature: "Approve", +// Source: source, +// } + +// // Start log +// pl.SetLogInfo(&event, input, "started", "approve") + +// err = dg.I.Transaction(func(tx *gorm.DB) error { +// data, err = ReadDetailData(input, &event, tx) +// if err != nil { +// return err +// } + +// if data.IsApproved() { +// event.Status = "failed" +// event.ErrInfo = pl.ErrorInfo{ +// Code: "data-state-mismatch", +// Detail: "prescription is already approved", +// Raw: errors.New("prescription is already approved"), +// } +// return pl.SetLogError(&event, input) +// } + +// data.Status_Code = erc.DSCApproved +// 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": "approved", +// }, +// Data: data.ToResponse(), +// }, nil + +// } diff --git a/pkg/use-case-helper/use-case-helper.go b/pkg/use-case-helper/use-case-helper.go index 9fd8351d..04a8eada 100644 --- a/pkg/use-case-helper/use-case-helper.go +++ b/pkg/use-case-helper/use-case-helper.go @@ -103,6 +103,13 @@ func HandleMiddlewareError(event *pl.Event, mwType, mwName string, logData inter return pl.SetLogError(event, logData) } +func IsDataNotFoundError(err error) bool { + if err == nil { + return false + } + return strings.Contains(err.Error(), "code: data-notFound") +} + func AddPrefix(prefix string, str string) string { return prefix + str } From 202bb32e9c8ed2bd84966a9942cb59ed64e11d11 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Mon, 22 Sep 2025 13:21:29 +0700 Subject: [PATCH 7/7] feat (prescription): add approve + create medication --- .../domain/main-entities/prescription/dto.go | 20 ++-- .../main-entities/prescription/entity.go | 4 + .../interface/main-handler/main-handler.go | 9 +- .../main-handler/prescription/handler.go | 12 ++ .../main-use-case/prescription/case.go | 103 +++++++++-------- .../main-use-case/prescription/helper.go | 107 ++++++++++++++++++ 6 files changed, 196 insertions(+), 59 deletions(-) diff --git a/internal/domain/main-entities/prescription/dto.go b/internal/domain/main-entities/prescription/dto.go index e693a1c2..107509e1 100644 --- a/internal/domain/main-entities/prescription/dto.go +++ b/internal/domain/main-entities/prescription/dto.go @@ -11,10 +11,10 @@ import ( ) type CreateDto struct { - Encounter_Id *uint `json:"encounter_id"` - Doctor_Id *uint `json:"doctor_id"` - IssuedAt *time.Time `json:"issuedAt"` - Status_Code *erc.DataStatusCode `json:"status_code"` + Encounter_Id *uint `json:"encounter_id"` + Doctor_Id *uint `json:"doctor_id"` + IssuedAt *time.Time `json:"issuedAt"` + Status_Code erc.DataStatusCode `json:"status_code"` } type ReadListDto struct { @@ -55,12 +55,12 @@ type MetaDto struct { type ResponseDto struct { ecore.Main - Encounter_Id *uint `json:"encounter_id"` - Encounter *ee.Encounter `json:"encounter,omitempty"` - Doctor_Id *uint `json:"doctor_id"` - Doctor *ed.Doctor `json:"doctor,omitempty"` - IssuedAt *time.Time `json:"issuedAt"` - Status_Code *erc.DataStatusCode `json:"status_code"` + Encounter_Id *uint `json:"encounter_id"` + Encounter *ee.Encounter `json:"encounter,omitempty"` + Doctor_Id *uint `json:"doctor_id"` + Doctor *ed.Doctor `json:"doctor,omitempty"` + IssuedAt *time.Time `json:"issuedAt"` + Status_Code erc.DataStatusCode `json:"status_code"` } func (d Prescription) ToResponse() ResponseDto { diff --git a/internal/domain/main-entities/prescription/entity.go b/internal/domain/main-entities/prescription/entity.go index 20386bf4..bdc2d2fb 100644 --- a/internal/domain/main-entities/prescription/entity.go +++ b/internal/domain/main-entities/prescription/entity.go @@ -19,3 +19,7 @@ type Prescription struct { IssuedAt *time.Time `json:"issuedAt"` Status_Code erc.DataStatusCode `json:"status_code"` } + +func (d Prescription) IsApproved() bool { + return d.Status_Code == erc.DSCDone +} diff --git a/internal/interface/main-handler/main-handler.go b/internal/interface/main-handler/main-handler.go index 121a2c8d..930e30f1 100644 --- a/internal/interface/main-handler/main-handler.go +++ b/internal/interface/main-handler/main-handler.go @@ -116,7 +116,6 @@ func SetRoutes() http.Handler { hc.RegCrud(r, "/v1/soapi", auth.GuardMW, soapi.O) hc.RegCrud(r, "/v1/adime", auth.GuardMW, adime.O) hc.RegCrud(r, "/v1/sbar", auth.GuardMW, sbar.O) - hc.RegCrud(r, "/v1/prescription", prescription.O) hc.RegCrud(r, "/v1/prescription-item", prescriptionitem.O) hc.RegCrud(r, "/v1/device-order-item", deviceorderitem.O) hc.RegCrud(r, "/v1/material-order-item", materialorderitem.O) @@ -138,6 +137,14 @@ func SetRoutes() http.Handler { "PATCH /{id}/complete": mcuorderitem.O.Complete, "PATCH /{id}/set-schedule": mcuorderitem.O.SetSchedule, }) + hk.GroupRoutes("/v1/prescription", r, hk.MapHandlerFunc{ + "GET /": prescription.O.GetList, + "GET /{id}": prescription.O.GetDetail, + "POST /": prescription.O.Create, + "PATCH /{id}": prescription.O.Update, + "DELETE /{id}": prescription.O.Delete, + "PATCH /{id}/approve": prescription.O.Approve, + }) hk.GroupRoutes("/v1/mcu-order-sub-item", r, hk.MapHandlerFunc{ "GET /": mcuordersubitem.O.GetList, "GET /{id}": mcuordersubitem.O.GetDetail, diff --git a/internal/interface/main-handler/prescription/handler.go b/internal/interface/main-handler/prescription/handler.go index 1ac30d97..fe73e3fe 100644 --- a/internal/interface/main-handler/prescription/handler.go +++ b/internal/interface/main-handler/prescription/handler.go @@ -69,3 +69,15 @@ func (obj myBase) Delete(w http.ResponseWriter, r *http.Request) { res, err := u.Delete(dto) rw.DataResponse(w, res, err) } + +func (obj myBase) Approve(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.Approve(dto) + rw.DataResponse(w, res, err) +} diff --git a/internal/use-case/main-use-case/prescription/case.go b/internal/use-case/main-use-case/prescription/case.go index 43c0a9e9..ce9bc9ba 100644 --- a/internal/use-case/main-use-case/prescription/case.go +++ b/internal/use-case/main-use-case/prescription/case.go @@ -1,10 +1,13 @@ package prescription import ( + "errors" "strconv" e "simrs-vx/internal/domain/main-entities/prescription" + erc "simrs-vx/internal/domain/references/common" + dg "github.com/karincake/apem/db-gorm-pg" d "github.com/karincake/dodol" @@ -278,61 +281,65 @@ func Delete(input e.DeleteDto) (*d.Data, error) { } -// func Approve(input e.ReadDetailDto) (*d.Data, error) { -// var data *e.Prescription -// var err error +func Approve(input e.ReadDetailDto) (*d.Data, error) { + var data *e.Prescription + var err error -// event := pl.Event{ -// Feature: "Approve", -// Source: source, -// } + event := pl.Event{ + Feature: "Approve", + Source: source, + } -// // Start log -// pl.SetLogInfo(&event, input, "started", "approve") + // Start log + pl.SetLogInfo(&event, input, "started", "approve") -// err = dg.I.Transaction(func(tx *gorm.DB) error { -// data, err = ReadDetailData(input, &event, tx) -// if err != nil { -// return err -// } + err = dg.I.Transaction(func(tx *gorm.DB) error { + data, err = ReadDetailData(input, &event, tx) + if err != nil { + return err + } -// if data.IsApproved() { -// event.Status = "failed" -// event.ErrInfo = pl.ErrorInfo{ -// Code: "data-state-mismatch", -// Detail: "prescription is already approved", -// Raw: errors.New("prescription is already approved"), -// } -// return pl.SetLogError(&event, input) -// } + if data.IsApproved() { + event.Status = "failed" + event.ErrInfo = pl.ErrorInfo{ + Code: "data-state-mismatch", + Detail: "prescription is already approved", + Raw: errors.New("prescription is already approved"), + } + return pl.SetLogError(&event, input) + } -// data.Status_Code = erc.DSCApproved -// 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) -// } + data.Status_Code = erc.DSCDone + 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") + if err := createMedication(input.Id, &event, tx); err != nil { + return err + } -// return nil -// }) + pl.SetLogInfo(&event, nil, "complete") -// if err != nil { -// return nil, err -// } + return nil + }) -// return &d.Data{ -// Meta: d.IS{ -// "source": source, -// "structure": "single-data", -// "status": "approved", -// }, -// Data: data.ToResponse(), -// }, nil + if err != nil { + return nil, err + } -// } + return &d.Data{ + Meta: d.IS{ + "source": source, + "structure": "single-data", + "status": "approved", + }, + Data: data.ToResponse(), + }, nil + +} diff --git a/internal/use-case/main-use-case/prescription/helper.go b/internal/use-case/main-use-case/prescription/helper.go index 13f8f2e6..7c61469b 100644 --- a/internal/use-case/main-use-case/prescription/helper.go +++ b/internal/use-case/main-use-case/prescription/helper.go @@ -5,7 +5,23 @@ Any functions that are used internally by the use-case package prescription import ( + em "simrs-vx/internal/domain/main-entities/medication" + emei "simrs-vx/internal/domain/main-entities/medication-item" + emi "simrs-vx/internal/domain/main-entities/medicine-mix" + emmi "simrs-vx/internal/domain/main-entities/medicine-mix-item" e "simrs-vx/internal/domain/main-entities/prescription" + epi "simrs-vx/internal/domain/main-entities/prescription-item" + + um "simrs-vx/internal/use-case/main-use-case/medication" + umei "simrs-vx/internal/use-case/main-use-case/medication-item" + umi "simrs-vx/internal/use-case/main-use-case/medicine-mix" + ummi "simrs-vx/internal/use-case/main-use-case/medicine-mix-item" + upi "simrs-vx/internal/use-case/main-use-case/prescription-item" + + pl "simrs-vx/pkg/logger" + pu "simrs-vx/pkg/use-case-helper" + + "gorm.io/gorm" ) func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Prescription) { @@ -22,3 +38,94 @@ func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.Prescription) { data.IssuedAt = inputSrc.IssuedAt data.Status_Code = inputSrc.Status_Code } + +func createMedication(prescription_id uint, event *pl.Event, tx *gorm.DB) error { + pl.SetLogInfo(event, nil, "started", "createMedication") + + prescription, err := ReadDetailData(e.ReadDetailDto{Id: prescription_id}, event, tx) + if err != nil { + return err + } + + prescriptionItem, _, err := upi.ReadListData(epi.ReadListDto{FilterDto: epi.FilterDto{Prescription_Id: &prescription.Id}}, event, tx) + if err != nil { + return err + } + + if len(prescriptionItem) == 0 { + return nil + } + + medicationCreate := em.CreateDto{ + Encounter_Id: prescription.Encounter_Id, + IssuedAt: pu.GetTimeNow(), + } + medication, err := um.CreateData(medicationCreate, event, tx) + if err != nil { + return err + } + + for _, prescriptionItem := range prescriptionItem { + if prescriptionItem.IsMix { + medMix_id, err := createMedicineMixAndItem(*prescriptionItem.MedicineMix, event, tx) + if err != nil { + return err + } + prescriptionItem.MedicineMix_Id = medMix_id + } + err := createMedicationItem(medication.Id, prescriptionItem, event, tx) + if err != nil { + return err + } + } + return nil +} + +func createMedicineMixAndItem(input emi.MedicineMix, event *pl.Event, tx *gorm.DB) (*uint, error) { + pl.SetLogInfo(event, nil, "started", "createMedicineMix") + + medicineMixCreate := emi.CreateDto{ + Name: input.Name, + } + medicineMix, err := umi.CreateData(medicineMixCreate, event, tx) + if err != nil { + return nil, err + } + + // recreate medicineMixItem with new medicineMix_id to keep medMixItem remain the same for prescriptionItem that is created + for _, medicineMixItem := range input.MixItems { + medicineMixItemCreate := emmi.CreateDto{ + MedicineMix_Id: &medicineMix.Id, + Medicine_Id: medicineMixItem.Medicine_Id, + Dose: medicineMixItem.Dose, + } + _, err := ummi.CreateData(medicineMixItemCreate, event, tx) + if err != nil { + return nil, err + } + + } + return &medicineMix.Id, nil +} + +func createMedicationItem(medication_id uint, input epi.PrescriptionItem, event *pl.Event, tx *gorm.DB) error { + pl.SetLogInfo(event, nil, "started", "createMedicationItem") + + medicationItemCreate := emei.CreateDto{ + Medication_Id: &medication_id, + IsMix: input.IsMix, + Medicine_Id: input.Medicine_Id, + MedicineMix_Id: input.MedicineMix_Id, + Usage: input.Usage, + Interval: input.Interval, + IntervalUnit_Code: input.IntervalUnit_Code, + Quantity: input.Quantity, + } + + _, err := umei.CreateData(medicationItemCreate, event, tx) + if err != nil { + return err + } + + return nil +}