Skip to content

Commit d79b7d3

Browse files
authored
Merge pull request #509 from NHSDigital/release/2025-02-21
Release/2025 02 21
2 parents 3415da6 + a3a6a68 commit d79b7d3

File tree

28 files changed

+1378
-48
lines changed

28 files changed

+1378
-48
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Changelog
22

3+
## 2025-02-21
4+
- [PI-754] Search Product
5+
- Dependabot: datamodel-code-generator
6+
37
## 2025-02-20
48
- [PI-790] Remove EPR from swagger
59

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
2025.02.20
1+
2025.02.21

changelog/2025-02-21.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
- [PI-754] Search Product
2+
- Dependabot: datamodel-code-generator

infrastructure/swagger/05_paths.yaml

Lines changed: 69 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ x-definitions:
1414
tags:
1515
- name: Core Product ID Endpoints
1616
description: Create, Read and Delete Product IDs
17-
17+
- name: Options
18+
description: These exist for CORS
1819
paths:
1920
/_status:
2021
get:
@@ -44,6 +45,8 @@ paths:
4445
options:
4546
operationId: createproductteamcors
4647
summary: Create a Product Team resource (OPTIONS)
48+
tags:
49+
- Options
4750
responses:
4851
"400":
4952
$ref: "#/components/responses/BadRequest"
@@ -161,6 +164,8 @@ paths:
161164
options:
162165
operationId: createproductcors
163166
summary: Create a Product resource (OPTIONS)
167+
tags:
168+
- Options
164169
parameters:
165170
- $ref: "#/components/parameters/ProductTeamId"
166171
responses:
@@ -228,25 +233,69 @@ paths:
228233
security:
229234
- ${authoriser_name}: []
230235
- app-level0: []
231-
# get:
232-
# operationId: searchCpmProduct
233-
# summary: Retrieve all Products associated with a Product Team (GET)
234-
# parameters:
235-
# - $ref: "#/components/parameters/ProductTeamId"
236-
# - $ref: "#/components/parameters/HeaderVersion"
237-
# - $ref: "#/components/parameters/HeaderRequestId"
238-
# - $ref: "#/components/parameters/HeaderCorrelationId"
239-
# responses:
240-
# "200":
241-
# $ref: "#/components/responses/ProductSearch"
242-
# "404":
243-
# $ref: "#/components/responses/NotFound"
244-
# x-amazon-apigateway-integration:
245-
# <<: *ApiGatewayIntegration
246-
# uri: ${method_searchCpmProduct}
247-
# security:
248-
# - ${authoriser_name}: []
249-
# - app-level0: []
236+
237+
/Product:
238+
options:
239+
operationId: searchproductcors
240+
summary: Search Products (OPTIONS)
241+
tags:
242+
- Options
243+
responses:
244+
"400":
245+
$ref: "#/components/responses/BadRequest"
246+
"200":
247+
description: "200 response"
248+
headers:
249+
Access-Control-Allow-Origin:
250+
schema:
251+
type: "string"
252+
Access-Control-Allow-Methods:
253+
schema:
254+
type: "string"
255+
Access-Control-Allow-Headers:
256+
schema:
257+
type: "string"
258+
content:
259+
application/json:
260+
schema:
261+
$ref: "#/components/schemas/Empty"
262+
x-amazon-apigateway-integration:
263+
responses:
264+
default:
265+
statusCode: "200"
266+
responseParameters:
267+
method.response.header.Access-Control-Allow-Methods: "'GET,OPTIONS'"
268+
method.response.header.Access-Control-Allow-Headers: "'apikey,authorization,content-type,version'"
269+
method.response.header.Access-Control-Allow-Origin: "'*'"
270+
requestTemplates:
271+
application/json: '{"statusCode": 200}'
272+
passthroughBehavior: "never"
273+
type: "mock"
274+
security:
275+
- ${authoriser_name}: []
276+
- app-level0: []
277+
get:
278+
operationId: searchProduct
279+
summary: Retrieve all Products associated with a Product Team or Organisation (GET)
280+
tags:
281+
- Core Product ID Endpoints
282+
parameters:
283+
- $ref: "#/components/parameters/ProductTeamIdQuery"
284+
- $ref: "#/components/parameters/OrganisationCodeQuery"
285+
- $ref: "#/components/parameters/HeaderVersion"
286+
- $ref: "#/components/parameters/HeaderRequestId"
287+
- $ref: "#/components/parameters/HeaderCorrelationId"
288+
responses:
289+
"200":
290+
$ref: "#/components/responses/ProductSearch"
291+
"400":
292+
$ref: "#/components/responses/SearchProductBadRequest"
293+
x-amazon-apigateway-integration:
294+
<<: *ApiGatewayIntegration
295+
uri: ${method_searchProduct}
296+
security:
297+
- ${authoriser_name}: []
298+
- app-level0: []
250299

251300
/ProductTeam/{product_team_id}/Product/{product_id}:
252301
get:

infrastructure/swagger/07_components--schemas--domain.yaml

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,3 +124,78 @@ components:
124124
example:
125125
code: "RESOURCE_DELETED"
126126
message: "P.XYZ-123 has been deleted."
127+
ProductSearchResponse:
128+
type: object
129+
properties:
130+
results:
131+
type: array
132+
items:
133+
type: object
134+
properties:
135+
org_code:
136+
type: string
137+
product_teams:
138+
type: array
139+
items:
140+
type: object
141+
properties:
142+
product_team_id:
143+
type: string
144+
products:
145+
type: array
146+
items:
147+
type: object
148+
properties:
149+
id:
150+
type: string
151+
name:
152+
type: string
153+
product_team_id:
154+
type: string
155+
ods_code:
156+
type: string
157+
status:
158+
type: string
159+
keys:
160+
type: array
161+
items:
162+
type: object
163+
properties:
164+
key_type:
165+
type: string
166+
key_value:
167+
type: string
168+
created_on:
169+
type: string
170+
updated_on:
171+
type: string
172+
nullable: true
173+
deleted_on:
174+
type: string
175+
nullable: true
176+
example:
177+
results:
178+
- org_code: "xyzzy"
179+
product_teams:
180+
- product_team_id: "1234"
181+
products:
182+
- id: "P.123"
183+
product_team_id: "1234"
184+
name: "My Great Product 1"
185+
ods_code: "F5H1R"
186+
status: "active"
187+
created_on: "2024-10-15T10:00:00Z"
188+
updated_on: "null"
189+
deleted_on: "null"
190+
keys: []
191+
- product_team_id: "5678"
192+
products:
193+
- id: "P.xyz"
194+
product_team_id: "5678"
195+
name: "My Great Product 3"
196+
ods_code: "F5H1R"
197+
status: "active"
198+
created_on: "2024-10-15T10:00:00Z"
199+
updated_on: "null"
200+
deleted_on: "null"
201+
keys: []

infrastructure/swagger/12_components--responses.yaml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,25 @@ components:
6969
message: "Duplicate 'Interaction ID' provided: value '<INTERACTION ID>' occurs <N> times in the questionnaire response."
7070
- code: "VALIDATION_ERROR"
7171
message: "SubCpmProductPathParams.environment: value is not a valid enumeration member; permitted: 'dev', 'qa', 'ref', 'int', 'prod'"
72+
SearchProductBadRequest:
73+
description: searchProduct Bad request
74+
content:
75+
application/json:
76+
schema:
77+
$ref: "#/components/schemas/ErrorResponse"
78+
examples:
79+
ValidationError:
80+
value:
81+
errors:
82+
- code: "VALIDATION_ERROR"
83+
message: "SearchProductQueryParams.__root__: Please provide exactly one valid query parameter: {'product_team_id', 'organisation_code'}."
84+
- code: "VALIDATION_ERROR"
85+
message: "SearchSDSDeviceQueryParams.foo: extra fields not permitted"
86+
headers:
87+
Access-Control-Allow-Origin:
88+
schema:
89+
type: string
90+
example: "*"
7291
UnprocessableContent:
7392
description: Unprocessable Content
7493
content:
@@ -125,3 +144,9 @@ components:
125144
application/json:
126145
schema:
127146
$ref: "#/components/schemas/CPMProductDeleteResponse"
147+
ProductSearch:
148+
description: Search Product operation successful
149+
content:
150+
application/json:
151+
schema:
152+
$ref: "#/components/schemas/ProductSearchResponse"
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,17 @@
11
---
2+
components:
3+
parameters:
4+
ProductTeamIdQuery:
5+
name: product_team_id
6+
in: query
7+
required: false
8+
description: The ID of the product team to filter results by.
9+
schema:
10+
type: string
11+
OrganisationCodeQuery:
12+
name: organisation_code
13+
in: query
14+
required: false
15+
description: The organisation code to filter results by.
16+
schema:
17+
type: string

infrastructure/terraform/per_workspace/main.tf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ module "lambdas" {
129129
}
130130
}
131131
environment_variables = {
132-
DYNAMODB_TABLE = contains(["createProductTeam", "readProductTeam", "deleteProductTeam", "createCpmProduct", "readCpmProduct", "searchCpmProduct", "deleteCpmProduct"], each.key) ? module.cpmtable.dynamodb_table_name : module.eprtable.dynamodb_table_name
132+
DYNAMODB_TABLE = contains(["createProductTeam", "readProductTeam", "deleteProductTeam", "createCpmProduct", "readCpmProduct", "searchProduct", "deleteCpmProduct"], each.key) ? module.cpmtable.dynamodb_table_name : module.eprtable.dynamodb_table_name
133133
}
134134
attach_policy_statements = length((fileset("${path.module}/../../../src/api/${each.key}/policies", "*.json"))) > 0
135135
policy_statements = {

pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "connecting-party-manager"
3-
version = "2025.02.20"
3+
version = "2025.02.21"
44
description = "Repository for the Connecting Party Manager API and related services"
55
authors = ["NHS England"]
66
license = "LICENSE.md"
@@ -41,7 +41,7 @@ hypothesis = "^6.87.3"
4141
aws-lambda-powertools = { extras = ["aws-sdk"], version = "^2.26.0" }
4242
parse = "^1.19.1"
4343
pytest-mock = "^3.12.0"
44-
datamodel-code-generator = "^0.26.0"
44+
datamodel-code-generator = "^0.28.1"
4545
pyyaml = "^6.0.1"
4646
proxygen-cli = "^2.1.14"
4747
moto = "^5.0.1"

src/api/deleteProductTeam/src/v1/steps.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from http import HTTPStatus
22

33
from aws_lambda_powertools.utilities.data_classes import APIGatewayProxyEvent
4+
from domain.core.enum import Status
45
from domain.core.error import ConflictError
56
from domain.core.product_team import ProductTeam
67
from domain.repository.cpm_product_repository import CpmProductRepository
@@ -29,7 +30,9 @@ def read_products(data, cache):
2930
product_repo = CpmProductRepository(
3031
table_name=cache["DYNAMODB_TABLE"], dynamodb_client=cache["DYNAMODB_CLIENT"]
3132
)
32-
cpm_products = product_repo.search(product_team_id=product_team.id)
33+
cpm_products = product_repo.search_by_product_team(
34+
product_team_id=product_team.id, status=Status.ACTIVE
35+
)
3336

3437
if cpm_products:
3538
product_ids = [str(product.id) for product in cpm_products]

0 commit comments

Comments
 (0)