diff --git a/app/modules/loyalty/routes/api/merchant.py b/app/modules/loyalty/routes/api/merchant.py index 87bdddb0..58d2a604 100644 --- a/app/modules/loyalty/routes/api/merchant.py +++ b/app/modules/loyalty/routes/api/merchant.py @@ -38,6 +38,7 @@ from app.modules.loyalty.schemas import ( CardResponse, MerchantSettingsResponse, PinCreate, + PinCreateForMerchant, PinDetailListResponse, PinDetailResponse, PinResponse, @@ -339,22 +340,24 @@ def list_pins( @router.post("/pins", response_model=PinResponse, status_code=201) def create_pin( - data: PinCreate, - store_id: int = Query(..., gt=0), + data: PinCreateForMerchant, merchant: Merchant = Depends(get_merchant_for_current_user), db: Session = Depends(get_db), ): - """Create a new staff PIN.""" + """Create a new staff PIN. ``store_id`` comes from the body — the + merchant portal isn't scoped to a single store like the store API is. + """ # Validate store belongs to merchant locations = program_service.get_merchant_locations(db, merchant.id) store_ids = [loc.id for loc in locations] - if store_id not in store_ids: + if data.store_id not in store_ids: from app.modules.tenancy.exceptions import StoreNotFoundException - raise StoreNotFoundException(str(store_id), identifier_type="id") + raise StoreNotFoundException(str(data.store_id), identifier_type="id") program = program_service.require_program_by_merchant(db, merchant.id) - pin = pin_service.create_pin(db, program.id, store_id, data) + pin_data = PinCreate(name=data.name, staff_id=data.staff_id, pin=data.pin) + pin = pin_service.create_pin(db, program.id, data.store_id, pin_data) return PinResponse.model_validate(pin) diff --git a/app/modules/loyalty/schemas/__init__.py b/app/modules/loyalty/schemas/__init__.py index 4e6da940..e073df4a 100644 --- a/app/modules/loyalty/schemas/__init__.py +++ b/app/modules/loyalty/schemas/__init__.py @@ -39,6 +39,7 @@ from app.modules.loyalty.schemas.card import ( from app.modules.loyalty.schemas.pin import ( # Staff PIN PinCreate, + PinCreateForMerchant, PinDetailListResponse, PinDetailResponse, PinListResponse, @@ -131,6 +132,7 @@ __all__ = [ "PointsAdjustResponse", # PIN "PinCreate", + "PinCreateForMerchant", "PinUpdate", "PinResponse", "PinDetailResponse", diff --git a/app/modules/loyalty/schemas/pin.py b/app/modules/loyalty/schemas/pin.py index 87a8b2e7..c65b6e2f 100644 --- a/app/modules/loyalty/schemas/pin.py +++ b/app/modules/loyalty/schemas/pin.py @@ -31,6 +31,14 @@ class PinCreate(BaseModel): ) +class PinCreateForMerchant(PinCreate): + """PinCreate from the merchant portal — carries the target store_id in + the body since the merchant has no per-store auth context (unlike the + store-side endpoint which reads store_id from the JWT).""" + + store_id: int = Field(..., gt=0, description="Store this PIN belongs to") + + class PinUpdate(BaseModel): """Schema for updating a staff PIN."""