feat (generate-file): not tested yet

This commit is contained in:
dpurbosakti
2025-11-17 17:18:22 +07:00
parent 8073236d06
commit 69a13dd37d
9 changed files with 340 additions and 16 deletions

No files matched your search

@@ -0,0 +1,18 @@
package generatefile
import (
"net/http"
rw "github.com/karincake/risoles"
u "simrs-vx/internal/use-case/main-use-case/generate-file"
)
func Generate(w http.ResponseWriter, r *http.Request) {
dto := u.GenerateDto{}
if res := rw.ValidateStructByIOR(w, r.Body, &dto); !res {
return
}
res, err := u.Generate(dto)
rw.DataResponse(w, res, err)
}
@@ -18,6 +18,7 @@ import (
encounter "simrs-vx/internal/interface/main-handler/encounter"
encounterdocument "simrs-vx/internal/interface/main-handler/encounter-document"
generalconsent "simrs-vx/internal/interface/main-handler/general-consent"
generatefile "simrs-vx/internal/interface/main-handler/generate-file"
internalreference "simrs-vx/internal/interface/main-handler/internal-reference"
materialorder "simrs-vx/internal/interface/main-handler/material-order"
materialorderitem "simrs-vx/internal/interface/main-handler/material-order-item"
@@ -280,6 +281,7 @@ func SetRoutes() http.Handler {
hc.RegCrud(r, "/v1/upload-file", uploadfile.O)
hc.RegCrud(r, "/v1/encounter-document", encounterdocument.O)
hc.RegCrud(r, "/v1/general-consent", generalconsent.O)
r.HandleFunc("POST /v1/generate-file", generatefile.Generate)
/******************** actor ********************/
hc.RegCrud(r, "/v1/person", person.O)
@@ -1,15 +1,18 @@
package generatefile
import (
// "encoding/json"
"encoding/json"
"errors"
// egc "simrs-vx/internal/domain/main-entities/general-consent"
// ugc "simrs-vx/internal/use-case/main-use-case/general-consent"
egc "simrs-vx/internal/domain/main-entities/general-consent"
ugc "simrs-vx/internal/use-case/main-use-case/general-consent"
pl "simrs-vx/pkg/logger"
dg "github.com/karincake/apem/db-gorm-pg"
d "github.com/karincake/dodol"
erc "simrs-vx/internal/domain/references/common"
ere "simrs-vx/internal/domain/references/encounter"
)
@@ -28,18 +31,55 @@ func Generate(input GenerateDto) (*d.Data, error) {
// general-consent
case ere.DTCGC:
// get value from general consent by ref_id
// gc, err := ugc.ReadDetailData(ugc.ReadDetailDto{Ref_Id: input.Ref_Id}, &event, nil)
// if err != nil {
// return nil, err
// }
gc, err := ugc.ReadDetailData(egc.ReadDetailDto{Id: *input.Ref_Id}, &event, nil)
if err != nil {
return nil, err
}
// map template data
// gc
// templateData := GeneralConsentPDF{}
// gcUnmarshalled := json.Unmarshal(g)
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 nil, err
}
} else {
return nil, errors.New("no value in this general consent")
}
return nil, nil
input.FormatType = erc.DFTCPDF
input.TemplateName = TDNGC
// 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")
}
return nil, nil
}
@@ -0,0 +1,83 @@
package generatefile
import (
"errors"
"fmt"
"mime"
"path/filepath"
"time"
erc "simrs-vx/internal/domain/references/common"
docscfg "simrs-vx/internal/infra/docs-cfg"
pf "simrs-vx/pkg/file-helper"
pm "simrs-vx/pkg/minio-helper"
pp "simrs-vx/pkg/pdf-helper"
)
// generate temporary file, upload to minio, generate public url, delete temporary file
func generateFile(input GenerateDto, templateData any) (string, error) {
newPath, err := pf.PathToSaveFile(fmt.Sprintf("./public/%s/%d/%s", input.EntityType_Code, *input.Ref_Id, input.Type_Code))
if err != nil {
return "", err
}
fPath := fmt.Sprintf("%s/%s_%s.%s", newPath, input.Type_Code, time.Now().Format("20060102150405"), input.FormatType)
templatePath := docscfg.O.GetPath() + string(input.TemplateName)
switch input.FormatType {
case erc.DFTCPDF:
if err := generatePDF(GeneratePDFdto{
TemplatePath: templatePath,
TemplateData: templateData,
PdfPath: fPath,
}); err != nil {
return "", err
}
case erc.DFTCTXLSX:
// TODO: generate xlsx
case erc.DFTCTCSV:
// TODO: generate csv
default:
return "", errors.New("invalid format type")
}
bucketName := input.EntityType_Code
objectName := fmt.Sprintf("%v/%s-%d", *input.Ref_Id, input.Type_Code, time.Now().UnixNano())
pdfUpload := pm.UploadPathInput{
BucketName: string(bucketName),
Name: objectName,
Path: fPath,
ContentType: mime.TypeByExtension(filepath.Ext(fPath)),
}
// create bucket if not exist, create object in bucket
info, err := pm.I.FPutObject(pdfUpload)
if err != nil {
return "", err
}
// generate public url
urlPub := pm.I.GenerateUrl(info.Bucket, info.Key)
if err := pf.DeleteFolder(fPath); err != nil {
return "", err
}
return urlPub, nil
}
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)
if err != nil {
return errors.New("generate pdf by command error : " + err.Error())
}
} else {
return errors.New("parse template error : " + err.Error())
}
return nil
}
@@ -14,12 +14,26 @@ type GeneralConsentPDF struct {
}
type GenerateDto struct {
EntityType_Code ere.EntityTypeCode `form:"entityType_code"`
Ref_Id *uint `form:"ref_id"`
Type_Code ere.DocTypeCode `form:"type_code"`
FormatType erc.DocFormatTypeCode `form:"formatType"`
EntityType_Code ere.EntityTypeCode `json:"entityType_code"`
Ref_Id *uint `json:"ref_id"`
Type_Code ere.DocTypeCode `json:"type_code"`
FormatType erc.DocFormatTypeCode `json:"formatType"`
TemplateName TemplateDocsName `json:"-"`
}
type GeneratePDFdto struct {
TemplatePath string
TemplateData any
PdfPath string
}
type ResponseDto struct {
FileUrl string `json:"fileUrl"`
}
type TemplateDocsName string
// TemplateDocsName is the name of the template file in the assets/docs folder
const (
TDNGC TemplateDocsName = "general-consent.html"
)