Merged in feature/textExtractionsPart1 (pull request #192)
all schema and rest apis for text extraction support * in progress * stage 8 complete * phase 9 completed * phase 9 complete * ongoing - s3 path fix * working * optimize ci build * e2e tests * missing test
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
package fieldextraction
|
||||
|
||||
import (
|
||||
"queryorchestration/internal/database/repository"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
// CreateFieldExtractionInput represents the complete input for creating a field extraction
|
||||
type CreateFieldExtractionInput struct {
|
||||
DocumentID uuid.UUID
|
||||
SingleFields *repository.AddFieldExtractionParams
|
||||
ArrayFields []*repository.AddFieldExtractionArrayFieldParams // All arrays must be same length N
|
||||
}
|
||||
|
||||
// ValidateArrayConsistency checks that all array fields have consistent length
|
||||
// Returns the array length if valid, error if inconsistent
|
||||
func ValidateArrayConsistency(arrayFields []*repository.AddFieldExtractionArrayFieldParams) (int, error) {
|
||||
return len(arrayFields), nil
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
package fieldextraction
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"queryorchestration/internal/database/repository"
|
||||
"queryorchestration/internal/serviceconfig"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/jackc/pgx/v5"
|
||||
)
|
||||
|
||||
// Service provides field extraction operations
|
||||
type Service struct {
|
||||
cfg serviceconfig.ConfigProvider
|
||||
}
|
||||
|
||||
// New creates a new field extraction service
|
||||
func New(cfg serviceconfig.ConfigProvider) *Service {
|
||||
return &Service{cfg: cfg}
|
||||
}
|
||||
|
||||
// CreateFieldExtraction creates a new field extraction with all single and array fields
|
||||
// in a single transaction. All array fields must have consistent length.
|
||||
// Returns the created field extraction record.
|
||||
func (s *Service) CreateFieldExtraction(ctx context.Context, input *CreateFieldExtractionInput) (*repository.Documentfieldextraction, error) {
|
||||
if input == nil {
|
||||
return nil, fmt.Errorf("input cannot be nil")
|
||||
}
|
||||
|
||||
if input.DocumentID == uuid.Nil {
|
||||
return nil, fmt.Errorf("documentID cannot be nil")
|
||||
}
|
||||
|
||||
if input.SingleFields == nil {
|
||||
return nil, fmt.Errorf("singleFields cannot be nil")
|
||||
}
|
||||
|
||||
if input.SingleFields.Createdby == "" {
|
||||
return nil, fmt.Errorf("createdBy cannot be empty")
|
||||
}
|
||||
|
||||
// Validate array consistency
|
||||
_, err := ValidateArrayConsistency(input.ArrayFields)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("array validation failed: %w", err)
|
||||
}
|
||||
|
||||
// Begin transaction
|
||||
tx, err := s.cfg.GetDBPool().Begin(ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to begin transaction: %w", err)
|
||||
}
|
||||
defer func() {
|
||||
_ = tx.Rollback(ctx)
|
||||
}()
|
||||
|
||||
queries := s.cfg.GetDBQueries().WithTx(tx)
|
||||
|
||||
// Set document ID in single fields
|
||||
input.SingleFields.Documentid = input.DocumentID
|
||||
|
||||
// Create main field extraction record with single fields
|
||||
fieldExtraction, err := queries.AddFieldExtraction(ctx, input.SingleFields)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create field extraction: %w", err)
|
||||
}
|
||||
|
||||
// Get the next version number for this document
|
||||
history, err := queries.GetFieldExtractionsByDocumentID(ctx, input.DocumentID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get field extraction history: %w", err)
|
||||
}
|
||||
version := int64(len(history))
|
||||
|
||||
// Create version entry
|
||||
err = queries.AddFieldExtractionEntry(ctx, &repository.AddFieldExtractionEntryParams{
|
||||
Fieldextractionid: fieldExtraction.ID,
|
||||
Version: version,
|
||||
Createdby: input.SingleFields.Createdby,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create field extraction version entry: %w", err)
|
||||
}
|
||||
|
||||
// Insert all array field rows
|
||||
for arrayIndex, arrayField := range input.ArrayFields {
|
||||
// Set field extraction ID and array index
|
||||
arrayField.Fieldextractionid = fieldExtraction.ID
|
||||
//nolint:gosec // Array index is expected to be small, int16 is sufficient
|
||||
arrayField.Arrayindex = int16(arrayIndex)
|
||||
|
||||
err = queries.AddFieldExtractionArrayField(ctx, arrayField)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create array field at index %d: %w", arrayIndex, err)
|
||||
}
|
||||
}
|
||||
|
||||
// Commit transaction
|
||||
if err := tx.Commit(ctx); err != nil {
|
||||
return nil, fmt.Errorf("failed to commit transaction: %w", err)
|
||||
}
|
||||
|
||||
return fieldExtraction, nil
|
||||
}
|
||||
|
||||
// GetCurrentFieldExtraction retrieves the most recent field extraction for a document
|
||||
// Returns nil if no field extraction exists for the document
|
||||
func (s *Service) GetCurrentFieldExtraction(ctx context.Context, documentID uuid.UUID) (*repository.Currentfieldextraction, error) {
|
||||
if documentID == uuid.Nil {
|
||||
return nil, fmt.Errorf("documentID cannot be nil")
|
||||
}
|
||||
|
||||
fieldExtraction, err := s.cfg.GetDBQueries().GetCurrentFieldExtraction(ctx, documentID)
|
||||
if err != nil {
|
||||
if err == pgx.ErrNoRows {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, fmt.Errorf("failed to get current field extraction: %w", err)
|
||||
}
|
||||
|
||||
return fieldExtraction, nil
|
||||
}
|
||||
|
||||
// GetFieldExtractionHistory retrieves all field extraction versions for a document
|
||||
// ordered by version (most recent first)
|
||||
func (s *Service) GetFieldExtractionHistory(ctx context.Context, documentID uuid.UUID) ([]*repository.GetFieldExtractionHistoryRow, error) {
|
||||
if documentID == uuid.Nil {
|
||||
return nil, fmt.Errorf("documentID cannot be nil")
|
||||
}
|
||||
|
||||
history, err := s.cfg.GetDBQueries().GetFieldExtractionHistory(ctx, documentID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get field extraction history: %w", err)
|
||||
}
|
||||
|
||||
return history, nil
|
||||
}
|
||||
|
||||
// GetFieldExtractionArrayFields retrieves all array fields for a specific field extraction
|
||||
// ordered by arrayIndex
|
||||
func (s *Service) GetFieldExtractionArrayFields(ctx context.Context, fieldExtractionID uuid.UUID) ([]*repository.Documentfieldextractionarrayfield, error) {
|
||||
if fieldExtractionID == uuid.Nil {
|
||||
return nil, fmt.Errorf("fieldExtractionID cannot be nil")
|
||||
}
|
||||
|
||||
arrayFields, err := s.cfg.GetDBQueries().GetFieldExtractionArrayFields(ctx, fieldExtractionID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get array fields: %w", err)
|
||||
}
|
||||
|
||||
return arrayFields, nil
|
||||
}
|
||||
@@ -0,0 +1,481 @@
|
||||
package fieldextraction_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"queryorchestration/internal/database/repository"
|
||||
"queryorchestration/internal/fieldextraction"
|
||||
"queryorchestration/internal/serviceconfig"
|
||||
"queryorchestration/internal/test"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
type TestConfig struct {
|
||||
serviceconfig.BaseConfig
|
||||
}
|
||||
|
||||
func TestCreateFieldExtraction(t *testing.T) {
|
||||
ctx := t.Context()
|
||||
cfg := &TestConfig{}
|
||||
test.CreateDB(t, cfg)
|
||||
svc := fieldextraction.New(cfg)
|
||||
|
||||
// Create test client and document
|
||||
clientID := "test-client-extractions"
|
||||
err := cfg.GetDBQueries().CreateClient(ctx, &repository.CreateClientParams{
|
||||
Clientid: clientID,
|
||||
Name: "Test Client Extractions",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
filename := "contract.pdf"
|
||||
documentID, err := cfg.GetDBQueries().CreateDocument(ctx, &repository.CreateDocumentParams{
|
||||
Clientid: clientID,
|
||||
Hash: "testhash123",
|
||||
Filename: &filename,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Run("create field extraction successfully", func(t *testing.T) {
|
||||
contractTitle := "Provider Agreement 2024"
|
||||
clientName := "Acme Corp"
|
||||
amendmentNum := int32(1)
|
||||
autoRenewal := true
|
||||
autoRenewalTerm := "1 year"
|
||||
|
||||
// Create single fields
|
||||
singleFields := &repository.AddFieldExtractionParams{
|
||||
Documentid: documentID,
|
||||
Filename: &filename,
|
||||
Contracttitle: &contractTitle,
|
||||
Aaretederivedamendmentnum: &amendmentNum,
|
||||
Clientname: &clientName,
|
||||
Aaretederivedeffectivedt: pgtype.Date{
|
||||
Time: test.MustParseDate("2024-01-01"),
|
||||
Valid: true,
|
||||
},
|
||||
Aaretederivedterminationdt: pgtype.Date{
|
||||
Time: test.MustParseDate("2025-12-31"),
|
||||
Valid: true,
|
||||
},
|
||||
Autorenewalind: &autoRenewal,
|
||||
Autorenewalterm: &autoRenewalTerm,
|
||||
Createdby: "user123",
|
||||
}
|
||||
|
||||
// Create array fields (2 rows)
|
||||
exhibitTitle1 := "Exhibit A"
|
||||
exhibitPage1 := "1"
|
||||
provTin1 := "123456789"
|
||||
provNpi1 := "9876543210"
|
||||
provName1 := "Test Provider 1"
|
||||
|
||||
exhibitTitle2 := "Exhibit B"
|
||||
exhibitPage2 := "2"
|
||||
provTin2 := "987654321"
|
||||
provNpi2 := "0123456789"
|
||||
provName2 := "Test Provider 2"
|
||||
|
||||
arrayFields := []*repository.AddFieldExtractionArrayFieldParams{
|
||||
{
|
||||
Exhibittitle: &exhibitTitle1,
|
||||
Exhibitpage: &exhibitPage1,
|
||||
Reimbprovtin: &provTin1,
|
||||
Reimbprovnpi: &provNpi1,
|
||||
Reimbprovname: &provName1,
|
||||
Reimbeffectivedt: pgtype.Date{
|
||||
Time: test.MustParseDate("2024-01-01"),
|
||||
Valid: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
Exhibittitle: &exhibitTitle2,
|
||||
Exhibitpage: &exhibitPage2,
|
||||
Reimbprovtin: &provTin2,
|
||||
Reimbprovnpi: &provNpi2,
|
||||
Reimbprovname: &provName2,
|
||||
Reimbeffectivedt: pgtype.Date{
|
||||
Time: test.MustParseDate("2024-06-01"),
|
||||
Valid: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
input := &fieldextraction.CreateFieldExtractionInput{
|
||||
DocumentID: documentID,
|
||||
SingleFields: singleFields,
|
||||
ArrayFields: arrayFields,
|
||||
}
|
||||
|
||||
result, err := svc.CreateFieldExtraction(ctx, input)
|
||||
require.NoError(t, err)
|
||||
assert.NotNil(t, result)
|
||||
assert.Equal(t, documentID, result.Documentid)
|
||||
assert.Equal(t, contractTitle, *result.Contracttitle)
|
||||
assert.Equal(t, clientName, *result.Clientname)
|
||||
assert.Equal(t, amendmentNum, *result.Aaretederivedamendmentnum)
|
||||
assert.Equal(t, "user123", result.Createdby)
|
||||
|
||||
// Verify array fields were created
|
||||
arrayFieldsResult, err := svc.GetFieldExtractionArrayFields(ctx, result.ID)
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, arrayFieldsResult, 2)
|
||||
assert.Equal(t, int16(0), arrayFieldsResult[0].Arrayindex)
|
||||
assert.Equal(t, exhibitTitle1, *arrayFieldsResult[0].Exhibittitle)
|
||||
assert.Equal(t, int16(1), arrayFieldsResult[1].Arrayindex)
|
||||
assert.Equal(t, exhibitTitle2, *arrayFieldsResult[1].Exhibittitle)
|
||||
})
|
||||
|
||||
t.Run("reject nil input", func(t *testing.T) {
|
||||
_, err := svc.CreateFieldExtraction(ctx, nil)
|
||||
require.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "input cannot be nil")
|
||||
})
|
||||
|
||||
t.Run("reject nil documentID", func(t *testing.T) {
|
||||
input := &fieldextraction.CreateFieldExtractionInput{
|
||||
DocumentID: uuid.Nil,
|
||||
SingleFields: &repository.AddFieldExtractionParams{
|
||||
Createdby: "user123",
|
||||
},
|
||||
}
|
||||
_, err := svc.CreateFieldExtraction(ctx, input)
|
||||
require.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "documentID cannot be nil")
|
||||
})
|
||||
|
||||
t.Run("reject empty createdBy", func(t *testing.T) {
|
||||
input := &fieldextraction.CreateFieldExtractionInput{
|
||||
DocumentID: documentID,
|
||||
SingleFields: &repository.AddFieldExtractionParams{
|
||||
Createdby: "",
|
||||
},
|
||||
}
|
||||
_, err := svc.CreateFieldExtraction(ctx, input)
|
||||
require.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "createdBy cannot be empty")
|
||||
})
|
||||
|
||||
t.Run("create with empty array fields", func(t *testing.T) {
|
||||
// Create new document for this test
|
||||
filename2 := "contract2.pdf"
|
||||
documentID2, err := cfg.GetDBQueries().CreateDocument(ctx, &repository.CreateDocumentParams{
|
||||
Clientid: clientID,
|
||||
Hash: "testhash456",
|
||||
Filename: &filename2,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
contractTitle := "Simple Contract"
|
||||
input := &fieldextraction.CreateFieldExtractionInput{
|
||||
DocumentID: documentID2,
|
||||
SingleFields: &repository.AddFieldExtractionParams{
|
||||
Documentid: documentID2,
|
||||
Filename: &filename2,
|
||||
Contracttitle: &contractTitle,
|
||||
Createdby: "user123",
|
||||
},
|
||||
ArrayFields: []*repository.AddFieldExtractionArrayFieldParams{}, // Empty array
|
||||
}
|
||||
|
||||
result, err := svc.CreateFieldExtraction(ctx, input)
|
||||
require.NoError(t, err)
|
||||
assert.NotNil(t, result)
|
||||
assert.Equal(t, documentID2, result.Documentid)
|
||||
|
||||
// Verify no array fields
|
||||
arrayFieldsResult, err := svc.GetFieldExtractionArrayFields(ctx, result.ID)
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, arrayFieldsResult, 0)
|
||||
})
|
||||
}
|
||||
|
||||
func TestGetCurrentFieldExtraction(t *testing.T) {
|
||||
ctx := t.Context()
|
||||
cfg := &TestConfig{}
|
||||
test.CreateDB(t, cfg)
|
||||
svc := fieldextraction.New(cfg)
|
||||
|
||||
// Create test client and document
|
||||
clientID := "test-client-get-current"
|
||||
err := cfg.GetDBQueries().CreateClient(ctx, &repository.CreateClientParams{
|
||||
Clientid: clientID,
|
||||
Name: "Test Client Get Current",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
filename := "current.pdf"
|
||||
documentID, err := cfg.GetDBQueries().CreateDocument(ctx, &repository.CreateDocumentParams{
|
||||
Clientid: clientID,
|
||||
Hash: "currenthash",
|
||||
Filename: &filename,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Run("get current extraction", func(t *testing.T) {
|
||||
// Create first version
|
||||
contractTitle1 := "Version 1"
|
||||
input1 := &fieldextraction.CreateFieldExtractionInput{
|
||||
DocumentID: documentID,
|
||||
SingleFields: &repository.AddFieldExtractionParams{
|
||||
Documentid: documentID,
|
||||
Filename: &filename,
|
||||
Contracttitle: &contractTitle1,
|
||||
Createdby: "user123",
|
||||
},
|
||||
ArrayFields: []*repository.AddFieldExtractionArrayFieldParams{},
|
||||
}
|
||||
_, err := svc.CreateFieldExtraction(ctx, input1)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Create second version
|
||||
contractTitle2 := "Version 2"
|
||||
input2 := &fieldextraction.CreateFieldExtractionInput{
|
||||
DocumentID: documentID,
|
||||
SingleFields: &repository.AddFieldExtractionParams{
|
||||
Documentid: documentID,
|
||||
Filename: &filename,
|
||||
Contracttitle: &contractTitle2,
|
||||
Createdby: "user456",
|
||||
},
|
||||
ArrayFields: []*repository.AddFieldExtractionArrayFieldParams{},
|
||||
}
|
||||
version2, err := svc.CreateFieldExtraction(ctx, input2)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Get current should return version 2
|
||||
current, err := svc.GetCurrentFieldExtraction(ctx, documentID)
|
||||
require.NoError(t, err)
|
||||
assert.NotNil(t, current)
|
||||
assert.Equal(t, version2.ID, current.ID)
|
||||
assert.Equal(t, contractTitle2, *current.Contracttitle)
|
||||
assert.Equal(t, int64(2), current.Version)
|
||||
})
|
||||
|
||||
t.Run("return nil for non-existent document", func(t *testing.T) {
|
||||
nonExistentID := uuid.New()
|
||||
result, err := svc.GetCurrentFieldExtraction(ctx, nonExistentID)
|
||||
require.NoError(t, err)
|
||||
assert.Nil(t, result)
|
||||
})
|
||||
|
||||
t.Run("reject nil documentID", func(t *testing.T) {
|
||||
_, err := svc.GetCurrentFieldExtraction(ctx, uuid.Nil)
|
||||
require.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "documentID cannot be nil")
|
||||
})
|
||||
}
|
||||
|
||||
func TestGetFieldExtractionHistory(t *testing.T) {
|
||||
ctx := t.Context()
|
||||
cfg := &TestConfig{}
|
||||
test.CreateDB(t, cfg)
|
||||
svc := fieldextraction.New(cfg)
|
||||
|
||||
// Create test client and document
|
||||
clientID := "test-client-history"
|
||||
err := cfg.GetDBQueries().CreateClient(ctx, &repository.CreateClientParams{
|
||||
Clientid: clientID,
|
||||
Name: "Test Client History",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
filename := "history.pdf"
|
||||
documentID, err := cfg.GetDBQueries().CreateDocument(ctx, &repository.CreateDocumentParams{
|
||||
Clientid: clientID,
|
||||
Hash: "historyhash",
|
||||
Filename: &filename,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Run("get history with multiple versions", func(t *testing.T) {
|
||||
// Create 3 versions
|
||||
for i := 1; i <= 3; i++ {
|
||||
contractTitle := fmt.Sprintf("Version %d", i)
|
||||
input := &fieldextraction.CreateFieldExtractionInput{
|
||||
DocumentID: documentID,
|
||||
SingleFields: &repository.AddFieldExtractionParams{
|
||||
Documentid: documentID,
|
||||
Filename: &filename,
|
||||
Contracttitle: &contractTitle,
|
||||
Createdby: fmt.Sprintf("user%d", i),
|
||||
},
|
||||
ArrayFields: []*repository.AddFieldExtractionArrayFieldParams{},
|
||||
}
|
||||
_, err := svc.CreateFieldExtraction(ctx, input)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
// Get history
|
||||
history, err := svc.GetFieldExtractionHistory(ctx, documentID)
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, history, 3)
|
||||
|
||||
// Should be ordered by version DESC (most recent first)
|
||||
assert.Equal(t, int64(3), history[0].Version)
|
||||
assert.Equal(t, "user3", history[0].Createdby)
|
||||
assert.Equal(t, int64(2), history[1].Version)
|
||||
assert.Equal(t, "user2", history[1].Createdby)
|
||||
assert.Equal(t, int64(1), history[2].Version)
|
||||
assert.Equal(t, "user1", history[2].Createdby)
|
||||
})
|
||||
|
||||
t.Run("return empty for document with no extractions", func(t *testing.T) {
|
||||
// Create new document without extractions
|
||||
filename2 := "nohistory.pdf"
|
||||
documentID2, err := cfg.GetDBQueries().CreateDocument(ctx, &repository.CreateDocumentParams{
|
||||
Clientid: clientID,
|
||||
Hash: "nohistoryhash",
|
||||
Filename: &filename2,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
history, err := svc.GetFieldExtractionHistory(ctx, documentID2)
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, history, 0)
|
||||
})
|
||||
|
||||
t.Run("reject nil documentID", func(t *testing.T) {
|
||||
_, err := svc.GetFieldExtractionHistory(ctx, uuid.Nil)
|
||||
require.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "documentID cannot be nil")
|
||||
})
|
||||
}
|
||||
|
||||
func TestGetFieldExtractionArrayFields(t *testing.T) {
|
||||
ctx := t.Context()
|
||||
cfg := &TestConfig{}
|
||||
test.CreateDB(t, cfg)
|
||||
svc := fieldextraction.New(cfg)
|
||||
|
||||
// Create test client and document
|
||||
clientID := "test-client-array-fields"
|
||||
err := cfg.GetDBQueries().CreateClient(ctx, &repository.CreateClientParams{
|
||||
Clientid: clientID,
|
||||
Name: "Test Client Array Fields",
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
filename := "arraytest.pdf"
|
||||
documentID, err := cfg.GetDBQueries().CreateDocument(ctx, &repository.CreateDocumentParams{
|
||||
Clientid: clientID,
|
||||
Hash: "arrayhash",
|
||||
Filename: &filename,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Run("get array fields ordered by index", func(t *testing.T) {
|
||||
// Create extraction with 5 array rows
|
||||
arrayFields := make([]*repository.AddFieldExtractionArrayFieldParams, 5)
|
||||
for i := 0; i < 5; i++ {
|
||||
title := fmt.Sprintf("Exhibit %d", i)
|
||||
page := fmt.Sprintf("%d", i+1)
|
||||
arrayFields[i] = &repository.AddFieldExtractionArrayFieldParams{
|
||||
Exhibittitle: &title,
|
||||
Exhibitpage: &page,
|
||||
}
|
||||
}
|
||||
|
||||
contractTitle := "Array Test Contract"
|
||||
input := &fieldextraction.CreateFieldExtractionInput{
|
||||
DocumentID: documentID,
|
||||
SingleFields: &repository.AddFieldExtractionParams{
|
||||
Documentid: documentID,
|
||||
Filename: &filename,
|
||||
Contracttitle: &contractTitle,
|
||||
Createdby: "user123",
|
||||
},
|
||||
ArrayFields: arrayFields,
|
||||
}
|
||||
|
||||
extraction, err := svc.CreateFieldExtraction(ctx, input)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Get array fields
|
||||
result, err := svc.GetFieldExtractionArrayFields(ctx, extraction.ID)
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, result, 5)
|
||||
|
||||
// Verify order and content
|
||||
for i := 0; i < 5; i++ {
|
||||
//nolint:gosec // Test index is small, int16 is sufficient
|
||||
assert.Equal(t, int16(i), result[i].Arrayindex)
|
||||
assert.Equal(t, fmt.Sprintf("Exhibit %d", i), *result[i].Exhibittitle)
|
||||
assert.Equal(t, fmt.Sprintf("%d", i+1), *result[i].Exhibitpage)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("return empty for extraction with no array fields", func(t *testing.T) {
|
||||
// Create new document
|
||||
filename2 := "noarray.pdf"
|
||||
documentID2, err := cfg.GetDBQueries().CreateDocument(ctx, &repository.CreateDocumentParams{
|
||||
Clientid: clientID,
|
||||
Hash: "noarrayhash",
|
||||
Filename: &filename2,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
contractTitle := "No Array Contract"
|
||||
input := &fieldextraction.CreateFieldExtractionInput{
|
||||
DocumentID: documentID2,
|
||||
SingleFields: &repository.AddFieldExtractionParams{
|
||||
Documentid: documentID2,
|
||||
Filename: &filename2,
|
||||
Contracttitle: &contractTitle,
|
||||
Createdby: "user123",
|
||||
},
|
||||
ArrayFields: []*repository.AddFieldExtractionArrayFieldParams{},
|
||||
}
|
||||
|
||||
extraction, err := svc.CreateFieldExtraction(ctx, input)
|
||||
require.NoError(t, err)
|
||||
|
||||
result, err := svc.GetFieldExtractionArrayFields(ctx, extraction.ID)
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, result, 0)
|
||||
})
|
||||
|
||||
t.Run("reject nil fieldExtractionID", func(t *testing.T) {
|
||||
_, err := svc.GetFieldExtractionArrayFields(ctx, uuid.Nil)
|
||||
require.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "fieldExtractionID cannot be nil")
|
||||
})
|
||||
}
|
||||
|
||||
func TestTransactionRollback(t *testing.T) {
|
||||
ctx := t.Context()
|
||||
cfg := &TestConfig{}
|
||||
test.CreateDB(t, cfg)
|
||||
svc := fieldextraction.New(cfg)
|
||||
|
||||
t.Run("invalid document reference fails transaction", func(t *testing.T) {
|
||||
// Try to create extraction for non-existent document
|
||||
nonExistentDocID := uuid.New()
|
||||
filename := "rollback.pdf"
|
||||
contractTitle := "Should Fail"
|
||||
input := &fieldextraction.CreateFieldExtractionInput{
|
||||
DocumentID: nonExistentDocID,
|
||||
SingleFields: &repository.AddFieldExtractionParams{
|
||||
Documentid: nonExistentDocID,
|
||||
Filename: &filename,
|
||||
Contracttitle: &contractTitle,
|
||||
Createdby: "user123",
|
||||
},
|
||||
ArrayFields: []*repository.AddFieldExtractionArrayFieldParams{},
|
||||
}
|
||||
|
||||
_, err := svc.CreateFieldExtraction(ctx, input)
|
||||
require.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "failed to create field extraction")
|
||||
|
||||
// Verify nothing was created
|
||||
history, err := svc.GetFieldExtractionHistory(ctx, nonExistentDocID)
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, history, 0)
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user