Coverage for src/henrri_connect/customers/asynchro.py: 80%

55 statements  

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

1""" 

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

3 

4Classes: 

5- ``henrri_connect.customers.asynchro.AsyncCustomersClient`` 

6 Accès asynchrone aux endpoints clients. 

7 

8Notes: 

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

10aux endpoints. 

11""" 

12 

13from __future__ import annotations 

14 

15from typing import TYPE_CHECKING, overload, Optional 

16 

17from ..models import Address, Contact, Customer, CustomerRequest, PagedListResponse 

18from ..models.base import CustomerType 

19from ..utils import clean 

20 

21if TYPE_CHECKING: 

22 from ..connect import AsyncHenrriClient 

23 

24BASE_CUSTOMERS = "/v1/customers" 

25 

26class AsyncCustomersClient: 

27 """ 

28 Accès asynchrone aux endpoints clients. 

29 

30 Arguments 

31 - ``client`` (AsyncHenrriClient) : Client HTTP. 

32 

33 Methods 

34 - ``delete`` : Supprime un client. 

35 - ``delete_contact`` : Supprime un contact. 

36 - ``list_customers`` : Liste les clients avec pagination et filtres optionnels. 

37 - ``get_best_sales`` : Récupère les meilleurs clients. 

38 - ``get_last_used`` : Récupère le dernier client utilisé. 

39 - ``add`` : Crée un nouveau client. 

40 - ``get`` : Récupère un client par son identifiant. 

41 - ``modify`` : Met à jour un client. 

42 - ``get_address`` : Récupère l'adresse d'un client. 

43 - ``list_contacts`` : Liste les contacts d'un client. 

44 - ``add_contact`` : Crée un nouveau contact. 

45 - ``get_contact`` : Récupère un contact d'un client. 

46 - ``modify_contact`` : Met à jour un contact. 

47 """ 

48 

49 def __init__(self, client: AsyncHenrriClient) -> None: 

50 self._c = client 

51 

52 @overload 

53 async def list_customers( 

54 self, 

55 *, 

56 request: CustomerRequest, 

57 with_selected_fields: bool = True, 

58 with_totals: bool = False, 

59 only_current_page: bool = True 

60 ) -> PagedListResponse[Customer]:... 

61 @overload 

62 async def list_customers( 

63 self, 

64 *, 

65 request: CustomerRequest, 

66 with_selected_fields: bool = False, 

67 with_totals: None = None, 

68 only_current_page: None = None, 

69 ):... 

70 async def list_customers( 

71 self, 

72 *, 

73 request: CustomerRequest, 

74 with_selected_fields: bool = True, 

75 with_totals: Optional[bool] = False, 

76 only_current_page: Optional[bool] = True 

77 ): 

78 """ 

79 Liste les clients avec pagination et filtres optionnels. 

80 

81 Arguments 

82 - ``request`` (CustomerRequest) : Paramètres de recherche. 

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

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

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

86 actuelle. 

87 

88 Returns 

89 - ``PagedListResponse[Customer]`` : Liste paginée de clients. 

90 """ 

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

92 if with_selected_fields: 

93 if with_totals and only_current_page: 

94 params["with_totals"] = with_totals 

95 params["only_current_page"] = only_current_page 

96 resp = await self._c.request( 

97 "GET", 

98 f"{BASE_CUSTOMERS}/with-selected-fields", 

99 params=params 

100 ) 

101 else: 

102 raise ValueError( 

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

104 ) 

105 else: 

106 resp = await self._c.request("GET", BASE_CUSTOMERS, params=params) 

107 return PagedListResponse[Customer].model_validate(resp.json()) 

108 

109 async def add(self, customer: Customer) -> Customer: 

110 """ 

111 Crée un nouveau client. 

112 

113 Arguments 

114 - ``customer`` (Customer) : Client à créer. 

115 

116 Returns 

117 - ``Customer`` : Client créé. 

118 """ 

119 resp = await self._c.request( 

120 "POST", 

121 BASE_CUSTOMERS, 

122 json=customer.model_dump(by_alias=True, exclude_unset=True, exclude_none=True), 

123 ) 

124 return Customer.model_validate(resp.json()) 

125 

126 async def get_best_sales( 

127 self, 

128 *, 

129 year: int, 

130 ) -> PagedListResponse[Customer]: 

131 """ 

132 Récupère les meilleurs clients. 

133 

134 Arguments 

135 - ``year`` (int) : Année concerne (minimum 2000, maximum 2100). 

136 

137 Returns 

138 - ``PagedListResponse[Customer]`` : Liste paginée de clients. 

139 """ 

140 params = { 

141 "year": year 

142 } 

143 resp = await self._c.request("GET", f"{BASE_CUSTOMERS}/best-sales", params=params) 

144 return PagedListResponse[Customer].model_validate(resp.json()) 

145 

146 async def get_last_used(self, customer_type: CustomerType, limit: int) -> Customer: 

147 """ 

148 Récupère les derniers clients utilisés. 

149 

150 Arguments 

151 - ``customer_type`` (CustomerType) : Type de client. 

152 - ``limit`` (int) : Nombre de clients maximum. 

153 

154 Returns 

155 - ``Customer`` : Derniers clients utilisés. 

156 """ 

157 params = { 

158 "Types": customer_type, 

159 "Limit": limit, 

160 } 

161 resp = await self._c.request("GET", f"{BASE_CUSTOMERS}/last-used", params=params) 

162 return Customer.model_validate(resp.json()) 

163 

164 async def get(self, customer_id: int) -> Customer: 

165 """ 

166 Récupère un client par son identifiant. 

167 

168 Arguments 

169 - ``customer_id`` (int) : Identifiant du client. 

170 

171 Returns 

172 - ``Customer`` : Client. 

173 """ 

174 resp = await self._c.request("GET", f"{BASE_CUSTOMERS}/{customer_id}") 

175 return Customer.model_validate(resp.json()) 

176 

177 async def modify(self, customer_id: int, customer: Customer) -> Customer: 

178 """ 

179 Met à jour un client existant. 

180 

181 Arguments 

182 - ``customer_id`` (int) : Identifiant du client. 

183 - ``customer`` (Customer) : Client à mettre à jour. 

184 

185 Returns 

186 - ``Customer`` : Client mis à jour. 

187 """ 

188 resp = await self._c.request( 

189 "PUT", 

190 f"{BASE_CUSTOMERS}/{customer_id}", 

191 json=customer.model_dump(by_alias=True, exclude_unset=True, exclude_none=True), 

192 ) 

193 return Customer.model_validate(resp.json()) 

194 

195 async def delete(self, customer_id: int) -> None: 

196 """ 

197 Supprime un client. 

198 

199 Arguments 

200 - ``customer_id`` (int) : Identifiant du client. 

201 

202 Returns 

203 - ``None``. 

204 """ 

205 await self._c.request("DELETE", f"{BASE_CUSTOMERS}/{customer_id}") 

206 

207 async def get_address(self, customer_id: int) -> Address: 

208 """ 

209 Récupère l'adresse d'un client. 

210 

211 Arguments 

212 - ``customer_id`` (int) : Identifiant du client. 

213 

214 Returns 

215 - ``henrri_connect.models.Address`` : Adresse du client. 

216 """ 

217 resp = await self._c.request("GET", f"{BASE_CUSTOMERS}/{customer_id}/address") 

218 return Address.model_validate(resp.json()) 

219 

220 async def list_contacts(self, customer_id: int) -> list[Contact]: 

221 """ 

222 Liste les contacts d'un client. 

223 

224 Arguments 

225 - ``customer_id`` (int) : Identifiant du client. 

226 

227 Returns 

228 - ``list[Contact]`` : Liste de contacts. 

229 """ 

230 resp = await self._c.request("GET", f"{BASE_CUSTOMERS}/{customer_id}/contacts") 

231 return [Contact.model_validate(c) for c in resp.json()] 

232 

233 async def add_contact(self, customer_id: int, contact: Contact) -> Contact: 

234 """ 

235 Ajoute un contact à un client. 

236 

237 Arguments 

238 - ``customer_id`` (int) : Identifiant du client. 

239 - ``contact`` (Contact) : Contact à ajouter. 

240 

241 Returns 

242 - ``Contact`` : Contact ajouté. 

243 """ 

244 resp = await self._c.request( 

245 "POST", 

246 f"{BASE_CUSTOMERS}/{customer_id}/contacts", 

247 json=contact.model_dump(by_alias=True, exclude_unset=True, exclude_none=True), 

248 ) 

249 return Contact.model_validate(resp.json()) 

250 

251 async def get_contact(self, customer_id: int, contact_id: int) -> Contact: 

252 """ 

253 Récupère un contact d'un client. 

254 

255 Arguments 

256 - ``customer_id`` (int) : Identifiant du client. 

257 - ``contact_id`` (int) : Identifiant du contact. 

258 

259 Returns 

260 - ``Contact`` : Contact. 

261 """ 

262 resp = await self._c.request("GET", f"{BASE_CUSTOMERS}/{customer_id}/contacts/{contact_id}") 

263 return Contact.model_validate(resp.json()) 

264 

265 async def modify_contact(self, customer_id: int, contact_id: int, contact: Contact) -> Contact: 

266 """ 

267 Met à jour un contact d'un client. 

268 

269 Arguments 

270 - ``customer_id`` (int) : Identifiant du client. 

271 - ``contact_id`` (int) : Identifiant du contact. 

272 - ``contact`` (Contact) : Contact à mettre à jour. 

273 

274 Returns 

275 - ``Contact`` : Contact mis à jour. 

276 """ 

277 resp = await self._c.request( 

278 "PUT", 

279 f"{BASE_CUSTOMERS}/{customer_id}/contacts/{contact_id}", 

280 json=contact.model_dump(by_alias=True, exclude_unset=True, exclude_none=True), 

281 ) 

282 return Contact.model_validate(resp.json()) 

283 

284 async def delete_contact(self, customer_id: int, contact_id: int) -> None: 

285 """ 

286 Supprime un contact d'un client. 

287 

288 Arguments 

289 - ``customer_id`` (int) : Identifiant du client. 

290 - ``contact_id`` (int) : Identifiant du contact. 

291 

292 Returns 

293 - ``None``. 

294 """ 

295 await self._c.request("DELETE", f"{BASE_CUSTOMERS}/{customer_id}/contacts/{contact_id}")