Skip to content

Commit 38b7f0f

Browse files
CROSSLINK-266 Add duplicate action outcome
1 parent 8ca3ec7 commit 38b7f0f

14 files changed

Lines changed: 64 additions & 30 deletions

broker/handler/iso18626-handler.go

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"time"
1313

1414
"github.com/indexdata/crosslink/broker/catalog"
15+
"github.com/indexdata/crosslink/broker/service"
1516
"github.com/indexdata/crosslink/broker/shim"
1617

1718
"github.com/indexdata/crosslink/broker/adapter"
@@ -190,10 +191,15 @@ func checkDuplicateRequest(ctx common.ExtendedContext, request *iso18626.Request
190191
patronId = request.PatronInfo.PatronId
191192
}
192193

193-
lookupParams := service.CreateHoldingsParams(ill_db.IllTransactionData{
194-
BibliographicInfo: request.BibliographicInfo,
195-
ServiceInfo: request.ServiceInfo,
196-
})
194+
if patronId == "" {
195+
return nil
196+
}
197+
198+
lookupParams := catalog.LookupParamsFromBibliographicInfo(request.BibliographicInfo, request.ServiceInfo)
199+
200+
if lookupParams.ServiceType == "" {
201+
return nil
202+
}
197203

198204
_, err := repo.FindDuplicateIllTransaction(ctx, ill_db.FindDuplicateIllTransactionParams{
199205
RequesterSymbol: createPgText(requesterSymbol),

broker/handler/iso18626-handler_test.go

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -280,19 +280,15 @@ func TestCheckDuplicateRequest(t *testing.T) {
280280
wantSvcType: "Loan",
281281
},
282282
{
283-
name: "nil PatronInfo - uses empty patron ID in query",
283+
name: "nil PatronInfo - skips duplicate check (can't verify same patron)",
284284
request: &iso18626.Request{
285285
BibliographicInfo: iso18626.BibliographicInfo{SupplierUniqueRecordId: "rec-1"},
286286
ServiceInfo: &iso18626.ServiceInfo{ServiceType: iso18626.TypeServiceTypeLoan},
287287
},
288288
peer: ill_db.Peer{CustomData: directory.Entry{DuplicateCheckWindowHours: &window1}},
289289
repoErr: pgx.ErrNoRows,
290290
wantErr: nil,
291-
wantRepoCalled: true,
292-
wantPatronId: "",
293-
wantWindowHrs: 1,
294-
wantIdentifier: "rec-1",
295-
wantSvcType: "Loan",
291+
wantRepoCalled: false,
296292
},
297293
{
298294
name: "isbn passed as parameter to DB query",
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
DROP INDEX IF EXISTS idx_ill_transaction_requester_timestamp;
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
CREATE INDEX IF NOT EXISTS idx_ill_transaction_requester_timestamp
2+
ON ill_transaction (requester_symbol, timestamp DESC)
3+
INCLUDE (id);

broker/oapi/open-api.yaml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -705,7 +705,7 @@ components:
705705
description: Action message
706706
outcome:
707707
type: string
708-
description: Action outcome ("success", "failure", "review")
708+
description: Action outcome ("success", "failure", "review", "duplicate")
709709
fromState:
710710
type: string
711711
description: State before action execution
@@ -911,6 +911,9 @@ components:
911911
review:
912912
type: string
913913
description: Target state when the action requires review.
914+
duplicate:
915+
type: string
916+
description: Target state when the action is a duplicate.
914917
params:
915918
type: object
916919
description: Parameters for the action. The presence of parameters indicates that the action requires additional input to be executed.

broker/patron_request/service/action_mapping.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,10 @@ func (r *ActionMapping) GetActionTransition(pr pr_db.PatronRequest, action pr_db
239239
if actionConfig.Transitions.Review != nil && *actionConfig.Transitions.Review != "" {
240240
return pr_db.PatronRequestState(*actionConfig.Transitions.Review), true
241241
}
242+
case ActionOutcomeDuplicate:
243+
if actionConfig.Transitions.Duplicate != nil && *actionConfig.Transitions.Duplicate != "" {
244+
return pr_db.PatronRequestState(*actionConfig.Transitions.Duplicate), true
245+
}
242246
}
243247
return "", false
244248
}

broker/patron_request/service/message_sender.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,11 @@ func (ms *PatronRequestMessageSender) sendBorrowingRequest(ctx common.ExtendedCo
161161
result.IncomingMessage = w.IllMessage
162162
if w.StatusCode != http.StatusOK || w.IllMessage == nil || w.IllMessage.RequestConfirmation == nil ||
163163
w.IllMessage.RequestConfirmation.ConfirmationHeader.MessageStatus != iso18626.TypeMessageStatusOK {
164+
if w.IllMessage.RequestConfirmation.ErrorData != nil &&
165+
w.IllMessage.RequestConfirmation.ErrorData.ErrorValue == string(handler.ReqIsDuplicate) {
166+
result.ActionResult = &events.ActionResult{Outcome: ActionOutcomeDuplicate}
167+
return actionExecutionResult{status: events.EventStatusSuccess, result: &result, pr: pr}
168+
}
164169
result.ActionResult = &events.ActionResult{Outcome: ActionOutcomeFailure}
165170
return actionExecutionResult{status: events.EventStatusProblem, result: &result, pr: pr}
166171
}

broker/patron_request/service/statemodel.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,12 @@ func validateActionTransitions(action proapi.ModelAction, stateName string, allo
221221
return fmt.Errorf("action %s in state %s has invalid review transition target %s", action.Name, stateName, target)
222222
}
223223
}
224+
if action.Transitions.Duplicate != nil && *action.Transitions.Duplicate != "" {
225+
target := *action.Transitions.Duplicate
226+
if !hasTransitionTarget(allowedTransitionTargets, target) {
227+
return fmt.Errorf("action %s in state %s has invalid duplicate transition target %s", action.Name, stateName, target)
228+
}
229+
}
224230
return nil
225231
}
226232

broker/patron_request/service/statemodel_capabilities.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@ import (
1111
type MessageEvent string
1212

1313
const (
14-
ActionOutcomeSuccess = "success"
15-
ActionOutcomeFailure = "failure"
16-
ActionOutcomeReview = "review"
14+
ActionOutcomeSuccess = "success"
15+
ActionOutcomeFailure = "failure"
16+
ActionOutcomeReview = "review"
17+
ActionOutcomeDuplicate = "duplicate"
1718
)
1819

1920
const (

broker/patron_request/service/statemodel_test.go

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -333,9 +333,10 @@ func TestValidateStateModelInvalidActionSuccessTransitionTarget(t *testing.T) {
333333
{
334334
Name: string(BorrowerActionValidate),
335335
Transitions: &struct {
336-
Failure *string `json:"failure,omitempty"`
337-
Review *string `json:"review,omitempty"`
338-
Success *string `json:"success,omitempty"`
336+
Duplicate *string `json:"duplicate,omitempty"`
337+
Failure *string `json:"failure,omitempty"`
338+
Review *string `json:"review,omitempty"`
339+
Success *string `json:"success,omitempty"`
339340
}{
340341
Success: &invalidTarget,
341342
},
@@ -366,9 +367,10 @@ func TestValidateStateModelInvalidActionFailureTransitionTarget(t *testing.T) {
366367
{
367368
Name: string(BorrowerActionSendRequest),
368369
Transitions: &struct {
369-
Failure *string `json:"failure,omitempty"`
370-
Review *string `json:"review,omitempty"`
371-
Success *string `json:"success,omitempty"`
370+
Duplicate *string `json:"duplicate,omitempty"`
371+
Failure *string `json:"failure,omitempty"`
372+
Review *string `json:"review,omitempty"`
373+
Success *string `json:"success,omitempty"`
372374
}{
373375
Failure: &invalidTarget,
374376
},
@@ -426,9 +428,10 @@ func TestValidateStateModelActionTransitionTargetMustExistInModelForSameSide(t *
426428
{
427429
Name: string(BorrowerActionValidate),
428430
Transitions: &struct {
429-
Failure *string `json:"failure,omitempty"`
430-
Review *string `json:"review,omitempty"`
431-
Success *string `json:"success,omitempty"`
431+
Duplicate *string `json:"duplicate,omitempty"`
432+
Failure *string `json:"failure,omitempty"`
433+
Review *string `json:"review,omitempty"`
434+
Success *string `json:"success,omitempty"`
432435
}{
433436
Success: &transition,
434437
},
@@ -459,9 +462,10 @@ func TestValidateStateModelActionTransitionCannotCrossSides(t *testing.T) {
459462
{
460463
Name: string(BorrowerActionValidate),
461464
Transitions: &struct {
462-
Failure *string `json:"failure,omitempty"`
463-
Review *string `json:"review,omitempty"`
464-
Success *string `json:"success,omitempty"`
465+
Duplicate *string `json:"duplicate,omitempty"`
466+
Failure *string `json:"failure,omitempty"`
467+
Review *string `json:"review,omitempty"`
468+
Success *string `json:"success,omitempty"`
465469
}{
466470
Success: &transition,
467471
},

0 commit comments

Comments
 (0)