Coverage for packages/clopos/src/integrify/clopos/schemas/products/request.py: 97%

67 statements  

« prev     ^ index     » next       coverage.py v7.16.0, created at 2026-10-19 02:39 +0000

1from typing import Literal 

2 

3from integrify.api import PayloadBaseModel 

4from integrify.clopos.helpers import BoolInt 

5from integrify.clopos.schemas.common.request import ByIDRequest, PaginatedDataRequest 

6from integrify.clopos.schemas.enums import ProductType 

7from integrify.utils import UnsetField 

8from pydantic import Field, field_serializer, model_serializer 

9from typing_extensions import NotRequired, TypedDict 

10 

11 

12class GetProducstRequestFilter(TypedDict): 

13 type: NotRequired[list[ProductType]] 

14 """Filters by product type. Possible values: GOODS, DISH, TIMER, PREPARATION, INGREDIENT""" 

15 

16 category_id: NotRequired[list[int]] 

17 """Lists products belonging to the specified category IDs""" 

18 

19 station_id: NotRequired[list[int]] 

20 """Retrieves products assigned to the specified station IDs""" 

21 

22 tags: NotRequired[list[int]] 

23 """Filters for products with the specified tag IDs""" 

24 

25 giftable: NotRequired[BoolInt] 

26 """Filters for products that are ("1") or are not giftable""" 

27 

28 discountable: NotRequired[BoolInt] 

29 """Filters for products that are ("1") or are not discountable""" 

30 

31 inventory_behavior: NotRequired[int] 

32 """Filters by inventory behavior mode (e.g., "3")""" 

33 

34 have_ingredients: NotRequired[BoolInt] 

35 """Retrieves products that have a recipe/ingredients ("1")""" 

36 

37 sold_by_portion: NotRequired[BoolInt] 

38 """Lists products sold by portion ("1")""" 

39 

40 has_variants: NotRequired[BoolInt] 

41 """Lists products that have variants (`modifications`) ("1")""" 

42 

43 has_modifiers: NotRequired[BoolInt] 

44 """Lists products that have modifier group (`modificator_groups`) ("1")""" 

45 

46 has_barcode: NotRequired[BoolInt] 

47 """Retrieves products that have a barcode ("1")""" 

48 

49 has_service_charge: NotRequired[BoolInt] 

50 """Lists products to which a service charge applies ("1")""" 

51 

52 

53class GetProductsRequest(PaginatedDataRequest): 

54 selects: UnsetField[list[str] | str] = Field(serialization_alias='selects[]') 

55 filters: UnsetField[GetProducstRequestFilter] 

56 

57 @field_serializer('selects') 

58 def serialize_selects(self, value): 

59 """Transform to comma-separated string""" 

60 if isinstance(value, str): 

61 return value 

62 return ','.join(value) 

63 

64 @field_serializer('filters') 

65 def serialize_filters(self, filters): 

66 """Transform to [field_name, value] format""" 

67 result = {} 

68 for key, value in filters.items(): 

69 if value is not None: # Only include non-None values 69 ↛ 68line 69 didn't jump to line 68 because the condition on line 69 was always true

70 result[key] = [key, value] 

71 

72 return result 

73 

74 

75class GetProductByIDRequest(ByIDRequest): 

76 with_: UnsetField[ 

77 list[ 

78 Literal[ 

79 'taxes', 

80 'unit', 

81 'modifications', 

82 'modificator_groups', 

83 'recipe', 

84 'packages', 

85 'media', 

86 'tags', 

87 'setting', 

88 ] 

89 ] 

90 ] = Field(serialization_alias='with[]') 

91 

92 

93class StopListFilter(TypedDict): 

94 by: Literal['id', 'limit', 'timestamp'] 

95 from_: int 

96 to: NotRequired[int] 

97 

98 

99class GetStopListRequest(PayloadBaseModel): 

100 filters: UnsetField[list[StopListFilter]] 

101 

102 @model_serializer 

103 def serialize_model(self) -> dict: 

104 """Model serializer""" 

105 data = {} 

106 

107 for i, filter_ in enumerate(self.filters or []): 

108 data[f'filters[{i}][0]'] = filter_['by'] 

109 data[f'filters[{i}][1][0]'] = filter_['from_'] 

110 

111 if 'to' in filter_: 111 ↛ 107line 111 didn't jump to line 107 because the condition on line 111 was always true

112 data[f'filters[{i}][1][1]'] = filter_['to'] 

113 

114 return data