Home Assistant Unofficial Reference 2024.12.1
services.py
Go to the documentation of this file.
1 """Services for the Picnic integration."""
2 
3 from __future__ import annotations
4 
5 from typing import cast
6 
7 from python_picnic_api import PicnicAPI
8 import voluptuous as vol
9 
10 from homeassistant.core import HomeAssistant, ServiceCall
12 
13 from .const import (
14  ATTR_AMOUNT,
15  ATTR_CONFIG_ENTRY_ID,
16  ATTR_PRODUCT_ID,
17  ATTR_PRODUCT_IDENTIFIERS,
18  ATTR_PRODUCT_NAME,
19  CONF_API,
20  DOMAIN,
21  SERVICE_ADD_PRODUCT_TO_CART,
22 )
23 
24 
25 class PicnicServiceException(Exception):
26  """Exception for Picnic services."""
27 
28 
29 async def async_register_services(hass: HomeAssistant) -> None:
30  """Register services for the Picnic integration, if not registered yet."""
31 
32  if hass.services.has_service(DOMAIN, SERVICE_ADD_PRODUCT_TO_CART):
33  return
34 
35  async def async_add_product_service(call: ServiceCall):
36  api_client = await get_api_client(hass, call.data[ATTR_CONFIG_ENTRY_ID])
37  await handle_add_product(hass, api_client, call)
38 
39  hass.services.async_register(
40  DOMAIN,
41  SERVICE_ADD_PRODUCT_TO_CART,
42  async_add_product_service,
43  schema=vol.Schema(
44  {
45  vol.Required(ATTR_CONFIG_ENTRY_ID): cv.string,
46  vol.Exclusive(ATTR_PRODUCT_ID, ATTR_PRODUCT_IDENTIFIERS): cv.string,
47  vol.Exclusive(ATTR_PRODUCT_NAME, ATTR_PRODUCT_IDENTIFIERS): cv.string,
48  vol.Optional(ATTR_AMOUNT): vol.All(vol.Coerce(int), vol.Range(min=1)),
49  }
50  ),
51  )
52 
53 
54 async def get_api_client(hass: HomeAssistant, config_entry_id: str) -> PicnicAPI:
55  """Get the right Picnic API client based on the device id, else get the default one."""
56  if config_entry_id not in hass.data[DOMAIN]:
57  raise ValueError(f"Config entry with id {config_entry_id} not found!")
58  return hass.data[DOMAIN][config_entry_id][CONF_API]
59 
60 
62  hass: HomeAssistant, api_client: PicnicAPI, call: ServiceCall
63 ) -> None:
64  """Handle the call for the add_product service."""
65  product_id = call.data.get(ATTR_PRODUCT_ID)
66  if not product_id:
67  product_id = await hass.async_add_executor_job(
68  product_search, api_client, cast(str, call.data[ATTR_PRODUCT_NAME])
69  )
70 
71  if not product_id:
72  raise PicnicServiceException("No product found or no product ID given!")
73 
74  await hass.async_add_executor_job(
75  api_client.add_product, product_id, call.data.get(ATTR_AMOUNT, 1)
76  )
77 
78 
79 def product_search(api_client: PicnicAPI, product_name: str | None) -> str | None:
80  """Query the api client for the product name."""
81  if product_name is None:
82  return None
83 
84  search_result = api_client.search(product_name)
85 
86  if not search_result or "items" not in search_result[0]:
87  return None
88 
89  # Return the first valid result
90  for item in search_result[0]["items"]:
91  if "name" in item:
92  return str(item["id"])
93 
94  return None
PicnicAPI get_api_client(HomeAssistant hass, str config_entry_id)
Definition: services.py:54
None async_register_services(HomeAssistant hass)
Definition: services.py:29
str|None product_search(PicnicAPI api_client, str|None product_name)
Definition: services.py:79
None handle_add_product(HomeAssistant hass, PicnicAPI api_client, ServiceCall call)
Definition: services.py:63