Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
1b4ca6c
Add PutPatronRequestsId
adamdickmeiss Jul 14, 2026
5f762bb
Add tests
adamdickmeiss Jul 14, 2026
6ae7f0f
editable state property
adamdickmeiss Jul 14, 2026
6b7d2e6
Merge branch 'main' into ILLDEV-430-put-patron-request
adamdickmeiss Jul 14, 2026
693f2c0
CP
adamdickmeiss Jul 15, 2026
104fd48
Potential fix for pull request finding
adamdickmeiss Jul 15, 2026
189d17b
Potential fix for pull request finding
adamdickmeiss Jul 15, 2026
13bfb1f
Potential fix for pull request finding
adamdickmeiss Jul 15, 2026
a247782
Update tests
adamdickmeiss Jul 15, 2026
72bea0b
Check ownership before checking if already sent
adamdickmeiss Jul 15, 2026
6b41295
Potential fix for pull request finding
adamdickmeiss Jul 15, 2026
b2bc141
Potential fix for pull request finding
adamdickmeiss Jul 15, 2026
5c88f89
Potential fix for pull request finding
adamdickmeiss Jul 15, 2026
85b6eb3
Guard check ill repo == nil
adamdickmeiss Jul 15, 2026
0c4b748
Merge remote-tracking branch 'origin/ILLDEV-430-put-patron-request' i…
adamdickmeiss Jul 15, 2026
7873f95
Revert "Potential fix for pull request finding"
adamdickmeiss Jul 15, 2026
f81a3d1
CP
adamdickmeiss Jul 15, 2026
37bccd1
internal server error
adamdickmeiss Jul 15, 2026
6cab3b9
Potential fix for pull request finding
adamdickmeiss Jul 15, 2026
243d793
No need for TrimSpace
adamdickmeiss Jul 15, 2026
307b510
Check for specified symbol
adamdickmeiss Jul 15, 2026
33a120f
Tests, guards before ill trans check
adamdickmeiss Jul 15, 2026
1628ed6
Potential fix for pull request finding
adamdickmeiss Jul 15, 2026
58ebca9
Fix open api yaml
adamdickmeiss Jul 15, 2026
6c2e4d3
Use editable flag to check if PUT patron request is allowed
adamdickmeiss Jul 15, 2026
529c544
Potential fix for pull request finding
adamdickmeiss Jul 15, 2026
6d964ab
Add e2e test for update and NEEDS_REVIEW state
adamdickmeiss Jul 16, 2026
70465a0
Potential fix for pull request finding
adamdickmeiss Jul 16, 2026
385ff6c
Preserve original note if no new given
adamdickmeiss Jul 16, 2026
c891861
Preserve patron if not given
adamdickmeiss Jul 16, 2026
1823c79
Merge remote-tracking branch 'origin/main' into ILLDEV-430-put-patron…
adamdickmeiss Jul 19, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions broker/oapi/open-api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -847,6 +847,9 @@ components:
type: string
description: Name of the primary action for this state.
Must be one of the actions defined in the actions array and is only meaningful when actions is present.
editable:
type: boolean
description: Indicates that a patron request can be updated in this state
actions:
type: array
description: List of all actions that may be performed on the request when in this state
Expand Down Expand Up @@ -1842,6 +1845,51 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/Error'
put:
summary: Update a borrower-side patron request
description: >
Updates are only permitted while the request is still editable per the state model (and before it has been sent).
tags:
- patron-requests-api
parameters:
- in: path
name: id
schema:
type: string
required: true
description: ID of the patron request to update
- $ref: '#/components/parameters/Tenant'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreatePatronRequest'
responses:
'200':
description: Patron request updated successfully
content:
application/json:
schema:
$ref: '#/components/schemas/PatronRequest'
'400':
description: Bad Request.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'404':
description: Patron request not found
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
'500':
description: Internal Server Error
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
delete:
summary: Delete a patron request
tags:
Expand Down
124 changes: 124 additions & 0 deletions broker/patron_request/api/api-handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -505,6 +505,130 @@ func isSideParamValid(side *string) bool {
return side != nil && (*side == string(prservice.SideBorrowing) || *side == string(prservice.SideLending))
}

func (a *PatronRequestApiHandler) checkEditable(w http.ResponseWriter, ctx common.ExtendedContext, pr pr_db.PatronRequest) bool {
stateModel, err := a.actionMappingService.GetStateModelForRequest(pr.IllRequest)
if err != nil {
api.AddInternalError(ctx, w, err)
return true
}
editable := false
if stateModel != nil && stateModel.States != nil {
for _, st := range stateModel.States {
if st.Side == proapi.REQUESTER && st.Name == string(pr.State) {
editable = st.Editable != nil && *st.Editable
break
}
}
}
if !editable {
api.AddBadRequestError(ctx, w, fmt.Errorf("patron request is not editable in state %q", pr.State))
return true
}
return false
}

func (a *PatronRequestApiHandler) PutPatronRequestsId(w http.ResponseWriter, r *http.Request, id string, params proapi.PutPatronRequestsIdParams) {
logParams := map[string]string{"method": "PutPatronRequestsId", "id": id}
ctx := common.CreateExtCtxWithArgs(r.Context(), &common.LoggerArgs{Other: logParams})

var newPr proapi.CreatePatronRequest
err := decodeRequiredBody(r, &newPr)
if err != nil {
api.AddBadRequestError(ctx, w, err)
return
}
tenant, err := a.tenantResolver.Resolve(ctx, r, newPr.RequesterSymbol)
if err != nil {
api.AddBadRequestError(ctx, w, err)
return
}
symbol, err := tenant.GetRequestSymbol()
if err != nil {
api.AddBadRequestError(ctx, w, err)
return
}
if symbol == "" {
api.AddBadRequestError(ctx, w, errors.New("symbol must be specified"))
return
}
logParams["symbol"] = symbol
ctx = common.CreateExtCtxWithArgs(r.Context(), &common.LoggerArgs{Other: logParams})
Comment thread
Copilot marked this conversation as resolved.

if newPr.Id == nil {
newPr.Id = &id
} else if *newPr.Id != id {
api.AddBadRequestError(ctx, w, fmt.Errorf("patron request id does not match"))
return
}
Comment thread
adamdickmeiss marked this conversation as resolved.
existingPr, err := a.prRepo.GetPatronRequestById(ctx, id)
if err != nil {
handleDbError(w, ctx, err)
return
}
if !a.checkOwnership(w, ctx, existingPr.Side, existingPr.RequesterSymbol, existingPr.SupplierSymbol, nil, tenant) {
return
}
Comment thread
adamdickmeiss marked this conversation as resolved.
if existingPr.Side != prservice.SideBorrowing {
api.AddBadRequestError(ctx, w, fmt.Errorf("only borrower-side patron requests can be updated"))
return
}
Comment thread
adamdickmeiss marked this conversation as resolved.
Comment thread
adamdickmeiss marked this conversation as resolved.
Comment thread
adamdickmeiss marked this conversation as resolved.
Comment thread
adamdickmeiss marked this conversation as resolved.
Comment thread
adamdickmeiss marked this conversation as resolved.
Comment thread
adamdickmeiss marked this conversation as resolved.
if !existingPr.RequesterSymbol.Valid || existingPr.RequesterSymbol.String == "" {
api.AddInternalError(ctx, w, fmt.Errorf("existing patron request missing requesterSymbol"))
return
}
if newPr.RequesterSymbol != nil && *newPr.RequesterSymbol != "" && *newPr.RequesterSymbol != existingPr.RequesterSymbol.String {
api.AddBadRequestError(ctx, w, fmt.Errorf("requesterSymbol does not match existing patron request"))
return
}
if a.checkEditable(w, ctx, existingPr) {
return
}
symbol = existingPr.RequesterSymbol.String
logParams["symbol"] = symbol
ctx = common.CreateExtCtxWithArgs(r.Context(), &common.LoggerArgs{Other: logParams})
newPr.RequesterSymbol = &symbol
Comment thread
Copilot marked this conversation as resolved.
creationTime := time.Now()
if existingPr.CreatedAt.Valid {
creationTime = existingPr.CreatedAt.Time
}
Comment thread
Copilot marked this conversation as resolved.
if newPr.Patron == nil && existingPr.Patron.Valid {
patron := existingPr.Patron.String
newPr.Patron = &patron
}
illRequest, requesterReqId, err := a.parseAndValidateIllRequest(ctx, &newPr, creationTime)
if err != nil {
if errors.Is(err, errInvalidPatronRequest) {
api.AddBadRequestError(ctx, w, err)
return
}
api.AddInternalError(ctx, w, err)
return
}

existingPr.RequesterReqID = getDbText(&requesterReqId)
existingPr.IllRequest = illRequest
existingPr.Patron = getDbText(newPr.Patron)
if newPr.InternalNote != nil {
var note pgtype.Text
if trimmed := strings.TrimSpace(*newPr.InternalNote); trimmed != "" {
note = pgtype.Text{Valid: true, String: trimmed}
}
existingPr.InternalNote = note
}
updatedPr, err := a.prRepo.UpdatePatronRequest(ctx, pr_db.UpdatePatronRequestParams(existingPr))
if err != nil {
api.AddInternalError(ctx, w, err)
return
}
Comment thread
adamdickmeiss marked this conversation as resolved.
prView, err := a.prRepo.GetPatronRequestSearchView(ctx, updatedPr.ID)
if err != nil {
api.AddInternalError(ctx, w, err)
return
}
w.Header().Set("Content-Type", "application/json")
_ = json.NewEncoder(w).Encode(toApiPatronRequest(r, prView))
}

func (a *PatronRequestApiHandler) GetPatronRequestsId(w http.ResponseWriter, r *http.Request, id string, params proapi.GetPatronRequestsIdParams) {
logParams := map[string]string{"method": "GetPatronRequestsId", "id": id}
if params.Side != nil {
Expand Down
Loading
Loading