Merged in feature/textExtractionsPart2 (pull request #193)
Continue finishing the parts of the text extraction plan * add missing fields
This commit is contained in:
@@ -141,6 +141,42 @@ func (s *Controllers) GetFieldExtractionHistory(ctx echo.Context, params GetFiel
|
||||
})
|
||||
}
|
||||
|
||||
// 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{}
|
||||
@@ -160,6 +196,59 @@ func buildFieldExtractionResponse(current *repository.Currentfieldextraction, ar
|
||||
}
|
||||
}
|
||||
|
||||
// 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{
|
||||
@@ -300,12 +389,57 @@ func convertAPIArrayFieldItemToRepo(item *ArrayFieldItem) *repository.AddFieldEx
|
||||
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)
|
||||
@@ -317,6 +451,37 @@ func convertAPIArrayFieldItemToRepo(item *ArrayFieldItem) *repository.AddFieldEx
|
||||
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)
|
||||
@@ -391,11 +556,56 @@ func convertRepoArrayFieldToAPI(f *repository.Documentfieldextractionarrayfield)
|
||||
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
|
||||
@@ -409,6 +619,37 @@ func convertRepoArrayFieldToAPI(f *repository.Documentfieldextractionarrayfield)
|
||||
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)
|
||||
|
||||
Reference in New Issue
Block a user