- ID
- 4cd39eca-3a3f-4dba-9d92-5c23aebc3db4
BE-7470 Create service layer for upsert in cookbooks app
- source :: https://hungryroot.atlassian.net/browse/BE-7470
- tags :: Hungryroot API Project
- epic :: EP-627 Exp 232: Cookbook MVP
- sprint :: HR BE Sprint 107
- status :: Status - To Do
- priority :: Priority - High
- points :: 1
Description
Following our service-first architecture, we need to implement the business
logic layer for Cookbooks. This task involves creating the CookbookService class
to handle complex upsert (create or update) operations based on the slug field.
This service must manage transactional integrity when handling nested data,
including Cookbook Authors, Dietary Tags, and Cookbook Items. Logic should be
abstracted away from the API views to ensure reusability and data consistency.
Acceptance Criteria
Service Structure: CookbookService class is created at
cookbooks/services/cookbook_service.py.
Upsert Logic: The upsert_cookbook method correctly creates a new cookbook or
updates an existing one based on the slug.
Transactional Integrity: All database operations within the upsert process are
wrapped in transaction.atomic() to ensure rollback on failure.
Related Entities:
Author: Correctly links an existing CookbookAuthor based on slug (no creation of
authors in this flow).
Tags: Correctly sets Many-to-Many dietary_tags.
Items: Correctly replaces existing items (clear old, create new) based on
provided data.
Testing: Unit tests cover:
Successful creation of a cookbook with nested data.
Successful update of an existing cookbook.
Transaction rollback verification (simulate an error during item creation to
ensure cookbook isn't partially saved).
Code Quality: Type hinting matches the provided specification; code passes
linting.
Technical Implementation Notes
File Path: cookbooks/services/cookbook_service.py
Key Considerations:
Atomic Transactions: Ensure transaction.atomic() is used at the top level of
upsert_cookbook.
Item Replacement: The current spec requires a "clear and recreate" strategy for
items (cookbook.items.clear()). Ensure this is intentional per design (vs.
updating existing items by ID).
Author Handling: The service should link an existing author, not create a new
one during this flow. If the author slug doesn't exist, the author field should
remain unchanged or handle gracefully (per code spec above).