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 +}