Skip to content

Commit cc7bec8

Browse files
CROSSLINK-211 Add notification endpoint and populate notifications
1 parent 5938306 commit cc7bec8

7 files changed

Lines changed: 596 additions & 2 deletions

File tree

broker/oapi/open-api.yaml

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -738,6 +738,54 @@ components:
738738
- barcode
739739
- createdAt
740740

741+
PrNotification:
742+
type: object
743+
title: Notification
744+
description: Patron request notification
745+
properties:
746+
id:
747+
type: string
748+
description: Notification id
749+
fromSymbol:
750+
type: string
751+
description: Symbol of notification sender
752+
toSymbol:
753+
type: string
754+
description: Symbol of notification receiver
755+
side:
756+
type: string
757+
description: Patron request side
758+
note:
759+
type: string
760+
description: Note of notification
761+
cost:
762+
type: number
763+
format: double
764+
description: Cost amount
765+
currency:
766+
type: string
767+
description: Currency symbol
768+
condition:
769+
type: string
770+
description: Condition of notification
771+
receipt:
772+
type: string
773+
description: Receipt of notification
774+
createdAt:
775+
type: string
776+
format: date-time
777+
description: Notification creation date time
778+
acknowledgedAt:
779+
type: string
780+
format: date-time
781+
description: Notification acknowledged at date time
782+
required:
783+
- id
784+
- fromSymbol
785+
- toSymbol
786+
- side
787+
- createdAt
788+
741789
paths:
742790
/:
743791
get:
@@ -1348,6 +1396,43 @@ paths:
13481396
schema:
13491397
$ref: '#/components/schemas/Error'
13501398

1399+
/patron_requests/{id}/notifications:
1400+
get:
1401+
summary: Retrieve patron request related notifications
1402+
parameters:
1403+
- in: path
1404+
name: id
1405+
schema:
1406+
type: string
1407+
required: true
1408+
description: ID of the patron request
1409+
- $ref: '#/components/parameters/Tenant'
1410+
- $ref: '#/components/parameters/Side'
1411+
- $ref: '#/components/parameters/Symbol'
1412+
tags:
1413+
- patron-requests-api
1414+
responses:
1415+
'200':
1416+
description: Successful retrieval of patron request notifications
1417+
content:
1418+
application/json:
1419+
schema:
1420+
type: array
1421+
items:
1422+
$ref: '#/components/schemas/PrNotification'
1423+
'400':
1424+
description: Bad Request. Invalid query parameters.
1425+
content:
1426+
application/json:
1427+
schema:
1428+
$ref: '#/components/schemas/Error'
1429+
'500':
1430+
description: Internal Server Error
1431+
content:
1432+
application/json:
1433+
schema:
1434+
$ref: '#/components/schemas/Error'
1435+
13511436
/sse/events:
13521437
get:
13531438
summary: Subscribe to real-time notifications. Notification is send out every time when ISO18626 message is sent out

broker/patron_request/api/api-handler.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,36 @@ func (a *PatronRequestApiHandler) GetPatronRequestsIdItems(w http.ResponseWriter
462462
writeJsonResponse(w, responseItems)
463463
}
464464

465+
func (a *PatronRequestApiHandler) GetPatronRequestsIdNotifications(w http.ResponseWriter, r *http.Request, id string, params proapi.GetPatronRequestsIdNotificationsParams) {
466+
symbol, err := api.GetSymbolForRequest(r, a.tenant, params.XOkapiTenant, params.Symbol)
467+
logParams := map[string]string{"method": "GetPatronRequestsIdNotifications", "id": id, "symbol": symbol}
468+
469+
if params.Side != nil {
470+
logParams["side"] = *params.Side
471+
}
472+
ctx := common.CreateExtCtxWithArgs(context.Background(), &common.LoggerArgs{Other: logParams})
473+
474+
if err != nil {
475+
addBadRequestError(ctx, w, err)
476+
return
477+
}
478+
pr := a.getPatronRequestById(w, ctx, id, params.Side, symbol)
479+
if pr == nil {
480+
return
481+
}
482+
list, err := a.prRepo.GetNotificationsByPrId(ctx, pr.ID)
483+
if err != nil {
484+
addInternalError(ctx, w, err)
485+
return
486+
}
487+
488+
var responseList []proapi.PrNotification
489+
for _, n := range list {
490+
responseList = append(responseList, toApiNotification(n))
491+
}
492+
writeJsonResponse(w, responseList)
493+
}
494+
465495
func writeJsonResponse(w http.ResponseWriter, resp any) {
466496
w.Header().Set("Content-Type", "application/json")
467497
w.WriteHeader(http.StatusOK)
@@ -588,3 +618,28 @@ func toApiItem(item pr_db.Item) proapi.PrItem {
588618
CreatedAt: item.CreatedAt.Time,
589619
}
590620
}
621+
622+
func toApiNotification(notification pr_db.Notification) proapi.PrNotification {
623+
var ackAt *time.Time
624+
if notification.AcknowledgedAt.Valid {
625+
t := notification.AcknowledgedAt.Time
626+
ackAt = &t
627+
}
628+
var cost *float64
629+
if notification.Cost.Valid {
630+
f, _ := notification.Cost.Float64Value()
631+
val := f.Float64
632+
cost = &val
633+
}
634+
return proapi.PrNotification{
635+
Id: notification.ID,
636+
FromSymbol: notification.FromSymbol,
637+
ToSymbol: notification.ToSymbol,
638+
Side: string(notification.Side),
639+
Note: toString(notification.Note),
640+
Cost: cost,
641+
Currency: toString(notification.Currency),
642+
CreatedAt: notification.CreatedAt.Time,
643+
AcknowledgedAt: ackAt,
644+
}
645+
}

broker/patron_request/api/api-handler_test.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,42 @@ func TestGetPatronRequestsIdEventsErrorGettingEvents(t *testing.T) {
305305
assert.Contains(t, rr.Body.String(), "DB error")
306306
}
307307

308+
func TestGetPatronRequestsIdNotificationsNoSymbol(t *testing.T) {
309+
handler := NewPrApiHandler(new(PrRepoError), mockEventBus, mockEventRepo, common.NewTenant(""), 10)
310+
req, _ := http.NewRequest("GET", "/", nil)
311+
rr := httptest.NewRecorder()
312+
handler.GetPatronRequestsIdNotifications(rr, req, "3", proapi.GetPatronRequestsIdNotificationsParams{Side: &proapiBorrowingSide})
313+
assert.Equal(t, http.StatusBadRequest, rr.Code)
314+
assert.Contains(t, rr.Body.String(), "symbol must be specified")
315+
}
316+
317+
func TestGetPatronRequestsIdNotificationsDbError(t *testing.T) {
318+
handler := NewPrApiHandler(new(PrRepoError), mockEventBus, mockEventRepo, common.NewTenant(""), 10)
319+
req, _ := http.NewRequest("GET", "/", nil)
320+
rr := httptest.NewRecorder()
321+
handler.GetPatronRequestsIdNotifications(rr, req, "1", proapi.GetPatronRequestsIdNotificationsParams{Symbol: &symbol, Side: &proapiBorrowingSide})
322+
assert.Equal(t, http.StatusInternalServerError, rr.Code)
323+
assert.Contains(t, rr.Body.String(), "DB error")
324+
}
325+
326+
func TestGetPatronRequestsIdNotificationsNotFoundBecauseOfSide(t *testing.T) {
327+
handler := NewPrApiHandler(new(PrRepoError), mockEventBus, mockEventRepo, common.NewTenant(""), 10)
328+
req, _ := http.NewRequest("GET", "/", nil)
329+
rr := httptest.NewRecorder()
330+
handler.GetPatronRequestsIdNotifications(rr, req, "3", proapi.GetPatronRequestsIdNotificationsParams{Symbol: &symbol, Side: &proapiLendingSide})
331+
assert.Equal(t, http.StatusNotFound, rr.Code)
332+
assert.Contains(t, rr.Body.String(), "not found")
333+
}
334+
335+
func TestGetPatronRequestsIdNotificationsErrorGettingEvents(t *testing.T) {
336+
handler := NewPrApiHandler(new(PrRepoError), mockEventBus, new(mocks.MockEventRepositoryError), common.NewTenant(""), 10)
337+
req, _ := http.NewRequest("GET", "/", nil)
338+
rr := httptest.NewRecorder()
339+
handler.GetPatronRequestsIdNotifications(rr, req, "3", proapi.GetPatronRequestsIdNotificationsParams{Symbol: &symbol, Side: &proapiBorrowingSide})
340+
assert.Equal(t, http.StatusInternalServerError, rr.Code)
341+
assert.Contains(t, rr.Body.String(), "DB error")
342+
}
343+
308344
func TestToDbPatronRequest(t *testing.T) {
309345
handler := NewPrApiHandler(new(PrRepoError), mockEventBus, mockEventRepo, common.NewTenant(""), 10)
310346
ctx := common.CreateExtCtxWithArgs(context.Background(), &common.LoggerArgs{})
@@ -366,6 +402,10 @@ func (r *PrRepoError) GetNextHrid(ctx common.ExtendedContext, prefix string) (st
366402
return strings.ToUpper(prefix) + "-" + strconv.FormatInt(r.counter, 10), nil
367403
}
368404

405+
func (r *PrRepoError) GetNotificationsByPrId(ctx common.ExtendedContext, prId string) ([]pr_db.Notification, error) {
406+
return []pr_db.Notification{}, errors.New("DB error")
407+
}
408+
369409
type MockEventBus struct {
370410
mock.Mock
371411
events.EventBus

broker/patron_request/service/action_test.go

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -705,8 +705,9 @@ func (m *MockEventBus) CreateNotice(id string, eventName events.EventName, data
705705
type MockPrRepo struct {
706706
mock.Mock
707707
pr_db.PgPrRepo
708-
savedPr pr_db.PatronRequest
709-
savedItems []pr_db.Item
708+
savedPr pr_db.PatronRequest
709+
savedItems []pr_db.Item
710+
savedNotifications []pr_db.Notification
710711
}
711712

712713
func (r *MockPrRepo) GetPatronRequestById(ctx common.ExtendedContext, id string) (pr_db.PatronRequest, error) {
@@ -743,6 +744,17 @@ func (r *MockPrRepo) SaveItem(ctx common.ExtendedContext, params pr_db.SaveItemP
743744
return pr_db.Item(params), nil
744745
}
745746

747+
func (r *MockPrRepo) SaveNotification(ctx common.ExtendedContext, params pr_db.SaveNotificationParams) (pr_db.Notification, error) {
748+
if r.savedNotifications == nil {
749+
r.savedNotifications = []pr_db.Notification{}
750+
}
751+
r.savedNotifications = append(r.savedNotifications, pr_db.Notification(params))
752+
if params.PrID == "error" {
753+
return pr_db.Notification{}, errors.New("db error")
754+
}
755+
return pr_db.Notification(params), nil
756+
}
757+
746758
type MockIso18626Handler struct {
747759
mock.Mock
748760
handler.Iso18626Handler

0 commit comments

Comments
 (0)