Files
query-orchestration/api/queryAPI/fieldextractions.go
T
Jay Brown 3bdc27f4de Merged in feature/textExtractionsPart2 (pull request #193)
Continue finishing the parts of the text extraction plan

* add missing fields
2025-12-02 19:13:08 +00:00

703 lines
28 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,
})
}
// GetFieldExtractionByVersion retrieves a specific version of field extraction for a document.
// This endpoint returns the full field extraction data for a specific version.
func (s *Controllers) GetFieldExtractionByVersion(ctx echo.Context, params GetFieldExtractionByVersionParams) error {
documentID := uuid.UUID(params.DocumentId)
if documentID == uuid.Nil {
return echo.NewHTTPError(http.StatusBadRequest, "documentId is required")
}
if params.Version < 1 {
return echo.NewHTTPError(http.StatusBadRequest, "version must be at least 1")
}
// Get field extraction by version
extraction, err := s.svc.FieldExtraction.GetFieldExtractionByVersion(ctx.Request().Context(), documentID, params.Version)
if err != nil {
slog.Error("failed to get field extraction by version", "error", err, "document_id", documentID, "version", params.Version)
return echo.NewHTTPError(http.StatusInternalServerError, "failed to get field extraction")
}
if extraction == nil {
return echo.NewHTTPError(http.StatusNotFound, fmt.Sprintf("no field extraction found for document at version %d", params.Version))
}
// Fetch array fields
arrayFields, err := s.svc.FieldExtraction.GetFieldExtractionArrayFields(ctx.Request().Context(), extraction.ID)
if err != nil {
slog.Error("failed to get array fields", "error", err, "extraction_id", extraction.ID)
return echo.NewHTTPError(http.StatusInternalServerError, "failed to get array fields")
}
// Build response
response := buildFieldExtractionResponseFromVersionRow(extraction, arrayFields)
return ctx.JSON(http.StatusOK, response)
}
// 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),
}
}
// buildFieldExtractionResponseFromVersionRow builds the API response from the version-specific repository types
func buildFieldExtractionResponseFromVersionRow(row *repository.GetFieldExtractionByVersionRow, arrayFields []*repository.Documentfieldextractionarrayfield) *FieldExtractionResponse {
createdAt := time.Time{}
if row.Createdat.Valid {
createdAt = row.Createdat.Time
}
return &FieldExtractionResponse{
Id: openapi_types.UUID(row.ID),
DocumentId: DocumentID(row.Documentid),
//nolint:gosec // Version is a small number, int32 is sufficient
Version: int32(row.Version), // Already 1-based in database
SingleFields: convertRepoSingleFieldsToAPIFromVersionRow(row),
ArrayFields: convertRepoArrayFieldsToAPI(arrayFields),
CreatedAt: createdAt,
CreatedBy: openapi_types.Email(row.Createdby),
}
}
// convertRepoSingleFieldsToAPIFromVersionRow converts repository GetFieldExtractionByVersionRow to API SingleFields
func convertRepoSingleFieldsToAPIFromVersionRow(row *repository.GetFieldExtractionByVersionRow) SingleFields {
sf := SingleFields{
FileName: row.Filename,
ContractTitle: row.Contracttitle,
AareteDerivedAmendmentNum: row.Aaretederivedamendmentnum,
ClientName: row.Clientname,
PayerName: row.Payername,
PayerState: row.Payerstate,
ProviderState: row.Providerstate,
FilenameTin: row.Filenametin,
ProvGroupTin: row.Provgrouptin,
ProvGroupNpi: row.Provgroupnpi,
ProvGroupNameFull: row.Provgroupnamefull,
ProvOtherTin: row.Provothertin,
ProvOtherNpi: row.Provothernpi,
ProvOtherNameFull: row.Provothernamefull,
AutoRenewalInd: row.Autorenewalind,
AutoRenewalTerm: row.Autorenewalterm,
}
// Convert dates
if row.Aaretederivedeffectivedt.Valid {
d := pgDateToAPIDate(row.Aaretederivedeffectivedt)
sf.AareteDerivedEffectiveDt = &d
}
if row.Aaretederivedterminationdt.Valid {
d := pgDateToAPIDate(row.Aaretederivedterminationdt)
sf.AareteDerivedTerminationDt = &d
}
return sf
}
// 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
// Grouper extended fields
params.Aaretederivedgrouperversion = item.AareteDerivedGrouperVersion
params.Grouperalternativelevelofcare = item.GrouperAlternativeLevelOfCare
params.Grouperseverity = item.GrouperSeverity
params.Grouperriskofmortalitysubclass = item.GrouperRiskOfMortalitySubclass
// Outlier fields
params.Outlierterm = item.OutlierTerm
params.Rangenbrdays = item.RangeNbrDays
params.Outlierexclusioncd = item.OutlierExclusionCd
params.Outlierexclusioncddesc = item.OutlierExclusionCdDesc
// Facility adjustment fields
params.Facilityadjustmentterm = item.FacilityAdjustmentTerm
// Rate escalator fields
params.Rateescalatordesc = item.RateEscalatorDesc
// Stop loss fields
params.Stoplossterm = item.StopLossTerm
params.Stoplossexclusioncd = item.StopLossExclusionCd
params.Stoplossexclusiondesc = item.StopLossExclusionDesc
// Boolean fields
params.Carveoutind = item.CarveoutInd
params.Lesserofind = item.LesserOfInd
params.Greaterofind = item.GreaterOfInd
params.Defaultind = item.DefaultInd
// Grouper extended boolean fields
params.Grouperseverityind = item.GrouperSeverityInd
params.Groupertransferind = item.GrouperTransferInd
params.Grouperreadmissionsind = item.GrouperReadmissionsInd
params.Grouperhacind = item.GrouperHacInd
// Outlier boolean fields
params.Outlierfirstdollarind = item.OutlierFirstDollarInd
// Facility adjustment boolean fields
params.Dshind = item.DshInd
params.Imeind = item.ImeInd
params.Ntapind = item.NtapInd
params.Ucind = item.UcInd
params.Gmeind = item.GmeInd
// Rate escalator boolean fields
params.Rateescalatorind = item.RateEscalatorInd
// Stop loss boolean fields
params.Stoplossfirstdollarind = item.StopLossFirstDollarInd
// 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)
// Outlier numeric fields
params.Outlierfixedlossnbrdaysthreshold = float64ToPgNumeric(item.OutlierFixedLossNbrDaysThreshold)
params.Outlierfixedlossthreshold = float64ToPgNumeric(item.OutlierFixedLossThreshold)
params.Outliermaximum = float64ToPgNumeric(item.OutlierMaximum)
params.Outliermaximumfrequency = float64ToPgNumeric(item.OutlierMaximumFrequency)
params.Outlierpctrate = float64ToPgNumeric(item.OutlierPctRate)
// Facility adjustment numeric fields
params.Dshpctrate = float64ToPgNumeric(item.DshPctRate)
params.Dshfeerate = float64ToPgNumeric(item.DshFeeRate)
params.Imepctrate = float64ToPgNumeric(item.ImePctRate)
params.Imefeerate = float64ToPgNumeric(item.ImeFeeRate)
params.Ntappctrate = float64ToPgNumeric(item.NtapPctRate)
params.Ntapfeerate = float64ToPgNumeric(item.NtapFeeRate)
params.Ucpctrate = float64ToPgNumeric(item.UcPctRate)
params.Ucfeerate = float64ToPgNumeric(item.UcFeeRate)
params.Gmepctrate = float64ToPgNumeric(item.GmePctRate)
params.Gmefeerate = float64ToPgNumeric(item.GmeFeeRate)
// Rate escalator numeric fields
params.Rateescalatormaxrateincpct = float64ToPgNumeric(item.RateEscalatorMaxRateIncPct)
params.Rateescalatorratechangetimeline = float64ToPgNumeric(item.RateEscalatorRateChangeTimeline)
// Stop loss numeric fields
params.Stoplossrangenbrdays = float64ToPgNumeric(item.StopLossRangeNbrDays)
params.Stoplossfixedlossthreshold = float64ToPgNumeric(item.StopLossFixedLossThreshold)
params.Stoplossmaximum = float64ToPgNumeric(item.StopLossMaximum)
params.Stoplossmaximumfrequency = float64ToPgNumeric(item.StopLossMaximumFrequency)
params.Stoplossdailymaxrate = float64ToPgNumeric(item.StopLossDailyMaxRate)
params.Stoplosspctrateonexcesscharges = float64ToPgNumeric(item.StopLossPctRateOnExcessCharges)
// 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,
// Grouper extended string fields
AareteDerivedGrouperVersion: f.Aaretederivedgrouperversion,
GrouperAlternativeLevelOfCare: f.Grouperalternativelevelofcare,
GrouperSeverity: f.Grouperseverity,
GrouperRiskOfMortalitySubclass: f.Grouperriskofmortalitysubclass,
// Outlier string fields
OutlierTerm: f.Outlierterm,
RangeNbrDays: f.Rangenbrdays,
OutlierExclusionCd: f.Outlierexclusioncd,
OutlierExclusionCdDesc: f.Outlierexclusioncddesc,
// Facility adjustment string fields
FacilityAdjustmentTerm: f.Facilityadjustmentterm,
// Rate escalator string fields
RateEscalatorDesc: f.Rateescalatordesc,
// Stop loss string fields
StopLossTerm: f.Stoplossterm,
StopLossExclusionCd: f.Stoplossexclusioncd,
StopLossExclusionDesc: f.Stoplossexclusiondesc,
// Boolean fields
CarveoutInd: f.Carveoutind,
LesserOfInd: f.Lesserofind,
GreaterOfInd: f.Greaterofind,
DefaultInd: f.Defaultind,
// Grouper extended boolean fields
GrouperSeverityInd: f.Grouperseverityind,
GrouperTransferInd: f.Groupertransferind,
GrouperReadmissionsInd: f.Grouperreadmissionsind,
GrouperHacInd: f.Grouperhacind,
// Outlier boolean fields
OutlierFirstDollarInd: f.Outlierfirstdollarind,
// Facility adjustment boolean fields
DshInd: f.Dshind,
ImeInd: f.Imeind,
NtapInd: f.Ntapind,
UcInd: f.Ucind,
GmeInd: f.Gmeind,
// Rate escalator boolean fields
RateEscalatorInd: f.Rateescalatorind,
// Stop loss boolean fields
StopLossFirstDollarInd: f.Stoplossfirstdollarind,
}
// 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)
// Outlier numeric fields
item.OutlierFixedLossNbrDaysThreshold = pgNumericToFloat64(f.Outlierfixedlossnbrdaysthreshold)
item.OutlierFixedLossThreshold = pgNumericToFloat64(f.Outlierfixedlossthreshold)
item.OutlierMaximum = pgNumericToFloat64(f.Outliermaximum)
item.OutlierMaximumFrequency = pgNumericToFloat64(f.Outliermaximumfrequency)
item.OutlierPctRate = pgNumericToFloat64(f.Outlierpctrate)
// Facility adjustment numeric fields
item.DshPctRate = pgNumericToFloat64(f.Dshpctrate)
item.DshFeeRate = pgNumericToFloat64(f.Dshfeerate)
item.ImePctRate = pgNumericToFloat64(f.Imepctrate)
item.ImeFeeRate = pgNumericToFloat64(f.Imefeerate)
item.NtapPctRate = pgNumericToFloat64(f.Ntappctrate)
item.NtapFeeRate = pgNumericToFloat64(f.Ntapfeerate)
item.UcPctRate = pgNumericToFloat64(f.Ucpctrate)
item.UcFeeRate = pgNumericToFloat64(f.Ucfeerate)
item.GmePctRate = pgNumericToFloat64(f.Gmepctrate)
item.GmeFeeRate = pgNumericToFloat64(f.Gmefeerate)
// Rate escalator numeric fields
item.RateEscalatorMaxRateIncPct = pgNumericToFloat64(f.Rateescalatormaxrateincpct)
item.RateEscalatorRateChangeTimeline = pgNumericToFloat64(f.Rateescalatorratechangetimeline)
// Stop loss numeric fields
item.StopLossRangeNbrDays = pgNumericToFloat64(f.Stoplossrangenbrdays)
item.StopLossFixedLossThreshold = pgNumericToFloat64(f.Stoplossfixedlossthreshold)
item.StopLossMaximum = pgNumericToFloat64(f.Stoplossmaximum)
item.StopLossMaximumFrequency = pgNumericToFloat64(f.Stoplossmaximumfrequency)
item.StopLossDailyMaxRate = pgNumericToFloat64(f.Stoplossdailymaxrate)
item.StopLossPctRateOnExcessCharges = pgNumericToFloat64(f.Stoplosspctrateonexcesscharges)
// 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
}