Skip to content

Commit 95dcaef

Browse files
committed
feat: Add endpoint for serial logs
1 parent 52ee475 commit 95dcaef

3 files changed

Lines changed: 138 additions & 1 deletion

File tree

requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ canonicalwebteam.discourse==7.1.1
66
canonicalwebteam.blog==6.8.4
77
canonicalwebteam.search==2.1.2
88
canonicalwebteam.image-template==1.9.0
9-
canonicalwebteam.store-api==7.3.10
9+
canonicalwebteam.store-api==7.4.10
1010
canonicalwebteam.launchpad==0.9.0
1111
django-openid-auth==0.17
1212
Flask-OpenID==1.3.1

tests/endpoints/tests_models.py

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,3 +342,109 @@ def test_create_remodel_allowlist_general_error(
342342
self.assertEqual(response.status_code, 500)
343343
self.assertFalse(data["success"])
344344
self.assertEqual(data["message"], "An error occurred")
345+
346+
347+
class TestGetSerialLog(TestModelServiceEndpoints):
348+
@patch(
349+
"canonicalwebteam.store_api.publishergw.PublisherGW"
350+
+ ".get_store_model_serial_log"
351+
)
352+
@patch("canonicalwebteam.store_api.dashboard.Dashboard.get_store")
353+
def test_get_serial_log_success(self, mock_get_store, mock_get_serial_log):
354+
mock_serial_log = [
355+
{
356+
"brand-id": "test-brand-id",
357+
"created-at": "2026-03-23T04:00:23.875000",
358+
"model-name": "test-model",
359+
"serial": "test-serial",
360+
}
361+
]
362+
mock_get_serial_log.return_value = {"items": mock_serial_log}
363+
mock_get_store.return_value = {"brand-id": "test-brand-id"}
364+
365+
response = self.client.get("/api/store/1/models/test-model/serial-log")
366+
data = response.json
367+
368+
self.assertEqual(response.status_code, 200)
369+
self.assertTrue(data["success"])
370+
self.assertEqual(data["data"], mock_serial_log)
371+
372+
@patch(
373+
"canonicalwebteam.store_api.publishergw.PublisherGW"
374+
+ ".get_store_model_serial_log"
375+
)
376+
@patch("canonicalwebteam.store_api.dashboard.Dashboard.get_store")
377+
def test_get_serial_log_empty(self, mock_get_store, mock_get_serial_log):
378+
mock_get_serial_log.return_value = {"items": []}
379+
mock_get_store.return_value = {"brand-id": "test-brand-id"}
380+
381+
response = self.client.get("/api/store/1/models/test-model/serial-log")
382+
data = response.json
383+
384+
self.assertEqual(response.status_code, 200)
385+
self.assertTrue(data["success"])
386+
self.assertEqual(data["data"], [])
387+
388+
@patch(
389+
"canonicalwebteam.store_api.publishergw.PublisherGW"
390+
+ ".get_store_model_serial_log"
391+
)
392+
@patch("canonicalwebteam.store_api.dashboard.Dashboard.get_store")
393+
def test_get_serial_log_unauthorized(
394+
self, mock_get_store, mock_get_serial_log
395+
):
396+
mock_get_serial_log.side_effect = StoreApiResponseErrorList(
397+
"unauthorized", 401, [{"message": "unauthorized"}]
398+
)
399+
mock_get_store.return_value = {"brand-id": "test-brand-id"}
400+
401+
response = self.client.get("/api/store/1/models/test-model/serial-log")
402+
data = response.json
403+
404+
self.assertEqual(response.status_code, 500)
405+
self.assertFalse(data["success"])
406+
self.assertEqual(data["message"], "Store not found")
407+
408+
@patch(
409+
"canonicalwebteam.store_api.publishergw.PublisherGW"
410+
+ ".get_store_model_serial_log"
411+
)
412+
@patch("canonicalwebteam.store_api.dashboard.Dashboard.get_store")
413+
def test_get_serial_log_store_not_found(
414+
self, mock_get_store, mock_get_serial_log
415+
):
416+
mock_get_serial_log.side_effect = StoreApiResponseErrorList(
417+
"Store not found", 404, [{"message": "Store not found"}]
418+
)
419+
mock_get_store.return_value = {"brand-id": "test-brand-id"}
420+
421+
response = self.client.get(
422+
"/api/store/999/models/test-model/serial-log"
423+
)
424+
data = response.json
425+
426+
self.assertEqual(response.status_code, 500)
427+
self.assertFalse(data["success"])
428+
self.assertEqual(data["message"], "Store not found")
429+
430+
@patch(
431+
"canonicalwebteam.store_api.publishergw.PublisherGW"
432+
+ ".get_store_model_serial_log"
433+
)
434+
@patch("canonicalwebteam.store_api.dashboard.Dashboard.get_store")
435+
def test_get_serial_log_general_error(
436+
self, mock_get_store, mock_get_serial_log
437+
):
438+
mock_get_serial_log.side_effect = StoreApiResponseErrorList(
439+
"Internal server error",
440+
500,
441+
[{"message": "Internal server error"}],
442+
)
443+
mock_get_store.return_value = {"brand-id": "test-brand-id"}
444+
445+
response = self.client.get("/api/store/1/models/test-model/serial-log")
446+
data = response.json
447+
448+
self.assertEqual(response.status_code, 500)
449+
self.assertFalse(data["success"])
450+
self.assertEqual(data["message"], "Internal server error")

webapp/endpoints/models.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,3 +347,34 @@ def create_remodel_allowlist(store_id: str):
347347
res["message"] = "An error occurred"
348348

349349
return make_response(res, 500)
350+
351+
352+
@models.route("/api/store/<store_id>/models/<model_name>/serial-log")
353+
@login_required
354+
@exchange_required
355+
def get_serial_log(store_id: str, model_name: str):
356+
res = {}
357+
358+
try:
359+
brand_id = get_brand_id(flask.session, store_id)
360+
logs = publisher_gateway.get_store_model_serial_log(
361+
flask.session,
362+
brand_id,
363+
model_name,
364+
)
365+
res["data"] = logs["items"]
366+
res["success"] = True
367+
response = make_response(res, 200)
368+
except StoreApiResponseErrorList as error_list:
369+
error_messages = [
370+
f"{error.get('message', 'An error occurred')}"
371+
for error in error_list.errors
372+
]
373+
if "unauthorized" in error_messages:
374+
res["message"] = "Store not found"
375+
else:
376+
res["message"] = " ".join(error_messages)
377+
res["success"] = False
378+
response = make_response(res, 500)
379+
380+
return response

0 commit comments

Comments
 (0)