"""Logic for Carveouts.""" from operator import attrgetter from carveouts.constants import DEFAULT_OA_USER from carveouts.models import ( country, country_carveout, releases, service_carveout, service_country_carveout, service_opt_out, subaccount, vendor, vendor_contract, ) from carveouts.models.schemas import ( AccountCarveoutResponse, CarveoutPayload, CarveoutResponse, ProductCarveoutResponse, SubaccountCarveoutResponse, ) def delete_product_service_carveouts(product_id: int) -> None: """Delete product Level service carveouts. Args: product_id (int) : Release/Product id """ service_carveout.delete_product_carveouts(product_id) def delete_product_service_country_carveouts(product_id: int) -> None: """Delete product level service country carveouts. Args: product_id (int): Release/Product id """ service_country_carveout.delete_product_carveouts(product_id) def get_product_carveouts(product_id: int) -> CarveoutResponse: """Get product carveouts from all levels.""" _ = releases.get_product(product_id) carveouts = CarveoutResponse( account=AccountCarveoutResponse( country=[], service=[], service_country=[], new_service_opt_outs=[], ), subaccount=SubaccountCarveoutResponse( country=[], service=[], service_country=[], ), product=ProductCarveoutResponse( country=[], service=[], service_country=[], new_service_opt_outs=[], ), ) vendor_id = releases.get_vendor_id(product_id) vendor_contract_id = vendor_contract.get_active_contract_id(vendor_id) carveouts = _get_vendor_carveouts(vendor_contract_id, carveouts) subaccount_id = releases.get_subaccount_id(product_id) carveouts = _get_subaccount_carveouts(subaccount_id, carveouts) carveouts = carveouts.model_copy( update={ "product": _format_response( ProductCarveoutResponse, service_carveout.get_product_carveouts(product_id), service_country_carveout.get_product_carveouts(product_id), country_carveout.get_product_carveouts(product_id), service_opt_out.get_product_opt_outs(product_id), ) } ) return carveouts def _format_service_country_carveouts( carveouts: set[service_country_carveout.ServiceCountryCarveout], ) -> dict[int, set[str]]: condensed_carveouts: dict[int, set[str]] = {} for carveout in carveouts: condensed_carveouts.setdefault(carveout.service_id, set()) condensed_carveouts[carveout.service_id].add(carveout.country_code) return condensed_carveouts def _format_response( carveout_response_class: type[AccountCarveoutResponse] | type[SubaccountCarveoutResponse] | type[ProductCarveoutResponse], service_carveouts: set[service_carveout.ServiceCarveout], service_country_carveouts: set[service_country_carveout.ServiceCountryCarveout], country_carveouts: set[country_carveout.CountryCarveout], service_opt_outs: set[int], ) -> AccountCarveoutResponse | SubaccountCarveoutResponse | ProductCarveoutResponse: carveout_response = carveout_response_class( service=sorted(service_carveouts, key=attrgetter("service_id")), service_country=[ { "service_id": service_id, "countries": sorted(countries), } for service_id, countries in _format_service_country_carveouts( service_country_carveouts ).items() ], country=sorted({carveout.country_code for carveout in country_carveouts}), ) if hasattr(carveout_response, "new_service_opt_outs"): carveout_response = carveout_response.model_copy( update={"new_service_opt_outs": list(service_opt_outs)} ) return carveout_response def get_subaccount_carveouts(subaccount_id: int) -> CarveoutResponse: """Get subaccount carveouts from specific vendor and subaccount levels.""" subaccount_id, vendor_id = subaccount.get_subaccount(subaccount_id) carveouts = CarveoutResponse( account=AccountCarveoutResponse( country=[], service=[], service_country=[], new_service_opt_outs=[], ), subaccount=SubaccountCarveoutResponse( country=[], service=[], service_country=[], ), ) vendor_contract_id = vendor_contract.get_active_contract_id(vendor_id) carveouts = _get_vendor_carveouts(vendor_contract_id, carveouts) carveouts = _get_subaccount_carveouts(subaccount_id, carveouts) return carveouts def _get_vendor_carveouts( vendor_contract_id: int | None, carveouts: CarveoutResponse ) -> CarveoutResponse: if not vendor_contract_id: return carveouts return carveouts.model_copy( update={ "account": _format_response( AccountCarveoutResponse, service_carveout.get_vendor_carveouts(vendor_contract_id), service_country_carveout.get_vendor_carveouts(vendor_contract_id), country_carveout.get_vendor_carveouts(vendor_contract_id), service_opt_out.get_vendor_opt_outs(vendor_contract_id), ) } ) def _get_subaccount_carveouts( subaccount_id: int | None, carveouts: CarveoutResponse ) -> CarveoutResponse: if not subaccount_id: return carveouts return carveouts.model_copy( update={ "subaccount": _format_response( SubaccountCarveoutResponse, service_carveout.get_subaccount_carveouts(subaccount_id), service_country_carveout.get_subaccount_carveouts(subaccount_id), country_carveout.get_subaccount_carveouts(subaccount_id), set(), ) } ) def get_account_carveouts(vendor_id: int) -> CarveoutResponse: """Get account (vendor contract) carveouts from specific vendor.""" vendor_id = vendor.get_vendor_id(vendor_id) carveouts = CarveoutResponse( account=AccountCarveoutResponse( country=[], service=[], service_country=[], new_service_opt_outs=[], ), ) vendor_contract_id = vendor_contract.get_active_contract_id(vendor_id) carveouts = _get_vendor_carveouts(vendor_contract_id, carveouts) return carveouts def delete_product_country_carveouts(product_id: int) -> None: """Delete product Level country carveouts. Args: product_id (int) : Release/Product id """ _ = releases.get_product(product_id) country_carveout.delete_product_carveouts(product_id) def save_product_carveouts(product_id: int, payload: CarveoutPayload) -> None: """Add product carveouts.""" product = releases.get_product(product_id) if payload.service is not None: carveouts = [ service_carveout.ServiceCarveout( service_id=int(service.service_id), service_name=None, distribution_types=service.distribution_types, ) for service in payload.service ] service_carveout.add_product_carveouts( product_id=product.product_id, upc=product.upc, carveouts=carveouts, updated_by=(payload.updated_by if payload.updated_by else DEFAULT_OA_USER), ) if payload.service_country is not None: service_country_carveout.add_product_carveouts( product_id=product.product_id, upc=product.upc, carveouts=payload.service_country, ) if payload.country is not None: country_carveout.add_product_carveouts( product_id=product.product_id, upc=product.upc, country_ids=country.get_country_ids(payload.country), ) if payload.opt_out is not None: service_opt_out.add_product_opt_outs( product_id=product.product_id, upc=product.upc, distribution_types=payload.opt_out, ) def save_account_carveouts(vendor_contract_id: int, payload: CarveoutPayload) -> None: """Save account/contract carveouts.""" if payload.service is not None: carveouts = [ service_carveout.ServiceCarveout( service_id=int(service.service_id), service_name=None, distribution_types=service.distribution_types, ) for service in payload.service ] service_carveout.add_account_carveouts( vendor_contract_id=vendor_contract_id, carveouts=carveouts, updated_by=(payload.updated_by if payload.updated_by else DEFAULT_OA_USER), ) if payload.service_country: # not implemented yet pass if payload.country is not None: country_carveout.update_account_carveouts( vendor_contract_id=vendor_contract_id, country_codes=payload.country, ) if payload.opt_out: # not implemented yet pass def create_new_service_carveouts(service_id: int, updated_by: int) -> None: """Create new service carveouts for all products. Args: service_id (int): Service ID updated_by (int): User ID """ service_carveout.create_account_new_service_carveouts(service_id, updated_by) service_carveout.create_product_new_service_carveouts(service_id, updated_by)