From 12fe331f0eb851caa729f5f74374c88ac69e7985 Mon Sep 17 00:00:00 2001 From: Janis Saldabols Date: Wed, 25 Mar 2026 11:15:18 +0200 Subject: [PATCH 1/7] CROSSLINK-234 Add full text search --- broker/README.md | 3 +- .../migrations/021_add_items_to_pr.down.sql | 40 +++++++++ broker/migrations/021_add_items_to_pr.up.sql | 87 +++++++++++++++++++ broker/oapi/open-api.yaml | 8 +- broker/patron_request/api/api-handler.go | 35 +++++++- broker/patron_request/db/prcql.go | 14 +++ broker/patron_request/db/prmodels.go | 33 +++++++ broker/patron_request/db/prrepo.go | 2 + broker/patron_request/service/action.go | 36 +++++++- broker/patron_request/service/action_test.go | 40 ++++++++- .../patron_request/service/message-handler.go | 37 +++++++- broker/sqlc/pr_query.sql | 9 +- broker/sqlc/pr_schema.sql | 4 +- broker/sqlc/sqlc.yaml | 6 ++ .../patron_request/api/api-handler_test.go | 69 ++++++++++++++- broker/test/patron_request/db/prrepo_test.go | 2 + 16 files changed, 408 insertions(+), 17 deletions(-) create mode 100644 broker/migrations/021_add_items_to_pr.down.sql create mode 100644 broker/migrations/021_add_items_to_pr.up.sql diff --git a/broker/README.md b/broker/README.md index 987c0038..c3fce557 100644 --- a/broker/README.md +++ b/broker/README.md @@ -82,7 +82,7 @@ Configuration is provided via environment variables: | `DB_DATABASE` | Database name | `crosslink` | | `DB_PORT` | Database port | `25432` | | `DB_SCHEMA` | Database schema to use | `crosslink_broker` | -| `DB_PROVISION` | Should app create DB role/schema (`true`/`false`) | `false` | +| `DB_PROVISION` | Should app create DB role/schema (`true`/`false`) | `false` | | `DB_MIGRATE` | Should app run DB migrations (`true`/`false`) | `true` | | `LOG_LEVEL` | Log level: `ERROR`, `WARN`, `INFO`, `DEBUG` | `INFO` | | `ENABLE_JSON_LOG` | Should JSON log format be enabled | `false` | @@ -108,6 +108,7 @@ Configuration is provided via environment variables: | `TENANT_TO_SYMBOL` | Pattern to map tenant to `requesterSymbol` when accessing the API via Okapi, | (empty value) | | | the `{tenant}` token is replaced by the `X-Okapi-Tenant` header value | | | `SUPPLIER_PATRON_PATTERN` | Pattern used to create patron ID when receiving Request on supplier side | `%v_user` | +| `LANGUAGE` | Language parameter used for ts_vector search in DB | `english` | # Build diff --git a/broker/migrations/021_add_items_to_pr.down.sql b/broker/migrations/021_add_items_to_pr.down.sql new file mode 100644 index 00000000..a6f99663 --- /dev/null +++ b/broker/migrations/021_add_items_to_pr.down.sql @@ -0,0 +1,40 @@ +DROP TRIGGER IF EXISTS trigger_update_patron_request_search_tsvector ON patron_request; + +DROP FUNCTION IF EXISTS update_patron_request_search_tsvector; + +DROP INDEX IF EXISTS idx_patron_request_search; + +DROP VIEW IF EXISTS patron_request_search_view; + +ALTER TABLE patron_request DROP COLUMN IF EXISTS search; +ALTER TABLE patron_request DROP COLUMN IF EXISTS language; + +DROP TRIGGER IF EXISTS trigger_update_patron_request_items ON items; + +DROP FUNCTION IF EXISTS update_patron_request_items CASCADE; + +ALTER TABLE patron_request DROP COLUMN IF EXISTS items; + +CREATE OR REPLACE VIEW patron_request_search_view AS +SELECT + pr.*, + EXISTS ( + SELECT 1 + FROM notification n + WHERE n.pr_id = pr.id + ) AS has_notification, + EXISTS ( + SELECT 1 + FROM notification n + WHERE n.pr_id = pr.id and cost is not null + ) AS has_cost, + EXISTS ( + SELECT 1 + FROM notification n + WHERE n.pr_id = pr.id and acknowledged_at is null + ) AS has_unread_notification, + pr.ill_request -> 'serviceInfo' ->> 'serviceType' AS service_type, + pr.ill_request -> 'serviceInfo' -> 'serviceLevel' ->> '#text' AS service_level, + immutable_to_timestamp(pr.ill_request -> 'serviceInfo' ->> 'needBeforeDate') AS needed_at +FROM patron_request pr; + diff --git a/broker/migrations/021_add_items_to_pr.up.sql b/broker/migrations/021_add_items_to_pr.up.sql new file mode 100644 index 00000000..684c4df9 --- /dev/null +++ b/broker/migrations/021_add_items_to_pr.up.sql @@ -0,0 +1,87 @@ +ALTER TABLE patron_request ADD COLUMN items JSONB NOT NULL DEFAULT '[]'::jsonb; + +CREATE OR REPLACE FUNCTION update_patron_request_items() +RETURNS TRIGGER AS $$ +BEGIN +UPDATE patron_request +SET items = ( + SELECT jsonb_agg(to_jsonb(i) - 'pr_id') + FROM item i + WHERE i.pr_id = NEW.pr_id +) +WHERE id = NEW.pr_id; + +RETURN NEW; +END; +$$ LANGUAGE plpgsql; + +-- Create the trigger +CREATE TRIGGER trigger_update_patron_request_items + AFTER INSERT OR UPDATE ON item + FOR EACH ROW + EXECUTE FUNCTION update_patron_request_items(); + + +-- Add the search field as a tsvector column +ALTER TABLE patron_request + ADD COLUMN search tsvector, + ADD COLUMN language regconfig NOT NULL DEFAULT 'english'; + +-- Create a trigger function to update the search tsvector +CREATE OR REPLACE FUNCTION update_patron_request_search_tsvector() +RETURNS TRIGGER AS $$ +BEGIN + -- Update the search tsvector column + NEW.search := to_tsvector(NEW.language, + COALESCE(NEW.requester_req_id, '') || ' ' || + COALESCE(NEW.patron, '') || ' ' || + COALESCE(NEW.ill_request->'patronInfo'->>'givenName', '') || ' ' || + COALESCE(NEW.ill_request->'patronInfo'->>'surname', '') || ' ' || + COALESCE(NEW.ill_request->'patronInfo'->>'patronId', '') || ' ' || + COALESCE(NEW.ill_request->'bibliographicInfo'->>'title', '') || ' ' || + COALESCE(NEW.ill_request->'bibliographicInfo'->>'author', '') || ' ' || + COALESCE( + (SELECT string_agg( + COALESCE(item->>'itemId', '') || ' ' || + COALESCE(item->>'barcode', '') || ' ' || + COALESCE(item->>'callnum', ''), ' ' + ) + FROM jsonb_array_elements(NEW.items) AS item), '' + ) + ); + +RETURN NEW; +END; +$$ LANGUAGE plpgsql; + +-- Create a trigger to update the search tsvector on insert or update +CREATE TRIGGER trigger_update_patron_request_search_tsvector + BEFORE INSERT OR UPDATE ON patron_request + FOR EACH ROW + EXECUTE FUNCTION update_patron_request_search_tsvector(); + +CREATE INDEX idx_patron_request_search ON patron_request USING gin(search); + +DROP VIEW IF EXISTS patron_request_search_view; +CREATE OR REPLACE VIEW patron_request_search_view AS +SELECT + pr.*, + EXISTS ( + SELECT 1 + FROM notification n + WHERE n.pr_id = pr.id + ) AS has_notification, + EXISTS ( + SELECT 1 + FROM notification n + WHERE n.pr_id = pr.id and cost is not null + ) AS has_cost, + EXISTS ( + SELECT 1 + FROM notification n + WHERE n.pr_id = pr.id and acknowledged_at is null + ) AS has_unread_notification, + pr.ill_request -> 'serviceInfo' ->> 'serviceType' AS service_type, + pr.ill_request -> 'serviceInfo' -> 'serviceLevel' ->> '#text' AS service_level, + immutable_to_timestamp(pr.ill_request -> 'serviceInfo' ->> 'needBeforeDate') AS needed_at +FROM patron_request pr; \ No newline at end of file diff --git a/broker/oapi/open-api.yaml b/broker/oapi/open-api.yaml index 6a585c37..f1622594 100644 --- a/broker/oapi/open-api.yaml +++ b/broker/oapi/open-api.yaml @@ -477,6 +477,11 @@ components: lastActionResult: type: string description: Latest action status ("NEW", "PROCESSING", "SUCCESS", "PROBLEM", "ERROR") + items: + type: array + description: List of patron request items + items: + $ref: '#/components/schemas/PrItem' required: - id - timestamp @@ -1140,7 +1145,8 @@ paths: Use this endpoint to retrieve patron requests. Query parameter cql can be used to filter the results. With cql you can use these fields state, side, requester_symbol, supplier_symbol, needs_attention, - has_notification, has_cost, has_unread_notification, service_type, service_level, created_at, needed_at, requester_req_id. + has_notification, has_cost, has_unread_notification, service_type, service_level, created_at, needed_at, + requester_req_id, title, patron, cql.serverChoice. tags: - patron-requests-api parameters: diff --git a/broker/patron_request/api/api-handler.go b/broker/patron_request/api/api-handler.go index 116f3c2c..9634afff 100644 --- a/broker/patron_request/api/api-handler.go +++ b/broker/patron_request/api/api-handler.go @@ -215,7 +215,23 @@ func (a *PatronRequestApiHandler) PostPatronRequests(w http.ResponseWriter, r *h return } dbreq := buildDbPatronRequest(&newPr, params.XOkapiTenant, creationTime, requesterReqId, illRequest) - pr, err := a.prRepo.CreatePatronRequest(ctx, (pr_db.CreatePatronRequestParams)(dbreq)) + pr, err := a.prRepo.CreatePatronRequest(ctx, pr_db.CreatePatronRequestParams{ + ID: dbreq.ID, + Timestamp: dbreq.Timestamp, + IllRequest: dbreq.IllRequest, + State: dbreq.State, + Side: dbreq.Side, + Patron: dbreq.Patron, + RequesterSymbol: dbreq.RequesterSymbol, + SupplierSymbol: dbreq.SupplierSymbol, + Tenant: dbreq.Tenant, + RequesterReqID: dbreq.RequesterReqID, + NeedsAttention: dbreq.NeedsAttention, + LastAction: dbreq.LastAction, + LastActionOutcome: dbreq.LastActionOutcome, + LastActionResult: dbreq.LastActionResult, + Language: dbreq.Language, + }) if err != nil { var pgErr *pgconn.PgError if errors.As(err, &pgErr) && pgerrcode.IsIntegrityConstraintViolation(pgErr.Code) { @@ -548,6 +564,10 @@ func addNotFoundError(w http.ResponseWriter) { } func toApiPatronRequest(request pr_db.PatronRequest, illRequest iso18626.Request) proapi.PatronRequest { + var items []proapi.PrItem + for _, item := range request.Items { + items = append(items, toApiPrItem(item)) + } return proapi.PatronRequest{ Id: request.ID, Timestamp: request.Timestamp.Time, @@ -562,6 +582,7 @@ func toApiPatronRequest(request pr_db.PatronRequest, illRequest iso18626.Request LastAction: toString(request.LastAction), LastActionOutcome: toString(request.LastActionOutcome), LastActionResult: toString(request.LastActionResult), + Items: &items, } } @@ -691,6 +712,7 @@ func buildDbPatronRequest( IllRequest: illRequest, Tenant: getDbText(tenant), RequesterReqID: getDbText(&requesterReqId), + Language: pr_db.LANGUAGE, // LastAction, LastActionOutcome and LastActionResult are not set on creation // they will be updated when the first action is executed. } @@ -716,6 +738,17 @@ func toApiItem(item pr_db.Item) proapi.PrItem { } } +func toApiPrItem(item pr_db.PrItem) proapi.PrItem { + return proapi.PrItem{ + Id: item.ID, + Barcode: item.Barcode, + CallNumber: item.CallNumber, + ItemId: item.ItemID, + Title: item.Title, + CreatedAt: time.Time(item.CreatedAt), + } +} + func toApiNotification(notification pr_db.Notification) (proapi.PrNotification, error) { var ackAt *time.Time if notification.AcknowledgedAt.Valid { diff --git a/broker/patron_request/db/prcql.go b/broker/patron_request/db/prcql.go index a7890407..97504953 100644 --- a/broker/patron_request/db/prcql.go +++ b/broker/patron_request/db/prcql.go @@ -7,8 +7,11 @@ import ( "github.com/indexdata/cql-go/cql" "github.com/indexdata/cql-go/pgcql" + "github.com/indexdata/go-utils/utils" ) +var LANGUAGE = utils.GetEnv("LANGUAGE", "english") + type FieldAllRecords struct{} func (f *FieldAllRecords) GetColumn() string { return "" } @@ -64,6 +67,15 @@ func handlePatronRequestsQuery(cqlString string, noBaseArgs int) (pgcql.Query, e nf = pgcql.NewFieldDate() def.AddField("needed_at", nf) + f = pgcql.NewFieldString().WithExact().WithColumn("ill_request->'bibliographicInfo'->>'title'") + def.AddField("title", f) + + f = pgcql.NewFieldString().WithExact() + def.AddField("patron", f) + + ftv := pgcql.NewFieldTsVector().WithLanguage(LANGUAGE).WithServerChoiceRel(cql.ALL).WithColumn("search") + def.AddField("cql.serverChoice", ftv) + var parser cql.Parser query, err := parser.Parse(cqlString) if err != nil { @@ -118,6 +130,8 @@ func (q *Queries) ListPatronRequestsCql(ctx context.Context, db DBTX, arg ListPa &i.LastAction, &i.LastActionOutcome, &i.LastActionResult, + &i.Language, + &i.Items, &i.FullCount, ); err != nil { return nil, err diff --git a/broker/patron_request/db/prmodels.go b/broker/patron_request/db/prmodels.go index f11e02fe..bce290b1 100644 --- a/broker/patron_request/db/prmodels.go +++ b/broker/patron_request/db/prmodels.go @@ -1,5 +1,10 @@ package pr_db +import ( + "strings" + "time" +) + type PatronRequestState string type PatronRequestSide string type PatronRequestAction string @@ -10,3 +15,31 @@ const ( NotificationRejected NotificationReceipt = "REJECTED" NotificationSeen NotificationReceipt = "SEEN" ) + +type CustomTime time.Time + +const customTimeLayout = "2006-01-02T15:04:05.999999" + +func (ct CustomTime) MarshalJSON() ([]byte, error) { + t := time.Time(ct) + return []byte(`"` + t.Format(customTimeLayout) + `"`), nil +} + +func (ct *CustomTime) UnmarshalJSON(b []byte) error { + s := strings.Trim(string(b), `"`) + t, err := time.Parse(customTimeLayout, s) + if err != nil { + return err + } + *ct = CustomTime(t) + return nil +} + +type PrItem struct { + ID string `json:"id"` + Barcode string `json:"barcode"` + CallNumber *string `json:"call_number"` + Title *string `json:"title"` + ItemID *string `json:"item_id"` + CreatedAt CustomTime `json:"created_at"` +} diff --git a/broker/patron_request/db/prrepo.go b/broker/patron_request/db/prrepo.go index 563783ae..ae5e6bfc 100644 --- a/broker/patron_request/db/prrepo.go +++ b/broker/patron_request/db/prrepo.go @@ -90,6 +90,8 @@ func (r *PgPrRepo) ListPatronRequests(ctx common.ExtendedContext, params ListPat LastAction: r.LastAction, LastActionOutcome: r.LastActionOutcome, LastActionResult: r.LastActionResult, + Language: r.Language, + Items: r.Items, }) } } else { diff --git a/broker/patron_request/service/action.go b/broker/patron_request/service/action.go index 1f82a1eb..ae0c95b9 100644 --- a/broker/patron_request/service/action.go +++ b/broker/patron_request/service/action.go @@ -124,7 +124,23 @@ func (a *PatronRequestActionService) finalizeActionExecution(ctx common.Extended } var err error - updatedPr, err = a.prRepo.UpdatePatronRequest(ctx, pr_db.UpdatePatronRequestParams(updatedPr)) + updatedPr, err = a.prRepo.UpdatePatronRequest(ctx, pr_db.UpdatePatronRequestParams{ + ID: updatedPr.ID, + Timestamp: updatedPr.Timestamp, + IllRequest: updatedPr.IllRequest, + State: updatedPr.State, + Side: updatedPr.Side, + Patron: updatedPr.Patron, + RequesterSymbol: updatedPr.RequesterSymbol, + SupplierSymbol: updatedPr.SupplierSymbol, + Tenant: updatedPr.Tenant, + RequesterReqID: updatedPr.RequesterReqID, + NeedsAttention: updatedPr.NeedsAttention, + LastAction: updatedPr.LastAction, + LastActionOutcome: updatedPr.LastActionOutcome, + LastActionResult: updatedPr.LastActionResult, + Language: updatedPr.Language, + }) if err != nil { return a.logErrorAndReturnResult(ctx, "failed to update patron request", err) } @@ -783,7 +799,23 @@ func (a *PatronRequestActionService) setNeedsAttention(ctx common.ExtendedContex return nil } prToUpdate.NeedsAttention = true - _, err = repo.UpdatePatronRequest(ctx, pr_db.UpdatePatronRequestParams(prToUpdate)) + _, err = repo.UpdatePatronRequest(ctx, pr_db.UpdatePatronRequestParams{ + ID: prToUpdate.ID, + Timestamp: prToUpdate.Timestamp, + IllRequest: prToUpdate.IllRequest, + State: prToUpdate.State, + Side: prToUpdate.Side, + Patron: prToUpdate.Patron, + RequesterSymbol: prToUpdate.RequesterSymbol, + SupplierSymbol: prToUpdate.SupplierSymbol, + Tenant: prToUpdate.Tenant, + RequesterReqID: prToUpdate.RequesterReqID, + NeedsAttention: prToUpdate.NeedsAttention, + LastAction: prToUpdate.LastAction, + LastActionOutcome: prToUpdate.LastActionOutcome, + LastActionResult: prToUpdate.LastActionResult, + Language: prToUpdate.Language, + }) return err }) if err != nil { diff --git a/broker/patron_request/service/action_test.go b/broker/patron_request/service/action_test.go index feb4558d..5084d20e 100644 --- a/broker/patron_request/service/action_test.go +++ b/broker/patron_request/service/action_test.go @@ -1238,16 +1238,48 @@ func (r *MockPrRepo) UpdatePatronRequest(ctx common.ExtendedContext, params pr_d if strings.Contains(params.ID, "error") || strings.Contains(params.RequesterReqID.String, "error") { return pr_db.PatronRequest{}, errors.New("db error") } - r.savedPr = pr_db.PatronRequest(params) - return pr_db.PatronRequest(params), nil + r.savedPr = pr_db.PatronRequest{ + ID: params.ID, + Timestamp: params.Timestamp, + IllRequest: params.IllRequest, + State: params.State, + Side: params.Side, + Patron: params.Patron, + RequesterSymbol: params.RequesterSymbol, + SupplierSymbol: params.SupplierSymbol, + Tenant: params.Tenant, + RequesterReqID: params.RequesterReqID, + NeedsAttention: params.NeedsAttention, + LastAction: params.LastAction, + LastActionOutcome: params.LastActionOutcome, + LastActionResult: params.LastActionResult, + Language: params.Language, + } + return r.savedPr, nil } func (r *MockPrRepo) CreatePatronRequest(ctx common.ExtendedContext, params pr_db.CreatePatronRequestParams) (pr_db.PatronRequest, error) { if strings.Contains(params.ID, "error") || strings.Contains(params.RequesterReqID.String, "error") { return pr_db.PatronRequest{}, errors.New("db error") } - r.savedPr = pr_db.PatronRequest(params) - return pr_db.PatronRequest(params), nil + r.savedPr = pr_db.PatronRequest{ + ID: params.ID, + Timestamp: params.Timestamp, + IllRequest: params.IllRequest, + State: params.State, + Side: params.Side, + Patron: params.Patron, + RequesterSymbol: params.RequesterSymbol, + SupplierSymbol: params.SupplierSymbol, + Tenant: params.Tenant, + RequesterReqID: params.RequesterReqID, + NeedsAttention: params.NeedsAttention, + LastAction: params.LastAction, + LastActionOutcome: params.LastActionOutcome, + LastActionResult: params.LastActionResult, + Language: params.Language, + } + return r.savedPr, nil } func (r *MockPrRepo) GetLendingRequestBySupplierSymbolAndRequesterReqId(ctx common.ExtendedContext, symbol string, requesterReqId string) (pr_db.PatronRequest, error) { diff --git a/broker/patron_request/service/message-handler.go b/broker/patron_request/service/message-handler.go index 741643f6..30de7a87 100644 --- a/broker/patron_request/service/message-handler.go +++ b/broker/patron_request/service/message-handler.go @@ -235,7 +235,23 @@ func (m *PatronRequestMessageHandler) handleSupplyingAgencyMessage(ctx common.Ex } func (m *PatronRequestMessageHandler) updatePatronRequestAndCreateSamResponse(ctx common.ExtendedContext, pr pr_db.PatronRequest, sam iso18626.SupplyingAgencyMessage, stateChanged bool) (events.EventStatus, *iso18626.ISO18626Message, error) { - _, err := m.prRepo.UpdatePatronRequest(ctx, pr_db.UpdatePatronRequestParams(pr)) + _, err := m.prRepo.UpdatePatronRequest(ctx, pr_db.UpdatePatronRequestParams{ + ID: pr.ID, + Timestamp: pr.Timestamp, + IllRequest: pr.IllRequest, + State: pr.State, + Side: pr.Side, + Patron: pr.Patron, + RequesterSymbol: pr.RequesterSymbol, + SupplierSymbol: pr.SupplierSymbol, + Tenant: pr.Tenant, + RequesterReqID: pr.RequesterReqID, + NeedsAttention: pr.NeedsAttention, + LastAction: pr.LastAction, + LastActionOutcome: pr.LastActionOutcome, + LastActionResult: pr.LastActionResult, + Language: pr.Language, + }) if err != nil { return createSAMResponse(sam, iso18626.TypeMessageStatusERROR, &iso18626.ErrorData{ ErrorType: iso18626.TypeErrorTypeUnrecognisedDataValue, @@ -334,6 +350,7 @@ func (m *PatronRequestMessageHandler) handleRequestMessage(ctx common.ExtendedCo IllRequest: request, SupplierSymbol: getDbText(supplierSymbol), RequesterReqID: getDbText(raRequestId), + Language: pr_db.LANGUAGE, }) if err != nil { status, response, handleErr := createRequestResponse(request, iso18626.TypeMessageStatusERROR, &iso18626.ErrorData{ @@ -447,7 +464,23 @@ func createRAMResponse(ram iso18626.RequestingAgencyMessage, messageStatus iso18 } func (m *PatronRequestMessageHandler) updatePatronRequestAndCreateRamResponse(ctx common.ExtendedContext, pr pr_db.PatronRequest, ram iso18626.RequestingAgencyMessage, action *iso18626.TypeAction, stateChanged bool) (events.EventStatus, *iso18626.ISO18626Message, error) { - _, err := m.prRepo.UpdatePatronRequest(ctx, pr_db.UpdatePatronRequestParams(pr)) + _, err := m.prRepo.UpdatePatronRequest(ctx, pr_db.UpdatePatronRequestParams{ + ID: pr.ID, + Timestamp: pr.Timestamp, + IllRequest: pr.IllRequest, + State: pr.State, + Side: pr.Side, + Patron: pr.Patron, + RequesterSymbol: pr.RequesterSymbol, + SupplierSymbol: pr.SupplierSymbol, + Tenant: pr.Tenant, + RequesterReqID: pr.RequesterReqID, + NeedsAttention: pr.NeedsAttention, + LastAction: pr.LastAction, + LastActionOutcome: pr.LastActionOutcome, + LastActionResult: pr.LastActionResult, + Language: pr.Language, + }) if err != nil { return createRAMResponse(ram, iso18626.TypeMessageStatusERROR, action, &iso18626.ErrorData{ ErrorType: iso18626.TypeErrorTypeUnrecognisedDataValue, diff --git a/broker/sqlc/pr_query.sql b/broker/sqlc/pr_query.sql index e0918204..4ab6ca4f 100644 --- a/broker/sqlc/pr_query.sql +++ b/broker/sqlc/pr_query.sql @@ -12,7 +12,7 @@ WHERE id = $1 LIMIT 1; -- name: ListPatronRequests :many -SELECT id, timestamp, ill_request, state, side, patron, requester_symbol, supplier_symbol, tenant, requester_req_id, needs_attention, last_action, last_action_outcome, last_action_result, COUNT(*) OVER () as full_count +SELECT id, timestamp, ill_request, state, side, patron, requester_symbol, supplier_symbol, tenant, requester_req_id, needs_attention, last_action, last_action_outcome, last_action_result, language, items, COUNT(*) OVER () as full_count FROM patron_request_search_view ORDER BY timestamp LIMIT $1 OFFSET $2; @@ -31,13 +31,14 @@ SET timestamp = $2, needs_attention = $11, last_action = $12, last_action_outcome = $13, - last_action_result = $14 + last_action_result = $14, + language = $15 WHERE id = $1 RETURNING sqlc.embed(patron_request); -- name: CreatePatronRequest :one -INSERT INTO patron_request (id, timestamp, ill_request, state, side, patron, requester_symbol, supplier_symbol, tenant, requester_req_id, needs_attention, last_action, last_action_outcome, last_action_result) -VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14) +INSERT INTO patron_request (id, timestamp, ill_request, state, side, patron, requester_symbol, supplier_symbol, tenant, requester_req_id, needs_attention, last_action, last_action_outcome, last_action_result, language) +VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15) RETURNING sqlc.embed(patron_request); -- name: DeletePatronRequest :exec diff --git a/broker/sqlc/pr_schema.sql b/broker/sqlc/pr_schema.sql index 6a89b85f..94c3ee19 100644 --- a/broker/sqlc/pr_schema.sql +++ b/broker/sqlc/pr_schema.sql @@ -14,7 +14,9 @@ CREATE TABLE patron_request needs_attention BOOLEAN NOT NULL DEFAULT false, last_action VARCHAR, last_action_outcome VARCHAR, - last_action_result VARCHAR + last_action_result VARCHAR, + items JSONB NOT NULL DEFAULT '[]'::jsonb, + language regconfig NOT NULL DEFAULT 'english' ); CREATE OR REPLACE FUNCTION get_next_hrid(prefix VARCHAR) RETURNS VARCHAR AS $$ diff --git a/broker/sqlc/sqlc.yaml b/broker/sqlc/sqlc.yaml index 5a774b7a..e1d83221 100644 --- a/broker/sqlc/sqlc.yaml +++ b/broker/sqlc/sqlc.yaml @@ -84,6 +84,12 @@ sql: - column: "patron_request.side" go_type: type: "PatronRequestSide" + - column: "patron_request.items" + go_type: + type: "[]PrItem" + - column: "patron_request_search_view.items" + go_type: + type: "[]PrItem" - column: "notification.side" go_type: type: "PatronRequestSide" diff --git a/broker/test/patron_request/api/api-handler_test.go b/broker/test/patron_request/api/api-handler_test.go index 27eea3f6..1edc2b03 100644 --- a/broker/test/patron_request/api/api-handler_test.go +++ b/broker/test/patron_request/api/api-handler_test.go @@ -19,6 +19,7 @@ import ( "github.com/indexdata/crosslink/broker/patron_request/proapi" "github.com/indexdata/crosslink/directory" "github.com/indexdata/crosslink/iso18626" + "github.com/jackc/pgx/v5/pgtype" "github.com/google/uuid" "github.com/indexdata/crosslink/broker/adapter" @@ -183,7 +184,8 @@ func TestCrud(t *testing.T) { "side%3Dborrowing%20and%20requester_symbol%3D"+*foundPr.RequesterSymbol+ "%20and%20requester_req_id%3D"+*foundPr.RequesterRequestId+"%20and%20needs_attention%3Dfalse%20and%20"+ "has_notification%3Dfalse%20and%20has_cost%3Dfalse%20and%20has_unread_notification%3Dfalse%20and%20"+ - "service_type%3DCopy%20and%20service_level%3DCopy%20and%20created_at%3E2026-03-16%20and%20needed_at%3E2026-03-16", []byte{}, 200) + "service_type%3DCopy%20and%20service_level%3DCopy%20and%20created_at%3E2026-03-16%20and%20needed_at%3E2026-03-16"+ + "%20and%20title%3D%22Typed%20request%20round%20trip%22%20and%20patron%3Dp1%20and%20cql.serverChoice%20all%20round", []byte{}, 200) err = json.Unmarshal(respBytes, &foundPrs) assert.NoError(t, err, "failed to unmarshal patron request") @@ -572,6 +574,71 @@ func TestGetStateModelCapabilities(t *testing.T) { assert.True(t, slices.Contains(capabilities.SupplierMessageEvents, string(prservice.SupplierCancelRejected))) } +func TestServerChoice(t *testing.T) { + appCtx := common.CreateExtCtxWithArgs(context.Background(), nil) + prId := uuid.NewString() + _, err := prRepo.CreatePatronRequest(appCtx, pr_db.CreatePatronRequestParams{ + ID: prId, + Timestamp: pgtype.Timestamp{ + Time: time.Now(), + Valid: true, + }, + Side: prservice.SideBorrowing, + RequesterSymbol: pgtype.Text{ + String: "ISIL:REQ", + Valid: true, + }, + State: prservice.BorrowerStateValidated, + Language: "english", + RequesterReqID: pgtype.Text{ + String: "REQ-123", + Valid: true, + }, + Patron: pgtype.Text{ + String: "P456", + Valid: true, + }, + IllRequest: iso18626.Request{ + BibliographicInfo: iso18626.BibliographicInfo{ + Title: "Do Androids Dream of Electric Sheep?", + Author: "Ray Bradbury", + }, + PatronInfo: &iso18626.PatronInfo{ + GivenName: "John", + Surname: "Doe", + PatronId: "PP-789", + }, + }, + }) + assert.NoError(t, err) + itemId := uuid.NewString() + _, err = prRepo.SaveItem(appCtx, pr_db.SaveItemParams{ + ID: itemId, + PrID: prId, + Barcode: "BAR-321", + CallNumber: pgtype.Text{ + String: "CAL-321", + Valid: true, + }, + ItemID: pgtype.Text{ + String: "ITEM-321", + Valid: true, + }, + CreatedAt: pgtype.Timestamp{ + Time: time.Now(), + Valid: true, + }, + }) + assert.NoError(t, err) + + respBytes := httpRequest(t, "GET", basePath+"?symbol=ISIL:REQ&side=borrowing&cql.serverChoice%20all%20%22REQ-123%20P456%20Dream%20Ray%20Bradbury%20John%20Doe%20PP-789%20BAR-321%20CAL-321%20ITEM-321%22", []byte{}, 200) + var foundPrs proapi.PatronRequests + err = json.Unmarshal(respBytes, &foundPrs) + assert.NoError(t, err) + assert.Equal(t, int64(1), foundPrs.About.Count) + assert.Equal(t, prId, foundPrs.Items[0].Id) +} + func httpRequest2(t *testing.T, method string, uriPath string, reqbytes []byte, expectStatus int) (*http.Response, []byte) { client := http.DefaultClient hreq, err := http.NewRequest(method, getLocalhostWithPort()+uriPath, bytes.NewBuffer(reqbytes)) diff --git a/broker/test/patron_request/db/prrepo_test.go b/broker/test/patron_request/db/prrepo_test.go index 7d550182..7aa41330 100644 --- a/broker/test/patron_request/db/prrepo_test.go +++ b/broker/test/patron_request/db/prrepo_test.go @@ -75,6 +75,7 @@ func TestItem(t *testing.T) { Time: time.Now(), Valid: true, }, + Language: "english", }) assert.NoError(t, err) @@ -163,6 +164,7 @@ func TestNotification(t *testing.T) { Time: time.Now(), Valid: true, }, + Language: "english", }) assert.NoError(t, err) From bad613ca6344b2e4c9bfd50cda08ac09d9808946 Mon Sep 17 00:00:00 2001 From: Janis Saldabols Date: Thu, 26 Mar 2026 16:19:25 +0200 Subject: [PATCH 2/7] CROSSLINK-234 Fix copilot comments --- .../migrations/021_add_items_to_pr.down.sql | 2 +- broker/migrations/021_add_items_to_pr.up.sql | 41 +++++++++++++++++-- broker/patron_request/api/api-handler.go | 2 +- broker/patron_request/db/prmodels.go | 21 +++++++--- go.work.sum | 26 ++++++++++++ 5 files changed, 82 insertions(+), 10 deletions(-) diff --git a/broker/migrations/021_add_items_to_pr.down.sql b/broker/migrations/021_add_items_to_pr.down.sql index a6f99663..c12328d8 100644 --- a/broker/migrations/021_add_items_to_pr.down.sql +++ b/broker/migrations/021_add_items_to_pr.down.sql @@ -9,7 +9,7 @@ DROP VIEW IF EXISTS patron_request_search_view; ALTER TABLE patron_request DROP COLUMN IF EXISTS search; ALTER TABLE patron_request DROP COLUMN IF EXISTS language; -DROP TRIGGER IF EXISTS trigger_update_patron_request_items ON items; +DROP TRIGGER IF EXISTS trigger_update_patron_request_items ON item; DROP FUNCTION IF EXISTS update_patron_request_items CASCADE; diff --git a/broker/migrations/021_add_items_to_pr.up.sql b/broker/migrations/021_add_items_to_pr.up.sql index 684c4df9..2b09b491 100644 --- a/broker/migrations/021_add_items_to_pr.up.sql +++ b/broker/migrations/021_add_items_to_pr.up.sql @@ -42,9 +42,9 @@ BEGIN COALESCE(NEW.ill_request->'bibliographicInfo'->>'author', '') || ' ' || COALESCE( (SELECT string_agg( - COALESCE(item->>'itemId', '') || ' ' || + COALESCE(item->>'item_id', '') || ' ' || COALESCE(item->>'barcode', '') || ' ' || - COALESCE(item->>'callnum', ''), ' ' + COALESCE(item->>'call_number', ''), ' ' ) FROM jsonb_array_elements(NEW.items) AS item), '' ) @@ -84,4 +84,39 @@ SELECT pr.ill_request -> 'serviceInfo' ->> 'serviceType' AS service_type, pr.ill_request -> 'serviceInfo' -> 'serviceLevel' ->> '#text' AS service_level, immutable_to_timestamp(pr.ill_request -> 'serviceInfo' ->> 'needBeforeDate') AS needed_at -FROM patron_request pr; \ No newline at end of file +FROM patron_request pr; + +-- One-time backfill of items for existing patron_request rows +UPDATE patron_request pr +SET items = COALESCE( + ( + SELECT jsonb_agg(to_jsonb(i) - 'pr_id') + FROM item i + WHERE i.pr_id = pr.id + ), + '[]'::jsonb + ); +-- One-time backfill of search tsvector for existing patron_request rows +UPDATE patron_request pr +SET search = to_tsvector( + pr.language, + COALESCE(pr.requester_req_id, '') || ' ' || + COALESCE(pr.patron, '') || ' ' || + COALESCE(pr.ill_request->'patronInfo'->>'givenName', '') || ' ' || + COALESCE(pr.ill_request->'patronInfo'->>'surname', '') || ' ' || + COALESCE(pr.ill_request->'patronInfo'->>'patronId', '') || ' ' || + COALESCE(pr.ill_request->'bibliographicInfo'->>'title', '') || ' ' || + COALESCE(pr.ill_request->'bibliographicInfo'->>'author', '') || ' ' || + COALESCE( + ( + SELECT string_agg( + COALESCE(item->>'item_id', '') || ' ' || + COALESCE(item->>'barcode', '') || ' ' || + COALESCE(item->>'call_number', ''), + ' ' + ) + FROM jsonb_array_elements(pr.items) AS item + ), + '' + ) + ); \ No newline at end of file diff --git a/broker/patron_request/api/api-handler.go b/broker/patron_request/api/api-handler.go index 9634afff..832664b7 100644 --- a/broker/patron_request/api/api-handler.go +++ b/broker/patron_request/api/api-handler.go @@ -564,7 +564,7 @@ func addNotFoundError(w http.ResponseWriter) { } func toApiPatronRequest(request pr_db.PatronRequest, illRequest iso18626.Request) proapi.PatronRequest { - var items []proapi.PrItem + items := []proapi.PrItem{} for _, item := range request.Items { items = append(items, toApiPrItem(item)) } diff --git a/broker/patron_request/db/prmodels.go b/broker/patron_request/db/prmodels.go index bce290b1..c4d77537 100644 --- a/broker/patron_request/db/prmodels.go +++ b/broker/patron_request/db/prmodels.go @@ -20,6 +20,13 @@ type CustomTime time.Time const customTimeLayout = "2006-01-02T15:04:05.999999" +var postgresTimeLayouts = []string{ + "2006-01-02T15:04:05.999999", + "2006-01-02T15:04:05", + "2006-01-02 15:04:05.999999", + "2006-01-02 15:04:05", +} + func (ct CustomTime) MarshalJSON() ([]byte, error) { t := time.Time(ct) return []byte(`"` + t.Format(customTimeLayout) + `"`), nil @@ -27,12 +34,16 @@ func (ct CustomTime) MarshalJSON() ([]byte, error) { func (ct *CustomTime) UnmarshalJSON(b []byte) error { s := strings.Trim(string(b), `"`) - t, err := time.Parse(customTimeLayout, s) - if err != nil { - return err + var t time.Time + var err error + for _, layout := range postgresTimeLayouts { + t, err = time.Parse(layout, s) + if err == nil { + *ct = CustomTime(t) + return nil + } } - *ct = CustomTime(t) - return nil + return err } type PrItem struct { diff --git a/go.work.sum b/go.work.sum index 67d56d41..4f553b3d 100644 --- a/go.work.sum +++ b/go.work.sum @@ -2,6 +2,7 @@ cel.dev/expr v0.16.0 h1:yloc84fytn4zmJX2GU3TkXGsaieaV7dQ057Qs4sIG2Y= cel.dev/expr v0.16.0/go.mod h1:TRSuuV7DlVCE/uwv5QbAiW/v8l5O8C4eEPHeu7gf7Sg= cel.dev/expr v0.24.0 h1:56OvJKSH3hDGL0ml5uSxZmz3/3Pq4tJ+fb1unVLAFcY= cel.dev/expr v0.24.0/go.mod h1:hLPLo1W4QUmuYdA72RBX06QTs6MXw941piREPl3Yfiw= +cel.dev/expr v0.25.1 h1:1KrZg61W6TWSxuNZ37Xy49ps13NUovb66QLprthtwi4= cel.dev/expr v0.25.1/go.mod h1:hrXvqGP6G6gyx8UAHSHJ5RGk//1Oj5nXQ2NI02Nrsg4= cloud.google.com/go v0.112.1 h1:uJSeirPke5UNZHIb4SxfZklVSiWWVqW4oXlETwZziwM= cloud.google.com/go v0.112.1/go.mod h1:+Vbu+Y1UU+I1rjmzeMOb/8RfkKJK2Gyxi1X6jJCZLo4= @@ -69,6 +70,7 @@ cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykW cloud.google.com/go/compute/metadata v0.7.0/go.mod h1:j5MvL9PprKL39t166CoB1uVHfQMs4tFQZZcKwksXUjo= cloud.google.com/go/compute/metadata v0.8.0 h1:HxMRIbao8w17ZX6wBnjhcDkW6lTFpgcaobyVfZWqRLA= cloud.google.com/go/compute/metadata v0.8.0/go.mod h1:sYOGTp851OV9bOFJ9CH7elVvyzopvWQFNNghtDQ/Biw= +cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs= cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10= cloud.google.com/go/contactcenterinsights v1.13.0 h1:6Vs/YnDG5STGjlWMEjN/xtmft7MrOTOnOZYUZtGTx0w= cloud.google.com/go/contactcenterinsights v1.13.0/go.mod h1:ieq5d5EtHsu8vhe2y3amtZ+BE+AQwX5qAy7cpo0POsI= @@ -303,6 +305,7 @@ github.com/GoogleCloudPlatform/grpc-gcp-go/grpcgcp v1.5.3 h1:2afWGsMzkIcN8Qm4mgP github.com/GoogleCloudPlatform/grpc-gcp-go/grpcgcp v1.5.3/go.mod h1:dppbR7CwXD4pgtV9t3wD1812RaLDcBjtblcDF5f1vI0= github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.27.0 h1:ErKg/3iS1AKcTkf3yixlZ54f9U1rljCkQyEXWUnIUxc= github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.27.0/go.mod h1:yAZHSGnqScoU556rBOVkwLze6WP5N+U11RHuWaGVxwY= +github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.30.0 h1:sBEjpZlNHzK1voKq9695PJSX2o5NEXl7/OL3coiIY0c= github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.30.0/go.mod h1:P4WPRUkOhJC13W//jWpyfJNDAIpvRbAUIYLX/4jtlE0= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.53.0 h1:owcC2UnmsZycprQ5RfRgjydWhuoxg71LUfyiQdijZuM= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.53.0/go.mod h1:ZPpqegjbE99EPKsu3iUWV22A04wzGPcAY/ziSIQEEgs= @@ -411,7 +414,9 @@ github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1 github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM= github.com/bytedance/sonic v1.10.0-rc3 h1:uNSnscRapXTwUgTyOF0GVljYD08p9X/Lbr9MweSV3V0= github.com/bytedance/sonic v1.10.0-rc3/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4= +github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0= github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4= +github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM= github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= @@ -436,7 +441,9 @@ github.com/cilium/ebpf v0.9.1/go.mod h1:+OhNOIXx/Fnu1IE8bJz2dzOA+VSfyTfdNUVdlQnx github.com/cloudflare/cfssl v0.0.0-20180223231731-4e2dcbde5004 h1:lkAMpLVBDaj17e85keuznYcH5rqI438v41pKcBl4ZxQ= github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58 h1:F1EaeKL/ta07PY/k9Os/UFtwERei2/XzGemhpGnBKNg= github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58/go.mod h1:EOBUe0h4xcZ5GoxqC5SDxFQ8gwyZPKQoEzownBlhI80= +github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y= github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= +github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg= github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= github.com/cncf/xds/go v0.0.0-20240318125728-8a4994d93e50 h1:DBmgJDC9dTfkVyGgipamEh2BpGYxScCH1TOF1LL1cXc= github.com/cncf/xds/go v0.0.0-20240318125728-8a4994d93e50/go.mod h1:5e1+Vvlzido69INQaVO6d87Qn543Xr6nooe9Kz7oBFM= @@ -444,6 +451,7 @@ github.com/cncf/xds/go v0.0.0-20240723142845-024c85f92f20 h1:N+3sFI5GUjRKBi+i0Tx github.com/cncf/xds/go v0.0.0-20240723142845-024c85f92f20/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= github.com/cncf/xds/go v0.0.0-20250501225837-2ac532fd4443 h1:aQ3y1lwWyqYPiWZThqv1aFbZMiM9vblcSArJRf2Irls= github.com/cncf/xds/go v0.0.0-20250501225837-2ac532fd4443/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= +github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5 h1:6xNmx7iTtyBRev0+D/Tv1FZd4SCg8axKApyNyRsAt/w= github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5/go.mod h1:KdCmV+x/BuvyMxRnYBlmVaq4OLiKW6iRQfvC62cvdkI= github.com/cockroachdb/cockroach-go/v2 v2.1.1 h1:3XzfSMuUT0wBe1a3o5C0eOTcArhmmFAg2Jzh/7hhKqo= github.com/cockroachdb/cockroach-go/v2 v2.1.1/go.mod h1:7NtUnP6eK+l6k483WSYNrq3Kb23bWV10IRV1TyeSpwM= @@ -534,10 +542,13 @@ github.com/envoyproxy/go-control-plane v0.12.0/go.mod h1:ZBTaoJ23lqITozF0M6G4/Ir github.com/envoyproxy/go-control-plane v0.13.0 h1:HzkeUz1Knt+3bK+8LG1bxOO/jzWZmdxpwC51i202les= github.com/envoyproxy/go-control-plane v0.13.0/go.mod h1:GRaKG3dwvFoTg4nj7aXdZnvMg4d7nvT/wl9WgVXn3Q8= github.com/envoyproxy/go-control-plane v0.13.4/go.mod h1:kDfuBlDVsSj2MjrLEtRWtHlsWIFcGyB2RMO44Dc5GZA= +github.com/envoyproxy/go-control-plane v0.14.0 h1:hbG2kr4RuFj222B6+7T83thSPqLjwBIfQawTkC++2HA= github.com/envoyproxy/go-control-plane v0.14.0/go.mod h1:NcS5X47pLl/hfqxU70yPwL9ZMkUlwlKxtAohpi2wBEU= github.com/envoyproxy/go-control-plane/envoy v1.32.4 h1:jb83lalDRZSpPWW2Z7Mck/8kXZ5CQAFYVjQcdVIr83A= github.com/envoyproxy/go-control-plane/envoy v1.32.4/go.mod h1:Gzjc5k8JcJswLjAx1Zm+wSYE20UrLtt7JZMWiWQXQEw= +github.com/envoyproxy/go-control-plane/envoy v1.36.0 h1:yg/JjO5E7ubRyKX3m07GF3reDNEnfOboJ0QySbH736g= github.com/envoyproxy/go-control-plane/envoy v1.36.0/go.mod h1:ty89S1YCCVruQAm9OtKeEkQLTb+Lkz0k8v9W0Oxsv98= +github.com/envoyproxy/go-control-plane/ratelimit v0.1.0 h1:/G9QYbddjL25KvtKTv3an9lx6VBE2cnb8wp1vEGNYGI= github.com/envoyproxy/go-control-plane/ratelimit v0.1.0/go.mod h1:Wk+tMFAFbCXaJPzVVHnPgRKdUdwW/KdbRt94AzgRee4= github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A= github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew= @@ -545,6 +556,7 @@ github.com/envoyproxy/protoc-gen-validate v1.1.0 h1:tntQDh69XqOCOZsDz0lVJQez/2L6 github.com/envoyproxy/protoc-gen-validate v1.1.0/go.mod h1:sXRDRVmzEbkM7CVcM06s9shE/m23dg3wzjl0UWqJ2q4= github.com/envoyproxy/protoc-gen-validate v1.2.1 h1:DEo3O99U8j4hBFwbJfrz9VtgcDfUKS7KJ7spH3d86P8= github.com/envoyproxy/protoc-gen-validate v1.2.1/go.mod h1:d/C80l/jxXLdfEIhX1W2TmLfsJ31lvEjwamM4DxlWXU= +github.com/envoyproxy/protoc-gen-validate v1.3.0 h1:TvGH1wof4H33rezVKWSpqKz5NXWg5VPuZ0uONDT6eb4= github.com/envoyproxy/protoc-gen-validate v1.3.0/go.mod h1:HvYl7zwPa5mffgyeTUHA9zHIH36nmrm7oCbo4YKoSWA= github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 h1:Yzb9+7DPaBjB8zlTR87/ElzFsnQfuHnVUVqpZZIcV5Y= github.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84= @@ -576,11 +588,13 @@ github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= +github.com/gin-gonic/gin v1.10.1 h1:T0ujvqyCSqRopADpgPgiTT63DUQVSfojyME59Ei63pQ= github.com/gin-gonic/gin v1.10.1/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y= github.com/go-jose/go-jose/v3 v3.0.3 h1:fFKWeig/irsp7XD2zBxvnmA/XaRWp5V3CBsZXJF7G7k= github.com/go-jose/go-jose/v3 v3.0.3/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ= github.com/go-jose/go-jose/v4 v4.0.5 h1:M6T8+mKZl/+fNNuFHvGIzDz7BTLQPIounk/b9dw3AaE= github.com/go-jose/go-jose/v4 v4.0.5/go.mod h1:s3P1lRrkT8igV8D9OjyL4WRyHvjB6a4JSllnOrmmBOA= +github.com/go-jose/go-jose/v4 v4.1.3 h1:CVLmWDhDVRa6Mi/IgCgaopNosCaHz7zrMeF9MlZRkrs= github.com/go-jose/go-jose/v4 v4.1.3/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= github.com/go-kit/kit v0.8.0 h1:Wz+5lgoB0kkuqLEc6NVmwRknTKP6dTGbSqvhZtBI/j0= github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= @@ -595,6 +609,8 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= +github.com/go-playground/validator/v10 v10.14.1 h1:9c50NUPC30zyuKprjL3vNZ0m5oG+jU0zvx4AqHGnv4k= +github.com/go-playground/validator/v10 v10.14.1/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8= github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs= @@ -636,6 +652,7 @@ github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI= github.com/golang/glog v1.2.2 h1:1+mZ9upx1Dh6FmUTFR1naJ77miKiXgALjWOZ3NVFPmY= github.com/golang/glog v1.2.2/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= +github.com/golang/glog v1.2.5 h1:DrW6hGnjIhtvhOIiAKT6Psh/Kd/ldepEa81DKeiRJ5I= github.com/golang/glog v1.2.5/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -799,6 +816,7 @@ github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBF github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg= github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= +github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s= @@ -940,6 +958,7 @@ github.com/package-url/packageurl-go v0.1.1-0.20220428063043-89078438f170 h1:DiL github.com/package-url/packageurl-go v0.1.1-0.20220428063043-89078438f170/go.mod h1:uQd4a7Rh3ZsVg5j0lNyAfyxIeGde9yrlhjF78GzeW0c= github.com/pelletier/go-toml/v2 v2.0.9 h1:uH2qQXheeefCCkuBBSLi7jCiSmj3VRh2+Goq2N7Xxu0= github.com/pelletier/go-toml/v2 v2.0.9/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= +github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= @@ -1005,6 +1024,7 @@ github.com/spiffe/go-spiffe/v2 v2.1.1 h1:RT9kM8MZLZIsPTH+HKQEP5yaAk3yd/VBzlINaRj github.com/spiffe/go-spiffe/v2 v2.1.1/go.mod h1:5qg6rpqlwIub0JAiF1UK9IMD6BpPTmvG6yfSgDBs5lg= github.com/spiffe/go-spiffe/v2 v2.5.0 h1:N2I01KCUkv1FAjZXJMwh95KK1ZIQLYbPfhaxw8WS0hE= github.com/spiffe/go-spiffe/v2 v2.5.0/go.mod h1:P+NxobPc6wXhVtINNtFjNWGBTreew1GBUCwT2wPmb7g= +github.com/spiffe/go-spiffe/v2 v2.6.0 h1:l+DolpxNWYgruGQVV0xsfeya3CsC7m8iBzDnMpsbLuo= github.com/spiffe/go-spiffe/v2 v2.6.0/go.mod h1:gm2SeUoMZEtpnzPNs2Csc0D/gX33k1xIx7lEzqblHEs= github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad h1:fiWzISvDn0Csy5H0iwgAuJGQTUpVfEMJJd4nRFXogbc= github.com/stefanberger/go-pkcs11uri v0.0.0-20230803200340-78284954bff6 h1:pnnLyeX7o/5aX8qUQ69P/mLojDqwda8hFOCBTmP/6hw= @@ -1116,6 +1136,7 @@ go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= go.opentelemetry.io/contrib/detectors/gcp v1.36.0 h1:F7q2tNlCaHY9nMKHR6XH9/qkp8FktLnIcy6jJNyOCQw= go.opentelemetry.io/contrib/detectors/gcp v1.36.0/go.mod h1:IbBN8uAIIx734PTonTPxAxnjc2pQTxWNkwfstZ+6H2k= +go.opentelemetry.io/contrib/detectors/gcp v1.39.0 h1:kWRNZMsfBHZ+uHjiH4y7Etn2FK26LAGkNFw7RHv1DhE= go.opentelemetry.io/contrib/detectors/gcp v1.39.0/go.mod h1:t/OGqzHBa5v6RHZwrDBJ2OirWc+4q/w2fTbLZwAKjTk= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 h1:4Pp6oUg3+e/6M4C0A/3kJ2VYa++dsWVTtGgLVj5xtHg= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0/go.mod h1:Mjt1i1INqiaoZOMGR1RIUJN+i3ChKoFRqzrRQhlkbs0= @@ -1170,10 +1191,12 @@ go.opentelemetry.io/otel/trace v1.41.0/go.mod h1:U1NU4ULCoxeDKc09yCWdWe+3QoyweJc go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/arch v0.4.0 h1:A8WCeEWhLwPBKNbFi5Wv5UTCBx5zzubnXDlMOFAzFMc= golang.org/x/arch v0.4.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= +golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc= golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -1227,6 +1250,7 @@ golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= golang.org/x/oauth2 v0.34.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= +golang.org/x/oauth2 v0.35.0 h1:Mv2mzuHuZuY2+bkyWXIHMfhNdJAdwW3FuWeCPYN5GVQ= golang.org/x/oauth2 v0.35.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1286,6 +1310,7 @@ golang.org/x/telemetry v0.0.0-20250908211612-aef8a434d053/go.mod h1:+nZKN+XVh4LC golang.org/x/telemetry v0.0.0-20251008203120-078029d740a8 h1:LvzTn0GQhWuvKH/kVRS3R3bVAsdQWI7hvfLHGgh9+lU= golang.org/x/telemetry v0.0.0-20251008203120-078029d740a8/go.mod h1:Pi4ztBfryZoJEkyFTI5/Ocsu2jXyDr6iSdgJiYE/uwE= golang.org/x/telemetry v0.0.0-20260109210033-bd525da824e2/go.mod h1:b7fPSJ0pKZ3ccUh8gnTONJxhn3c/PS6tyzQvyqw4iA8= +golang.org/x/telemetry v0.0.0-20260209163413-e7419c687ee4 h1:bTLqdHv7xrGlFbvf5/TXNxy/iUwwdkjhqQTJDjW7aj0= golang.org/x/telemetry v0.0.0-20260209163413-e7419c687ee4/go.mod h1:g5NllXBEermZrmR51cJDQxmJUHUOfRAaNyWBM+R+548= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= @@ -1339,6 +1364,7 @@ golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU= golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= +gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= google.golang.org/api v0.169.0 h1:QwWPy71FgMWqJN/l6jVlFHUa29a7dcUy02I8o799nPY= google.golang.org/api v0.169.0/go.mod h1:gpNOiMA2tZ4mf5R9Iwf4rK/Dcz0fbdIgWYWVoxmsyLg= From 144bce9ebc602cfca4e166e1af44c4c017c5b0e6 Mon Sep 17 00:00:00 2001 From: Janis Saldabols Date: Thu, 26 Mar 2026 17:26:01 +0200 Subject: [PATCH 3/7] CROSSLINK-234 Add items in insert and update parameters --- broker/patron_request/api/api-handler.go | 18 +--------- broker/patron_request/service/action.go | 36 ++----------------- .../patron_request/service/message-handler.go | 36 ++----------------- broker/sqlc/pr_query.sql | 7 ++-- .../patron_request/api/api-handler_test.go | 2 +- 5 files changed, 10 insertions(+), 89 deletions(-) diff --git a/broker/patron_request/api/api-handler.go b/broker/patron_request/api/api-handler.go index 832664b7..17a9d86a 100644 --- a/broker/patron_request/api/api-handler.go +++ b/broker/patron_request/api/api-handler.go @@ -215,23 +215,7 @@ func (a *PatronRequestApiHandler) PostPatronRequests(w http.ResponseWriter, r *h return } dbreq := buildDbPatronRequest(&newPr, params.XOkapiTenant, creationTime, requesterReqId, illRequest) - pr, err := a.prRepo.CreatePatronRequest(ctx, pr_db.CreatePatronRequestParams{ - ID: dbreq.ID, - Timestamp: dbreq.Timestamp, - IllRequest: dbreq.IllRequest, - State: dbreq.State, - Side: dbreq.Side, - Patron: dbreq.Patron, - RequesterSymbol: dbreq.RequesterSymbol, - SupplierSymbol: dbreq.SupplierSymbol, - Tenant: dbreq.Tenant, - RequesterReqID: dbreq.RequesterReqID, - NeedsAttention: dbreq.NeedsAttention, - LastAction: dbreq.LastAction, - LastActionOutcome: dbreq.LastActionOutcome, - LastActionResult: dbreq.LastActionResult, - Language: dbreq.Language, - }) + pr, err := a.prRepo.CreatePatronRequest(ctx, pr_db.CreatePatronRequestParams(dbreq)) if err != nil { var pgErr *pgconn.PgError if errors.As(err, &pgErr) && pgerrcode.IsIntegrityConstraintViolation(pgErr.Code) { diff --git a/broker/patron_request/service/action.go b/broker/patron_request/service/action.go index ae0c95b9..1f82a1eb 100644 --- a/broker/patron_request/service/action.go +++ b/broker/patron_request/service/action.go @@ -124,23 +124,7 @@ func (a *PatronRequestActionService) finalizeActionExecution(ctx common.Extended } var err error - updatedPr, err = a.prRepo.UpdatePatronRequest(ctx, pr_db.UpdatePatronRequestParams{ - ID: updatedPr.ID, - Timestamp: updatedPr.Timestamp, - IllRequest: updatedPr.IllRequest, - State: updatedPr.State, - Side: updatedPr.Side, - Patron: updatedPr.Patron, - RequesterSymbol: updatedPr.RequesterSymbol, - SupplierSymbol: updatedPr.SupplierSymbol, - Tenant: updatedPr.Tenant, - RequesterReqID: updatedPr.RequesterReqID, - NeedsAttention: updatedPr.NeedsAttention, - LastAction: updatedPr.LastAction, - LastActionOutcome: updatedPr.LastActionOutcome, - LastActionResult: updatedPr.LastActionResult, - Language: updatedPr.Language, - }) + updatedPr, err = a.prRepo.UpdatePatronRequest(ctx, pr_db.UpdatePatronRequestParams(updatedPr)) if err != nil { return a.logErrorAndReturnResult(ctx, "failed to update patron request", err) } @@ -799,23 +783,7 @@ func (a *PatronRequestActionService) setNeedsAttention(ctx common.ExtendedContex return nil } prToUpdate.NeedsAttention = true - _, err = repo.UpdatePatronRequest(ctx, pr_db.UpdatePatronRequestParams{ - ID: prToUpdate.ID, - Timestamp: prToUpdate.Timestamp, - IllRequest: prToUpdate.IllRequest, - State: prToUpdate.State, - Side: prToUpdate.Side, - Patron: prToUpdate.Patron, - RequesterSymbol: prToUpdate.RequesterSymbol, - SupplierSymbol: prToUpdate.SupplierSymbol, - Tenant: prToUpdate.Tenant, - RequesterReqID: prToUpdate.RequesterReqID, - NeedsAttention: prToUpdate.NeedsAttention, - LastAction: prToUpdate.LastAction, - LastActionOutcome: prToUpdate.LastActionOutcome, - LastActionResult: prToUpdate.LastActionResult, - Language: prToUpdate.Language, - }) + _, err = repo.UpdatePatronRequest(ctx, pr_db.UpdatePatronRequestParams(prToUpdate)) return err }) if err != nil { diff --git a/broker/patron_request/service/message-handler.go b/broker/patron_request/service/message-handler.go index 30de7a87..361fdd15 100644 --- a/broker/patron_request/service/message-handler.go +++ b/broker/patron_request/service/message-handler.go @@ -235,23 +235,7 @@ func (m *PatronRequestMessageHandler) handleSupplyingAgencyMessage(ctx common.Ex } func (m *PatronRequestMessageHandler) updatePatronRequestAndCreateSamResponse(ctx common.ExtendedContext, pr pr_db.PatronRequest, sam iso18626.SupplyingAgencyMessage, stateChanged bool) (events.EventStatus, *iso18626.ISO18626Message, error) { - _, err := m.prRepo.UpdatePatronRequest(ctx, pr_db.UpdatePatronRequestParams{ - ID: pr.ID, - Timestamp: pr.Timestamp, - IllRequest: pr.IllRequest, - State: pr.State, - Side: pr.Side, - Patron: pr.Patron, - RequesterSymbol: pr.RequesterSymbol, - SupplierSymbol: pr.SupplierSymbol, - Tenant: pr.Tenant, - RequesterReqID: pr.RequesterReqID, - NeedsAttention: pr.NeedsAttention, - LastAction: pr.LastAction, - LastActionOutcome: pr.LastActionOutcome, - LastActionResult: pr.LastActionResult, - Language: pr.Language, - }) + _, err := m.prRepo.UpdatePatronRequest(ctx, pr_db.UpdatePatronRequestParams(pr)) if err != nil { return createSAMResponse(sam, iso18626.TypeMessageStatusERROR, &iso18626.ErrorData{ ErrorType: iso18626.TypeErrorTypeUnrecognisedDataValue, @@ -464,23 +448,7 @@ func createRAMResponse(ram iso18626.RequestingAgencyMessage, messageStatus iso18 } func (m *PatronRequestMessageHandler) updatePatronRequestAndCreateRamResponse(ctx common.ExtendedContext, pr pr_db.PatronRequest, ram iso18626.RequestingAgencyMessage, action *iso18626.TypeAction, stateChanged bool) (events.EventStatus, *iso18626.ISO18626Message, error) { - _, err := m.prRepo.UpdatePatronRequest(ctx, pr_db.UpdatePatronRequestParams{ - ID: pr.ID, - Timestamp: pr.Timestamp, - IllRequest: pr.IllRequest, - State: pr.State, - Side: pr.Side, - Patron: pr.Patron, - RequesterSymbol: pr.RequesterSymbol, - SupplierSymbol: pr.SupplierSymbol, - Tenant: pr.Tenant, - RequesterReqID: pr.RequesterReqID, - NeedsAttention: pr.NeedsAttention, - LastAction: pr.LastAction, - LastActionOutcome: pr.LastActionOutcome, - LastActionResult: pr.LastActionResult, - Language: pr.Language, - }) + _, err := m.prRepo.UpdatePatronRequest(ctx, pr_db.UpdatePatronRequestParams(pr)) if err != nil { return createRAMResponse(ram, iso18626.TypeMessageStatusERROR, action, &iso18626.ErrorData{ ErrorType: iso18626.TypeErrorTypeUnrecognisedDataValue, diff --git a/broker/sqlc/pr_query.sql b/broker/sqlc/pr_query.sql index 4ab6ca4f..38d140f9 100644 --- a/broker/sqlc/pr_query.sql +++ b/broker/sqlc/pr_query.sql @@ -32,13 +32,14 @@ SET timestamp = $2, last_action = $12, last_action_outcome = $13, last_action_result = $14, - language = $15 + items = $15, + language = $16 WHERE id = $1 RETURNING sqlc.embed(patron_request); -- name: CreatePatronRequest :one -INSERT INTO patron_request (id, timestamp, ill_request, state, side, patron, requester_symbol, supplier_symbol, tenant, requester_req_id, needs_attention, last_action, last_action_outcome, last_action_result, language) -VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15) +INSERT INTO patron_request (id, timestamp, ill_request, state, side, patron, requester_symbol, supplier_symbol, tenant, requester_req_id, needs_attention, last_action, last_action_outcome, last_action_result, items, language) +VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16) RETURNING sqlc.embed(patron_request); -- name: DeletePatronRequest :exec diff --git a/broker/test/patron_request/api/api-handler_test.go b/broker/test/patron_request/api/api-handler_test.go index 1edc2b03..6da91317 100644 --- a/broker/test/patron_request/api/api-handler_test.go +++ b/broker/test/patron_request/api/api-handler_test.go @@ -631,7 +631,7 @@ func TestServerChoice(t *testing.T) { }) assert.NoError(t, err) - respBytes := httpRequest(t, "GET", basePath+"?symbol=ISIL:REQ&side=borrowing&cql.serverChoice%20all%20%22REQ-123%20P456%20Dream%20Ray%20Bradbury%20John%20Doe%20PP-789%20BAR-321%20CAL-321%20ITEM-321%22", []byte{}, 200) + respBytes := httpRequest(t, "GET", basePath+"?symbol=ISIL:REQ&side=borrowing&cal=cql.serverChoice%20all%20%22REQ-123%20P456%20Dream%20Ray%20Bradbury%20John%20Doe%20PP-789%20BAR-321%20CAL-321%20ITEM-321%22", []byte{}, 200) var foundPrs proapi.PatronRequests err = json.Unmarshal(respBytes, &foundPrs) assert.NoError(t, err) From 794940d488c6869494a146967c50c7806157999c Mon Sep 17 00:00:00 2001 From: Janis Saldabols Date: Thu, 26 Mar 2026 17:50:02 +0200 Subject: [PATCH 4/7] CROSSLINK-234 Fix copilot comments --- broker/patron_request/api/api-handler.go | 1 + broker/patron_request/service/message-handler.go | 1 + broker/test/patron_request/api/api-handler_test.go | 1 + broker/test/patron_request/db/prrepo_test.go | 2 ++ 4 files changed, 5 insertions(+) diff --git a/broker/patron_request/api/api-handler.go b/broker/patron_request/api/api-handler.go index 17a9d86a..10c98ebd 100644 --- a/broker/patron_request/api/api-handler.go +++ b/broker/patron_request/api/api-handler.go @@ -697,6 +697,7 @@ func buildDbPatronRequest( Tenant: getDbText(tenant), RequesterReqID: getDbText(&requesterReqId), Language: pr_db.LANGUAGE, + Items: []pr_db.PrItem{}, // LastAction, LastActionOutcome and LastActionResult are not set on creation // they will be updated when the first action is executed. } diff --git a/broker/patron_request/service/message-handler.go b/broker/patron_request/service/message-handler.go index 361fdd15..463e5f6d 100644 --- a/broker/patron_request/service/message-handler.go +++ b/broker/patron_request/service/message-handler.go @@ -335,6 +335,7 @@ func (m *PatronRequestMessageHandler) handleRequestMessage(ctx common.ExtendedCo SupplierSymbol: getDbText(supplierSymbol), RequesterReqID: getDbText(raRequestId), Language: pr_db.LANGUAGE, + Items: []pr_db.PrItem{}, }) if err != nil { status, response, handleErr := createRequestResponse(request, iso18626.TypeMessageStatusERROR, &iso18626.ErrorData{ diff --git a/broker/test/patron_request/api/api-handler_test.go b/broker/test/patron_request/api/api-handler_test.go index 6da91317..c7022b7e 100644 --- a/broker/test/patron_request/api/api-handler_test.go +++ b/broker/test/patron_request/api/api-handler_test.go @@ -609,6 +609,7 @@ func TestServerChoice(t *testing.T) { PatronId: "PP-789", }, }, + Items: []pr_db.PrItem{}, }) assert.NoError(t, err) itemId := uuid.NewString() diff --git a/broker/test/patron_request/db/prrepo_test.go b/broker/test/patron_request/db/prrepo_test.go index 7aa41330..d7063271 100644 --- a/broker/test/patron_request/db/prrepo_test.go +++ b/broker/test/patron_request/db/prrepo_test.go @@ -76,6 +76,7 @@ func TestItem(t *testing.T) { Valid: true, }, Language: "english", + Items: []pr_db.PrItem{}, }) assert.NoError(t, err) @@ -165,6 +166,7 @@ func TestNotification(t *testing.T) { Valid: true, }, Language: "english", + Items: []pr_db.PrItem{}, }) assert.NoError(t, err) From cbfef1d4b99e55966166472ee79978122b7732db Mon Sep 17 00:00:00 2001 From: Janis Saldabols Date: Thu, 26 Mar 2026 17:53:53 +0200 Subject: [PATCH 5/7] CROSSLINK-234 Revert --- go.work.sum | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/go.work.sum b/go.work.sum index 4f553b3d..67d56d41 100644 --- a/go.work.sum +++ b/go.work.sum @@ -2,7 +2,6 @@ cel.dev/expr v0.16.0 h1:yloc84fytn4zmJX2GU3TkXGsaieaV7dQ057Qs4sIG2Y= cel.dev/expr v0.16.0/go.mod h1:TRSuuV7DlVCE/uwv5QbAiW/v8l5O8C4eEPHeu7gf7Sg= cel.dev/expr v0.24.0 h1:56OvJKSH3hDGL0ml5uSxZmz3/3Pq4tJ+fb1unVLAFcY= cel.dev/expr v0.24.0/go.mod h1:hLPLo1W4QUmuYdA72RBX06QTs6MXw941piREPl3Yfiw= -cel.dev/expr v0.25.1 h1:1KrZg61W6TWSxuNZ37Xy49ps13NUovb66QLprthtwi4= cel.dev/expr v0.25.1/go.mod h1:hrXvqGP6G6gyx8UAHSHJ5RGk//1Oj5nXQ2NI02Nrsg4= cloud.google.com/go v0.112.1 h1:uJSeirPke5UNZHIb4SxfZklVSiWWVqW4oXlETwZziwM= cloud.google.com/go v0.112.1/go.mod h1:+Vbu+Y1UU+I1rjmzeMOb/8RfkKJK2Gyxi1X6jJCZLo4= @@ -70,7 +69,6 @@ cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykW cloud.google.com/go/compute/metadata v0.7.0/go.mod h1:j5MvL9PprKL39t166CoB1uVHfQMs4tFQZZcKwksXUjo= cloud.google.com/go/compute/metadata v0.8.0 h1:HxMRIbao8w17ZX6wBnjhcDkW6lTFpgcaobyVfZWqRLA= cloud.google.com/go/compute/metadata v0.8.0/go.mod h1:sYOGTp851OV9bOFJ9CH7elVvyzopvWQFNNghtDQ/Biw= -cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs= cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10= cloud.google.com/go/contactcenterinsights v1.13.0 h1:6Vs/YnDG5STGjlWMEjN/xtmft7MrOTOnOZYUZtGTx0w= cloud.google.com/go/contactcenterinsights v1.13.0/go.mod h1:ieq5d5EtHsu8vhe2y3amtZ+BE+AQwX5qAy7cpo0POsI= @@ -305,7 +303,6 @@ github.com/GoogleCloudPlatform/grpc-gcp-go/grpcgcp v1.5.3 h1:2afWGsMzkIcN8Qm4mgP github.com/GoogleCloudPlatform/grpc-gcp-go/grpcgcp v1.5.3/go.mod h1:dppbR7CwXD4pgtV9t3wD1812RaLDcBjtblcDF5f1vI0= github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.27.0 h1:ErKg/3iS1AKcTkf3yixlZ54f9U1rljCkQyEXWUnIUxc= github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.27.0/go.mod h1:yAZHSGnqScoU556rBOVkwLze6WP5N+U11RHuWaGVxwY= -github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.30.0 h1:sBEjpZlNHzK1voKq9695PJSX2o5NEXl7/OL3coiIY0c= github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.30.0/go.mod h1:P4WPRUkOhJC13W//jWpyfJNDAIpvRbAUIYLX/4jtlE0= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.53.0 h1:owcC2UnmsZycprQ5RfRgjydWhuoxg71LUfyiQdijZuM= github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.53.0/go.mod h1:ZPpqegjbE99EPKsu3iUWV22A04wzGPcAY/ziSIQEEgs= @@ -414,9 +411,7 @@ github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1 github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM= github.com/bytedance/sonic v1.10.0-rc3 h1:uNSnscRapXTwUgTyOF0GVljYD08p9X/Lbr9MweSV3V0= github.com/bytedance/sonic v1.10.0-rc3/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4= -github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0= github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4= -github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM= github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM= github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= @@ -441,9 +436,7 @@ github.com/cilium/ebpf v0.9.1/go.mod h1:+OhNOIXx/Fnu1IE8bJz2dzOA+VSfyTfdNUVdlQnx github.com/cloudflare/cfssl v0.0.0-20180223231731-4e2dcbde5004 h1:lkAMpLVBDaj17e85keuznYcH5rqI438v41pKcBl4ZxQ= github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58 h1:F1EaeKL/ta07PY/k9Os/UFtwERei2/XzGemhpGnBKNg= github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58/go.mod h1:EOBUe0h4xcZ5GoxqC5SDxFQ8gwyZPKQoEzownBlhI80= -github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y= github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= -github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg= github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= github.com/cncf/xds/go v0.0.0-20240318125728-8a4994d93e50 h1:DBmgJDC9dTfkVyGgipamEh2BpGYxScCH1TOF1LL1cXc= github.com/cncf/xds/go v0.0.0-20240318125728-8a4994d93e50/go.mod h1:5e1+Vvlzido69INQaVO6d87Qn543Xr6nooe9Kz7oBFM= @@ -451,7 +444,6 @@ github.com/cncf/xds/go v0.0.0-20240723142845-024c85f92f20 h1:N+3sFI5GUjRKBi+i0Tx github.com/cncf/xds/go v0.0.0-20240723142845-024c85f92f20/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= github.com/cncf/xds/go v0.0.0-20250501225837-2ac532fd4443 h1:aQ3y1lwWyqYPiWZThqv1aFbZMiM9vblcSArJRf2Irls= github.com/cncf/xds/go v0.0.0-20250501225837-2ac532fd4443/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8= -github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5 h1:6xNmx7iTtyBRev0+D/Tv1FZd4SCg8axKApyNyRsAt/w= github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5/go.mod h1:KdCmV+x/BuvyMxRnYBlmVaq4OLiKW6iRQfvC62cvdkI= github.com/cockroachdb/cockroach-go/v2 v2.1.1 h1:3XzfSMuUT0wBe1a3o5C0eOTcArhmmFAg2Jzh/7hhKqo= github.com/cockroachdb/cockroach-go/v2 v2.1.1/go.mod h1:7NtUnP6eK+l6k483WSYNrq3Kb23bWV10IRV1TyeSpwM= @@ -542,13 +534,10 @@ github.com/envoyproxy/go-control-plane v0.12.0/go.mod h1:ZBTaoJ23lqITozF0M6G4/Ir github.com/envoyproxy/go-control-plane v0.13.0 h1:HzkeUz1Knt+3bK+8LG1bxOO/jzWZmdxpwC51i202les= github.com/envoyproxy/go-control-plane v0.13.0/go.mod h1:GRaKG3dwvFoTg4nj7aXdZnvMg4d7nvT/wl9WgVXn3Q8= github.com/envoyproxy/go-control-plane v0.13.4/go.mod h1:kDfuBlDVsSj2MjrLEtRWtHlsWIFcGyB2RMO44Dc5GZA= -github.com/envoyproxy/go-control-plane v0.14.0 h1:hbG2kr4RuFj222B6+7T83thSPqLjwBIfQawTkC++2HA= github.com/envoyproxy/go-control-plane v0.14.0/go.mod h1:NcS5X47pLl/hfqxU70yPwL9ZMkUlwlKxtAohpi2wBEU= github.com/envoyproxy/go-control-plane/envoy v1.32.4 h1:jb83lalDRZSpPWW2Z7Mck/8kXZ5CQAFYVjQcdVIr83A= github.com/envoyproxy/go-control-plane/envoy v1.32.4/go.mod h1:Gzjc5k8JcJswLjAx1Zm+wSYE20UrLtt7JZMWiWQXQEw= -github.com/envoyproxy/go-control-plane/envoy v1.36.0 h1:yg/JjO5E7ubRyKX3m07GF3reDNEnfOboJ0QySbH736g= github.com/envoyproxy/go-control-plane/envoy v1.36.0/go.mod h1:ty89S1YCCVruQAm9OtKeEkQLTb+Lkz0k8v9W0Oxsv98= -github.com/envoyproxy/go-control-plane/ratelimit v0.1.0 h1:/G9QYbddjL25KvtKTv3an9lx6VBE2cnb8wp1vEGNYGI= github.com/envoyproxy/go-control-plane/ratelimit v0.1.0/go.mod h1:Wk+tMFAFbCXaJPzVVHnPgRKdUdwW/KdbRt94AzgRee4= github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A= github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew= @@ -556,7 +545,6 @@ github.com/envoyproxy/protoc-gen-validate v1.1.0 h1:tntQDh69XqOCOZsDz0lVJQez/2L6 github.com/envoyproxy/protoc-gen-validate v1.1.0/go.mod h1:sXRDRVmzEbkM7CVcM06s9shE/m23dg3wzjl0UWqJ2q4= github.com/envoyproxy/protoc-gen-validate v1.2.1 h1:DEo3O99U8j4hBFwbJfrz9VtgcDfUKS7KJ7spH3d86P8= github.com/envoyproxy/protoc-gen-validate v1.2.1/go.mod h1:d/C80l/jxXLdfEIhX1W2TmLfsJ31lvEjwamM4DxlWXU= -github.com/envoyproxy/protoc-gen-validate v1.3.0 h1:TvGH1wof4H33rezVKWSpqKz5NXWg5VPuZ0uONDT6eb4= github.com/envoyproxy/protoc-gen-validate v1.3.0/go.mod h1:HvYl7zwPa5mffgyeTUHA9zHIH36nmrm7oCbo4YKoSWA= github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 h1:Yzb9+7DPaBjB8zlTR87/ElzFsnQfuHnVUVqpZZIcV5Y= github.com/evanphx/json-patch v4.12.0+incompatible h1:4onqiflcdA9EOZ4RxV643DvftH5pOlLGNtQ5lPWQu84= @@ -588,13 +576,11 @@ github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= -github.com/gin-gonic/gin v1.10.1 h1:T0ujvqyCSqRopADpgPgiTT63DUQVSfojyME59Ei63pQ= github.com/gin-gonic/gin v1.10.1/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y= github.com/go-jose/go-jose/v3 v3.0.3 h1:fFKWeig/irsp7XD2zBxvnmA/XaRWp5V3CBsZXJF7G7k= github.com/go-jose/go-jose/v3 v3.0.3/go.mod h1:5b+7YgP7ZICgJDBdfjZaIt+H/9L9T/YQrVfLAMboGkQ= github.com/go-jose/go-jose/v4 v4.0.5 h1:M6T8+mKZl/+fNNuFHvGIzDz7BTLQPIounk/b9dw3AaE= github.com/go-jose/go-jose/v4 v4.0.5/go.mod h1:s3P1lRrkT8igV8D9OjyL4WRyHvjB6a4JSllnOrmmBOA= -github.com/go-jose/go-jose/v4 v4.1.3 h1:CVLmWDhDVRa6Mi/IgCgaopNosCaHz7zrMeF9MlZRkrs= github.com/go-jose/go-jose/v4 v4.1.3/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= github.com/go-kit/kit v0.8.0 h1:Wz+5lgoB0kkuqLEc6NVmwRknTKP6dTGbSqvhZtBI/j0= github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= @@ -609,8 +595,6 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= -github.com/go-playground/validator/v10 v10.14.1 h1:9c50NUPC30zyuKprjL3vNZ0m5oG+jU0zvx4AqHGnv4k= -github.com/go-playground/validator/v10 v10.14.1/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8= github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs= @@ -652,7 +636,6 @@ github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI= github.com/golang/glog v1.2.2 h1:1+mZ9upx1Dh6FmUTFR1naJ77miKiXgALjWOZ3NVFPmY= github.com/golang/glog v1.2.2/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= -github.com/golang/glog v1.2.5 h1:DrW6hGnjIhtvhOIiAKT6Psh/Kd/ldepEa81DKeiRJ5I= github.com/golang/glog v1.2.5/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -816,7 +799,6 @@ github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBF github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg= github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= -github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s= @@ -958,7 +940,6 @@ github.com/package-url/packageurl-go v0.1.1-0.20220428063043-89078438f170 h1:DiL github.com/package-url/packageurl-go v0.1.1-0.20220428063043-89078438f170/go.mod h1:uQd4a7Rh3ZsVg5j0lNyAfyxIeGde9yrlhjF78GzeW0c= github.com/pelletier/go-toml/v2 v2.0.9 h1:uH2qQXheeefCCkuBBSLi7jCiSmj3VRh2+Goq2N7Xxu0= github.com/pelletier/go-toml/v2 v2.0.9/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= -github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= @@ -1024,7 +1005,6 @@ github.com/spiffe/go-spiffe/v2 v2.1.1 h1:RT9kM8MZLZIsPTH+HKQEP5yaAk3yd/VBzlINaRj github.com/spiffe/go-spiffe/v2 v2.1.1/go.mod h1:5qg6rpqlwIub0JAiF1UK9IMD6BpPTmvG6yfSgDBs5lg= github.com/spiffe/go-spiffe/v2 v2.5.0 h1:N2I01KCUkv1FAjZXJMwh95KK1ZIQLYbPfhaxw8WS0hE= github.com/spiffe/go-spiffe/v2 v2.5.0/go.mod h1:P+NxobPc6wXhVtINNtFjNWGBTreew1GBUCwT2wPmb7g= -github.com/spiffe/go-spiffe/v2 v2.6.0 h1:l+DolpxNWYgruGQVV0xsfeya3CsC7m8iBzDnMpsbLuo= github.com/spiffe/go-spiffe/v2 v2.6.0/go.mod h1:gm2SeUoMZEtpnzPNs2Csc0D/gX33k1xIx7lEzqblHEs= github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad h1:fiWzISvDn0Csy5H0iwgAuJGQTUpVfEMJJd4nRFXogbc= github.com/stefanberger/go-pkcs11uri v0.0.0-20230803200340-78284954bff6 h1:pnnLyeX7o/5aX8qUQ69P/mLojDqwda8hFOCBTmP/6hw= @@ -1136,7 +1116,6 @@ go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= go.opentelemetry.io/contrib/detectors/gcp v1.36.0 h1:F7q2tNlCaHY9nMKHR6XH9/qkp8FktLnIcy6jJNyOCQw= go.opentelemetry.io/contrib/detectors/gcp v1.36.0/go.mod h1:IbBN8uAIIx734PTonTPxAxnjc2pQTxWNkwfstZ+6H2k= -go.opentelemetry.io/contrib/detectors/gcp v1.39.0 h1:kWRNZMsfBHZ+uHjiH4y7Etn2FK26LAGkNFw7RHv1DhE= go.opentelemetry.io/contrib/detectors/gcp v1.39.0/go.mod h1:t/OGqzHBa5v6RHZwrDBJ2OirWc+4q/w2fTbLZwAKjTk= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 h1:4Pp6oUg3+e/6M4C0A/3kJ2VYa++dsWVTtGgLVj5xtHg= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0/go.mod h1:Mjt1i1INqiaoZOMGR1RIUJN+i3ChKoFRqzrRQhlkbs0= @@ -1191,12 +1170,10 @@ go.opentelemetry.io/otel/trace v1.41.0/go.mod h1:U1NU4ULCoxeDKc09yCWdWe+3QoyweJc go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/arch v0.4.0 h1:A8WCeEWhLwPBKNbFi5Wv5UTCBx5zzubnXDlMOFAzFMc= golang.org/x/arch v0.4.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= -golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc= golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -1250,7 +1227,6 @@ golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= golang.org/x/oauth2 v0.34.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= -golang.org/x/oauth2 v0.35.0 h1:Mv2mzuHuZuY2+bkyWXIHMfhNdJAdwW3FuWeCPYN5GVQ= golang.org/x/oauth2 v0.35.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1310,7 +1286,6 @@ golang.org/x/telemetry v0.0.0-20250908211612-aef8a434d053/go.mod h1:+nZKN+XVh4LC golang.org/x/telemetry v0.0.0-20251008203120-078029d740a8 h1:LvzTn0GQhWuvKH/kVRS3R3bVAsdQWI7hvfLHGgh9+lU= golang.org/x/telemetry v0.0.0-20251008203120-078029d740a8/go.mod h1:Pi4ztBfryZoJEkyFTI5/Ocsu2jXyDr6iSdgJiYE/uwE= golang.org/x/telemetry v0.0.0-20260109210033-bd525da824e2/go.mod h1:b7fPSJ0pKZ3ccUh8gnTONJxhn3c/PS6tyzQvyqw4iA8= -golang.org/x/telemetry v0.0.0-20260209163413-e7419c687ee4 h1:bTLqdHv7xrGlFbvf5/TXNxy/iUwwdkjhqQTJDjW7aj0= golang.org/x/telemetry v0.0.0-20260209163413-e7419c687ee4/go.mod h1:g5NllXBEermZrmR51cJDQxmJUHUOfRAaNyWBM+R+548= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= @@ -1364,7 +1339,6 @@ golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU= golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= -gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= google.golang.org/api v0.169.0 h1:QwWPy71FgMWqJN/l6jVlFHUa29a7dcUy02I8o799nPY= google.golang.org/api v0.169.0/go.mod h1:gpNOiMA2tZ4mf5R9Iwf4rK/Dcz0fbdIgWYWVoxmsyLg= From d42d73dbfd8876310fb7730fc1f1112c1a4daf44 Mon Sep 17 00:00:00 2001 From: Janis Saldabols Date: Fri, 27 Mar 2026 10:13:45 +0200 Subject: [PATCH 6/7] CROSSLINK-234 Correct migration script name --- ...{021_add_items_to_pr.down.sql => 022_add_items_to_pr.down.sql} | 0 .../{021_add_items_to_pr.up.sql => 022_add_items_to_pr.up.sql} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename broker/migrations/{021_add_items_to_pr.down.sql => 022_add_items_to_pr.down.sql} (100%) rename broker/migrations/{021_add_items_to_pr.up.sql => 022_add_items_to_pr.up.sql} (100%) diff --git a/broker/migrations/021_add_items_to_pr.down.sql b/broker/migrations/022_add_items_to_pr.down.sql similarity index 100% rename from broker/migrations/021_add_items_to_pr.down.sql rename to broker/migrations/022_add_items_to_pr.down.sql diff --git a/broker/migrations/021_add_items_to_pr.up.sql b/broker/migrations/022_add_items_to_pr.up.sql similarity index 100% rename from broker/migrations/021_add_items_to_pr.up.sql rename to broker/migrations/022_add_items_to_pr.up.sql From 228d449c1d02b80bb7c4dcfb0bf871adcfb2e716 Mon Sep 17 00:00:00 2001 From: Janis Saldabols Date: Fri, 27 Mar 2026 11:17:45 +0200 Subject: [PATCH 7/7] CROSSLINK-234 Use correct time format --- broker/migrations/022_add_items_to_pr.up.sql | 16 +++++++- broker/patron_request/db/prmodels.go | 43 +++----------------- 2 files changed, 20 insertions(+), 39 deletions(-) diff --git a/broker/migrations/022_add_items_to_pr.up.sql b/broker/migrations/022_add_items_to_pr.up.sql index 2b09b491..fc1b4a0b 100644 --- a/broker/migrations/022_add_items_to_pr.up.sql +++ b/broker/migrations/022_add_items_to_pr.up.sql @@ -5,7 +5,13 @@ RETURNS TRIGGER AS $$ BEGIN UPDATE patron_request SET items = ( - SELECT jsonb_agg(to_jsonb(i) - 'pr_id') + SELECT jsonb_agg( + (to_jsonb(i) - 'pr_id') || + jsonb_build_object( + 'created_at', + to_char(i.created_at, 'YYYY-MM-DD"T"HH24:MI:SS.US') || to_char(i.created_at, 'TZH:TZM') + ) + ) FROM item i WHERE i.pr_id = NEW.pr_id ) @@ -90,7 +96,13 @@ FROM patron_request pr; UPDATE patron_request pr SET items = COALESCE( ( - SELECT jsonb_agg(to_jsonb(i) - 'pr_id') + SELECT jsonb_agg( + (to_jsonb(i) - 'pr_id') || + jsonb_build_object( + 'created_at', + to_char(i.created_at, 'YYYY-MM-DD"T"HH24:MI:SS.US') || to_char(i.created_at, 'TZH:TZM') + ) + ) FROM item i WHERE i.pr_id = pr.id ), diff --git a/broker/patron_request/db/prmodels.go b/broker/patron_request/db/prmodels.go index c4d77537..779bf977 100644 --- a/broker/patron_request/db/prmodels.go +++ b/broker/patron_request/db/prmodels.go @@ -1,7 +1,6 @@ package pr_db import ( - "strings" "time" ) @@ -16,41 +15,11 @@ const ( NotificationSeen NotificationReceipt = "SEEN" ) -type CustomTime time.Time - -const customTimeLayout = "2006-01-02T15:04:05.999999" - -var postgresTimeLayouts = []string{ - "2006-01-02T15:04:05.999999", - "2006-01-02T15:04:05", - "2006-01-02 15:04:05.999999", - "2006-01-02 15:04:05", -} - -func (ct CustomTime) MarshalJSON() ([]byte, error) { - t := time.Time(ct) - return []byte(`"` + t.Format(customTimeLayout) + `"`), nil -} - -func (ct *CustomTime) UnmarshalJSON(b []byte) error { - s := strings.Trim(string(b), `"`) - var t time.Time - var err error - for _, layout := range postgresTimeLayouts { - t, err = time.Parse(layout, s) - if err == nil { - *ct = CustomTime(t) - return nil - } - } - return err -} - type PrItem struct { - ID string `json:"id"` - Barcode string `json:"barcode"` - CallNumber *string `json:"call_number"` - Title *string `json:"title"` - ItemID *string `json:"item_id"` - CreatedAt CustomTime `json:"created_at"` + ID string `json:"id"` + Barcode string `json:"barcode"` + CallNumber *string `json:"call_number"` + Title *string `json:"title"` + ItemID *string `json:"item_id"` + CreatedAt time.Time `json:"created_at"` }