Coverage for src/henrri_connect/items/synchro.py: 86%

36 statements  

« prev     ^ index     » next       coverage.py v7.14.1, created at 2026-06-05 10:54 +0200

1""" 

2Sous-client pour les endpoints /v1/items. 

3 

4Classes: 

5- ``henrri_connect.items.synchro.SyncItemsClient`` 

6 Accès synchrone aux endpoints articles. 

7 

8Notes: 

9- Utiliser de préférence l'objet ``henrri_connect.SyncHenrriClient`` pour acceder aux endpoints. 

10""" 

11 

12from __future__ import annotations 

13 

14from typing import TYPE_CHECKING, overload, Optional 

15 

16from ..models import Item, PagedListResponse, ItemsQuery 

17from ..utils import clean 

18 

19if TYPE_CHECKING: 

20 from ..connect import SyncHenrriClient 

21 

22ITEMS_ENDPOINT = "/v1/items" 

23 

24 

25class SyncItemsClient: 

26 """ 

27 Accès synchrone aux endpoints articles. 

28 

29 Arguments 

30 - ``client`` : Objet ``henrri_connect.SyncHenrriClient`` pour acceder aux endpoints. 

31 

32 Methods 

33 - ``list_items`` : Liste les articles avec pagination et filtres optionnels. 

34 - ``add`` : Crée un nouvel article. 

35 - ``get`` : Récupère un article par son identifiant. 

36 - ``modify`` : Modifie un article par son identifiant. 

37 - ``delete`` : Supprime un article par son identifiant. 

38 - ``get_most_used`` : Récupère les articles les plus utilisés. 

39 - ``get_best_sales`` : Récupère les articles les plus vendus. 

40 - ``list_with_selected_fields`` : Liste les articles avec sélection de champs. 

41 """ 

42 

43 def __init__(self, client: SyncHenrriClient) -> None: 

44 self._c = client 

45 

46 @overload 

47 def list_items( 

48 self, 

49 *, 

50 request: ItemsQuery, 

51 with_selected_fields: bool = True, 

52 with_totals: bool = False, 

53 only_current_page: bool = True 

54 ) -> PagedListResponse[Item]:... 

55 @overload 

56 def list_items( 

57 self, 

58 *, 

59 request: ItemsQuery, 

60 with_selected_fields: bool = False, 

61 with_totals: None = None, 

62 only_current_page: None = None, 

63 ) -> PagedListResponse[Item]:... 

64 def list_items( 

65 self, 

66 *, 

67 request: ItemsQuery, 

68 with_selected_fields: bool = True, 

69 with_totals: Optional[bool] = False, 

70 only_current_page: Optional[bool] = True 

71 ) -> PagedListResponse[Item]: 

72 """ 

73 Liste les articles avec pagination et filtres optionnels. 

74 

75 Arguments 

76 - ``request`` (ItemsQuery) : Paramètres de recherche. 

77 - ``with_selected_fields`` (bool) : Si True, lance une requête de recherche avancée. 

78 - ``with_totals`` (bool) : Si True, renvoie les totaux. 

79 - ``only_current_page`` (bool) : Si True, renvoie uniquement les articles de la page 

80 actuelle. 

81 

82 Returns 

83 - ``PagedListResponse[Item]`` : Liste paginée d'articles. 

84 """ 

85 params = clean(request.model_dump(by_alias=True)) 

86 if with_selected_fields: 

87 if with_totals and only_current_page: 

88 params["with_totals"] = with_totals 

89 params["only_current_page"] = only_current_page 

90 resp = self._c.request( 

91 "GET", 

92 f"{ITEMS_ENDPOINT}/with-selected-fields", 

93 params=params 

94 ) 

95 else: 

96 raise ValueError( 

97 "with_totals and only_current_page must be True if with_selected_fields is True" 

98 ) 

99 else: 

100 resp = self._c.request("GET", ITEMS_ENDPOINT, params=params) 

101 return PagedListResponse[Item].model_validate(resp.json()) 

102 

103 def add(self, item: Item) -> Item: 

104 """ 

105 Crée un nouvel article. 

106 

107 Arguments 

108 - ``item`` (Item) : Article à créer. 

109 

110 Returns 

111 - ``Item`` : Article créé. 

112 """ 

113 resp = self._c.request( 

114 "POST", 

115 ITEMS_ENDPOINT, 

116 json=item.model_dump(by_alias=True, exclude_unset=True, exclude_none=True), 

117 ) 

118 return Item.model_validate(resp.json()) 

119 

120 def get(self, item_id: int) -> Item: 

121 """ 

122 Récupère un article par son identifiant. 

123 

124 Arguments 

125 - ``item_id`` (int) : Identifiant de l'article. 

126 

127 Returns 

128 - ``Item`` : Article rencontré. 

129 """ 

130 resp = self._c.request("GET", f"{ITEMS_ENDPOINT}/{item_id}") 

131 return Item.model_validate(resp.json()) 

132 

133 def modify(self, item_id: int, item: Item) -> Item: 

134 """ 

135 Met à jour un article existant. 

136 

137 Arguments 

138 - ``item_id`` (int) : Identifiant de l'article. 

139 - ``item`` (Item) : Article à mettre à jour. 

140 

141 Returns 

142 - ``Item`` : Article mis à jour. 

143 """ 

144 resp = self._c.request( 

145 "PUT", 

146 f"{ITEMS_ENDPOINT}/{item_id}", 

147 json=item.model_dump(by_alias=True, exclude_unset=True, exclude_none=True), 

148 ) 

149 return Item.model_validate(resp.json()) 

150 

151 def delete(self, item_id: int) -> None: 

152 """ 

153 Supprime un article. 

154 

155 Arguments 

156 - ``item_id`` (int) : Identifiant de l'article à supprimer. 

157 

158 Returns 

159 - ``None`` : Article supprimé. 

160 """ 

161 self._c.request("DELETE", f"{ITEMS_ENDPOINT}/{item_id}") 

162 

163 def get_most_used(self) -> PagedListResponse[Item]: 

164 """ 

165 Récupère les articles les plus utilisés. 

166 

167 Arguments 

168 - None 

169 

170 Returns 

171 - ``PagedListResponse[Item]`` : Liste paginée d'articles. 

172 """ 

173 resp = self._c.request("GET", f"{ITEMS_ENDPOINT}/most-used") 

174 return PagedListResponse[Item].model_validate(resp.json()) 

175 

176 def get_best_sales(self, *, year: int) -> PagedListResponse[Item]: 

177 """ 

178 Récupère les articles les plus vendus. 

179 

180 Arguments 

181 - ``year`` (int) : Année de recherche. 

182 

183 Returns 

184 - ``PagedListResponse[Item]`` : Liste paginée d'articles. 

185 """ 

186 params = { 

187 "year": year 

188 } 

189 resp = self._c.request("GET", f"{ITEMS_ENDPOINT}/with-selected-fields", params=params) 

190 return PagedListResponse[Item].model_validate(resp.json())