From f207b2716f762f3ed260ed4ef2b4064bb45567c0 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Wed, 19 Nov 2025 14:10:28 +0700 Subject: [PATCH 1/7] adjust control letter template html --- assets/docs/control-letter.html | 132 ++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 assets/docs/control-letter.html diff --git a/assets/docs/control-letter.html b/assets/docs/control-letter.html new file mode 100644 index 00000000..10425b28 --- /dev/null +++ b/assets/docs/control-letter.html @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + +
+ logo + +
+ SURAT RENCANA KONTROL +
+
+ RSUD dr. Saiful Anwar +
+
+
+ No. :replace +
+
+
+ Kepada Yth +
+
+
+ DANI SETIAWAN +
+
+ Sp./Sub. Rehabilitasi Medik +
+
+ +
+ Mohon Pemeriksaan dan Penanganan Lebih Lanjut: +
+ + + + + + + + + + + + + + + + + + + + + + + +
+ No.Kartu + + :Replace +
+ Nama Peserta + + :Replace +
+ Tgl.Lahir + + :Replace +
+ Diagnosa + + :Replace +
+ Rencana Kontrol + + :Replace +
+ +
+ Demikian atas bantuannya, diucapkan banyak terima kasih. +
+ + + + + + +
+ Mengetahui, DPJP :Replace +
+ +
+ Tgl. Entry: 2025-06-07 | Tgl. Cetak: 07-06-2025 16:52 PM +
+ +
+ + + \ No newline at end of file From a5ea881e1f6ff35be2d71acdaa63fd7bca7f9302 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Wed, 19 Nov 2025 16:17:23 +0700 Subject: [PATCH 2/7] wip, need to test --- assets/docs/control-letter.html | 20 +- .../vclaim-sep-control-letter/dto.go | 16 +- .../domain/references/encounter/encounter.go | 1 + .../vclaim-sep-control-letter/case.go | 277 ++++++++++++++++++ .../vclaim-sep-control-letter/helper.go | 24 ++ .../vclaim-sep-control-letter/lib.go | 148 ++++++++++ .../middleware-runner.go | 103 +++++++ .../vclaim-sep-control-letter/middleware.go | 9 + .../vclaim-sep-control-letter/tycovar.go | 44 +++ .../main-use-case/generate-file/case.go | 97 +++++- .../main-use-case/generate-file/tycovar.go | 61 +++- 11 files changed, 775 insertions(+), 25 deletions(-) create mode 100644 internal/use-case/bpjs-use-case/vclaim-sep-control-letter/case.go create mode 100644 internal/use-case/bpjs-use-case/vclaim-sep-control-letter/helper.go create mode 100644 internal/use-case/bpjs-use-case/vclaim-sep-control-letter/lib.go create mode 100644 internal/use-case/bpjs-use-case/vclaim-sep-control-letter/middleware-runner.go create mode 100644 internal/use-case/bpjs-use-case/vclaim-sep-control-letter/middleware.go create mode 100644 internal/use-case/bpjs-use-case/vclaim-sep-control-letter/tycovar.go diff --git a/assets/docs/control-letter.html b/assets/docs/control-letter.html index 10425b28..c55c7b9d 100644 --- a/assets/docs/control-letter.html +++ b/assets/docs/control-letter.html @@ -37,7 +37,7 @@
- No. :replace + No. : {{ .Number }}
@@ -52,10 +52,10 @@
- DANI SETIAWAN + {{ .Doctor_Name }}
- Sp./Sub. Rehabilitasi Medik + Sp./Sub. {{ .DstUnit_Name }}
@@ -72,7 +72,7 @@ No.Kartu - :Replace + : {{ .CardNumber }} @@ -80,7 +80,7 @@ Nama Peserta - :Replace + : {{ .Name }} @@ -88,7 +88,7 @@ Tgl.Lahir - :Replace + : {{ .BirthDate }} @@ -96,7 +96,7 @@ Diagnosa - :Replace + : {{ .Diagnose }} @@ -104,7 +104,7 @@ Rencana Kontrol - :Replace + : {{ .PlanDate }} @@ -117,13 +117,13 @@ - Mengetahui, DPJP :Replace + Mengetahui, DPJP : {{ .ResponsibleDoctor_Name }}
- Tgl. Entry: 2025-06-07 | Tgl. Cetak: 07-06-2025 16:52 PM + Tgl. Cetak : {{ .PrintDate }}
diff --git a/internal/domain/bpjs-entities/vclaim-sep-control-letter/dto.go b/internal/domain/bpjs-entities/vclaim-sep-control-letter/dto.go index f12b57da..19530c2c 100644 --- a/internal/domain/bpjs-entities/vclaim-sep-control-letter/dto.go +++ b/internal/domain/bpjs-entities/vclaim-sep-control-letter/dto.go @@ -6,6 +6,9 @@ import ( type CreateDto struct { VclaimSep_Number *string `json:"vclaimSep_number"` + Number *string `json:"number" gorm:"unique;size:20"` + Value *string `json:"value"` + FileUrl *string `json:"fileUrl" gorm:"unique;size:1024"` } type ReadListDto struct { @@ -20,7 +23,8 @@ type FilterDto struct { } type ReadDetailDto struct { - Id uint `json:"id"` + Id *uint `json:"id"` + Number *string `json:"number"` } type UpdateDto struct { @@ -29,7 +33,8 @@ type UpdateDto struct { } type DeleteDto struct { - Id uint `json:"id"` + Id uint `json:"id"` + Number *string `json:"number"` } type MetaDto struct { @@ -41,12 +46,17 @@ type MetaDto struct { type ResponseDto struct { ecore.Main VclaimSep_Number *string `json:"vclaimSep_number"` - Counter *uint `json:"counter"` + Number *string `json:"number"` + Value *string `json:"value"` + FileUrl *string `json:"fileUrl"` } func (d VclaimSepControlLetter) ToResponse() ResponseDto { resp := ResponseDto{ VclaimSep_Number: d.VclaimSep_Number, + Number: d.Number, + Value: d.Value, + FileUrl: d.FileUrl, } resp.Main = d.Main return resp diff --git a/internal/domain/references/encounter/encounter.go b/internal/domain/references/encounter/encounter.go index 532e1625..1acee75b 100644 --- a/internal/domain/references/encounter/encounter.go +++ b/internal/domain/references/encounter/encounter.go @@ -120,6 +120,7 @@ const ( DTCSEP DocTypeCode = "vclaim-sep" // SEP DTCSIPP DocTypeCode = "vclaim-sipp" // SIPP DTCGC DocTypeCode = "general-consent" + DTCVSCL DocTypeCode = "vclaim-control-letter" // vclaim control letter ETCPerson EntityTypeCode = "person" ETCEncounter EntityTypeCode = "encounter" diff --git a/internal/use-case/bpjs-use-case/vclaim-sep-control-letter/case.go b/internal/use-case/bpjs-use-case/vclaim-sep-control-letter/case.go new file mode 100644 index 00000000..7c19819f --- /dev/null +++ b/internal/use-case/bpjs-use-case/vclaim-sep-control-letter/case.go @@ -0,0 +1,277 @@ +package vclaimsepcontrolletter + +import ( + "strconv" + + e "simrs-vx/internal/domain/bpjs-entities/vclaim-sep-control-letter" + + 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 = "vclaim-sep-control-letter" + +func Create(input e.CreateDto) (*d.Data, error) { + data := e.VclaimSepControlLetter{} + + 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.VclaimSepControlLetter + var dataList []e.VclaimSepControlLetter + 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 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), + "record_currentCount": strconv.Itoa(len(dataList)), + }, + Data: e.ToResponseList(dataList), + }, nil +} + +func ReadDetail(input e.ReadDetailDto) (*d.Data, error) { + var data *e.VclaimSepControlLetter + 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{Number: input.Number} + var data *e.VclaimSepControlLetter + 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{Number: input.Number} + var data *e.VclaimSepControlLetter + 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/bpjs-use-case/vclaim-sep-control-letter/helper.go b/internal/use-case/bpjs-use-case/vclaim-sep-control-letter/helper.go new file mode 100644 index 00000000..891e7c4d --- /dev/null +++ b/internal/use-case/bpjs-use-case/vclaim-sep-control-letter/helper.go @@ -0,0 +1,24 @@ +/* +DESCRIPTION: +Any functions that are used internally by the use-case +*/ +package vclaimsepcontrolletter + +import ( + e "simrs-vx/internal/domain/bpjs-entities/vclaim-sep-control-letter" +) + +func setData[T *e.CreateDto | *e.UpdateDto](input T, data *e.VclaimSepControlLetter) { + var inputSrc *e.CreateDto + if inputT, ok := any(input).(*e.CreateDto); ok { + inputSrc = inputT + } else { + inputTemp := any(input).(*e.UpdateDto) + inputSrc = &inputTemp.CreateDto + } + + data.VclaimSep_Number = inputSrc.VclaimSep_Number + data.Number = inputSrc.Number + data.Value = inputSrc.Value + data.FileUrl = inputSrc.FileUrl +} diff --git a/internal/use-case/bpjs-use-case/vclaim-sep-control-letter/lib.go b/internal/use-case/bpjs-use-case/vclaim-sep-control-letter/lib.go new file mode 100644 index 00000000..9f66baff --- /dev/null +++ b/internal/use-case/bpjs-use-case/vclaim-sep-control-letter/lib.go @@ -0,0 +1,148 @@ +package vclaimsepcontrolletter + +import ( + e "simrs-vx/internal/domain/bpjs-entities/vclaim-sep-control-letter" + + plh "simrs-vx/pkg/lib-helper" + 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.VclaimSepControlLetter, error) { + pl.SetLogInfo(event, nil, "started", "DBCreate") + + data := e.VclaimSepControlLetter{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + setData(&input, &data) + + if err := tx.Create(&data).Error; err != nil { + return nil, plh.HandleCreateError(input, event, err) + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func ReadListData(input e.ReadListDto, event *pl.Event, dbx ...*gorm.DB) ([]e.VclaimSepControlLetter, *e.MetaDto, error) { + pl.SetLogInfo(event, input, "started", "DBReadList") + data := []e.VclaimSepControlLetter{} + pagination := gh.Pagination{} + count := int64(0) + meta := e.MetaDto{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + tx = tx. + Model(&e.VclaimSepControlLetter{}). + Scopes(gh.Preload(input.Includes)). + Scopes(gh.Filter(input.FilterDto)). + Count(&count). + Scopes(gh.Paginate(input, &pagination)). + Scopes(gh.Sort(input.Sort)) + + if err := tx.Find(&data).Error; err != nil { + if err == gorm.ErrRecordNotFound { + return nil, &meta, nil + } + return nil, nil, plh.HandleListError(input, event, err) + } + + 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.VclaimSepControlLetter, error) { + pl.SetLogInfo(event, input, "started", "DBReadDetail") + data := e.VclaimSepControlLetter{} + + var tx *gorm.DB + if len(dbx) > 0 { + tx = dbx[0] + } else { + tx = dg.I + } + + if input.Number != nil { + tx = tx.Where("\"Number\" = ?", *input.Number) + } + if input.Id != nil { + 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 + } + } + + pl.SetLogInfo(event, nil, "complete") + return &data, nil +} + +func UpdateData(input e.UpdateDto, data *e.VclaimSepControlLetter, 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.VclaimSepControlLetter, 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/bpjs-use-case/vclaim-sep-control-letter/middleware-runner.go b/internal/use-case/bpjs-use-case/vclaim-sep-control-letter/middleware-runner.go new file mode 100644 index 00000000..c0a0ecae --- /dev/null +++ b/internal/use-case/bpjs-use-case/vclaim-sep-control-letter/middleware-runner.go @@ -0,0 +1,103 @@ +package vclaimsepcontrolletter + +import ( + e "simrs-vx/internal/domain/bpjs-entities/vclaim-sep-control-letter" + 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.VclaimSepControlLetter) 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.VclaimSepControlLetter) 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.VclaimSepControlLetter) 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.VclaimSepControlLetter) 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.VclaimSepControlLetter) 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/bpjs-use-case/vclaim-sep-control-letter/middleware.go b/internal/use-case/bpjs-use-case/vclaim-sep-control-letter/middleware.go new file mode 100644 index 00000000..57262cc2 --- /dev/null +++ b/internal/use-case/bpjs-use-case/vclaim-sep-control-letter/middleware.go @@ -0,0 +1,9 @@ +package vclaimsepcontrolletter + +// 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/bpjs-use-case/vclaim-sep-control-letter/tycovar.go b/internal/use-case/bpjs-use-case/vclaim-sep-control-letter/tycovar.go new file mode 100644 index 00000000..2e921ae9 --- /dev/null +++ b/internal/use-case/bpjs-use-case/vclaim-sep-control-letter/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 vclaimsepcontrolletter + +import ( + "gorm.io/gorm" + + e "simrs-vx/internal/domain/bpjs-entities/vclaim-sep-control-letter" +) + +type createMw struct { + Name string + Func func(input *e.CreateDto, data *e.VclaimSepControlLetter, tx *gorm.DB) error +} + +type readListMw struct { + Name string + Func func(input *e.ReadListDto, data *e.VclaimSepControlLetter, tx *gorm.DB) error +} + +type readDetailMw struct { + Name string + Func func(input *e.ReadDetailDto, data *e.VclaimSepControlLetter, 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/generate-file/case.go b/internal/use-case/main-use-case/generate-file/case.go index 1c3ca51b..f0e71203 100644 --- a/internal/use-case/main-use-case/generate-file/case.go +++ b/internal/use-case/main-use-case/generate-file/case.go @@ -4,9 +4,15 @@ import ( "encoding/json" "errors" + evs "simrs-vx/internal/domain/bpjs-entities/vclaim-sep" + evscl "simrs-vx/internal/domain/bpjs-entities/vclaim-sep-control-letter" egc "simrs-vx/internal/domain/main-entities/general-consent" + + uvs "simrs-vx/internal/use-case/bpjs-use-case/vclaim-sep" + uvscl "simrs-vx/internal/use-case/bpjs-use-case/vclaim-sep-control-letter" ugc "simrs-vx/internal/use-case/main-use-case/general-consent" + pc "simrs-vx/pkg/conv-helper" pl "simrs-vx/pkg/logger" pu "simrs-vx/pkg/use-case-helper" @@ -25,6 +31,8 @@ func Generate(input GenerateDto) (*d.Data, error) { Source: source, } + var response ResponseDto + // Start log pl.SetLogInfo(&event, input, "started", "create") @@ -32,7 +40,7 @@ func Generate(input GenerateDto) (*d.Data, error) { // general-consent case ere.DTCGC: // get value from general consent by ref_id - gc, err := ugc.ReadDetailData(egc.ReadDetailDto{Id: *input.Ref_Id}, &event) + gc, err := ugc.ReadDetailData(egc.ReadDetailDto{Id: uint(*pc.StringToUint64(*input.Ref_Id))}, &event) if err != nil { return nil, err } @@ -75,20 +83,89 @@ func Generate(input GenerateDto) (*d.Data, error) { return nil, err } - response := ResponseDto{ + response = ResponseDto{ + FileUrl: urlPub, + } + + // control-letter + case ere.DTCVSCL: + // get value from control letter by ref_id + cl, err := uvscl.ReadDetailData(evscl.ReadDetailDto{Number: input.Ref_Id}, &event) + if err != nil { + if !pu.IsDataNotFoundError(err) { + return nil, err + } + } + + if cl != nil && cl.FileUrl != nil { + if err := removeFile(string(input.EntityType_Code), *cl.FileUrl); err != nil { + return nil, err + } + } + + // map template data + clData := VclaimControlLetter{} + if input.Data != nil { + err := json.Unmarshal([]byte(*input.Data), &clData) + if err != nil { + event.ErrInfo = pl.ErrorInfo{ + Code: "data-unmarshal-fail", + Detail: err.Error(), + Raw: err, + } + return nil, err + } + } else { + return nil, errors.New("there is no data to be used") + } + + if cl == nil { + createCL := evscl.CreateDto{ + VclaimSep_Number: &clData.VclaimSep.Number, + Number: &clData.Number, + Value: input.Data, + } + if cl, err = uvscl.CreateData(createCL, &event); err != nil { + return nil, err + } + + } + // get encounter id by vclaim sep number + vs, err := uvs.ReadDetailData(evs.ReadDetailDto{Number: &clData.VclaimSep.Number}, &event) + if err != nil { + return nil, err + } + + input.FormatType = erc.DFTCPDF + input.TemplateName = TDNCL + input.Encounter_Id = vs.Encounter_Id + + templateData := clData.generateTemplateData() + // generate file + urlPub, err := generateFile(input, templateData) + if err != nil { + return nil, err + } + + cl.FileUrl = &urlPub + if err := dg.I.Save(&cl).Error; err != nil { + return nil, err + } + + response = ResponseDto{ FileUrl: urlPub, } - return &d.Data{ - Meta: d.II{ - "source": source, - "structure": "single-data", - "status": "created", - }, - Data: response, - }, nil default: return nil, errors.New("invalid type code") } + return &d.Data{ + Meta: d.II{ + "source": source, + "structure": "single-data", + "status": "created", + }, + Data: response, + }, nil } diff --git a/internal/use-case/main-use-case/generate-file/tycovar.go b/internal/use-case/main-use-case/generate-file/tycovar.go index fed3e28c..ecfbc6a1 100644 --- a/internal/use-case/main-use-case/generate-file/tycovar.go +++ b/internal/use-case/main-use-case/generate-file/tycovar.go @@ -1,8 +1,13 @@ package generatefile import ( + "fmt" + "time" + erc "simrs-vx/internal/domain/references/common" ere "simrs-vx/internal/domain/references/encounter" + + pu "simrs-vx/pkg/use-case-helper" ) type GeneralConsentPDF struct { @@ -14,18 +19,34 @@ type GeneralConsentPDF struct { Date string `json:"date"` } +type ControlLetterPDF struct { + Number string + Doctor_Name string + DstUnit_Name string + CardNumber string + Name string + BirthDate string + Diagnose string + PlanDate string + ResponsibleDoctor_Name string + PrintDate string +} + type GenerateDto struct { EntityType_Code ere.EntityTypeCode `json:"entityType_code" validate:"required"` - Ref_Id *uint `json:"ref_id" validate:"required"` + Ref_Id *string `json:"ref_id" validate:"required"` Type_Code ere.DocTypeCode `json:"type_code" validate:"required"` FormatType erc.DocFormatTypeCode `json:"formatType"` TemplateName TemplateDocsName `json:"-"` Encounter_Id *uint `json:"-"` + + Data *string `json:"data"` } type VclaimControlLetter struct { Number string `json:"noSuratKontrol"` - Date string `json:"tglRencanaKontrol"` + PlannedControlDate string `json:"tglRencanaKontrol"` + IssuedDate string `json:"tglTerbit"` Doctor_Name string `json:"namaDokter"` DstUnit_Name string `json:"namaPoliTujuan"` ResponsibleDoctor_Name string `json:"namaDokterPembuat"` @@ -60,4 +81,40 @@ type TemplateDocsName string // TemplateDocsName is the name of the template file in the assets/docs folder const ( TDNGC TemplateDocsName = "general-consent.html" + TDNCL TemplateDocsName = "control-letter.html" ) + +func (v VclaimControlLetter) generateTemplateData() ControlLetterPDF { + + return ControlLetterPDF{ + Number: v.Number, + Doctor_Name: v.Doctor_Name, + DstUnit_Name: v.DstUnit_Name, + CardNumber: v.VclaimSep.VclaimMember.CardNumber, + Name: v.generateNameWithGender(), + BirthDate: v.generateBirthDate(), + Diagnose: v.VclaimSep.Diagnose, + PlanDate: v.PlannedControlDate, + ResponsibleDoctor_Name: v.ResponsibleDoctor_Name, + PrintDate: generatePrintDate(), + } +} + +func (v VclaimControlLetter) generateNameWithGender() string { + gender := "Perempuan" + if v.VclaimSep.VclaimMember.Gender == "L" { + gender = "Laki-Laki" + } + + return fmt.Sprintf("%s (%s)", v.VclaimSep.VclaimMember.Name, gender) +} + +func (v VclaimControlLetter) generateBirthDate() string { + t, _ := time.Parse("2006-01-02", v.VclaimSep.VclaimMember.BirthDate) + return pu.FormatIndonesianDate(t) +} + +func generatePrintDate() string { + now := time.Now() + return now.Format("2006/01/02") +} From 279636682d01ad6ace029c55e5256f7012a7a547 Mon Sep 17 00:00:00 2001 From: Munawwirul Jamal Date: Thu, 20 Nov 2025 07:56:31 +0700 Subject: [PATCH 3/7] feat/things-munaja: updated mcu-order-item --- .../migrations/20251120005512.sql | 2 ++ cmd/main-migration/migrations/atlas.sum | 5 +++-- .../mcu-order-item/base/entity.go | 20 +++++++++++++++++++ .../main-entities/mcu-order-item/entity.go | 14 +++---------- 4 files changed, 28 insertions(+), 13 deletions(-) create mode 100644 cmd/main-migration/migrations/20251120005512.sql create mode 100644 internal/domain/main-entities/mcu-order-item/base/entity.go diff --git a/cmd/main-migration/migrations/20251120005512.sql b/cmd/main-migration/migrations/20251120005512.sql new file mode 100644 index 00000000..8fd4b6af --- /dev/null +++ b/cmd/main-migration/migrations/20251120005512.sql @@ -0,0 +1,2 @@ +-- Modify "McuOrderItem" table +ALTER TABLE "public"."McuOrderItem" ADD COLUMN "Note" character varying(1024) NULL; diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index a6e1b68c..9f7c1d2e 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:fNeqUpbdIqGDiH68u1bwwMgHTEOmmEWeI+IIYEq6pto= +h1:NZkNXHrJksgpcktPStE4yM6IBy+NgX8X6cY2ffSLCDU= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -118,4 +118,5 @@ h1:fNeqUpbdIqGDiH68u1bwwMgHTEOmmEWeI+IIYEq6pto= 20251113101344.sql h1:xaOZvAUP1fFfnO+syEFOzJUIg5lTfBe5AWHPbBWuCLA= 20251113120533.sql h1:f3/U1Ve2yF2zSMhkt+xtwF8wUYfUKYwgbNeGfE37EW4= 20251114062746.sql h1:FInLaEFQByESEwFJKuKnuUSTKmcDpi3ZXaxkKwz2+D8= -20251117005942.sql h1:mW/TC8GgFgPLZ7PBVQnn9mChEekAcwfQMCbzXnoaw9w= +20251117005942.sql h1:wD3BWrUSmo1HlW16V3lkaBkJvbAZ0fNk77te7J9NhOc= +20251120005512.sql h1:gd0rKVlIHXbOQ6J3Bl6NTiZ6fF3GQdobgAUVXW455wI= diff --git a/internal/domain/main-entities/mcu-order-item/base/entity.go b/internal/domain/main-entities/mcu-order-item/base/entity.go new file mode 100644 index 00000000..dcfb0625 --- /dev/null +++ b/internal/domain/main-entities/mcu-order-item/base/entity.go @@ -0,0 +1,20 @@ +package mcuorderitem + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + ems "simrs-vx/internal/domain/main-entities/mcu-src" + "time" + + erc "simrs-vx/internal/domain/references/common" +) + +type McuOrderItem struct { + ecore.Main // adjust this according to the needs + McuOrder_Id *uint `json:"mcuOrder_id" gorm:"uniqueIndex:idx_order_src"` + McuSrc_Code *string `json:"mcuSrc_code" gorm:"uniqueIndex:idx_order_src"` + McuSrc *ems.McuSrc `json:"mcuSrc,omitempty" gorm:"foreignKey:McuSrc_Code;references:Code"` + ExaminationDate *time.Time `json:"examinationDate"` + Note *string `json:"note" gorm:"size:1024"` + Result *string `json:"result"` + Status_Code erc.DataStatusCode `json:"status_code"` +} diff --git a/internal/domain/main-entities/mcu-order-item/entity.go b/internal/domain/main-entities/mcu-order-item/entity.go index 97384243..48a57bac 100644 --- a/internal/domain/main-entities/mcu-order-item/entity.go +++ b/internal/domain/main-entities/mcu-order-item/entity.go @@ -1,23 +1,15 @@ package mcuorderitem import ( - ecore "simrs-vx/internal/domain/base-entities/core" emo "simrs-vx/internal/domain/main-entities/mcu-order" - ems "simrs-vx/internal/domain/main-entities/mcu-src" - "time" + emoib "simrs-vx/internal/domain/main-entities/mcu-order-item/base" erc "simrs-vx/internal/domain/references/common" ) type McuOrderItem struct { - ecore.Main // adjust this according to the needs - McuOrder_Id *uint `json:"mcuOrder_id" gorm:"uniqueIndex:idx_order_src"` - McuOrder *emo.McuOrder `json:"mcuOrder,omitempty" gorm:"foreignKey:McuOrder_Id;references:Id"` - McuSrc_Code *string `json:"mcuSrc_code" gorm:"uniqueIndex:idx_order_src"` - McuSrc *ems.McuSrc `json:"mcuSrc,omitempty" gorm:"foreignKey:McuSrc_Code;references:Code"` - ExaminationDate *time.Time `json:"examinationDate"` - Result *string `json:"result"` - Status_Code erc.DataStatusCode `json:"status_code"` + emoib.McuOrderItem + McuOrder *emo.McuOrder `json:"mcuOrder,omitempty" gorm:"foreignKey:McuOrder_Id;references:Id"` } func (d McuOrderItem) IsCompleted() bool { From ffb8c4e413b410c84d4337e482b5dd0c7b30180a Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Thu, 20 Nov 2025 13:18:33 +0700 Subject: [PATCH 4/7] feat (generate-file): control letter done --- assets/docs/control-letter.html | 67 ++++-- .../main-use-case/generate-file/case.go | 226 +++++++++--------- .../main-use-case/generate-file/helper.go | 9 +- .../main-use-case/generate-file/tycovar.go | 9 +- pkg/pdf-helper/pdf-helper.go | 19 +- 5 files changed, 185 insertions(+), 145 deletions(-) diff --git a/assets/docs/control-letter.html b/assets/docs/control-letter.html index c55c7b9d..780a052f 100644 --- a/assets/docs/control-letter.html +++ b/assets/docs/control-letter.html @@ -3,6 +3,9 @@ @@ -25,7 +34,7 @@ - - - -
- logo + logo
@@ -35,15 +44,10 @@ RSUD dr. Saiful Anwar
-
- No. : {{ .Number }} -
+
+ No. : {{ .Number }}
@@ -65,46 +69,50 @@ Mohon Pemeriksaan dan Penanganan Lebih Lanjut:
- + + + + +
No.Kartu : - : {{ .CardNumber }} + {{ .CardNumber }}
Nama Peserta : - : {{ .Name }} + {{ .Name }}
Tgl.Lahir : - : {{ .BirthDate }} + {{ .BirthDate }}
Diagnosa : - : {{ .Diagnose }} + {{ .Diagnose }}
Rencana Kontrol : - : {{ .PlanDate }} + {{ .PlanDate }}
@@ -112,19 +120,26 @@
Demikian atas bantuannya, diucapkan banyak terima kasih.
- - - - - - -
- Mengetahui, DPJP : {{ .ResponsibleDoctor_Name }} -
-
- Tgl. Cetak : {{ .PrintDate }} -
+ + + + + + + + + + + + + + + + + + +
Mengetahui:
Tgl. Cetak: {{ .PrintDate }}{{ .ResponsibleDoctor_Name }}
diff --git a/internal/use-case/main-use-case/generate-file/case.go b/internal/use-case/main-use-case/generate-file/case.go index f0e71203..39cb2f02 100644 --- a/internal/use-case/main-use-case/generate-file/case.go +++ b/internal/use-case/main-use-case/generate-file/case.go @@ -18,6 +18,7 @@ import ( dg "github.com/karincake/apem/db-gorm-pg" d "github.com/karincake/dodol" + "gorm.io/gorm" erc "simrs-vx/internal/domain/references/common" ere "simrs-vx/internal/domain/references/encounter" @@ -36,128 +37,137 @@ func Generate(input GenerateDto) (*d.Data, error) { // Start log pl.SetLogInfo(&event, input, "started", "create") - switch input.Type_Code { - // general-consent - case ere.DTCGC: - // get value from general consent by ref_id - gc, err := ugc.ReadDetailData(egc.ReadDetailDto{Id: uint(*pc.StringToUint64(*input.Ref_Id))}, &event) - if err != nil { - return nil, err - } - - if gc.FileUrl != nil { - if err := removeFile(string(input.EntityType_Code), *gc.FileUrl); err != nil { - return nil, err - } - } - - // map template data - templateData := GeneralConsentPDF{} - if gc.Value != nil { - err := json.Unmarshal([]byte(*gc.Value), &templateData) + err := dg.I.Transaction(func(tx *gorm.DB) error { + switch input.Type_Code { + // general-consent + case ere.DTCGC: + // get value from general consent by ref_id + gc, err := ugc.ReadDetailData(egc.ReadDetailDto{Id: uint(*pc.StringToUint64(*input.Ref_Id))}, &event) if err != nil { - event.ErrInfo = pl.ErrorInfo{ - Code: "data-unmarshal-fail", - Detail: err.Error(), - Raw: err, + return err + } + + if gc.FileUrl != nil { + if err := removeFile(string(input.EntityType_Code), *gc.FileUrl); err != nil { + return err } - return nil, err } - } else { - return nil, errors.New("no value in this general consent") - } - input.FormatType = erc.DFTCPDF - input.TemplateName = TDNGC - input.Encounter_Id = gc.Encounter_Id - templateData.Date = pu.FormatIndonesianDate(gc.CreatedAt) - - // generate file - urlPub, err := generateFile(input, templateData) - if err != nil { - return nil, err - } - - gc.FileUrl = &urlPub - if err := dg.I.Save(&gc).Error; err != nil { - return nil, err - } - - response = ResponseDto{ - FileUrl: urlPub, - } - - // control-letter - case ere.DTCVSCL: - // get value from control letter by ref_id - cl, err := uvscl.ReadDetailData(evscl.ReadDetailDto{Number: input.Ref_Id}, &event) - if err != nil { - if !pu.IsDataNotFoundError(err) { - return nil, err + // map template data + templateData := GeneralConsentPDF{} + if gc.Value != nil { + err := json.Unmarshal([]byte(*gc.Value), &templateData) + if err != nil { + event.ErrInfo = pl.ErrorInfo{ + Code: "data-unmarshal-fail", + Detail: err.Error(), + Raw: err, + } + return err + } + } else { + return errors.New("no value in this general consent") } - } - if cl != nil && cl.FileUrl != nil { - if err := removeFile(string(input.EntityType_Code), *cl.FileUrl); err != nil { - return nil, err - } - } + input.FormatType = erc.DFTCPDF + input.TemplateName = TDNGC + input.Encounter_Id = gc.Encounter_Id + templateData.Date = pu.FormatIndonesianDate(gc.CreatedAt) - // map template data - clData := VclaimControlLetter{} - if input.Data != nil { - err := json.Unmarshal([]byte(*input.Data), &clData) + // generate file + urlPub, err := generateFile(input, templateData) if err != nil { - event.ErrInfo = pl.ErrorInfo{ - Code: "data-unmarshal-fail", - Detail: err.Error(), - Raw: err, + return err + } + + gc.FileUrl = &urlPub + if err := dg.I.Save(&gc).Error; err != nil { + return err + } + + response = ResponseDto{ + FileUrl: urlPub, + } + + // control-letter + case ere.DTCVSCL: + // get value from control letter by ref_id + cl, err := uvscl.ReadDetailData(evscl.ReadDetailDto{Number: input.Ref_Id}, &event) + if err != nil { + if !pu.IsDataNotFoundError(err) { + return err } - return nil, err - } - } else { - return nil, errors.New("there is no data to be used") - } - - if cl == nil { - createCL := evscl.CreateDto{ - VclaimSep_Number: &clData.VclaimSep.Number, - Number: &clData.Number, - Value: input.Data, - } - if cl, err = uvscl.CreateData(createCL, &event); err != nil { - return nil, err } - } - // get encounter id by vclaim sep number - vs, err := uvs.ReadDetailData(evs.ReadDetailDto{Number: &clData.VclaimSep.Number}, &event) - if err != nil { - return nil, err + if cl != nil && cl.FileUrl != nil { + if err := removeFile(string(input.EntityType_Code), *cl.FileUrl); err != nil { + return err + } + } + + // map template data + clData := VclaimControlLetter{} + if input.Data != nil { + err := json.Unmarshal([]byte(*input.Data), &clData) + if err != nil { + event.ErrInfo = pl.ErrorInfo{ + Code: "data-unmarshal-fail", + Detail: err.Error(), + Raw: err, + } + return err + } + } else { + return errors.New("there is no data to be used") + } + + if cl == nil { + createCL := evscl.CreateDto{ + VclaimSep_Number: &clData.VclaimSep.Number, + Number: &clData.Number, + Value: input.Data, + } + if cl, err = uvscl.CreateData(createCL, &event, tx); err != nil { + return err + } + + } + // get encounter id by vclaim sep number + vs, err := uvs.ReadDetailData(evs.ReadDetailDto{Number: &clData.VclaimSep.Number}, &event) + if err != nil { + return err + } + + input.FormatType = erc.DFTCPDF + input.TemplateName = TDNCL + input.Encounter_Id = vs.Encounter_Id + input.UseA5Lanscape = true + + templateData := clData.generateTemplateData() + // generate file + urlPub, err := generateFile(input, templateData) + if err != nil { + return err + } + + cl.FileUrl = &urlPub + if err := tx.Save(&cl).Error; err != nil { + return err + } + + response = ResponseDto{ + FileUrl: urlPub, + } + + default: + return errors.New("invalid type code") } - input.FormatType = erc.DFTCPDF - input.TemplateName = TDNCL - input.Encounter_Id = vs.Encounter_Id + return nil + }) - templateData := clData.generateTemplateData() - // generate file - urlPub, err := generateFile(input, templateData) - if err != nil { - return nil, err - } - - cl.FileUrl = &urlPub - if err := dg.I.Save(&cl).Error; err != nil { - return nil, err - } - - response = ResponseDto{ - FileUrl: urlPub, - } - - default: - return nil, errors.New("invalid type code") + if err != nil { + return nil, err } return &d.Data{ diff --git a/internal/use-case/main-use-case/generate-file/helper.go b/internal/use-case/main-use-case/generate-file/helper.go index 9bee2212..8cd3543f 100644 --- a/internal/use-case/main-use-case/generate-file/helper.go +++ b/internal/use-case/main-use-case/generate-file/helper.go @@ -30,9 +30,10 @@ func generateFile(input GenerateDto, templateData any) (string, error) { switch input.FormatType { case erc.DFTCPDF: if err := generatePDF(GeneratePDFdto{ - TemplatePath: templatePath, - TemplateData: templateData, - PdfPath: fPath, + TemplatePath: templatePath, + TemplateData: templateData, + PdfPath: fPath, + UseA5Lanscape: input.UseA5Lanscape, }); err != nil { return "", err } @@ -73,7 +74,7 @@ func generatePDF(input GeneratePDFdto) error { // parse template data into html template r := pp.NewRequestPdf("") if err := r.ParseTemplate(input.TemplatePath, input.TemplateData); err == nil { - _, err := r.GenerateByCommand(input.PdfPath, input.TemplatePath) + _, err := r.GenerateByCommand(input.PdfPath, input.TemplatePath, input.UseA5Lanscape) if err != nil { return errors.New("generate pdf by command error : " + err.Error()) } diff --git a/internal/use-case/main-use-case/generate-file/tycovar.go b/internal/use-case/main-use-case/generate-file/tycovar.go index ecfbc6a1..2f6a0ced 100644 --- a/internal/use-case/main-use-case/generate-file/tycovar.go +++ b/internal/use-case/main-use-case/generate-file/tycovar.go @@ -39,6 +39,7 @@ type GenerateDto struct { FormatType erc.DocFormatTypeCode `json:"formatType"` TemplateName TemplateDocsName `json:"-"` Encounter_Id *uint `json:"-"` + UseA5Lanscape bool `json:"-"` Data *string `json:"data"` } @@ -46,7 +47,6 @@ type GenerateDto struct { type VclaimControlLetter struct { Number string `json:"noSuratKontrol"` PlannedControlDate string `json:"tglRencanaKontrol"` - IssuedDate string `json:"tglTerbit"` Doctor_Name string `json:"namaDokter"` DstUnit_Name string `json:"namaPoliTujuan"` ResponsibleDoctor_Name string `json:"namaDokterPembuat"` @@ -67,9 +67,10 @@ type VclaimMember struct { } type GeneratePDFdto struct { - TemplatePath string - TemplateData any - PdfPath string + TemplatePath string + TemplateData any + PdfPath string + UseA5Lanscape bool } type ResponseDto struct { diff --git a/pkg/pdf-helper/pdf-helper.go b/pkg/pdf-helper/pdf-helper.go index 597052eb..9878ecbd 100644 --- a/pkg/pdf-helper/pdf-helper.go +++ b/pkg/pdf-helper/pdf-helper.go @@ -47,9 +47,9 @@ func (r *RequestPdf) ParseTemplate(templatePath string, data interface{}) error return nil } -func (r *RequestPdf) GenerateByCommand(pdfPath string, templatePath string) (bool, error) { - // wkhtmltopdf -L 0 -R 0 -B 0 -s Legal --enable-local-file-access resultAntigen2.html out.pdf +func (r *RequestPdf) GenerateByCommand(pdfPath string, templatePath string, useA5Lanscape bool) (bool, error) { t := time.Now().Unix() + var cmd *exec.Cmd if _, err := os.Stat("cloneTemplate/"); os.IsNotExist(err) { errDir := os.Mkdir("cloneTemplate/", 0777) @@ -63,7 +63,20 @@ func (r *RequestPdf) GenerateByCommand(pdfPath string, templatePath string) (boo panic(err) } - cmd := exec.Command("wkhtmltopdf", "--enable-local-file-access", "-L", "0", "-R", "0", "-B", "0", "-s", "A4", "cloneTemplate/"+htmlName, pdfPath) + if !useA5Lanscape { + cmd = exec.Command("wkhtmltopdf", "--enable-local-file-access", "-L", "0", "-R", "0", "-B", "0", "-s", "A4", "cloneTemplate/"+htmlName, pdfPath) + } else { + cmd = exec.Command("wkhtmltopdf", + "--enable-local-file-access", + "-L", "0", // left margin + "-R", "0", // right margin + "-B", "0", // bottom margin + "-T", "0", // top margin + "-s", "A5", // page size A5 + "-O", "Landscape", // landscape mode + "cloneTemplate/"+htmlName, + pdfPath) + } if err := cmd.Run(); err != nil { return false, err From b5b15ed852cabcde316df810175b1676cc32b011 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Thu, 20 Nov 2025 13:24:51 +0700 Subject: [PATCH 5/7] migration from server --- cmd/main-migration/migrations/atlas.sum | 98 +++++++++++++------------ 1 file changed, 52 insertions(+), 46 deletions(-) diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 9f7c1d2e..5645ddc2 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:NZkNXHrJksgpcktPStE4yM6IBy+NgX8X6cY2ffSLCDU= +h1:DgafJ/z7PUlDk6JQZ+ZwOf1lD4zj6ErO+ojgeSuBuk0= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -75,48 +75,54 @@ h1:NZkNXHrJksgpcktPStE4yM6IBy+NgX8X6cY2ffSLCDU= 20251106040137.sql h1:ppcqkVoT0o9jZcjI/TN7LuaPxXhJQhnIXEJtloP/46o= 20251106041333.sql h1:2JkxyelQ/EeB+boL5bfpnzefw32ttEGKvKchtQjWmAU= 20251106042006.sql h1:ruppYa1kAJQUU3ufQBbKGMcXrGbGJJiRPclT+dNc/YQ= -20251106050412.sql h1:1002KYtHd8AwrQTMewbs/PPHDylHDghigE/3S7PVdMA= -20251106063418.sql h1:jPW/gBnbFl4RO39lQ0ZMDtYA6xbhyD6CgQupT50HmaY= -20251106071906.sql h1:leYGKxR3EQn794aOehf0sd/ZPmOnvBMZPy5/anGmRB4= -20251106073157.sql h1:KASMzjjjk5UB7Zj8lCRtM1utc4ZnDjlnpZbtTe3vONE= -20251106074218.sql h1:Z5q5deOvLaZDPhiVTN9st3/s56RepBa2YOyrMXBdj4A= -20251106081846.sql h1:P+VsWwhGt60adDIZuE/Aa38JVp/yX1rnsdpXpxASodw= -20251106082844.sql h1:Dmi5A8i9frQZvdXYPwc7f8CisZtBH8liSXq1rI6z1iM= -20251106090021.sql h1:4JwdKgO8T46YhyWVJUxpRIwudBDlG8QN1brSOYmgQ20= -20251106144745.sql h1:nqnQCzGrVJaq8ilOEOGXeRUL1dolj+OPWKuP8A92FRA= -20251107012049.sql h1:Pff4UqltGS3clSlGr0qq8CQM56L29wyxY0FC/N/YAhU= -20251107064812.sql h1:GB9a0ZfMYTIoGNmKUG+XcYUsTnRMFfT4/dAD71uCPc4= -20251107064937.sql h1:IC5pw1Ifj30hiE6dr5NMHXaSHoQI+vRd40N5ABgBHRI= -20251107071420.sql h1:9NO3iyLEXEtWa2kSRjM/8LyzuVIk6pdFL2SuheWjB08= -20251107074318.sql h1:7fHbSRrdjOmHh/xwnjCLwoiB5cW5zeH+uxLV0vZbkIA= -20251107075050.sql h1:np+3uTOnU9QNtK7Knaw8eRMhkyB9AwrtSNHphOBxbHY= -20251107080604.sql h1:cXDBLPJDVWLTG6yEJqkJsOQ7p7VYxLM2SY+mwO8qSHo= -20251107081830.sql h1:/S7OQZo4ZnK80t28g/JyiOTZtmWG/dP5Wg2zXNMQ/iE= -20251107091033.sql h1:/cbkF1nO/IjNSIfDJJx456KJtQ9rWFXOBFAkR/M2xiE= -20251107091209.sql h1:jrLQOUeV8ji2fg0pnEcs1bw4ANUxzTSMXC/rrHLIY+M= -20251107091541.sql h1:6UqbhQQRmzA2+eKu5lIvkwOkk+lH70QLZC8Pjpjcq68= -20251110012217.sql h1:C9HpX0iyHzKjyNv/5DSAn2MCHj6MX4p5UQ/NrY7QD0w= -20251110012306.sql h1:J54yb27d30LBbYp9n1P66gFVRlxPguKu0kxmWIBBG8g= -20251110052049.sql h1:232T2x8xTczJl9nk4jxJpZXhoOGYthhxjJ7nK8Jd8vg= -20251110062042.sql h1:WnfVUXrzYoj8qdkkjO9/JQQ8agGd4GfSHQdMjo7LDAg= -20251110063202.sql h1:hSzGfwVMWa6q3vwIQZUkxKgBNCzHjB+6GKy54zfV+oQ= -20251110063633.sql h1:/VpofIAqNS1CnazEnpW/+evbzn9Kew3xDW48r57M+Xg= -20251110085551.sql h1:bFZwSmfvVbTUr/enWB82WqjG88gpqcZ6s45btUvO0uo= -20251110091516.sql h1:KkJMwPQuaZQhiqnKrNQrgP12gw9rV8T3P2o3mtGTcvY= -20251110091948.sql h1:I4odAYrJdvNf1jPw6ppDC0XdI7v6vKBACg/ABwUgA7I= -20251110092729.sql h1:l1out8soEmVP6dNjaIOtGYo6QDcoJZRI8X1sjZ5ZGmo= -20251110093522.sql h1:nsz8jCxGjEdr/bz9g+4ozfZzIP803xONjVmucad1GMc= -20251110100258.sql h1:IBqt1VZj5WjQ+l9aAFGHOCCBtzb03KlLLihFLut7itg= -20251110100545.sql h1:6/LV7751iyKxE2xI6vO1zly+aHUwxXD/IBwLcVpKxqM= -20251110155448.sql h1:kFPobJB+cpflsXBAWUwy3lohuWvrb/VRlXnhJWl7i3Y= -20251111072601.sql h1:ch8F+yVhsSM5xY+TwMLY3PxdLa4Wuhtj76oyw79R7Js= -20251111073546.sql h1:cCv0NPscADAOBahRVqtDWFs6G2t7n+4a+RwlF8vk/c4= -20251111074148.sql h1:70TsV83u1gQ5TktI13K7NQiyCCa35Td2aR6CNtKUa4U= -20251111074652.sql h1:ddfQ/sRKMezPM75xBFTGytUQX5AwZ3znrJVpg73gKPA= -20251111082257.sql h1:ZsdLY1ROouos0l3oS0lkeSiuKLEUGbVvBhpcM2AVhkw= -20251111111017.sql h1:qrJ93dNtQwcuAvpsP/lAK/H63C4cinXrsVaPmWsTqkU= -20251113101344.sql h1:xaOZvAUP1fFfnO+syEFOzJUIg5lTfBe5AWHPbBWuCLA= -20251113120533.sql h1:f3/U1Ve2yF2zSMhkt+xtwF8wUYfUKYwgbNeGfE37EW4= -20251114062746.sql h1:FInLaEFQByESEwFJKuKnuUSTKmcDpi3ZXaxkKwz2+D8= -20251117005942.sql h1:wD3BWrUSmo1HlW16V3lkaBkJvbAZ0fNk77te7J9NhOc= -20251120005512.sql h1:gd0rKVlIHXbOQ6J3Bl6NTiZ6fF3GQdobgAUVXW455wI= +20251106050412.sql h1:MiEMJ1HCFYnalKuq3Z38xJeogfBAMqsTv2sG4EF8dDw= +20251106063418.sql h1:y3veDJPjKekOWLCZek/LgQwXPRhZtOppTfUXiqoL95s= +20251106071906.sql h1:/TUZA3XpMY23qEJXdkTwlzrNMvSSl6JJniPcgAttBaw= +20251106073157.sql h1:78txeibJ602DMD7huD618ZSMt6phSRzDNPTlo0PGyrc= +20251106074218.sql h1:8Xz7WywrtUnSxOHhlal53gG9rE7r86LFUt5zBFe/mIs= +20251106081846.sql h1:jp91Bf5bxGXMiUB1VIuN6y768vb2iWwow44WfCE5J5k= +20251106082844.sql h1:RHYzRO4G1fSWwf+xc/3QezZ/Iil67cZPIgNpNz3TNhQ= +20251106090021.sql h1:dFDk6mq+zjbYWmfWIrHf9DiKvvoXHjrr0++zssMTWP8= +20251106144745.sql h1:aHcr23iBFqCHer5D/SsPMXBCLjGqUYvWYfRU8jSJgIw= +20251107012049.sql h1:hu/7NHhnAkT4xK0RNtqmMDdH1Bo5EZbl7itDRjiCT+g= +20251107064812.sql h1:sfCXDQYnMf0ddrQ9oYljWJLLSt9NJjJV6o8VS3p7aZE= +20251107064937.sql h1:DlYGJ9LZFwZyR7jBP5zaGB128aIc4HAixBKPYCz9EkY= +20251107071420.sql h1:ynCdZAd2utLl+FhtWZwtahNXgIVOvuk3s/rOq7lfXA4= +20251107074318.sql h1:WE9cPhibWtZ0dbu1VEGirTeY6ijFYGMNhHdBtM32kOc= +20251107075050.sql h1:8tvneruqdynDOaJK1+0z4CH7YXZStZpGdqwIeOMLik4= +20251107080604.sql h1:8c4jd4Tql7tcdhbI9NS0tgvN+ADu9FnCf8wMUbmW7A0= +20251107081830.sql h1:SAAe3lmsm9vGXuSEsDdl7ad0EAxP5CMmFRDEgp9M7yY= +20251107091033.sql h1:JLdX/u7GUdBfjrPrMSNAqc8HtSoj0YA9iW9Vc6FJZdw= +20251107091209.sql h1:CzhYtwAwT+GHrbqcagnJE+v3mbl/rObf1IJaLCKlzrs= +20251107091541.sql h1:+3ZyWJTftDY2JeWThXuIxGWpUBnyMPyOyY4jBjdWYJI= +20251110012217.sql h1:f4Z8TuGc+XMSJ+Ekn4/PeHRE2FlHWkc5gKPJB0hAX7c= +20251110012306.sql h1:ENPyI6Kjdk6qKJQb0yJ6MCTDPAmO1WD/uhKuCSl+jYo= +20251110052049.sql h1:OrQ0acnyoQLKnTitZfnBcVr5jDslF59OFLaqT7SpdVs= +20251110062042.sql h1:9KwldQt0NpVPR86L0T4hlkfHAGau+7CiZYgu5rF+yhg= +20251110063202.sql h1:A117DuZmZ6U0jWHA3DISnr+yvBjKIr1ObrUr047YezQ= +20251110063633.sql h1:qTiC0F19JnhUIXF4LGJQ21jEV6kKGyhTr1x2kimFqPQ= +20251110085551.sql h1:HZcJM0RSC6HBaUSjKBE8MgDG8Vn9f3LmwA/OnT9Cp7I= +20251110091516.sql h1:W3AQhQLgirEWuCObbLl+Prdrbq6k6EEY1xcoWsmbog4= +20251110091948.sql h1:3tsITMrZr/T+L4wqUMz8sHS229jCJl4T0Nu3dMccxH8= +20251110092729.sql h1:uU+k88RH/e0Ns4/SmJl03RVYPscBAPuiLfxR6CJqaf0= +20251110093522.sql h1:O7upSj8VNjzvroL4IU59bfxKATOkAVGBArcUbVNq9aM= +20251110100258.sql h1://JSArUMNI3/gAtYDx2VN94C198SFW0ANjgs+p6eCRM= +20251110100545.sql h1:ENPOqeJYRpMI4e8VCKwaQgaql8se6pIidAhG2cjskBg= +20251110155448.sql h1:VW9KE0jxWy4flZ28sdXmhY6JWd6eKAX/cVL8KWRVii4= +20251111072601.sql h1:99WWzGjcDDFNC2cHRfPu4MBLWNrgPMY5HAYUbmIcVRA= +20251111073546.sql h1:iIGwFNfUgStdczw/PXTH3SD84xAyxrbZICofc3M8TMk= +20251111074148.sql h1:mzkezSKwCV2bTZ/0BHiTCX5qAy4uHpwar1xzwAH15Ko= +20251111074652.sql h1:lYh4/3BHV24pgPC0pP4RUKb+XtL/6AsZGPItRpnzBiQ= +20251111082257.sql h1:+cIZ1lf8HYGSL6t6U88plLKk8nOO1YVdV7h3YOM84ds= +20251111111017.sql h1:xzlhR2xLfOj4ddYlesS+bpEeDrxiAf5ILNOspsbZjBU= +20251113101344.sql h1:vSzThY3p6XYTj0dJ2uFVkHmlytyrFAnGE58CJLx364I= +20251113120533.sql h1:lfjgdqRGo/EohrVw8sWlFbDjh3ASTsfQ6pr3qjafqvc= +20251114062746.sql h1:6DLYjfJ60PkAABZTXvOwSE+xrU25oyoX7gpYlBnA9cw= +20251117005942.sql h1:0XoJKca8IOaB9QKFVF/qPY7jKcIgh6m/LODQuE06SAs= +20251117075427.sql h1:LhY2urosfoSu1/vkHmgsNP4JA4DuWBs9gL59yMqcF8M= +20251118074929.sql h1:3RWBD6BziQVw6WSfthgoVuhTELHER9NrIuZm4hY/F1A= +20251119063438.sql h1:EVTG3ZrHjCmM95YPASZTRPiwHrG6e33A2vO4hLSAaBQ= +20251119065730.sql h1:s98wnZOCW6NbnwDS3H53XIQ60u6B9bDwBLNvy5+Rn64= +20251119072302.sql h1:ZL+VHekLYqgNtOFKlj02WHrAk11dtTxQkmyTKE8IOzY= +20251119072450.sql h1:SiJy2vpSvoPFw4J1SW7HjGSJzrqR62NsjRYAeabV+kc= +20251120005512.sql h1:hJUaWXYJ3HiSquBTw8OKhymjA4O43ehAMGfiOY8W87Q= From 990f50e50c7d6f5b92f13572a131d265a924d3e1 Mon Sep 17 00:00:00 2001 From: dpurbosakti Date: Thu, 20 Nov 2025 14:45:18 +0700 Subject: [PATCH 6/7] add resume entity --- .../migrations/20251120074415.sql | 11 ++ cmd/main-migration/migrations/atlas.sum | 105 +++++++++--------- internal/domain/main-entities/resume/dto.go | 64 +++++++++++ .../domain/main-entities/resume/entity.go | 12 ++ internal/interface/migration/main-entities.go | 2 + 5 files changed, 142 insertions(+), 52 deletions(-) create mode 100644 cmd/main-migration/migrations/20251120074415.sql create mode 100644 internal/domain/main-entities/resume/dto.go create mode 100644 internal/domain/main-entities/resume/entity.go diff --git a/cmd/main-migration/migrations/20251120074415.sql b/cmd/main-migration/migrations/20251120074415.sql new file mode 100644 index 00000000..ae6cd675 --- /dev/null +++ b/cmd/main-migration/migrations/20251120074415.sql @@ -0,0 +1,11 @@ +-- Create "Resume" table +CREATE TABLE "public"."Resume" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Encounter_Id" bigint NOT NULL, + "Value" text NULL, + "FileUrl" character varying(1024) NULL, + PRIMARY KEY ("Id") +); diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 5645ddc2..0d9edc98 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:DgafJ/z7PUlDk6JQZ+ZwOf1lD4zj6ErO+ojgeSuBuk0= +h1:4U2KWXwY59v9g8NqCRfUlRU8S0gFHP+2zZo3VIYCy80= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -75,54 +75,55 @@ h1:DgafJ/z7PUlDk6JQZ+ZwOf1lD4zj6ErO+ojgeSuBuk0= 20251106040137.sql h1:ppcqkVoT0o9jZcjI/TN7LuaPxXhJQhnIXEJtloP/46o= 20251106041333.sql h1:2JkxyelQ/EeB+boL5bfpnzefw32ttEGKvKchtQjWmAU= 20251106042006.sql h1:ruppYa1kAJQUU3ufQBbKGMcXrGbGJJiRPclT+dNc/YQ= -20251106050412.sql h1:MiEMJ1HCFYnalKuq3Z38xJeogfBAMqsTv2sG4EF8dDw= -20251106063418.sql h1:y3veDJPjKekOWLCZek/LgQwXPRhZtOppTfUXiqoL95s= -20251106071906.sql h1:/TUZA3XpMY23qEJXdkTwlzrNMvSSl6JJniPcgAttBaw= -20251106073157.sql h1:78txeibJ602DMD7huD618ZSMt6phSRzDNPTlo0PGyrc= -20251106074218.sql h1:8Xz7WywrtUnSxOHhlal53gG9rE7r86LFUt5zBFe/mIs= -20251106081846.sql h1:jp91Bf5bxGXMiUB1VIuN6y768vb2iWwow44WfCE5J5k= -20251106082844.sql h1:RHYzRO4G1fSWwf+xc/3QezZ/Iil67cZPIgNpNz3TNhQ= -20251106090021.sql h1:dFDk6mq+zjbYWmfWIrHf9DiKvvoXHjrr0++zssMTWP8= -20251106144745.sql h1:aHcr23iBFqCHer5D/SsPMXBCLjGqUYvWYfRU8jSJgIw= -20251107012049.sql h1:hu/7NHhnAkT4xK0RNtqmMDdH1Bo5EZbl7itDRjiCT+g= -20251107064812.sql h1:sfCXDQYnMf0ddrQ9oYljWJLLSt9NJjJV6o8VS3p7aZE= -20251107064937.sql h1:DlYGJ9LZFwZyR7jBP5zaGB128aIc4HAixBKPYCz9EkY= -20251107071420.sql h1:ynCdZAd2utLl+FhtWZwtahNXgIVOvuk3s/rOq7lfXA4= -20251107074318.sql h1:WE9cPhibWtZ0dbu1VEGirTeY6ijFYGMNhHdBtM32kOc= -20251107075050.sql h1:8tvneruqdynDOaJK1+0z4CH7YXZStZpGdqwIeOMLik4= -20251107080604.sql h1:8c4jd4Tql7tcdhbI9NS0tgvN+ADu9FnCf8wMUbmW7A0= -20251107081830.sql h1:SAAe3lmsm9vGXuSEsDdl7ad0EAxP5CMmFRDEgp9M7yY= -20251107091033.sql h1:JLdX/u7GUdBfjrPrMSNAqc8HtSoj0YA9iW9Vc6FJZdw= -20251107091209.sql h1:CzhYtwAwT+GHrbqcagnJE+v3mbl/rObf1IJaLCKlzrs= -20251107091541.sql h1:+3ZyWJTftDY2JeWThXuIxGWpUBnyMPyOyY4jBjdWYJI= -20251110012217.sql h1:f4Z8TuGc+XMSJ+Ekn4/PeHRE2FlHWkc5gKPJB0hAX7c= -20251110012306.sql h1:ENPyI6Kjdk6qKJQb0yJ6MCTDPAmO1WD/uhKuCSl+jYo= -20251110052049.sql h1:OrQ0acnyoQLKnTitZfnBcVr5jDslF59OFLaqT7SpdVs= -20251110062042.sql h1:9KwldQt0NpVPR86L0T4hlkfHAGau+7CiZYgu5rF+yhg= -20251110063202.sql h1:A117DuZmZ6U0jWHA3DISnr+yvBjKIr1ObrUr047YezQ= -20251110063633.sql h1:qTiC0F19JnhUIXF4LGJQ21jEV6kKGyhTr1x2kimFqPQ= -20251110085551.sql h1:HZcJM0RSC6HBaUSjKBE8MgDG8Vn9f3LmwA/OnT9Cp7I= -20251110091516.sql h1:W3AQhQLgirEWuCObbLl+Prdrbq6k6EEY1xcoWsmbog4= -20251110091948.sql h1:3tsITMrZr/T+L4wqUMz8sHS229jCJl4T0Nu3dMccxH8= -20251110092729.sql h1:uU+k88RH/e0Ns4/SmJl03RVYPscBAPuiLfxR6CJqaf0= -20251110093522.sql h1:O7upSj8VNjzvroL4IU59bfxKATOkAVGBArcUbVNq9aM= -20251110100258.sql h1://JSArUMNI3/gAtYDx2VN94C198SFW0ANjgs+p6eCRM= -20251110100545.sql h1:ENPOqeJYRpMI4e8VCKwaQgaql8se6pIidAhG2cjskBg= -20251110155448.sql h1:VW9KE0jxWy4flZ28sdXmhY6JWd6eKAX/cVL8KWRVii4= -20251111072601.sql h1:99WWzGjcDDFNC2cHRfPu4MBLWNrgPMY5HAYUbmIcVRA= -20251111073546.sql h1:iIGwFNfUgStdczw/PXTH3SD84xAyxrbZICofc3M8TMk= -20251111074148.sql h1:mzkezSKwCV2bTZ/0BHiTCX5qAy4uHpwar1xzwAH15Ko= -20251111074652.sql h1:lYh4/3BHV24pgPC0pP4RUKb+XtL/6AsZGPItRpnzBiQ= -20251111082257.sql h1:+cIZ1lf8HYGSL6t6U88plLKk8nOO1YVdV7h3YOM84ds= -20251111111017.sql h1:xzlhR2xLfOj4ddYlesS+bpEeDrxiAf5ILNOspsbZjBU= -20251113101344.sql h1:vSzThY3p6XYTj0dJ2uFVkHmlytyrFAnGE58CJLx364I= -20251113120533.sql h1:lfjgdqRGo/EohrVw8sWlFbDjh3ASTsfQ6pr3qjafqvc= -20251114062746.sql h1:6DLYjfJ60PkAABZTXvOwSE+xrU25oyoX7gpYlBnA9cw= -20251117005942.sql h1:0XoJKca8IOaB9QKFVF/qPY7jKcIgh6m/LODQuE06SAs= -20251117075427.sql h1:LhY2urosfoSu1/vkHmgsNP4JA4DuWBs9gL59yMqcF8M= -20251118074929.sql h1:3RWBD6BziQVw6WSfthgoVuhTELHER9NrIuZm4hY/F1A= -20251119063438.sql h1:EVTG3ZrHjCmM95YPASZTRPiwHrG6e33A2vO4hLSAaBQ= -20251119065730.sql h1:s98wnZOCW6NbnwDS3H53XIQ60u6B9bDwBLNvy5+Rn64= -20251119072302.sql h1:ZL+VHekLYqgNtOFKlj02WHrAk11dtTxQkmyTKE8IOzY= -20251119072450.sql h1:SiJy2vpSvoPFw4J1SW7HjGSJzrqR62NsjRYAeabV+kc= -20251120005512.sql h1:hJUaWXYJ3HiSquBTw8OKhymjA4O43ehAMGfiOY8W87Q= +20251106050412.sql h1:1002KYtHd8AwrQTMewbs/PPHDylHDghigE/3S7PVdMA= +20251106063418.sql h1:jPW/gBnbFl4RO39lQ0ZMDtYA6xbhyD6CgQupT50HmaY= +20251106071906.sql h1:leYGKxR3EQn794aOehf0sd/ZPmOnvBMZPy5/anGmRB4= +20251106073157.sql h1:KASMzjjjk5UB7Zj8lCRtM1utc4ZnDjlnpZbtTe3vONE= +20251106074218.sql h1:Z5q5deOvLaZDPhiVTN9st3/s56RepBa2YOyrMXBdj4A= +20251106081846.sql h1:P+VsWwhGt60adDIZuE/Aa38JVp/yX1rnsdpXpxASodw= +20251106082844.sql h1:Dmi5A8i9frQZvdXYPwc7f8CisZtBH8liSXq1rI6z1iM= +20251106090021.sql h1:4JwdKgO8T46YhyWVJUxpRIwudBDlG8QN1brSOYmgQ20= +20251106144745.sql h1:nqnQCzGrVJaq8ilOEOGXeRUL1dolj+OPWKuP8A92FRA= +20251107012049.sql h1:Pff4UqltGS3clSlGr0qq8CQM56L29wyxY0FC/N/YAhU= +20251107064812.sql h1:GB9a0ZfMYTIoGNmKUG+XcYUsTnRMFfT4/dAD71uCPc4= +20251107064937.sql h1:IC5pw1Ifj30hiE6dr5NMHXaSHoQI+vRd40N5ABgBHRI= +20251107071420.sql h1:9NO3iyLEXEtWa2kSRjM/8LyzuVIk6pdFL2SuheWjB08= +20251107074318.sql h1:7fHbSRrdjOmHh/xwnjCLwoiB5cW5zeH+uxLV0vZbkIA= +20251107075050.sql h1:np+3uTOnU9QNtK7Knaw8eRMhkyB9AwrtSNHphOBxbHY= +20251107080604.sql h1:cXDBLPJDVWLTG6yEJqkJsOQ7p7VYxLM2SY+mwO8qSHo= +20251107081830.sql h1:/S7OQZo4ZnK80t28g/JyiOTZtmWG/dP5Wg2zXNMQ/iE= +20251107091033.sql h1:/cbkF1nO/IjNSIfDJJx456KJtQ9rWFXOBFAkR/M2xiE= +20251107091209.sql h1:jrLQOUeV8ji2fg0pnEcs1bw4ANUxzTSMXC/rrHLIY+M= +20251107091541.sql h1:6UqbhQQRmzA2+eKu5lIvkwOkk+lH70QLZC8Pjpjcq68= +20251110012217.sql h1:C9HpX0iyHzKjyNv/5DSAn2MCHj6MX4p5UQ/NrY7QD0w= +20251110012306.sql h1:J54yb27d30LBbYp9n1P66gFVRlxPguKu0kxmWIBBG8g= +20251110052049.sql h1:232T2x8xTczJl9nk4jxJpZXhoOGYthhxjJ7nK8Jd8vg= +20251110062042.sql h1:WnfVUXrzYoj8qdkkjO9/JQQ8agGd4GfSHQdMjo7LDAg= +20251110063202.sql h1:hSzGfwVMWa6q3vwIQZUkxKgBNCzHjB+6GKy54zfV+oQ= +20251110063633.sql h1:/VpofIAqNS1CnazEnpW/+evbzn9Kew3xDW48r57M+Xg= +20251110085551.sql h1:bFZwSmfvVbTUr/enWB82WqjG88gpqcZ6s45btUvO0uo= +20251110091516.sql h1:KkJMwPQuaZQhiqnKrNQrgP12gw9rV8T3P2o3mtGTcvY= +20251110091948.sql h1:I4odAYrJdvNf1jPw6ppDC0XdI7v6vKBACg/ABwUgA7I= +20251110092729.sql h1:l1out8soEmVP6dNjaIOtGYo6QDcoJZRI8X1sjZ5ZGmo= +20251110093522.sql h1:nsz8jCxGjEdr/bz9g+4ozfZzIP803xONjVmucad1GMc= +20251110100258.sql h1:IBqt1VZj5WjQ+l9aAFGHOCCBtzb03KlLLihFLut7itg= +20251110100545.sql h1:6/LV7751iyKxE2xI6vO1zly+aHUwxXD/IBwLcVpKxqM= +20251110155448.sql h1:kFPobJB+cpflsXBAWUwy3lohuWvrb/VRlXnhJWl7i3Y= +20251111072601.sql h1:ch8F+yVhsSM5xY+TwMLY3PxdLa4Wuhtj76oyw79R7Js= +20251111073546.sql h1:cCv0NPscADAOBahRVqtDWFs6G2t7n+4a+RwlF8vk/c4= +20251111074148.sql h1:70TsV83u1gQ5TktI13K7NQiyCCa35Td2aR6CNtKUa4U= +20251111074652.sql h1:ddfQ/sRKMezPM75xBFTGytUQX5AwZ3znrJVpg73gKPA= +20251111082257.sql h1:ZsdLY1ROouos0l3oS0lkeSiuKLEUGbVvBhpcM2AVhkw= +20251111111017.sql h1:qrJ93dNtQwcuAvpsP/lAK/H63C4cinXrsVaPmWsTqkU= +20251113101344.sql h1:xaOZvAUP1fFfnO+syEFOzJUIg5lTfBe5AWHPbBWuCLA= +20251113120533.sql h1:f3/U1Ve2yF2zSMhkt+xtwF8wUYfUKYwgbNeGfE37EW4= +20251114062746.sql h1:FInLaEFQByESEwFJKuKnuUSTKmcDpi3ZXaxkKwz2+D8= +20251117005942.sql h1:wD3BWrUSmo1HlW16V3lkaBkJvbAZ0fNk77te7J9NhOc= +20251117075427.sql h1:TqU9VKZa3I8YNXUGQWY3WVBYN+1FvyyaKy0hB1jgAho= +20251118074929.sql h1:p1KsWqCuR1JXA/jVO5BmOhCcaQ8clT7t0YRszAhPFbg= +20251119063438.sql h1:NVGM0X/LHD37EaPl8SNzkNiZDJ7AB1QR+LLwLh6WRdg= +20251119065730.sql h1:U5lzk1WvMB0bw3kwckou7jkEt4bwdYItwHr2Vxqe7w4= +20251119072302.sql h1:qCuI2WMEMF/XNbjV+RXPjBnuCKLu1Fia+mR9HiLWBIs= +20251119072450.sql h1:Xg+bTwqGyKPNFEQhJylvpz1wifdfmDJvcAq6vmNf0Ng= +20251120005512.sql h1:Ek6qpacAI/qVuTYxKno+uJyzn7s5z9pf3t7VA8gTzm4= +20251120074415.sql h1:4gmYBcmga1SBxRwrVaovGVvpRZFMV7vYzce0/IalryY= diff --git a/internal/domain/main-entities/resume/dto.go b/internal/domain/main-entities/resume/dto.go new file mode 100644 index 00000000..ea9485d7 --- /dev/null +++ b/internal/domain/main-entities/resume/dto.go @@ -0,0 +1,64 @@ +package resume + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" +) + +type CreateDto struct { + Encounter_Id *uint `json:"encounter_id"` + Value *string `json:"value"` +} + +type ReadListDto struct { + FilterDto + Includes string `json:"includes"` + Pagination ecore.Pagination +} + +type FilterDto struct { + Encounter_Id *uint `json:"encounter-id"` +} + +type ReadDetailDto struct { + Id uint `json:"id"` +} + +type UpdateDto struct { + Id uint `json:"id"` + CreateDto +} + +type DeleteDto struct { + Id uint `json:"id"` +} + +type MetaDto struct { + PageNumber int `json:"page_number"` + PageSize int `json:"page_size"` + Count int `json:"count"` +} + +type ResponseDto struct { + ecore.Main + Encounter_Id *uint `json:"encounter_id"` + Value *string `json:"value"` + FileUrl *string `json:"fileUrl"` +} + +func (d Resume) ToResponse() ResponseDto { + resp := ResponseDto{ + Encounter_Id: d.Encounter_Id, + Value: d.Value, + FileUrl: d.FileUrl, + } + resp.Main = d.Main + return resp +} + +func ToResponseList(data []Resume) []ResponseDto { + resp := make([]ResponseDto, len(data)) + for i, u := range data { + resp[i] = u.ToResponse() + } + return resp +} diff --git a/internal/domain/main-entities/resume/entity.go b/internal/domain/main-entities/resume/entity.go new file mode 100644 index 00000000..cf756870 --- /dev/null +++ b/internal/domain/main-entities/resume/entity.go @@ -0,0 +1,12 @@ +package resume + +import ( + "simrs-vx/internal/domain/base-entities/core" +) + +type Resume struct { + core.Main + Encounter_Id *uint `json:"encounter_id" gorm:"not null"` + Value *string `json:"value"` + FileUrl *string `json:"fileUrl" gorm:"size:1024"` +} diff --git a/internal/interface/migration/main-entities.go b/internal/interface/migration/main-entities.go index 23e7422c..d55a5e27 100644 --- a/internal/interface/migration/main-entities.go +++ b/internal/interface/migration/main-entities.go @@ -82,6 +82,7 @@ import ( regency "simrs-vx/internal/domain/main-entities/regency" rehab "simrs-vx/internal/domain/main-entities/rehab" responsibledoctorhist "simrs-vx/internal/domain/main-entities/responsible-doctor-hist" + resume "simrs-vx/internal/domain/main-entities/resume" room "simrs-vx/internal/domain/main-entities/room" sbar "simrs-vx/internal/domain/main-entities/sbar" soapi "simrs-vx/internal/domain/main-entities/soapi" @@ -213,5 +214,6 @@ func getMainEntities() []any { &chemoprotocol.ChemoProtocol{}, &fileattachemnt.EncounterDocument{}, &vclaimsepcontrolletter.VclaimSepControlLetter{}, + &resume.Resume{}, } } From 0b0676214c097806009cab99bda8028fe584fcd5 Mon Sep 17 00:00:00 2001 From: vanilia Date: Fri, 21 Nov 2025 10:39:37 +0700 Subject: [PATCH 7/7] add vclaimreference --- .../migrations/20251121033803.sql | 14 +++++++ cmd/main-migration/migrations/atlas.sum | 5 ++- .../{vclaim-sep => vclaim-reference}/dto.go | 40 +++++++++---------- .../bpjs-entities/vclaim-reference/entity.go | 15 +++++++ .../domain/main-entities/encounter/entity.go | 11 +++-- internal/interface/migration/main-entities.go | 2 + 6 files changed, 61 insertions(+), 26 deletions(-) create mode 100644 cmd/main-migration/migrations/20251121033803.sql rename internal/domain/bpjs-entities/{vclaim-sep => vclaim-reference}/dto.go (51%) create mode 100644 internal/domain/bpjs-entities/vclaim-reference/entity.go diff --git a/cmd/main-migration/migrations/20251121033803.sql b/cmd/main-migration/migrations/20251121033803.sql new file mode 100644 index 00000000..48cb7f47 --- /dev/null +++ b/cmd/main-migration/migrations/20251121033803.sql @@ -0,0 +1,14 @@ +-- Create "VclaimReference" table +CREATE TABLE "public"."VclaimReference" ( + "Id" bigserial NOT NULL, + "CreatedAt" timestamptz NULL, + "UpdatedAt" timestamptz NULL, + "DeletedAt" timestamptz NULL, + "Encounter_Id" bigint NULL, + "Date" timestamptz NULL, + "SrcCode" text NULL, + "SrcName" text NULL, + "Number" text NULL, + PRIMARY KEY ("Id"), + CONSTRAINT "fk_Encounter_VclaimReference" FOREIGN KEY ("Encounter_Id") REFERENCES "public"."Encounter" ("Id") ON UPDATE NO ACTION ON DELETE NO ACTION +); diff --git a/cmd/main-migration/migrations/atlas.sum b/cmd/main-migration/migrations/atlas.sum index 0d9edc98..87b0571b 100644 --- a/cmd/main-migration/migrations/atlas.sum +++ b/cmd/main-migration/migrations/atlas.sum @@ -1,4 +1,4 @@ -h1:4U2KWXwY59v9g8NqCRfUlRU8S0gFHP+2zZo3VIYCy80= +h1:9o177sOy5hbZmLRLBxkW8WN1dveIe0pyAXoU84eeq0Y= 20250904105930.sql h1:MEM6blCgke9DzWQSTnLzasbPIrcHssNNrJqZpSkEo6k= 20250904141448.sql h1:J8cmYNk4ZrG9fhfbi2Z1IWz7YkfvhFqTzrLFo58BPY0= 20250908062237.sql h1:Pu23yEW/aKkwozHoOuROvHS/GK4ngARJGdO7FB7HZuI= @@ -126,4 +126,5 @@ h1:4U2KWXwY59v9g8NqCRfUlRU8S0gFHP+2zZo3VIYCy80= 20251119072302.sql h1:qCuI2WMEMF/XNbjV+RXPjBnuCKLu1Fia+mR9HiLWBIs= 20251119072450.sql h1:Xg+bTwqGyKPNFEQhJylvpz1wifdfmDJvcAq6vmNf0Ng= 20251120005512.sql h1:Ek6qpacAI/qVuTYxKno+uJyzn7s5z9pf3t7VA8gTzm4= -20251120074415.sql h1:4gmYBcmga1SBxRwrVaovGVvpRZFMV7vYzce0/IalryY= +20251120074415.sql h1:NNUeJVA03EeBHJhHqPXEZoDv/PnC6yK1/cRhmukyaJo= +20251121033803.sql h1:1s3DvgbqF+lh/or9X6WGN2lwnYCZkP8JH6uJFHql15g= diff --git a/internal/domain/bpjs-entities/vclaim-sep/dto.go b/internal/domain/bpjs-entities/vclaim-reference/dto.go similarity index 51% rename from internal/domain/bpjs-entities/vclaim-sep/dto.go rename to internal/domain/bpjs-entities/vclaim-reference/dto.go index 8a174688..027359a3 100644 --- a/internal/domain/bpjs-entities/vclaim-sep/dto.go +++ b/internal/domain/bpjs-entities/vclaim-reference/dto.go @@ -1,16 +1,16 @@ -package vclaimsep +package vclaimreference import ( ecore "simrs-vx/internal/domain/base-entities/core" - evsh "simrs-vx/internal/domain/bpjs-entities/vclaim-sep-hist" + "time" ) type CreateDto struct { - Encounter_Id *uint `json:"encounter_id"` - Number *string `json:"number" validate:"maxLength=19"` - RequestPayload []byte `json:"requestPayload" validate:"maxLength=1024"` - - VclaimSepHist evsh.CreateDto + Encounter_Id *uint `json:"encounter_id"` + Date *time.Time `json:"date"` + SrcCode *string `json:"src_code"` + SrcName *string `json:"src_name"` + Number *string `json:"number"` } type ReadListDto struct { @@ -21,12 +21,11 @@ type ReadListDto struct { } type FilterDto struct { - Number *string `json:"number"` + Encounter_Id *uint `json:"encounter-id"` } type ReadDetailDto struct { - Id uint `json:"id"` - Number *string `json:"number"` + Id uint `json:"id"` } type UpdateDto struct { @@ -35,8 +34,7 @@ type UpdateDto struct { } type DeleteDto struct { - Id uint `json:"id"` - Number *string `json:"number"` + Id uint `json:"id"` } type MetaDto struct { @@ -47,27 +45,29 @@ type MetaDto struct { type ResponseDto struct { ecore.Main - Encounter_Id *uint `json:"encounter_id"` - Number *string `json:"number"` + Encounter_Id *uint `json:"encounter_id"` + Date *time.Time `json:"date"` + SrcCode *string `json:"src_code"` + SrcName *string `json:"src_name"` + Number *string `json:"number"` } -func (d VclaimSep) ToResponse() ResponseDto { +func (d VclaimReference) ToResponse() ResponseDto { resp := ResponseDto{ Encounter_Id: d.Encounter_Id, + Date: d.Date, + SrcCode: d.SrcCode, + SrcName: d.SrcName, Number: d.Number, } resp.Main = d.Main return resp } -func ToResponseList(data []VclaimSep) []ResponseDto { +func ToResponseList(data []VclaimReference) []ResponseDto { resp := make([]ResponseDto, len(data)) for i, u := range data { resp[i] = u.ToResponse() } return resp } - -func (c CreateDto) IsMessageSuccess() bool { - return c.VclaimSepHist.Message == "Sukses" -} diff --git a/internal/domain/bpjs-entities/vclaim-reference/entity.go b/internal/domain/bpjs-entities/vclaim-reference/entity.go new file mode 100644 index 00000000..a9a974d7 --- /dev/null +++ b/internal/domain/bpjs-entities/vclaim-reference/entity.go @@ -0,0 +1,15 @@ +package vclaimreference + +import ( + ecore "simrs-vx/internal/domain/base-entities/core" + "time" +) + +type VclaimReference struct { + ecore.Main + Encounter_Id *uint `json:"encounter_id"` + Date *time.Time `json:"date"` + SrcCode *string `json:"src_code"` + SrcName *string `json:"src_name"` + Number *string `json:"number"` +} diff --git a/internal/domain/main-entities/encounter/entity.go b/internal/domain/main-entities/encounter/entity.go index c188bb1a..61496f9e 100644 --- a/internal/domain/main-entities/encounter/entity.go +++ b/internal/domain/main-entities/encounter/entity.go @@ -1,7 +1,13 @@ package encounter import ( + "time" + + erc "simrs-vx/internal/domain/references/common" + ere "simrs-vx/internal/domain/references/encounter" + ecore "simrs-vx/internal/domain/base-entities/core" + evr "simrs-vx/internal/domain/bpjs-entities/vclaim-reference" evs "simrs-vx/internal/domain/bpjs-entities/vclaim-sep" eam "simrs-vx/internal/domain/main-entities/ambulatory" ea "simrs-vx/internal/domain/main-entities/appointment" @@ -19,10 +25,6 @@ import ( es "simrs-vx/internal/domain/main-entities/specialist" ess "simrs-vx/internal/domain/main-entities/subspecialist" eu "simrs-vx/internal/domain/main-entities/unit" - - erc "simrs-vx/internal/domain/references/common" - ere "simrs-vx/internal/domain/references/encounter" - "time" ) type Encounter struct { @@ -74,6 +76,7 @@ type Encounter struct { RehabChildren *[]er.Basic `json:"rehabChildren,omitempty" gorm:"foreignKey:Parent_Encounter_Id;references:Id"` EncounterDocuments *[]eed.EncounterDocument `json:"encounterDocuments,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` GeneralConsents *[]egc.GeneralConsent `json:"generalConsents,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` + VclaimReference *evr.VclaimReference `json:"vclaimReference,omitempty" gorm:"foreignKey:Encounter_Id;references:Id"` } func (d Encounter) IsDone() bool { diff --git a/internal/interface/migration/main-entities.go b/internal/interface/migration/main-entities.go index d55a5e27..0b4a62fd 100644 --- a/internal/interface/migration/main-entities.go +++ b/internal/interface/migration/main-entities.go @@ -103,6 +103,7 @@ import ( ///BPJS vclaimmember "simrs-vx/internal/domain/bpjs-entities/vclaim-member" + vclaimreference "simrs-vx/internal/domain/bpjs-entities/vclaim-reference" vclaimsep "simrs-vx/internal/domain/bpjs-entities/vclaim-sep" vclaimsepcontrolletter "simrs-vx/internal/domain/bpjs-entities/vclaim-sep-control-letter" vclaimsephist "simrs-vx/internal/domain/bpjs-entities/vclaim-sep-hist" @@ -215,5 +216,6 @@ func getMainEntities() []any { &fileattachemnt.EncounterDocument{}, &vclaimsepcontrolletter.VclaimSepControlLetter{}, &resume.Resume{}, + &vclaimreference.VclaimReference{}, } }