Merge branch 'migration-vanilia' of https://github.com/dikstub-rssa/simrs-be into feat/sync-from-simx-160

This commit is contained in:
vanilia
2025-11-21 10:43:45 +07:00
26 changed files with 1172 additions and 110 deletions
@@ -4,14 +4,21 @@ 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"
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"
@@ -25,70 +32,150 @@ func Generate(input GenerateDto) (*d.Data, error) {
Source: source,
}
var response ResponseDto
// 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: *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 nil, err
return err
}
} else {
return nil, errors.New("no value in this general consent")
if gc.FileUrl != nil {
if err := removeFile(string(input.EntityType_Code), *gc.FileUrl); err != nil {
return 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")
}
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 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
}
}
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 = TDNGC
input.Encounter_Id = gc.Encounter_Id
templateData.Date = pu.FormatIndonesianDate(gc.CreatedAt)
return nil
})
// 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,
}
return &d.Data{
Meta: d.II{
"source": source,
"structure": "single-data",
"status": "created",
},
Data: response,
}, nil
default:
return nil, errors.New("invalid type code")
if err != nil {
return nil, err
}
return &d.Data{
Meta: d.II{
"source": source,
"structure": "single-data",
"status": "created",
},
Data: response,
}, nil
}
@@ -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())
}
@@ -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:"-"`
UseA5Lanscape bool `json:"-"`
Data *string `json:"data"`
}
type VclaimControlLetter struct {
Number string `json:"noSuratKontrol"`
Date string `json:"tglRencanaKontrol"`
PlannedControlDate string `json:"tglRencanaKontrol"`
Doctor_Name string `json:"namaDokter"`
DstUnit_Name string `json:"namaPoliTujuan"`
ResponsibleDoctor_Name string `json:"namaDokterPembuat"`
@@ -46,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 {
@@ -60,4 +82,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")
}