-
Notifications
You must be signed in to change notification settings - Fork 0
CROSSLINK-264 retry-action #622
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
febe0f2
ac9170a
d2f057b
67708e4
fa8eb8c
920a937
ddb2333
4f1c545
e7bf570
524a26a
9529072
0b7be58
d1f9912
95586a0
cb56c77
d6da9bb
217bfb7
7544ce8
eb34de0
3bc091f
3f13e33
fdeb194
317fcb3
a78c2a1
ff241ea
846bac8
975772f
614664c
b281c10
780e65a
776c9c2
d742ac3
6cbd997
a13ff15
aa1678c
48216b6
7db5fe9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| DROP VIEW IF EXISTS patron_request_search_view; | ||
| ALTER TABLE patron_request DROP COLUMN next_req_id; | ||
| ALTER TABLE patron_request DROP COLUMN prev_req_id; | ||
| ALTER TABLE patron_request DROP COLUMN retry_bib_info; | ||
|
|
||
| CREATE 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, | ||
| (unread.unread_notifications_count > 0) AS has_unread_notification, | ||
| (pr.internal_note IS NOT NULL AND btrim(pr.internal_note) <> '') AS has_internal_note, | ||
| pr.ill_request -> 'serviceInfo' ->> 'serviceType' AS service_type, | ||
| pr.ill_request -> 'serviceInfo' -> 'serviceLevel' ->> '#text' AS service_level, | ||
|
adamdickmeiss marked this conversation as resolved.
|
||
| immutable_to_timestamp(pr.ill_request -> 'serviceInfo' ->> 'needBeforeDate') AS needed_at, | ||
| unread.unread_notifications_count AS unread_notifications_count | ||
| FROM patron_request pr | ||
| LEFT JOIN LATERAL ( | ||
| SELECT COUNT(*) AS unread_notifications_count | ||
| FROM notification n | ||
|
adamdickmeiss marked this conversation as resolved.
|
||
| WHERE n.pr_id = pr.id and n.acknowledged_at is null | ||
| ) unread ON true; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,31 @@ | ||
| ALTER TABLE patron_request ADD COLUMN next_req_id VARCHAR; | ||
| ALTER TABLE patron_request ADD COLUMN prev_req_id VARCHAR; | ||
| ALTER TABLE patron_request ADD COLUMN retry_bib_info JSONB; | ||
|
|
||
| DROP VIEW IF EXISTS patron_request_search_view; | ||
|
|
||
| CREATE VIEW patron_request_search_view AS | ||
| SELECT | ||
| pr.*, | ||
|
Comment on lines
+5
to
+9
|
||
| 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, | ||
| (unread.unread_notifications_count > 0) AS has_unread_notification, | ||
| (pr.internal_note IS NOT NULL AND btrim(pr.internal_note) <> '') AS has_internal_note, | ||
| 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, | ||
| unread.unread_notifications_count AS unread_notifications_count | ||
| FROM patron_request pr | ||
| LEFT JOIN LATERAL ( | ||
| SELECT COUNT(*) AS unread_notifications_count | ||
| FROM notification n | ||
| WHERE n.pr_id = pr.id and n.acknowledged_at is null | ||
| ) unread ON true; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -51,6 +51,8 @@ type actionParams struct { | |
| Cost *float64 `json:"cost,omitempty"` | ||
| Currency string `json:"currency,omitempty"` | ||
| ReasonUnfilled string `json:"reasonUnfilled,omitempty"` | ||
| ReasonRetry string `json:"reasonRetry,omitempty"` | ||
| ItemID string `json:"itemId,omitempty"` | ||
| } | ||
|
|
||
| func CreatePatronRequestActionService(prRepo pr_db.PrRepo, eventBus events.EventBus, iso18626Handler handler.Iso18626HandlerInterface, lmsCreator lms.LmsCreator) *PatronRequestActionService { | ||
|
|
@@ -275,6 +277,10 @@ func (a *PatronRequestActionService) handleBorrowingAction(ctx common.ExtendedCo | |
| return a.acceptConditionBorrowingRequest(ctx, pr) | ||
| case BorrowerActionRejectCondition: | ||
| return a.rejectConditionBorrowingRequest(ctx, pr) | ||
| case BorrowerActionRejectRetry: | ||
| return a.rejectRetryBorrowingRequest(pr) | ||
| case BorrowerActionAcceptRetry: | ||
| return a.acceptRetryBorrowingRequest(ctx, pr) | ||
| default: | ||
| status, result := logActionErrorAndReturnResult(ctx, "borrower action "+string(action)+" is not implemented yet", errors.New("invalid action")) | ||
| return actionExecutionResult{status: status, result: result, pr: pr} | ||
|
|
@@ -329,6 +335,8 @@ func (a *PatronRequestActionService) handleLenderAction(ctx common.ExtendedConte | |
| return a.markReceivedLenderRequest(ctx, pr, lms) | ||
| case LenderActionAcceptCancel: | ||
| return a.acceptCancelLenderRequest(ctx, pr) | ||
| case LenderActionAskRetry: | ||
| return a.askRetryLenderRequest(ctx, pr, params) | ||
| default: | ||
| status, result := logActionErrorAndReturnResult(ctx, "lender action "+string(action)+" is not implemented yet", errors.New("invalid action")) | ||
| return actionExecutionResult{status: status, result: result, pr: pr} | ||
|
|
@@ -528,6 +536,57 @@ func (a *PatronRequestActionService) rejectConditionBorrowingRequest(ctx common. | |
| return actionExecutionResult{status: events.EventStatusSuccess, result: &result, pr: pr} | ||
| } | ||
|
|
||
| func (a *PatronRequestActionService) rejectRetryBorrowingRequest(pr pr_db.PatronRequest) actionExecutionResult { | ||
| result := events.EventResult{} | ||
| return actionExecutionResult{status: events.EventStatusSuccess, result: &result, pr: pr} | ||
| } | ||
|
|
||
| func (a *PatronRequestActionService) acceptRetryBorrowingRequest(ctx common.ExtendedContext, pr pr_db.PatronRequest) actionExecutionResult { | ||
| result := events.EventResult{} | ||
|
|
||
| clone := pr_db.PatronRequest{} | ||
| clone.Side = pr.Side | ||
| clone.RequesterSymbol = pr.RequesterSymbol | ||
| clone.SupplierSymbol = pr.SupplierSymbol | ||
| clone.Patron = pr.Patron | ||
| clone.Tenant = pr.Tenant | ||
| var err error | ||
| clone.IllRequest, err = deepCopyISO18626Request(pr.IllRequest) | ||
| if err != nil { | ||
| status, result := logActionErrorAndReturnResult(ctx, "failed to clone IllRequest for retry", err) | ||
| return actionExecutionResult{status: status, result: result, pr: pr} | ||
| } | ||
| clone.State = BorrowerStateValidated | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @adamdickmeiss this is fragile. What if there's no BorrowerStateValidate in the state model? Also, there's no trace of this operation in the event log. I think we should create the new request in the initial state and run the auto-actions on it so it behaves like a regular request. |
||
| clone.TerminalState = false | ||
| clone.ID = uuid.NewString() | ||
| clone.RequesterReqID = getDbTextPtr(&clone.ID) | ||
| clone.CreatedAt = pgtype.Timestamp{Valid: true, Time: time.Now()} | ||
| clone.PrevReqID = getDbTextPtr(&pr.ID) | ||
| clone.Language = pr.Language | ||
| clone.Items = []pr_db.PrItem{} // items will be copied when the retry request is sent | ||
| clone.RetryBibInfo = nil // clear retry bib info to avoid confusion | ||
| if pr.RetryBibInfo != nil { | ||
| // only take selected fields from retry bib info to allow for corrections without affecting other fields | ||
| if pr.RetryBibInfo.SupplierUniqueRecordId != "" { | ||
| clone.IllRequest.BibliographicInfo.SupplierUniqueRecordId = pr.RetryBibInfo.SupplierUniqueRecordId | ||
| } | ||
| if pr.RetryBibInfo.Title != "" { | ||
| clone.IllRequest.BibliographicInfo.Title = pr.RetryBibInfo.Title | ||
| } | ||
| if pr.RetryBibInfo.Author != "" { | ||
| clone.IllRequest.BibliographicInfo.Author = pr.RetryBibInfo.Author | ||
| } | ||
| } | ||
|
|
||
| _, err = a.prRepo.CreatePatronRequest(ctx, pr_db.CreatePatronRequestParams(clone)) | ||
| if err != nil { | ||
| status, result := logActionErrorAndReturnResult(ctx, "failed to create patron request for retry", err) | ||
| return actionExecutionResult{status: status, result: result, pr: pr} | ||
| } | ||
|
Comment on lines
+581
to
+585
|
||
| pr.NextReqID = getDbTextPtr(&clone.ID) | ||
| return actionExecutionResult{status: events.EventStatusSuccess, result: &result, pr: pr} | ||
|
Comment on lines
+581
to
+587
|
||
| } | ||
|
|
||
| func (a *PatronRequestActionService) validateLenderRequest(ctx common.ExtendedContext, pr pr_db.PatronRequest, lms lms.LmsAdapter) actionExecutionResult { | ||
| institutionalPatron := lms.InstitutionalPatron(pr.RequesterSymbol.String) | ||
| _, err := lms.LookupUser(institutionalPatron) | ||
|
|
@@ -772,6 +831,32 @@ func (a *PatronRequestActionService) acceptCancelLenderRequest(ctx common.Extend | |
| return a.checkSupplyingResponse(status, eventResult, &result, httpStatus, pr) | ||
| } | ||
|
|
||
| func (a *PatronRequestActionService) askRetryLenderRequest(ctx common.ExtendedContext, pr pr_db.PatronRequest, params actionParams) actionExecutionResult { | ||
| var deliveryInfo *iso18626.DeliveryInfo | ||
| if params.ItemID != "" { | ||
| deliveryInfo = &iso18626.DeliveryInfo{ | ||
| ItemId: params.ItemID, | ||
| } | ||
| } | ||
| reasonRetry := string(iso18626.ReasonRetryNotFoundAsCited) | ||
| if params.ReasonRetry != "" { | ||
| reasonRetry = params.ReasonRetry | ||
| } | ||
| result := events.EventResult{} | ||
| status, eventResult, httpStatus := a.sendSupplyingAgencyMessage(ctx, pr, &result, | ||
| iso18626.MessageInfo{ | ||
| ReasonRetry: &iso18626.TypeSchemeValuePair{Text: reasonRetry}, | ||
| ReasonForMessage: iso18626.TypeReasonForMessageStatusChange, | ||
| Note: params.Note, | ||
| }, | ||
| iso18626.StatusInfo{Status: iso18626.TypeStatusRetryPossible}, | ||
| deliveryInfo) | ||
| if result.OutgoingMessage.SupplyingAgencyMessage != nil { | ||
| setSupplierMessage(*result.OutgoingMessage.SupplyingAgencyMessage, &pr) | ||
| } | ||
| return a.checkSupplyingResponse(status, eventResult, &result, httpStatus, pr) | ||
| } | ||
|
|
||
| func (a *PatronRequestActionService) checkSupplyingResponse(status events.EventStatus, eventResult *events.EventResult, result *events.EventResult, httpStatus *int, pr pr_db.PatronRequest) actionExecutionResult { | ||
| if httpStatus == nil { | ||
| return actionExecutionResult{status: status, result: eventResult, pr: pr} | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.