feat (prescription): add approve + create medication

This commit is contained in:
dpurbosakti
2025-09-22 13:21:29 +07:00
parent 02c86a9ec0
commit 202bb32e9c
6 changed files with 196 additions and 59 deletions
@@ -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 {
@@ -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
}
@@ -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,
@@ -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)
}
@@ -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
}
@@ -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
}