@@ -52,6 +52,10 @@ class PDLLinkProduction(BaseModel):
5252 linked_production_pdl_id : str | None = None # None to unlink
5353
5454
55+ class PDLUpdatePricingOption (BaseModel ):
56+ pricing_option : str | None = None # BASE, HC_HP, TEMPO, EJP, HC_WEEKEND
57+
58+
5559class PDLOrderItem (BaseModel ):
5660 id : str
5761 order : int
@@ -88,6 +92,7 @@ async def list_pdls(
8892 display_order = pdl .display_order ,
8993 subscribed_power = pdl .subscribed_power ,
9094 offpeak_hours = pdl .offpeak_hours ,
95+ pricing_option = pdl .pricing_option ,
9196 has_consumption = pdl .has_consumption ,
9297 has_production = pdl .has_production ,
9398 is_active = pdl .is_active ,
@@ -297,6 +302,7 @@ async def create_pdl(
297302 created_at = pdl .created_at ,
298303 subscribed_power = pdl .subscribed_power ,
299304 offpeak_hours = pdl .offpeak_hours ,
305+ pricing_option = pdl .pricing_option ,
300306 has_consumption = pdl .has_consumption ,
301307 has_production = pdl .has_production ,
302308 is_active = pdl .is_active ,
@@ -335,6 +341,7 @@ async def get_pdl(
335341 display_order = pdl .display_order ,
336342 subscribed_power = pdl .subscribed_power ,
337343 offpeak_hours = pdl .offpeak_hours ,
344+ pricing_option = pdl .pricing_option ,
338345 has_consumption = pdl .has_consumption ,
339346 has_production = pdl .has_production ,
340347 is_active = pdl .is_active ,
@@ -461,6 +468,62 @@ async def toggle_pdl_active(
461468 )
462469
463470
471+ @router .patch ("/{pdl_id}/pricing-option" , response_model = APIResponse )
472+ async def update_pdl_pricing_option (
473+ pdl_id : str = Path (..., description = "PDL ID (UUID)" , openapi_examples = {"example_uuid" : {"summary" : "Example UUID" , "value" : "550e8400-e29b-41d4-a716-446655440000" }}),
474+ pricing_data : PDLUpdatePricingOption = Body (..., openapi_examples = {
475+ "base" : {"summary" : "Tarif Base" , "value" : {"pricing_option" : "BASE" }},
476+ "hc_hp" : {"summary" : "Heures Creuses / Heures Pleines" , "value" : {"pricing_option" : "HC_HP" }},
477+ "tempo" : {"summary" : "Tarif Tempo" , "value" : {"pricing_option" : "TEMPO" }},
478+ "ejp" : {"summary" : "Effacement Jour de Pointe" , "value" : {"pricing_option" : "EJP" }},
479+ "hc_weekend" : {"summary" : "HC Nuit & Week-end" , "value" : {"pricing_option" : "HC_WEEKEND" }},
480+ "clear" : {"summary" : "Remove pricing option" , "value" : {"pricing_option" : None }}
481+ }),
482+ current_user : User = Depends (get_current_user ),
483+ db : AsyncSession = Depends (get_db ),
484+ ) -> APIResponse :
485+ """
486+ Update PDL pricing option (tariff type).
487+
488+ Available options:
489+ - **BASE**: Single price 24/7
490+ - **HC_HP**: Off-peak hours (Heures Creuses) / Peak hours (Heures Pleines)
491+ - **TEMPO**: 6-tier pricing based on day color (blue/white/red) and period (HC/HP)
492+ - **EJP**: Peak Day Curtailment (22 expensive days per year)
493+ - **HC_WEEKEND**: Off-peak hours extended to weekends
494+ """
495+ result = await db .execute (select (PDL ).where (PDL .id == pdl_id , PDL .user_id == current_user .id ))
496+ pdl = result .scalar_one_or_none ()
497+
498+ if not pdl :
499+ return APIResponse (success = False , error = ErrorDetail (code = "PDL_NOT_FOUND" , message = "PDL not found" ))
500+
501+ # Validate pricing option if provided
502+ valid_options = ["BASE" , "HC_HP" , "TEMPO" , "EJP" , "HC_WEEKEND" ]
503+ if pricing_data .pricing_option is not None and pricing_data .pricing_option not in valid_options :
504+ return APIResponse (
505+ success = False ,
506+ error = ErrorDetail (
507+ code = "INVALID_PRICING_OPTION" ,
508+ message = f"Invalid pricing option. Must be one of: { ', ' .join (valid_options )} "
509+ )
510+ )
511+
512+ pdl .pricing_option = pricing_data .pricing_option
513+
514+ await db .commit ()
515+ await db .refresh (pdl )
516+
517+ return APIResponse (
518+ success = True ,
519+ data = {
520+ "id" : pdl .id ,
521+ "usage_point_id" : pdl .usage_point_id ,
522+ "pricing_option" : pdl .pricing_option ,
523+ },
524+ )
525+
526+
464527@router .patch ("/{pdl_id}/link-production" , response_model = APIResponse )
465528async def link_production_pdl (
466529 pdl_id : str = Path (..., description = "PDL ID (UUID) of the consumption PDL" , openapi_examples = {"example_uuid" : {"summary" : "Example UUID" , "value" : "550e8400-e29b-41d4-a716-446655440000" }}),
@@ -701,6 +764,7 @@ async def admin_add_pdl(
701764 created_at = pdl .created_at ,
702765 subscribed_power = pdl .subscribed_power ,
703766 offpeak_hours = pdl .offpeak_hours ,
767+ pricing_option = pdl .pricing_option ,
704768 has_consumption = pdl .has_consumption ,
705769 has_production = pdl .has_production ,
706770 is_active = pdl .is_active ,
0 commit comments