462 lines
18 KiB
Go
462 lines
18 KiB
Go
|
|
package queryapi
|
||
|
|
|
||
|
|
import (
|
||
|
|
"fmt"
|
||
|
|
"log/slog"
|
||
|
|
"net/http"
|
||
|
|
"time"
|
||
|
|
|
||
|
|
"queryorchestration/internal/database/repository"
|
||
|
|
"queryorchestration/internal/fieldextraction"
|
||
|
|
|
||
|
|
"github.com/google/uuid"
|
||
|
|
"github.com/jackc/pgx/v5/pgtype"
|
||
|
|
"github.com/labstack/echo/v4"
|
||
|
|
openapi_types "github.com/oapi-codegen/runtime/types"
|
||
|
|
)
|
||
|
|
|
||
|
|
// CreateFieldExtraction creates a new field extraction with single-value and array fields.
|
||
|
|
// This endpoint creates a versioned field extraction record for a document.
|
||
|
|
func (s *Controllers) CreateFieldExtraction(ctx echo.Context) error {
|
||
|
|
var req FieldExtractionRequest
|
||
|
|
if err := ctx.Bind(&req); err != nil {
|
||
|
|
slog.Error("failed to parse field extraction request", "error", err)
|
||
|
|
return echo.NewHTTPError(http.StatusBadRequest, "invalid request body")
|
||
|
|
}
|
||
|
|
|
||
|
|
// Validate required fields
|
||
|
|
documentID := uuid.UUID(req.DocumentId)
|
||
|
|
if documentID == uuid.Nil {
|
||
|
|
return echo.NewHTTPError(http.StatusBadRequest, "documentId is required")
|
||
|
|
}
|
||
|
|
|
||
|
|
createdBy := string(req.CreatedBy)
|
||
|
|
if createdBy == "" {
|
||
|
|
return echo.NewHTTPError(http.StatusBadRequest, "createdBy is required")
|
||
|
|
}
|
||
|
|
|
||
|
|
// Convert API request to service input
|
||
|
|
input := &fieldextraction.CreateFieldExtractionInput{
|
||
|
|
DocumentID: documentID,
|
||
|
|
SingleFields: convertAPISingleFieldsToRepo(&req.SingleFields, createdBy),
|
||
|
|
ArrayFields: convertAPIArrayFieldsToRepo(req.ArrayFields),
|
||
|
|
}
|
||
|
|
|
||
|
|
// Create field extraction via service
|
||
|
|
extraction, err := s.svc.FieldExtraction.CreateFieldExtraction(ctx.Request().Context(), input)
|
||
|
|
if err != nil {
|
||
|
|
slog.Error("failed to create field extraction", "error", err, "document_id", documentID)
|
||
|
|
return echo.NewHTTPError(http.StatusInternalServerError, "failed to create field extraction")
|
||
|
|
}
|
||
|
|
|
||
|
|
// Fetch the current extraction to get version info
|
||
|
|
current, err := s.svc.FieldExtraction.GetCurrentFieldExtraction(ctx.Request().Context(), documentID)
|
||
|
|
if err != nil {
|
||
|
|
slog.Error("failed to get current field extraction after creation", "error", err, "document_id", documentID)
|
||
|
|
return echo.NewHTTPError(http.StatusInternalServerError, "failed to get created field extraction")
|
||
|
|
}
|
||
|
|
|
||
|
|
// Fetch array fields for response
|
||
|
|
arrayFields, err := s.svc.FieldExtraction.GetFieldExtractionArrayFields(ctx.Request().Context(), extraction.ID)
|
||
|
|
if err != nil {
|
||
|
|
slog.Error("failed to get array fields after creation", "error", err, "extraction_id", extraction.ID)
|
||
|
|
return echo.NewHTTPError(http.StatusInternalServerError, "failed to get array fields")
|
||
|
|
}
|
||
|
|
|
||
|
|
// Build response
|
||
|
|
response := buildFieldExtractionResponse(current, arrayFields)
|
||
|
|
|
||
|
|
return ctx.JSON(http.StatusCreated, response)
|
||
|
|
}
|
||
|
|
|
||
|
|
// GetCurrentFieldExtraction retrieves the most recent field extraction for a document.
|
||
|
|
// This returns the current (latest version) field extraction including all single and array fields.
|
||
|
|
func (s *Controllers) GetCurrentFieldExtraction(ctx echo.Context, params GetCurrentFieldExtractionParams) error {
|
||
|
|
documentID := uuid.UUID(params.DocumentId)
|
||
|
|
if documentID == uuid.Nil {
|
||
|
|
return echo.NewHTTPError(http.StatusBadRequest, "documentId is required")
|
||
|
|
}
|
||
|
|
|
||
|
|
// Get current field extraction
|
||
|
|
current, err := s.svc.FieldExtraction.GetCurrentFieldExtraction(ctx.Request().Context(), documentID)
|
||
|
|
if err != nil {
|
||
|
|
slog.Error("failed to get current field extraction", "error", err, "document_id", documentID)
|
||
|
|
return echo.NewHTTPError(http.StatusInternalServerError, "failed to get field extraction")
|
||
|
|
}
|
||
|
|
|
||
|
|
if current == nil {
|
||
|
|
return echo.NewHTTPError(http.StatusNotFound, "no field extraction found for document")
|
||
|
|
}
|
||
|
|
|
||
|
|
// Fetch array fields
|
||
|
|
arrayFields, err := s.svc.FieldExtraction.GetFieldExtractionArrayFields(ctx.Request().Context(), current.ID)
|
||
|
|
if err != nil {
|
||
|
|
slog.Error("failed to get array fields", "error", err, "extraction_id", current.ID)
|
||
|
|
return echo.NewHTTPError(http.StatusInternalServerError, "failed to get array fields")
|
||
|
|
}
|
||
|
|
|
||
|
|
// Build response
|
||
|
|
response := buildFieldExtractionResponse(current, arrayFields)
|
||
|
|
|
||
|
|
return ctx.JSON(http.StatusOK, response)
|
||
|
|
}
|
||
|
|
|
||
|
|
// GetFieldExtractionHistory retrieves all versions of field extractions for a document.
|
||
|
|
// This returns version metadata without the full field data for each version.
|
||
|
|
func (s *Controllers) GetFieldExtractionHistory(ctx echo.Context, params GetFieldExtractionHistoryParams) error {
|
||
|
|
documentID := uuid.UUID(params.DocumentId)
|
||
|
|
if documentID == uuid.Nil {
|
||
|
|
return echo.NewHTTPError(http.StatusBadRequest, "documentId is required")
|
||
|
|
}
|
||
|
|
|
||
|
|
// Get version history
|
||
|
|
history, err := s.svc.FieldExtraction.GetFieldExtractionHistory(ctx.Request().Context(), documentID)
|
||
|
|
if err != nil {
|
||
|
|
slog.Error("failed to get field extraction history", "error", err, "document_id", documentID)
|
||
|
|
return echo.NewHTTPError(http.StatusInternalServerError, "failed to get field extraction history")
|
||
|
|
}
|
||
|
|
|
||
|
|
// Convert to API response
|
||
|
|
versions := make([]FieldExtractionVersion, len(history))
|
||
|
|
for i, h := range history {
|
||
|
|
createdAt := time.Time{}
|
||
|
|
if h.Createdat.Valid {
|
||
|
|
createdAt = h.Createdat.Time
|
||
|
|
}
|
||
|
|
|
||
|
|
versions[i] = FieldExtractionVersion{
|
||
|
|
Id: openapi_types.UUID(h.ID),
|
||
|
|
DocumentId: DocumentID(h.Documentid),
|
||
|
|
//nolint:gosec // Version is a small number, int32 is sufficient
|
||
|
|
Version: int32(h.Version), // Already 1-based in database
|
||
|
|
CreatedAt: createdAt,
|
||
|
|
CreatedBy: openapi_types.Email(h.Createdby),
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return ctx.JSON(http.StatusOK, struct {
|
||
|
|
Versions []FieldExtractionVersion `json:"versions"`
|
||
|
|
}{
|
||
|
|
Versions: versions,
|
||
|
|
})
|
||
|
|
}
|
||
|
|
|
||
|
|
// buildFieldExtractionResponse builds the API response from the repository types
|
||
|
|
func buildFieldExtractionResponse(current *repository.Currentfieldextraction, arrayFields []*repository.Documentfieldextractionarrayfield) *FieldExtractionResponse {
|
||
|
|
createdAt := time.Time{}
|
||
|
|
if current.Createdat.Valid {
|
||
|
|
createdAt = current.Createdat.Time
|
||
|
|
}
|
||
|
|
|
||
|
|
return &FieldExtractionResponse{
|
||
|
|
Id: openapi_types.UUID(current.ID),
|
||
|
|
DocumentId: DocumentID(current.Documentid),
|
||
|
|
//nolint:gosec // Version is a small number, int32 is sufficient
|
||
|
|
Version: int32(current.Version), // Already 1-based in database
|
||
|
|
SingleFields: convertRepoSingleFieldsToAPI(current),
|
||
|
|
ArrayFields: convertRepoArrayFieldsToAPI(arrayFields),
|
||
|
|
CreatedAt: createdAt,
|
||
|
|
CreatedBy: openapi_types.Email(current.Createdby),
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// convertAPISingleFieldsToRepo converts API SingleFields to repository AddFieldExtractionParams
|
||
|
|
func convertAPISingleFieldsToRepo(sf *SingleFields, createdBy string) *repository.AddFieldExtractionParams {
|
||
|
|
params := &repository.AddFieldExtractionParams{
|
||
|
|
Createdby: createdBy,
|
||
|
|
}
|
||
|
|
|
||
|
|
if sf == nil {
|
||
|
|
return params
|
||
|
|
}
|
||
|
|
|
||
|
|
params.Filename = sf.FileName
|
||
|
|
params.Contracttitle = sf.ContractTitle
|
||
|
|
params.Aaretederivedamendmentnum = sf.AareteDerivedAmendmentNum
|
||
|
|
params.Clientname = sf.ClientName
|
||
|
|
params.Payername = sf.PayerName
|
||
|
|
params.Payerstate = sf.PayerState
|
||
|
|
params.Providerstate = sf.ProviderState
|
||
|
|
params.Filenametin = sf.FilenameTin
|
||
|
|
params.Provgrouptin = sf.ProvGroupTin
|
||
|
|
params.Provgroupnpi = sf.ProvGroupNpi
|
||
|
|
params.Provgroupnamefull = sf.ProvGroupNameFull
|
||
|
|
params.Provothertin = sf.ProvOtherTin
|
||
|
|
params.Provothernpi = sf.ProvOtherNpi
|
||
|
|
params.Provothernamefull = sf.ProvOtherNameFull
|
||
|
|
params.Autorenewalind = sf.AutoRenewalInd
|
||
|
|
params.Autorenewalterm = sf.AutoRenewalTerm
|
||
|
|
|
||
|
|
// Convert dates
|
||
|
|
if sf.AareteDerivedEffectiveDt != nil {
|
||
|
|
params.Aaretederivedeffectivedt = dateToPgDate(*sf.AareteDerivedEffectiveDt)
|
||
|
|
}
|
||
|
|
if sf.AareteDerivedTerminationDt != nil {
|
||
|
|
params.Aaretederivedterminationdt = dateToPgDate(*sf.AareteDerivedTerminationDt)
|
||
|
|
}
|
||
|
|
|
||
|
|
return params
|
||
|
|
}
|
||
|
|
|
||
|
|
// convertRepoSingleFieldsToAPI converts repository Currentfieldextraction to API SingleFields
|
||
|
|
func convertRepoSingleFieldsToAPI(cf *repository.Currentfieldextraction) SingleFields {
|
||
|
|
sf := SingleFields{
|
||
|
|
FileName: cf.Filename,
|
||
|
|
ContractTitle: cf.Contracttitle,
|
||
|
|
AareteDerivedAmendmentNum: cf.Aaretederivedamendmentnum,
|
||
|
|
ClientName: cf.Clientname,
|
||
|
|
PayerName: cf.Payername,
|
||
|
|
PayerState: cf.Payerstate,
|
||
|
|
ProviderState: cf.Providerstate,
|
||
|
|
FilenameTin: cf.Filenametin,
|
||
|
|
ProvGroupTin: cf.Provgrouptin,
|
||
|
|
ProvGroupNpi: cf.Provgroupnpi,
|
||
|
|
ProvGroupNameFull: cf.Provgroupnamefull,
|
||
|
|
ProvOtherTin: cf.Provothertin,
|
||
|
|
ProvOtherNpi: cf.Provothernpi,
|
||
|
|
ProvOtherNameFull: cf.Provothernamefull,
|
||
|
|
AutoRenewalInd: cf.Autorenewalind,
|
||
|
|
AutoRenewalTerm: cf.Autorenewalterm,
|
||
|
|
}
|
||
|
|
|
||
|
|
// Convert dates
|
||
|
|
if cf.Aaretederivedeffectivedt.Valid {
|
||
|
|
d := pgDateToAPIDate(cf.Aaretederivedeffectivedt)
|
||
|
|
sf.AareteDerivedEffectiveDt = &d
|
||
|
|
}
|
||
|
|
if cf.Aaretederivedterminationdt.Valid {
|
||
|
|
d := pgDateToAPIDate(cf.Aaretederivedterminationdt)
|
||
|
|
sf.AareteDerivedTerminationDt = &d
|
||
|
|
}
|
||
|
|
|
||
|
|
return sf
|
||
|
|
}
|
||
|
|
|
||
|
|
// convertAPIArrayFieldsToRepo converts API ArrayFieldItem slice to repository AddFieldExtractionArrayFieldParams slice
|
||
|
|
func convertAPIArrayFieldsToRepo(items []ArrayFieldItem) []*repository.AddFieldExtractionArrayFieldParams {
|
||
|
|
result := make([]*repository.AddFieldExtractionArrayFieldParams, len(items))
|
||
|
|
for i, item := range items {
|
||
|
|
result[i] = convertAPIArrayFieldItemToRepo(&item)
|
||
|
|
}
|
||
|
|
return result
|
||
|
|
}
|
||
|
|
|
||
|
|
// convertAPIArrayFieldItemToRepo converts a single API ArrayFieldItem to repository params
|
||
|
|
func convertAPIArrayFieldItemToRepo(item *ArrayFieldItem) *repository.AddFieldExtractionArrayFieldParams {
|
||
|
|
params := &repository.AddFieldExtractionArrayFieldParams{}
|
||
|
|
|
||
|
|
if item == nil {
|
||
|
|
return params
|
||
|
|
}
|
||
|
|
|
||
|
|
// String fields
|
||
|
|
params.Exhibittitle = item.ExhibitTitle
|
||
|
|
params.Exhibitpage = item.ExhibitPage
|
||
|
|
params.Reimbprovtin = item.ReimbProvTin
|
||
|
|
params.Reimbprovnpi = item.ReimbProvNpi
|
||
|
|
params.Reimbprovname = item.ReimbProvName
|
||
|
|
params.Aaretederivedclaimtypecd = item.AareteDerivedClaimTypeCd
|
||
|
|
params.Aaretederivedproduct = item.AareteDerivedProduct
|
||
|
|
params.Aaretederivedlob = item.AareteDerivedLob
|
||
|
|
params.Aaretederivedprogram = item.AareteDerivedProgram
|
||
|
|
params.Aaretederivednetwork = item.AareteDerivedNetwork
|
||
|
|
params.Aaretederivedprovtype = item.AareteDerivedProvType
|
||
|
|
params.Provtaxonomycd = item.ProvTaxonomyCd
|
||
|
|
params.Provtaxonomycddesc = item.ProvTaxonomyCdDesc
|
||
|
|
params.Provspecialtycd = item.ProvSpecialtyCd
|
||
|
|
params.Provspecialtycddesc = item.ProvSpecialtyCdDesc
|
||
|
|
params.Placeofservicecd = item.PlaceOfServiceCd
|
||
|
|
params.Placeofservicecddesc = item.PlaceOfServiceCdDesc
|
||
|
|
params.Billtypecd = item.BillTypeCd
|
||
|
|
params.Billtypecddesc = item.BillTypeCdDesc
|
||
|
|
params.Patientagemin = item.PatientAgeMin
|
||
|
|
params.Patientagemax = item.PatientAgeMax
|
||
|
|
params.Reimbterm = item.ReimbTerm
|
||
|
|
params.Lobprogramrelationship = item.LobProgramRelationship
|
||
|
|
params.Lobproductrelationship = item.LobProductRelationship
|
||
|
|
params.Aaretederivedreimbmethod = item.AareteDerivedReimbMethod
|
||
|
|
params.Unitofmeasure = item.UnitOfMeasure
|
||
|
|
params.Additiondesc = item.AdditionDesc
|
||
|
|
params.Aaretederivedadditionratechangetimeline = item.AareteDerivedAdditionRateChangeTimeline
|
||
|
|
params.Aaretederivedfeeschedule = item.AareteDerivedFeeSchedule
|
||
|
|
params.Aaretederivedfeescheduleversion = item.AareteDerivedFeeScheduleVersion
|
||
|
|
params.Serviceterm = item.ServiceTerm
|
||
|
|
params.Cpt4proccd = item.Cpt4ProcCd
|
||
|
|
params.Cpt4proccddesc = item.Cpt4ProcCdDesc
|
||
|
|
params.Cpt4procmod = item.Cpt4ProcMod
|
||
|
|
params.Cpt4procmoddesc = item.Cpt4ProcModDesc
|
||
|
|
params.Revenuecd = item.RevenueCd
|
||
|
|
params.Revenuecddesc = item.RevenueCdDesc
|
||
|
|
params.Diagcd = item.DiagCd
|
||
|
|
params.Diagcddesc = item.DiagCdDesc
|
||
|
|
params.Ndccd = item.NdcCd
|
||
|
|
params.Ndccddesc = item.NdcCdDesc
|
||
|
|
params.Claimadmittypecd = item.ClaimAdmitTypeCd
|
||
|
|
params.Authadmittypedesc = item.AuthAdmitTypeDesc
|
||
|
|
params.Claimstatuscd = item.ClaimStatusCd
|
||
|
|
params.Claimstatuscddesc = item.ClaimStatusCdDesc
|
||
|
|
params.Groupertype = item.GrouperType
|
||
|
|
params.Groupercd = item.GrouperCd
|
||
|
|
params.Groupercddesc = item.GrouperCdDesc
|
||
|
|
params.Carveoutcd = item.CarveoutCd
|
||
|
|
|
||
|
|
// Boolean fields
|
||
|
|
params.Carveoutind = item.CarveoutInd
|
||
|
|
params.Lesserofind = item.LesserOfInd
|
||
|
|
params.Greaterofind = item.GreaterOfInd
|
||
|
|
params.Defaultind = item.DefaultInd
|
||
|
|
|
||
|
|
// Numeric fields
|
||
|
|
params.Reimbpctrate = float64ToPgNumeric(item.ReimbPctRate)
|
||
|
|
params.Reimbfeerate = float64ToPgNumeric(item.ReimbFeeRate)
|
||
|
|
params.Reimbconversionfactor = float64ToPgNumeric(item.ReimbConversionFactor)
|
||
|
|
params.Triggercapthresholdamt = float64ToPgNumeric(item.TriggerCapThresholdAmt)
|
||
|
|
params.Triggerbasethreshold = float64ToPgNumeric(item.TriggerBaseThreshold)
|
||
|
|
params.Additionmaxfeerateinc = float64ToPgNumeric(item.AdditionMaxFeeRateInc)
|
||
|
|
params.Additionmaxpctrateinc = float64ToPgNumeric(item.AdditionMaxPctRateInc)
|
||
|
|
params.Grouperpctrate = float64ToPgNumeric(item.GrouperPctRate)
|
||
|
|
params.Grouperbaserate = float64ToPgNumeric(item.GrouperBaseRate)
|
||
|
|
|
||
|
|
// Date fields
|
||
|
|
if item.ReimbEffectiveDt != nil {
|
||
|
|
params.Reimbeffectivedt = dateToPgDate(*item.ReimbEffectiveDt)
|
||
|
|
}
|
||
|
|
if item.ReimbTerminationDt != nil {
|
||
|
|
params.Reimbterminationdt = dateToPgDate(*item.ReimbTerminationDt)
|
||
|
|
}
|
||
|
|
|
||
|
|
return params
|
||
|
|
}
|
||
|
|
|
||
|
|
// convertRepoArrayFieldsToAPI converts repository array fields to API ArrayFieldItem slice
|
||
|
|
func convertRepoArrayFieldsToAPI(fields []*repository.Documentfieldextractionarrayfield) []ArrayFieldItem {
|
||
|
|
result := make([]ArrayFieldItem, len(fields))
|
||
|
|
for i, f := range fields {
|
||
|
|
result[i] = convertRepoArrayFieldToAPI(f)
|
||
|
|
}
|
||
|
|
return result
|
||
|
|
}
|
||
|
|
|
||
|
|
// convertRepoArrayFieldToAPI converts a single repository array field to API ArrayFieldItem
|
||
|
|
func convertRepoArrayFieldToAPI(f *repository.Documentfieldextractionarrayfield) ArrayFieldItem {
|
||
|
|
item := ArrayFieldItem{
|
||
|
|
// String fields
|
||
|
|
ExhibitTitle: f.Exhibittitle,
|
||
|
|
ExhibitPage: f.Exhibitpage,
|
||
|
|
ReimbProvTin: f.Reimbprovtin,
|
||
|
|
ReimbProvNpi: f.Reimbprovnpi,
|
||
|
|
ReimbProvName: f.Reimbprovname,
|
||
|
|
AareteDerivedClaimTypeCd: f.Aaretederivedclaimtypecd,
|
||
|
|
AareteDerivedProduct: f.Aaretederivedproduct,
|
||
|
|
AareteDerivedLob: f.Aaretederivedlob,
|
||
|
|
AareteDerivedProgram: f.Aaretederivedprogram,
|
||
|
|
AareteDerivedNetwork: f.Aaretederivednetwork,
|
||
|
|
AareteDerivedProvType: f.Aaretederivedprovtype,
|
||
|
|
ProvTaxonomyCd: f.Provtaxonomycd,
|
||
|
|
ProvTaxonomyCdDesc: f.Provtaxonomycddesc,
|
||
|
|
ProvSpecialtyCd: f.Provspecialtycd,
|
||
|
|
ProvSpecialtyCdDesc: f.Provspecialtycddesc,
|
||
|
|
PlaceOfServiceCd: f.Placeofservicecd,
|
||
|
|
PlaceOfServiceCdDesc: f.Placeofservicecddesc,
|
||
|
|
BillTypeCd: f.Billtypecd,
|
||
|
|
BillTypeCdDesc: f.Billtypecddesc,
|
||
|
|
PatientAgeMin: f.Patientagemin,
|
||
|
|
PatientAgeMax: f.Patientagemax,
|
||
|
|
ReimbTerm: f.Reimbterm,
|
||
|
|
LobProgramRelationship: f.Lobprogramrelationship,
|
||
|
|
LobProductRelationship: f.Lobproductrelationship,
|
||
|
|
AareteDerivedReimbMethod: f.Aaretederivedreimbmethod,
|
||
|
|
UnitOfMeasure: f.Unitofmeasure,
|
||
|
|
AdditionDesc: f.Additiondesc,
|
||
|
|
AareteDerivedAdditionRateChangeTimeline: f.Aaretederivedadditionratechangetimeline,
|
||
|
|
AareteDerivedFeeSchedule: f.Aaretederivedfeeschedule,
|
||
|
|
AareteDerivedFeeScheduleVersion: f.Aaretederivedfeescheduleversion,
|
||
|
|
ServiceTerm: f.Serviceterm,
|
||
|
|
Cpt4ProcCd: f.Cpt4proccd,
|
||
|
|
Cpt4ProcCdDesc: f.Cpt4proccddesc,
|
||
|
|
Cpt4ProcMod: f.Cpt4procmod,
|
||
|
|
Cpt4ProcModDesc: f.Cpt4procmoddesc,
|
||
|
|
RevenueCd: f.Revenuecd,
|
||
|
|
RevenueCdDesc: f.Revenuecddesc,
|
||
|
|
DiagCd: f.Diagcd,
|
||
|
|
DiagCdDesc: f.Diagcddesc,
|
||
|
|
NdcCd: f.Ndccd,
|
||
|
|
NdcCdDesc: f.Ndccddesc,
|
||
|
|
ClaimAdmitTypeCd: f.Claimadmittypecd,
|
||
|
|
AuthAdmitTypeDesc: f.Authadmittypedesc,
|
||
|
|
ClaimStatusCd: f.Claimstatuscd,
|
||
|
|
ClaimStatusCdDesc: f.Claimstatuscddesc,
|
||
|
|
GrouperType: f.Groupertype,
|
||
|
|
GrouperCd: f.Groupercd,
|
||
|
|
GrouperCdDesc: f.Groupercddesc,
|
||
|
|
CarveoutCd: f.Carveoutcd,
|
||
|
|
|
||
|
|
// Boolean fields
|
||
|
|
CarveoutInd: f.Carveoutind,
|
||
|
|
LesserOfInd: f.Lesserofind,
|
||
|
|
GreaterOfInd: f.Greaterofind,
|
||
|
|
DefaultInd: f.Defaultind,
|
||
|
|
}
|
||
|
|
|
||
|
|
// Numeric fields
|
||
|
|
item.ReimbPctRate = pgNumericToFloat64(f.Reimbpctrate)
|
||
|
|
item.ReimbFeeRate = pgNumericToFloat64(f.Reimbfeerate)
|
||
|
|
item.ReimbConversionFactor = pgNumericToFloat64(f.Reimbconversionfactor)
|
||
|
|
item.TriggerCapThresholdAmt = pgNumericToFloat64(f.Triggercapthresholdamt)
|
||
|
|
item.TriggerBaseThreshold = pgNumericToFloat64(f.Triggerbasethreshold)
|
||
|
|
item.AdditionMaxFeeRateInc = pgNumericToFloat64(f.Additionmaxfeerateinc)
|
||
|
|
item.AdditionMaxPctRateInc = pgNumericToFloat64(f.Additionmaxpctrateinc)
|
||
|
|
item.GrouperPctRate = pgNumericToFloat64(f.Grouperpctrate)
|
||
|
|
item.GrouperBaseRate = pgNumericToFloat64(f.Grouperbaserate)
|
||
|
|
|
||
|
|
// Date fields
|
||
|
|
if f.Reimbeffectivedt.Valid {
|
||
|
|
d := pgDateToAPIDate(f.Reimbeffectivedt)
|
||
|
|
item.ReimbEffectiveDt = &d
|
||
|
|
}
|
||
|
|
if f.Reimbterminationdt.Valid {
|
||
|
|
d := pgDateToAPIDate(f.Reimbterminationdt)
|
||
|
|
item.ReimbTerminationDt = &d
|
||
|
|
}
|
||
|
|
|
||
|
|
return item
|
||
|
|
}
|
||
|
|
|
||
|
|
// dateToPgDate converts openapi_types.Date to pgtype.Date
|
||
|
|
func dateToPgDate(d openapi_types.Date) pgtype.Date {
|
||
|
|
return pgtype.Date{
|
||
|
|
Time: d.Time,
|
||
|
|
Valid: true,
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// pgDateToAPIDate converts pgtype.Date to openapi_types.Date
|
||
|
|
func pgDateToAPIDate(d pgtype.Date) openapi_types.Date {
|
||
|
|
return openapi_types.Date{
|
||
|
|
Time: d.Time,
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// float64ToPgNumeric converts *float64 to pgtype.Numeric
|
||
|
|
func float64ToPgNumeric(f *float64) pgtype.Numeric {
|
||
|
|
if f == nil {
|
||
|
|
return pgtype.Numeric{}
|
||
|
|
}
|
||
|
|
var num pgtype.Numeric
|
||
|
|
// Scan doesn't accept float64 directly, need to convert to string
|
||
|
|
_ = num.Scan(fmt.Sprintf("%v", *f))
|
||
|
|
return num
|
||
|
|
}
|
||
|
|
|
||
|
|
// pgNumericToFloat64 converts pgtype.Numeric to *float64
|
||
|
|
func pgNumericToFloat64(n pgtype.Numeric) *float64 {
|
||
|
|
if !n.Valid {
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
f, err := n.Float64Value()
|
||
|
|
if err != nil || !f.Valid {
|
||
|
|
return nil
|
||
|
|
}
|
||
|
|
return &f.Float64
|
||
|
|
}
|