SymfWebAPI 1.26.10.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (329) hide show
  1. SymfWebAPI/WebAPI/Interface/BankAccounts/Interfaces/IBankAccountsController/__init__.py +83 -0
  2. SymfWebAPI/WebAPI/Interface/BankAccounts/Interfaces/IBankAccountsController/_common.py +37 -0
  3. SymfWebAPI/WebAPI/Interface/BankAccounts/Interfaces/IBankAccountsController/_ops.py +33 -0
  4. SymfWebAPI/WebAPI/Interface/BankAccounts/Interfaces/__init__.py +21 -0
  5. SymfWebAPI/WebAPI/Interface/BankAccounts/ViewModels/__init__.py +16 -0
  6. SymfWebAPI/WebAPI/Interface/BankAccounts/__init__.py +22 -0
  7. SymfWebAPI/WebAPI/Interface/Common/Interfaces/ICurrencyRatesController/__init__.py +56 -0
  8. SymfWebAPI/WebAPI/Interface/Common/Interfaces/ICurrencyRatesController/_common.py +33 -0
  9. SymfWebAPI/WebAPI/Interface/Common/Interfaces/ICurrencyRatesController/_ops.py +26 -0
  10. SymfWebAPI/WebAPI/Interface/Common/Interfaces/IDocumentSeriesController/__init__.py +27 -0
  11. SymfWebAPI/WebAPI/Interface/Common/Interfaces/IDocumentSeriesController/_common.py +10 -0
  12. SymfWebAPI/WebAPI/Interface/Common/Interfaces/IDocumentSeriesController/_ops.py +13 -0
  13. SymfWebAPI/WebAPI/Interface/Common/Interfaces/IDocumentTypesController/__init__.py +41 -0
  14. SymfWebAPI/WebAPI/Interface/Common/Interfaces/IDocumentTypesController/_common.py +17 -0
  15. SymfWebAPI/WebAPI/Interface/Common/Interfaces/IDocumentTypesController/_ops.py +19 -0
  16. SymfWebAPI/WebAPI/Interface/Common/Interfaces/IKsefController/__init__.py +40 -0
  17. SymfWebAPI/WebAPI/Interface/Common/Interfaces/IKsefController/_common.py +20 -0
  18. SymfWebAPI/WebAPI/Interface/Common/Interfaces/IKsefController/_ops.py +14 -0
  19. SymfWebAPI/WebAPI/Interface/Common/Interfaces/IPaymentFormsController/__init__.py +27 -0
  20. SymfWebAPI/WebAPI/Interface/Common/Interfaces/IPaymentFormsController/_common.py +10 -0
  21. SymfWebAPI/WebAPI/Interface/Common/Interfaces/IPaymentFormsController/_ops.py +13 -0
  22. SymfWebAPI/WebAPI/Interface/Common/Interfaces/__init__.py +25 -0
  23. SymfWebAPI/WebAPI/Interface/Common/ViewModels/Aspects/__init__.py +45 -0
  24. SymfWebAPI/WebAPI/Interface/Common/ViewModels/__init__.py +118 -0
  25. SymfWebAPI/WebAPI/Interface/Common/__init__.py +22 -0
  26. SymfWebAPI/WebAPI/Interface/Contractors/Interfaces/IContractorCardIndexController/__init__.py +54 -0
  27. SymfWebAPI/WebAPI/Interface/Contractors/Interfaces/IContractorCardIndexController/_common.py +24 -0
  28. SymfWebAPI/WebAPI/Interface/Contractors/Interfaces/IContractorCardIndexController/_ops.py +17 -0
  29. SymfWebAPI/WebAPI/Interface/Contractors/Interfaces/IContractorDeliveryAddressesController/__init__.py +55 -0
  30. SymfWebAPI/WebAPI/Interface/Contractors/Interfaces/IContractorDeliveryAddressesController/_common.py +24 -0
  31. SymfWebAPI/WebAPI/Interface/Contractors/Interfaces/IContractorDeliveryAddressesController/_ops.py +23 -0
  32. SymfWebAPI/WebAPI/Interface/Contractors/Interfaces/IContractorDimensions2Controller/__init__.py +27 -0
  33. SymfWebAPI/WebAPI/Interface/Contractors/Interfaces/IContractorDimensions2Controller/_common.py +10 -0
  34. SymfWebAPI/WebAPI/Interface/Contractors/Interfaces/IContractorDimensions2Controller/_ops.py +13 -0
  35. SymfWebAPI/WebAPI/Interface/Contractors/Interfaces/IContractorDimensionsController/__init__.py +41 -0
  36. SymfWebAPI/WebAPI/Interface/Contractors/Interfaces/IContractorDimensionsController/_common.py +19 -0
  37. SymfWebAPI/WebAPI/Interface/Contractors/Interfaces/IContractorDimensionsController/_ops.py +17 -0
  38. SymfWebAPI/WebAPI/Interface/Contractors/Interfaces/IContractorsController/__init__.py +230 -0
  39. SymfWebAPI/WebAPI/Interface/Contractors/Interfaces/IContractorsController/_common.py +109 -0
  40. SymfWebAPI/WebAPI/Interface/Contractors/Interfaces/IContractorsController/_ops.py +100 -0
  41. SymfWebAPI/WebAPI/Interface/Contractors/Interfaces/__init__.py +25 -0
  42. SymfWebAPI/WebAPI/Interface/Contractors/ViewModels/__init__.py +64 -0
  43. SymfWebAPI/WebAPI/Interface/Contractors/__init__.py +22 -0
  44. SymfWebAPI/WebAPI/Interface/Dictionaries/Interfaces/IFKDictionariesController/__init__.py +129 -0
  45. SymfWebAPI/WebAPI/Interface/Dictionaries/Interfaces/IFKDictionariesController/_common.py +59 -0
  46. SymfWebAPI/WebAPI/Interface/Dictionaries/Interfaces/IFKDictionariesController/_ops.py +48 -0
  47. SymfWebAPI/WebAPI/Interface/Dictionaries/Interfaces/__init__.py +21 -0
  48. SymfWebAPI/WebAPI/Interface/Dictionaries/ViewModels/__init__.py +49 -0
  49. SymfWebAPI/WebAPI/Interface/Dictionaries/__init__.py +22 -0
  50. SymfWebAPI/WebAPI/Interface/Enums/FKConfigurator/__init__.py +41 -0
  51. SymfWebAPI/WebAPI/Interface/Enums/__init__.py +459 -0
  52. SymfWebAPI/WebAPI/Interface/FKF/AccountsChart/Interfaces/IFKAccountsChartController/__init__.py +42 -0
  53. SymfWebAPI/WebAPI/Interface/FKF/AccountsChart/Interfaces/IFKAccountsChartController/_common.py +17 -0
  54. SymfWebAPI/WebAPI/Interface/FKF/AccountsChart/Interfaces/IFKAccountsChartController/_ops.py +20 -0
  55. SymfWebAPI/WebAPI/Interface/FKF/AccountsChart/Interfaces/__init__.py +21 -0
  56. SymfWebAPI/WebAPI/Interface/FKF/AccountsChart/ViewModels/__init__.py +30 -0
  57. SymfWebAPI/WebAPI/Interface/FKF/AccountsChart/__init__.py +22 -0
  58. SymfWebAPI/WebAPI/Interface/FKF/Calculations/Interfaces/IFKCalculationsBusinessController/__init__.py +28 -0
  59. SymfWebAPI/WebAPI/Interface/FKF/Calculations/Interfaces/IFKCalculationsBusinessController/_common.py +9 -0
  60. SymfWebAPI/WebAPI/Interface/FKF/Calculations/Interfaces/IFKCalculationsBusinessController/_ops.py +14 -0
  61. SymfWebAPI/WebAPI/Interface/FKF/Calculations/Interfaces/IFKCalculationsController/__init__.py +478 -0
  62. SymfWebAPI/WebAPI/Interface/FKF/Calculations/Interfaces/IFKCalculationsController/_common.py +353 -0
  63. SymfWebAPI/WebAPI/Interface/FKF/Calculations/Interfaces/IFKCalculationsController/_ops.py +208 -0
  64. SymfWebAPI/WebAPI/Interface/FKF/Calculations/Interfaces/__init__.py +22 -0
  65. SymfWebAPI/WebAPI/Interface/FKF/Calculations/ViewModels/__init__.py +149 -0
  66. SymfWebAPI/WebAPI/Interface/FKF/Calculations/__init__.py +22 -0
  67. SymfWebAPI/WebAPI/Interface/FKF/Common/Interfaces/IFKCurrenciesTablesController/__init__.py +56 -0
  68. SymfWebAPI/WebAPI/Interface/FKF/Common/Interfaces/IFKCurrenciesTablesController/_common.py +33 -0
  69. SymfWebAPI/WebAPI/Interface/FKF/Common/Interfaces/IFKCurrenciesTablesController/_ops.py +26 -0
  70. SymfWebAPI/WebAPI/Interface/FKF/Common/Interfaces/IFKYearsController/__init__.py +27 -0
  71. SymfWebAPI/WebAPI/Interface/FKF/Common/Interfaces/IFKYearsController/_common.py +9 -0
  72. SymfWebAPI/WebAPI/Interface/FKF/Common/Interfaces/IFKYearsController/_ops.py +12 -0
  73. SymfWebAPI/WebAPI/Interface/FKF/Common/Interfaces/__init__.py +22 -0
  74. SymfWebAPI/WebAPI/Interface/FKF/Common/ViewModels/CriteriaFilter/__init__.py +14 -0
  75. SymfWebAPI/WebAPI/Interface/FKF/Common/ViewModels/__init__.py +50 -0
  76. SymfWebAPI/WebAPI/Interface/FKF/Common/__init__.py +22 -0
  77. SymfWebAPI/WebAPI/Interface/FKF/Contractors/Interfaces/IFKContractorDimensions2Controller/__init__.py +55 -0
  78. SymfWebAPI/WebAPI/Interface/FKF/Contractors/Interfaces/IFKContractorDimensions2Controller/_common.py +24 -0
  79. SymfWebAPI/WebAPI/Interface/FKF/Contractors/Interfaces/IFKContractorDimensions2Controller/_ops.py +25 -0
  80. SymfWebAPI/WebAPI/Interface/FKF/Contractors/Interfaces/IFKContractorDimensionsController/__init__.py +97 -0
  81. SymfWebAPI/WebAPI/Interface/FKF/Contractors/Interfaces/IFKContractorDimensionsController/_common.py +47 -0
  82. SymfWebAPI/WebAPI/Interface/FKF/Contractors/Interfaces/IFKContractorDimensionsController/_ops.py +37 -0
  83. SymfWebAPI/WebAPI/Interface/FKF/Contractors/Interfaces/IFKContractorsController/__init__.py +158 -0
  84. SymfWebAPI/WebAPI/Interface/FKF/Contractors/Interfaces/IFKContractorsController/_common.py +73 -0
  85. SymfWebAPI/WebAPI/Interface/FKF/Contractors/Interfaces/IFKContractorsController/_ops.py +70 -0
  86. SymfWebAPI/WebAPI/Interface/FKF/Contractors/Interfaces/__init__.py +23 -0
  87. SymfWebAPI/WebAPI/Interface/FKF/Contractors/ViewModels/V2026_1/__init__.py +35 -0
  88. SymfWebAPI/WebAPI/Interface/FKF/Contractors/ViewModels/__init__.py +79 -0
  89. SymfWebAPI/WebAPI/Interface/FKF/Contractors/__init__.py +22 -0
  90. SymfWebAPI/WebAPI/Interface/FKF/Dimensions/Interfaces/IFKDimensionsController/__init__.py +42 -0
  91. SymfWebAPI/WebAPI/Interface/FKF/Dimensions/Interfaces/IFKDimensionsController/_common.py +19 -0
  92. SymfWebAPI/WebAPI/Interface/FKF/Dimensions/Interfaces/IFKDimensionsController/_ops.py +20 -0
  93. SymfWebAPI/WebAPI/Interface/FKF/Dimensions/Interfaces/__init__.py +21 -0
  94. SymfWebAPI/WebAPI/Interface/FKF/Dimensions/__init__.py +21 -0
  95. SymfWebAPI/WebAPI/Interface/FKF/Documents/Interfaces/IFKDocumentAttachmentsController/__init__.py +41 -0
  96. SymfWebAPI/WebAPI/Interface/FKF/Documents/Interfaces/IFKDocumentAttachmentsController/_common.py +19 -0
  97. SymfWebAPI/WebAPI/Interface/FKF/Documents/Interfaces/IFKDocumentAttachmentsController/_ops.py +14 -0
  98. SymfWebAPI/WebAPI/Interface/FKF/Documents/Interfaces/IFKDocumentLinksController/__init__.py +41 -0
  99. SymfWebAPI/WebAPI/Interface/FKF/Documents/Interfaces/IFKDocumentLinksController/_common.py +19 -0
  100. SymfWebAPI/WebAPI/Interface/FKF/Documents/Interfaces/IFKDocumentLinksController/_ops.py +14 -0
  101. SymfWebAPI/WebAPI/Interface/FKF/Documents/Interfaces/IFKDocumentsBusinessIssueController/__init__.py +70 -0
  102. SymfWebAPI/WebAPI/Interface/FKF/Documents/Interfaces/IFKDocumentsBusinessIssueController/_common.py +27 -0
  103. SymfWebAPI/WebAPI/Interface/FKF/Documents/Interfaces/IFKDocumentsBusinessIssueController/_ops.py +31 -0
  104. SymfWebAPI/WebAPI/Interface/FKF/Documents/Interfaces/IFKDocumentsController/__init__.py +161 -0
  105. SymfWebAPI/WebAPI/Interface/FKF/Documents/Interfaces/IFKDocumentsController/_common.py +91 -0
  106. SymfWebAPI/WebAPI/Interface/FKF/Documents/Interfaces/IFKDocumentsController/_ops.py +75 -0
  107. SymfWebAPI/WebAPI/Interface/FKF/Documents/Interfaces/IFKDocumentsIssueController/__init__.py +43 -0
  108. SymfWebAPI/WebAPI/Interface/FKF/Documents/Interfaces/IFKDocumentsIssueController/_common.py +15 -0
  109. SymfWebAPI/WebAPI/Interface/FKF/Documents/Interfaces/IFKDocumentsIssueController/_ops.py +21 -0
  110. SymfWebAPI/WebAPI/Interface/FKF/Documents/Interfaces/__init__.py +25 -0
  111. SymfWebAPI/WebAPI/Interface/FKF/Documents/ViewModels/Issue/Business/__init__.py +75 -0
  112. SymfWebAPI/WebAPI/Interface/FKF/Documents/ViewModels/Issue/Custom/__init__.py +151 -0
  113. SymfWebAPI/WebAPI/Interface/FKF/Documents/ViewModels/Issue/__init__.py +12 -0
  114. SymfWebAPI/WebAPI/Interface/FKF/Documents/ViewModels/Rdf/__init__.py +13 -0
  115. SymfWebAPI/WebAPI/Interface/FKF/Documents/ViewModels/Transactions/__init__.py +33 -0
  116. SymfWebAPI/WebAPI/Interface/FKF/Documents/ViewModels/V2026_1/__init__.py +73 -0
  117. SymfWebAPI/WebAPI/Interface/FKF/Documents/ViewModels/__init__.py +227 -0
  118. SymfWebAPI/WebAPI/Interface/FKF/Documents/__init__.py +22 -0
  119. SymfWebAPI/WebAPI/Interface/FKF/Employees/Interfaces/IFKEmployeesController/__init__.py +99 -0
  120. SymfWebAPI/WebAPI/Interface/FKF/Employees/Interfaces/IFKEmployeesController/_common.py +45 -0
  121. SymfWebAPI/WebAPI/Interface/FKF/Employees/Interfaces/IFKEmployeesController/_ops.py +42 -0
  122. SymfWebAPI/WebAPI/Interface/FKF/Employees/Interfaces/__init__.py +21 -0
  123. SymfWebAPI/WebAPI/Interface/FKF/Employees/ViewModels/__init__.py +30 -0
  124. SymfWebAPI/WebAPI/Interface/FKF/Employees/__init__.py +22 -0
  125. SymfWebAPI/WebAPI/Interface/FKF/__init__.py +27 -0
  126. SymfWebAPI/WebAPI/Interface/HMF/Develogic/Interfaces/IDevelogicPurchasesController/__init__.py +28 -0
  127. SymfWebAPI/WebAPI/Interface/HMF/Develogic/Interfaces/IDevelogicPurchasesController/_common.py +10 -0
  128. SymfWebAPI/WebAPI/Interface/HMF/Develogic/Interfaces/IDevelogicPurchasesController/_ops.py +13 -0
  129. SymfWebAPI/WebAPI/Interface/HMF/Develogic/Interfaces/IDevelogicSalesController/__init__.py +58 -0
  130. SymfWebAPI/WebAPI/Interface/HMF/Develogic/Interfaces/IDevelogicSalesController/_common.py +27 -0
  131. SymfWebAPI/WebAPI/Interface/HMF/Develogic/Interfaces/IDevelogicSalesController/_ops.py +27 -0
  132. SymfWebAPI/WebAPI/Interface/HMF/Develogic/Interfaces/__init__.py +22 -0
  133. SymfWebAPI/WebAPI/Interface/HMF/Develogic/ViewModels/V2026_1/__init__.py +62 -0
  134. SymfWebAPI/WebAPI/Interface/HMF/Develogic/ViewModels/__init__.py +69 -0
  135. SymfWebAPI/WebAPI/Interface/HMF/Develogic/__init__.py +22 -0
  136. SymfWebAPI/WebAPI/Interface/HMF/__init__.py +21 -0
  137. SymfWebAPI/WebAPI/Interface/Interfaces/ISessionController/__init__.py +34 -0
  138. SymfWebAPI/WebAPI/Interface/Interfaces/ISessionController/_common.py +10 -0
  139. SymfWebAPI/WebAPI/Interface/Interfaces/ISessionController/_ops.py +9 -0
  140. SymfWebAPI/WebAPI/Interface/Interfaces/__init__.py +21 -0
  141. SymfWebAPI/WebAPI/Interface/InventoryStates/Interfaces/IInventoryStatesController/__init__.py +98 -0
  142. SymfWebAPI/WebAPI/Interface/InventoryStates/Interfaces/IInventoryStatesController/_common.py +46 -0
  143. SymfWebAPI/WebAPI/Interface/InventoryStates/Interfaces/IInventoryStatesController/_ops.py +44 -0
  144. SymfWebAPI/WebAPI/Interface/InventoryStates/Interfaces/__init__.py +21 -0
  145. SymfWebAPI/WebAPI/Interface/InventoryStates/ViewModels/__init__.py +11 -0
  146. SymfWebAPI/WebAPI/Interface/InventoryStates/__init__.py +22 -0
  147. SymfWebAPI/WebAPI/Interface/OSS/Interfaces/IOssContractorsController/__init__.py +55 -0
  148. SymfWebAPI/WebAPI/Interface/OSS/Interfaces/IOssContractorsController/_common.py +24 -0
  149. SymfWebAPI/WebAPI/Interface/OSS/Interfaces/IOssContractorsController/_ops.py +22 -0
  150. SymfWebAPI/WebAPI/Interface/OSS/Interfaces/IOssOrderController/__init__.py +58 -0
  151. SymfWebAPI/WebAPI/Interface/OSS/Interfaces/IOssOrderController/_common.py +25 -0
  152. SymfWebAPI/WebAPI/Interface/OSS/Interfaces/IOssOrderController/_ops.py +28 -0
  153. SymfWebAPI/WebAPI/Interface/OSS/Interfaces/IOssProductController/__init__.py +55 -0
  154. SymfWebAPI/WebAPI/Interface/OSS/Interfaces/IOssProductController/_common.py +24 -0
  155. SymfWebAPI/WebAPI/Interface/OSS/Interfaces/IOssProductController/_ops.py +24 -0
  156. SymfWebAPI/WebAPI/Interface/OSS/Interfaces/IOssProductMapsController/__init__.py +84 -0
  157. SymfWebAPI/WebAPI/Interface/OSS/Interfaces/IOssProductMapsController/_common.py +37 -0
  158. SymfWebAPI/WebAPI/Interface/OSS/Interfaces/IOssProductMapsController/_ops.py +36 -0
  159. SymfWebAPI/WebAPI/Interface/OSS/Interfaces/IOssReportsController/__init__.py +55 -0
  160. SymfWebAPI/WebAPI/Interface/OSS/Interfaces/IOssReportsController/_common.py +24 -0
  161. SymfWebAPI/WebAPI/Interface/OSS/Interfaces/IOssReportsController/_ops.py +24 -0
  162. SymfWebAPI/WebAPI/Interface/OSS/Interfaces/IOssSaleController/__init__.py +58 -0
  163. SymfWebAPI/WebAPI/Interface/OSS/Interfaces/IOssSaleController/_common.py +27 -0
  164. SymfWebAPI/WebAPI/Interface/OSS/Interfaces/IOssSaleController/_ops.py +28 -0
  165. SymfWebAPI/WebAPI/Interface/OSS/Interfaces/__init__.py +26 -0
  166. SymfWebAPI/WebAPI/Interface/OSS/ViewModels/Common/__init__.py +35 -0
  167. SymfWebAPI/WebAPI/Interface/OSS/ViewModels/Orders/__init__.py +64 -0
  168. SymfWebAPI/WebAPI/Interface/OSS/ViewModels/Sales/V2026_1/__init__.py +43 -0
  169. SymfWebAPI/WebAPI/Interface/OSS/ViewModels/Sales/__init__.py +85 -0
  170. SymfWebAPI/WebAPI/Interface/OSS/ViewModels/__init__.py +38 -0
  171. SymfWebAPI/WebAPI/Interface/OSS/__init__.py +22 -0
  172. SymfWebAPI/WebAPI/Interface/Orders/Interfaces/IOrderDimensions2Controller/__init__.py +70 -0
  173. SymfWebAPI/WebAPI/Interface/Orders/Interfaces/IOrderDimensions2Controller/_common.py +33 -0
  174. SymfWebAPI/WebAPI/Interface/Orders/Interfaces/IOrderDimensions2Controller/_ops.py +32 -0
  175. SymfWebAPI/WebAPI/Interface/Orders/Interfaces/IOrderDimensionsController/__init__.py +128 -0
  176. SymfWebAPI/WebAPI/Interface/Orders/Interfaces/IOrderDimensionsController/_common.py +63 -0
  177. SymfWebAPI/WebAPI/Interface/Orders/Interfaces/IOrderDimensionsController/_ops.py +52 -0
  178. SymfWebAPI/WebAPI/Interface/Orders/Interfaces/IOrdersController/__init__.py +236 -0
  179. SymfWebAPI/WebAPI/Interface/Orders/Interfaces/IOrdersController/_common.py +130 -0
  180. SymfWebAPI/WebAPI/Interface/Orders/Interfaces/IOrdersController/_ops.py +110 -0
  181. SymfWebAPI/WebAPI/Interface/Orders/Interfaces/IOrdersIssueController/__init__.py +115 -0
  182. SymfWebAPI/WebAPI/Interface/Orders/Interfaces/IOrdersIssueController/_common.py +55 -0
  183. SymfWebAPI/WebAPI/Interface/Orders/Interfaces/IOrdersIssueController/_ops.py +49 -0
  184. SymfWebAPI/WebAPI/Interface/Orders/Interfaces/__init__.py +24 -0
  185. SymfWebAPI/WebAPI/Interface/Orders/ViewModels/__init__.py +302 -0
  186. SymfWebAPI/WebAPI/Interface/Orders/__init__.py +22 -0
  187. SymfWebAPI/WebAPI/Interface/OwnOrders/Interfaces/IOwnOrderDimensions2Controller/__init__.py +70 -0
  188. SymfWebAPI/WebAPI/Interface/OwnOrders/Interfaces/IOwnOrderDimensions2Controller/_common.py +33 -0
  189. SymfWebAPI/WebAPI/Interface/OwnOrders/Interfaces/IOwnOrderDimensions2Controller/_ops.py +32 -0
  190. SymfWebAPI/WebAPI/Interface/OwnOrders/Interfaces/IOwnOrderDimensionsController/__init__.py +128 -0
  191. SymfWebAPI/WebAPI/Interface/OwnOrders/Interfaces/IOwnOrderDimensionsController/_common.py +63 -0
  192. SymfWebAPI/WebAPI/Interface/OwnOrders/Interfaces/IOwnOrderDimensionsController/_ops.py +52 -0
  193. SymfWebAPI/WebAPI/Interface/OwnOrders/Interfaces/IOwnOrdersController/__init__.py +207 -0
  194. SymfWebAPI/WebAPI/Interface/OwnOrders/Interfaces/IOwnOrdersController/_common.py +115 -0
  195. SymfWebAPI/WebAPI/Interface/OwnOrders/Interfaces/IOwnOrdersController/_ops.py +97 -0
  196. SymfWebAPI/WebAPI/Interface/OwnOrders/Interfaces/IOwnOrdersIssueController/__init__.py +99 -0
  197. SymfWebAPI/WebAPI/Interface/OwnOrders/Interfaces/IOwnOrdersIssueController/_common.py +47 -0
  198. SymfWebAPI/WebAPI/Interface/OwnOrders/Interfaces/IOwnOrdersIssueController/_ops.py +39 -0
  199. SymfWebAPI/WebAPI/Interface/OwnOrders/Interfaces/__init__.py +24 -0
  200. SymfWebAPI/WebAPI/Interface/OwnOrders/ViewModels/__init__.py +205 -0
  201. SymfWebAPI/WebAPI/Interface/OwnOrders/__init__.py +22 -0
  202. SymfWebAPI/WebAPI/Interface/Payments/Interfaces/IPaymentsController/__init__.py +189 -0
  203. SymfWebAPI/WebAPI/Interface/Payments/Interfaces/IPaymentsController/_common.py +104 -0
  204. SymfWebAPI/WebAPI/Interface/Payments/Interfaces/IPaymentsController/_ops.py +85 -0
  205. SymfWebAPI/WebAPI/Interface/Payments/Interfaces/ISettlementsController/__init__.py +114 -0
  206. SymfWebAPI/WebAPI/Interface/Payments/Interfaces/ISettlementsController/_common.py +69 -0
  207. SymfWebAPI/WebAPI/Interface/Payments/Interfaces/ISettlementsController/_ops.py +48 -0
  208. SymfWebAPI/WebAPI/Interface/Payments/Interfaces/__init__.py +22 -0
  209. SymfWebAPI/WebAPI/Interface/Payments/ViewModels/Issue/__init__.py +38 -0
  210. SymfWebAPI/WebAPI/Interface/Payments/ViewModels/IssueKP/__init__.py +30 -0
  211. SymfWebAPI/WebAPI/Interface/Payments/ViewModels/__init__.py +124 -0
  212. SymfWebAPI/WebAPI/Interface/Payments/__init__.py +22 -0
  213. SymfWebAPI/WebAPI/Interface/Products/Interfaces/IPriceListsController/__init__.py +42 -0
  214. SymfWebAPI/WebAPI/Interface/Products/Interfaces/IPriceListsController/_common.py +16 -0
  215. SymfWebAPI/WebAPI/Interface/Products/Interfaces/IPriceListsController/_ops.py +20 -0
  216. SymfWebAPI/WebAPI/Interface/Products/Interfaces/IProductDimensions2Controller/__init__.py +27 -0
  217. SymfWebAPI/WebAPI/Interface/Products/Interfaces/IProductDimensions2Controller/_common.py +10 -0
  218. SymfWebAPI/WebAPI/Interface/Products/Interfaces/IProductDimensions2Controller/_ops.py +13 -0
  219. SymfWebAPI/WebAPI/Interface/Products/Interfaces/IProductDimensionsController/__init__.py +41 -0
  220. SymfWebAPI/WebAPI/Interface/Products/Interfaces/IProductDimensionsController/_common.py +19 -0
  221. SymfWebAPI/WebAPI/Interface/Products/Interfaces/IProductDimensionsController/_ops.py +17 -0
  222. SymfWebAPI/WebAPI/Interface/Products/Interfaces/IProductPhotosController/__init__.py +28 -0
  223. SymfWebAPI/WebAPI/Interface/Products/Interfaces/IProductPhotosController/_common.py +11 -0
  224. SymfWebAPI/WebAPI/Interface/Products/Interfaces/IProductPhotosController/_ops.py +13 -0
  225. SymfWebAPI/WebAPI/Interface/Products/Interfaces/IProductPricesController/__init__.py +178 -0
  226. SymfWebAPI/WebAPI/Interface/Products/Interfaces/IProductPricesController/_common.py +77 -0
  227. SymfWebAPI/WebAPI/Interface/Products/Interfaces/IProductPricesController/_ops.py +80 -0
  228. SymfWebAPI/WebAPI/Interface/Products/Interfaces/IProductsController/__init__.py +247 -0
  229. SymfWebAPI/WebAPI/Interface/Products/Interfaces/IProductsController/_common.py +113 -0
  230. SymfWebAPI/WebAPI/Interface/Products/Interfaces/IProductsController/_ops.py +109 -0
  231. SymfWebAPI/WebAPI/Interface/Products/Interfaces/__init__.py +26 -0
  232. SymfWebAPI/WebAPI/Interface/Products/ViewModels/PriceCalculations/__init__.py +91 -0
  233. SymfWebAPI/WebAPI/Interface/Products/ViewModels/PriceLists/__init__.py +60 -0
  234. SymfWebAPI/WebAPI/Interface/Products/ViewModels/Prices/__init__.py +128 -0
  235. SymfWebAPI/WebAPI/Interface/Products/ViewModels/__init__.py +217 -0
  236. SymfWebAPI/WebAPI/Interface/Products/__init__.py +22 -0
  237. SymfWebAPI/WebAPI/Interface/Purchases/Interfaces/IPurchasesController/__init__.py +221 -0
  238. SymfWebAPI/WebAPI/Interface/Purchases/Interfaces/IPurchasesController/_common.py +124 -0
  239. SymfWebAPI/WebAPI/Interface/Purchases/Interfaces/IPurchasesController/_ops.py +103 -0
  240. SymfWebAPI/WebAPI/Interface/Purchases/Interfaces/IPurchasesDimensions2Controller/__init__.py +70 -0
  241. SymfWebAPI/WebAPI/Interface/Purchases/Interfaces/IPurchasesDimensions2Controller/_common.py +33 -0
  242. SymfWebAPI/WebAPI/Interface/Purchases/Interfaces/IPurchasesDimensions2Controller/_ops.py +32 -0
  243. SymfWebAPI/WebAPI/Interface/Purchases/Interfaces/IPurchasesDimensionsController/__init__.py +128 -0
  244. SymfWebAPI/WebAPI/Interface/Purchases/Interfaces/IPurchasesDimensionsController/_common.py +63 -0
  245. SymfWebAPI/WebAPI/Interface/Purchases/Interfaces/IPurchasesDimensionsController/_ops.py +52 -0
  246. SymfWebAPI/WebAPI/Interface/Purchases/Interfaces/IPurchasesIssueController/__init__.py +86 -0
  247. SymfWebAPI/WebAPI/Interface/Purchases/Interfaces/IPurchasesIssueController/_common.py +40 -0
  248. SymfWebAPI/WebAPI/Interface/Purchases/Interfaces/IPurchasesIssueController/_ops.py +38 -0
  249. SymfWebAPI/WebAPI/Interface/Purchases/Interfaces/__init__.py +24 -0
  250. SymfWebAPI/WebAPI/Interface/Purchases/ViewModels/V2026_1/__init__.py +171 -0
  251. SymfWebAPI/WebAPI/Interface/Purchases/ViewModels/__init__.py +245 -0
  252. SymfWebAPI/WebAPI/Interface/Purchases/__init__.py +22 -0
  253. SymfWebAPI/WebAPI/Interface/RepX/Interfaces/IReportsController/__init__.py +28 -0
  254. SymfWebAPI/WebAPI/Interface/RepX/Interfaces/IReportsController/_common.py +11 -0
  255. SymfWebAPI/WebAPI/Interface/RepX/Interfaces/IReportsController/_ops.py +13 -0
  256. SymfWebAPI/WebAPI/Interface/RepX/Interfaces/__init__.py +21 -0
  257. SymfWebAPI/WebAPI/Interface/RepX/ViewModels/__init__.py +14 -0
  258. SymfWebAPI/WebAPI/Interface/RepX/__init__.py +22 -0
  259. SymfWebAPI/WebAPI/Interface/Reservations/Interfaces/IReservationsController/__init__.py +114 -0
  260. SymfWebAPI/WebAPI/Interface/Reservations/Interfaces/IReservationsController/_common.py +50 -0
  261. SymfWebAPI/WebAPI/Interface/Reservations/Interfaces/IReservationsController/_ops.py +48 -0
  262. SymfWebAPI/WebAPI/Interface/Reservations/Interfaces/__init__.py +21 -0
  263. SymfWebAPI/WebAPI/Interface/Reservations/ViewModels/__init__.py +110 -0
  264. SymfWebAPI/WebAPI/Interface/Reservations/__init__.py +22 -0
  265. SymfWebAPI/WebAPI/Interface/Sales/Interfaces/IFiscalPrinterController/__init__.py +27 -0
  266. SymfWebAPI/WebAPI/Interface/Sales/Interfaces/IFiscalPrinterController/_common.py +10 -0
  267. SymfWebAPI/WebAPI/Interface/Sales/Interfaces/IFiscalPrinterController/_ops.py +12 -0
  268. SymfWebAPI/WebAPI/Interface/Sales/Interfaces/ISalesController/__init__.py +237 -0
  269. SymfWebAPI/WebAPI/Interface/Sales/Interfaces/ISalesController/_common.py +130 -0
  270. SymfWebAPI/WebAPI/Interface/Sales/Interfaces/ISalesController/_ops.py +111 -0
  271. SymfWebAPI/WebAPI/Interface/Sales/Interfaces/ISalesDimensions2Controller/__init__.py +70 -0
  272. SymfWebAPI/WebAPI/Interface/Sales/Interfaces/ISalesDimensions2Controller/_common.py +33 -0
  273. SymfWebAPI/WebAPI/Interface/Sales/Interfaces/ISalesDimensions2Controller/_ops.py +32 -0
  274. SymfWebAPI/WebAPI/Interface/Sales/Interfaces/ISalesDimensionsController/__init__.py +128 -0
  275. SymfWebAPI/WebAPI/Interface/Sales/Interfaces/ISalesDimensionsController/_common.py +63 -0
  276. SymfWebAPI/WebAPI/Interface/Sales/Interfaces/ISalesDimensionsController/_ops.py +52 -0
  277. SymfWebAPI/WebAPI/Interface/Sales/Interfaces/ISalesIssueController/__init__.py +129 -0
  278. SymfWebAPI/WebAPI/Interface/Sales/Interfaces/ISalesIssueController/_common.py +63 -0
  279. SymfWebAPI/WebAPI/Interface/Sales/Interfaces/ISalesIssueController/_ops.py +53 -0
  280. SymfWebAPI/WebAPI/Interface/Sales/Interfaces/__init__.py +25 -0
  281. SymfWebAPI/WebAPI/Interface/Sales/ViewModels/CorrectionIssue/V2026_1/__init__.py +42 -0
  282. SymfWebAPI/WebAPI/Interface/Sales/ViewModels/CorrectionIssue/__init__.py +23 -0
  283. SymfWebAPI/WebAPI/Interface/Sales/ViewModels/DocumentIssue/__init__.py +11 -0
  284. SymfWebAPI/WebAPI/Interface/Sales/ViewModels/__init__.py +325 -0
  285. SymfWebAPI/WebAPI/Interface/Sales/__init__.py +22 -0
  286. SymfWebAPI/WebAPI/Interface/ViewModels/__init__.py +16 -0
  287. SymfWebAPI/WebAPI/Interface/Warehouse/Interfaces/IDeliveriesController/__init__.py +27 -0
  288. SymfWebAPI/WebAPI/Interface/Warehouse/Interfaces/IDeliveriesController/_common.py +11 -0
  289. SymfWebAPI/WebAPI/Interface/Warehouse/Interfaces/IDeliveriesController/_ops.py +13 -0
  290. SymfWebAPI/WebAPI/Interface/Warehouse/Interfaces/IDeliveryDimensionsController/__init__.py +41 -0
  291. SymfWebAPI/WebAPI/Interface/Warehouse/Interfaces/IDeliveryDimensionsController/_common.py +19 -0
  292. SymfWebAPI/WebAPI/Interface/Warehouse/Interfaces/IDeliveryDimensionsController/_ops.py +17 -0
  293. SymfWebAPI/WebAPI/Interface/Warehouse/Interfaces/IWarehouseDocumentDimensions2Controller/__init__.py +70 -0
  294. SymfWebAPI/WebAPI/Interface/Warehouse/Interfaces/IWarehouseDocumentDimensions2Controller/_common.py +33 -0
  295. SymfWebAPI/WebAPI/Interface/Warehouse/Interfaces/IWarehouseDocumentDimensions2Controller/_ops.py +32 -0
  296. SymfWebAPI/WebAPI/Interface/Warehouse/Interfaces/IWarehouseDocumentDimensionsController/__init__.py +128 -0
  297. SymfWebAPI/WebAPI/Interface/Warehouse/Interfaces/IWarehouseDocumentDimensionsController/_common.py +63 -0
  298. SymfWebAPI/WebAPI/Interface/Warehouse/Interfaces/IWarehouseDocumentDimensionsController/_ops.py +52 -0
  299. SymfWebAPI/WebAPI/Interface/Warehouse/Interfaces/IWarehouseDocumentsController/__init__.py +177 -0
  300. SymfWebAPI/WebAPI/Interface/Warehouse/Interfaces/IWarehouseDocumentsController/_common.py +100 -0
  301. SymfWebAPI/WebAPI/Interface/Warehouse/Interfaces/IWarehouseDocumentsController/_ops.py +83 -0
  302. SymfWebAPI/WebAPI/Interface/Warehouse/Interfaces/IWarehouseDocumentsIssueController/__init__.py +85 -0
  303. SymfWebAPI/WebAPI/Interface/Warehouse/Interfaces/IWarehouseDocumentsIssueController/_common.py +38 -0
  304. SymfWebAPI/WebAPI/Interface/Warehouse/Interfaces/IWarehouseDocumentsIssueController/_ops.py +34 -0
  305. SymfWebAPI/WebAPI/Interface/Warehouse/Interfaces/__init__.py +26 -0
  306. SymfWebAPI/WebAPI/Interface/Warehouse/ViewModels/__init__.py +265 -0
  307. SymfWebAPI/WebAPI/Interface/Warehouse/__init__.py +22 -0
  308. SymfWebAPI/WebAPI/Interface/__init__.py +40 -0
  309. SymfWebAPI/WebAPI/__init__.py +21 -0
  310. SymfWebAPI/__init__.py +63 -0
  311. SymfWebAPI/client.py +129 -0
  312. SymfWebAPI/config.py +60 -0
  313. SymfWebAPI/enums.py +36 -0
  314. SymfWebAPI/errors.py +47 -0
  315. SymfWebAPI/executors.py +92 -0
  316. SymfWebAPI/operations.py +116 -0
  317. SymfWebAPI/protocols.py +85 -0
  318. SymfWebAPI/request_engine.py +43 -0
  319. SymfWebAPI/response.py +21 -0
  320. SymfWebAPI/runtime.py +85 -0
  321. SymfWebAPI/session.py +349 -0
  322. SymfWebAPI/transport/__init__.py +9 -0
  323. SymfWebAPI/transport/httpx_async.py +77 -0
  324. SymfWebAPI/transport/httpx_sync.py +78 -0
  325. symfwebapi-1.26.10.1.dist-info/METADATA +78 -0
  326. symfwebapi-1.26.10.1.dist-info/RECORD +329 -0
  327. symfwebapi-1.26.10.1.dist-info/WHEEL +5 -0
  328. symfwebapi-1.26.10.1.dist-info/licenses/LICENSE +29 -0
  329. symfwebapi-1.26.10.1.dist-info/top_level.txt +1 -0
SymfWebAPI/runtime.py ADDED
@@ -0,0 +1,85 @@
1
+ """Fabryki klientów Sync/Async oparte na domyślnych transportach."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Awaitable, Callable, Optional, cast
6
+
7
+ from .client import AsyncAPI, SyncAPI
8
+ from .config import ClientConfig
9
+ from .protocols import AsyncTransportProtocol, SyncTransportProtocol
10
+ from .session import SessionManager, SessionState
11
+ from .transport import AsyncHttpxTransport, SyncHttpxTransport
12
+
13
+
14
+ def build_sync_client(
15
+ config: ClientConfig,
16
+ *,
17
+ transport: SyncTransportProtocol | None = None,
18
+ manage_transport: bool | None = None,
19
+ on_session_open: Optional[Callable[[SessionState], None]] = None,
20
+ on_session_close: Optional[Callable[[SessionState], None]] = None,
21
+ on_session_invalidate: Optional[Callable[[SessionState], None]] = None,
22
+ ) -> SyncAPI:
23
+ """Tworzy w pełni skonfigurowanego SyncAPI."""
24
+
25
+ own_transport = False
26
+ if transport is None:
27
+ transport = SyncHttpxTransport(config)
28
+ own_transport = True
29
+ if manage_transport is not None:
30
+ own_transport = manage_transport
31
+
32
+ session_manager = SessionManager(
33
+ config,
34
+ backend=transport,
35
+ on_open=on_session_open,
36
+ on_close=on_session_close,
37
+ on_invalidate=on_session_invalidate,
38
+ )
39
+ shutdown_hook: Optional[Callable[[], None]] = None
40
+ if own_transport and hasattr(transport, "close"):
41
+ shutdown_hook = cast(Callable[[], None], getattr(transport, "close"))
42
+
43
+ return SyncAPI(
44
+ config,
45
+ session_manager=session_manager,
46
+ request_fn=transport.request,
47
+ shutdown_hook=shutdown_hook,
48
+ )
49
+
50
+
51
+ def build_async_client(
52
+ config: ClientConfig,
53
+ *,
54
+ transport: AsyncTransportProtocol | None = None,
55
+ manage_transport: bool | None = None,
56
+ on_session_open: Optional[Callable[[SessionState], None]] = None,
57
+ on_session_close: Optional[Callable[[SessionState], None]] = None,
58
+ on_session_invalidate: Optional[Callable[[SessionState], None]] = None,
59
+ ) -> AsyncAPI:
60
+ """Tworzy AsyncAPI gotowe do użycia."""
61
+
62
+ own_transport = False
63
+ if transport is None:
64
+ transport = AsyncHttpxTransport(config)
65
+ own_transport = True
66
+ if manage_transport is not None:
67
+ own_transport = manage_transport
68
+
69
+ session_manager = SessionManager(
70
+ config,
71
+ backend=transport,
72
+ on_open=on_session_open,
73
+ on_close=on_session_close,
74
+ on_invalidate=on_session_invalidate,
75
+ )
76
+ shutdown_hook: Optional[Callable[[], Awaitable[None]]] = None
77
+ if own_transport and hasattr(transport, "aclose"):
78
+ shutdown_hook = cast(Callable[[], Awaitable[None]], getattr(transport, "aclose"))
79
+
80
+ return AsyncAPI(
81
+ config,
82
+ session_manager=session_manager,
83
+ request_fn=transport.request,
84
+ shutdown_hook=shutdown_hook,
85
+ )
SymfWebAPI/session.py ADDED
@@ -0,0 +1,349 @@
1
+ """Zarządzanie sesją WebAPI (handshake, odświeżanie, zamykanie)."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import asyncio
6
+ from dataclasses import dataclass
7
+ from datetime import datetime, timedelta, timezone
8
+ import logging
9
+ import threading
10
+ from typing import Optional, Protocol, Callable, Any
11
+
12
+ from .config import ClientConfig
13
+
14
+
15
+ class SessionBackend(Protocol):
16
+ """Minimalny interfejs backendu wykonującego żądania sesyjne."""
17
+
18
+ async def open_async(self, device_name: str) -> str:
19
+ """Zwraca nowy token sesyjny."""
20
+
21
+ def open_sync(self, device_name: str) -> str:
22
+ """Wariant synchroniczny."""
23
+
24
+ async def close_async(self, token: str) -> None:
25
+ """Zamyka wskazaną sesję."""
26
+
27
+ def close_sync(self, token: str) -> None:
28
+ """Wariant synchroniczny."""
29
+
30
+
31
+ @dataclass(slots=True)
32
+ class SessionState:
33
+ token: Optional[str] = None
34
+ opened_at: Optional[datetime] = None
35
+ expires_at: Optional[datetime] = None
36
+
37
+ def is_expired(self, *, max_age: Optional[timedelta], now: Optional[datetime] = None) -> bool:
38
+ if not self.token:
39
+ return True
40
+ now = now or datetime.now(timezone.utc)
41
+ if self.expires_at and now >= self.expires_at:
42
+ return True
43
+ if max_age and self.opened_at:
44
+ return now - self.opened_at >= max_age
45
+ return False
46
+
47
+
48
+ class _SharedSessionState:
49
+ """Thread-safe shared state used by sync/async session managers."""
50
+
51
+ def __init__(self, config: ClientConfig) -> None:
52
+ self._config = config
53
+ self.state = SessionState()
54
+ self.lock = threading.RLock()
55
+ self.condition = threading.Condition(self.lock)
56
+ self.refreshing = False
57
+ self._async_waiters: list[tuple[Any, Any]] = []
58
+
59
+ def is_fresh(self) -> bool:
60
+ return not self.state.is_expired(max_age=self._config.max_session_age)
61
+
62
+ def wait_for_refresh_locked(self) -> None:
63
+ while self.refreshing:
64
+ self.condition.wait()
65
+
66
+ async def wait_for_refresh_async(self) -> None:
67
+ loop = asyncio.get_running_loop()
68
+ with self.lock:
69
+ if not self.refreshing:
70
+ return
71
+ future = loop.create_future()
72
+ self._async_waiters.append((loop, future))
73
+
74
+ try:
75
+ await future
76
+ finally:
77
+ with self.lock:
78
+ self._async_waiters = [
79
+ (registered_loop, registered_future)
80
+ for registered_loop, registered_future in self._async_waiters
81
+ if registered_future is not future
82
+ ]
83
+
84
+ def _notify_async_waiters_locked(self) -> None:
85
+ for loop, future in self._async_waiters:
86
+ if future.done():
87
+ continue
88
+ try:
89
+ loop.call_soon_threadsafe(future.set_result, None)
90
+ except RuntimeError:
91
+ continue
92
+ self._async_waiters.clear()
93
+
94
+ def fail_refresh(self) -> None:
95
+ with self.lock:
96
+ self.refreshing = False
97
+ self.condition.notify_all()
98
+ self._notify_async_waiters_locked()
99
+
100
+ def commit_refresh(self, token: str) -> SessionState:
101
+ now = datetime.now(timezone.utc)
102
+ expires_at = now + self._config.max_session_age if self._config.max_session_age else None
103
+ new_state = SessionState(token=token, opened_at=now, expires_at=expires_at)
104
+ with self.lock:
105
+ self.state = new_state
106
+ self.refreshing = False
107
+ self.condition.notify_all()
108
+ self._notify_async_waiters_locked()
109
+ return self.state
110
+
111
+
112
+ class SyncSessionManager:
113
+ """Synchronous session lifecycle coordinator."""
114
+
115
+ def __init__(
116
+ self,
117
+ config: ClientConfig,
118
+ backend: SessionBackend,
119
+ shared_state: Optional[_SharedSessionState] = None,
120
+ *,
121
+ logger: logging.Logger,
122
+ on_open: Optional[Callable[[SessionState], None]] = None,
123
+ on_close: Optional[Callable[[SessionState], None]] = None,
124
+ on_invalidate: Optional[Callable[[SessionState], None]] = None,
125
+ ) -> None:
126
+ self._config = config
127
+ self._backend = backend
128
+ self._shared = shared_state or _SharedSessionState(config)
129
+ self._logger = logger
130
+ self._on_open = on_open
131
+ self._on_close = on_close
132
+ self._on_invalidate = on_invalidate
133
+
134
+ @property
135
+ def state(self) -> SessionState:
136
+ return self._shared.state
137
+
138
+ def _close_previous_sync(self, previous_state: SessionState) -> None:
139
+ token = previous_state.token
140
+ if not token:
141
+ return
142
+ try:
143
+ self._backend.close_sync(token)
144
+ self._logger.info("Closed previous sync session for device=%s", self._config.device_name)
145
+ if self._on_close:
146
+ self._on_close(previous_state)
147
+ except Exception:
148
+ self._logger.warning(
149
+ "Failed to close previous sync session for device=%s",
150
+ self._config.device_name,
151
+ exc_info=True,
152
+ )
153
+
154
+ def ensure_sync(self) -> SessionState:
155
+ while True:
156
+ with self._shared.lock:
157
+ if self._shared.is_fresh():
158
+ return self._shared.state
159
+ if self._shared.refreshing:
160
+ self._shared.wait_for_refresh_locked()
161
+ continue
162
+ self._shared.refreshing = True
163
+ previous_state = self._shared.state
164
+
165
+ try:
166
+ self._close_previous_sync(previous_state)
167
+ token = self._backend.open_sync(self._config.device_name)
168
+ except Exception:
169
+ self._shared.fail_refresh()
170
+ raise
171
+
172
+ new_state = self._shared.commit_refresh(token)
173
+ self._logger.info("Opened sync session for device=%s", self._config.device_name)
174
+ if self._on_open:
175
+ self._on_open(new_state)
176
+ return new_state
177
+
178
+ def close_sync(self) -> None:
179
+ with self._shared.lock:
180
+ self._shared.wait_for_refresh_locked()
181
+ if not self._shared.state.token:
182
+ return
183
+ token = self._shared.state.token
184
+ prev_state = self._shared.state
185
+ self._shared.state = SessionState()
186
+ self._shared.condition.notify_all()
187
+
188
+ try:
189
+ self._backend.close_sync(token)
190
+ self._logger.info("Closed sync session for device=%s", self._config.device_name)
191
+ finally:
192
+ if self._on_close:
193
+ self._on_close(prev_state)
194
+
195
+ def invalidate(self) -> None:
196
+ with self._shared.lock:
197
+ self._shared.wait_for_refresh_locked()
198
+ if self._shared.state.token:
199
+ self._logger.info("Invalidated session for device=%s", self._config.device_name)
200
+ if self._on_invalidate:
201
+ self._on_invalidate(self._shared.state)
202
+ self._shared.state = SessionState()
203
+ self._shared.condition.notify_all()
204
+
205
+
206
+ class AsyncSessionManager:
207
+ """Asynchronous session lifecycle coordinator."""
208
+
209
+ def __init__(
210
+ self,
211
+ config: ClientConfig,
212
+ backend: SessionBackend,
213
+ shared_state: Optional[_SharedSessionState] = None,
214
+ *,
215
+ logger: logging.Logger,
216
+ on_open: Optional[Callable[[SessionState], None]] = None,
217
+ on_close: Optional[Callable[[SessionState], None]] = None,
218
+ ) -> None:
219
+ self._config = config
220
+ self._backend = backend
221
+ self._shared = shared_state or _SharedSessionState(config)
222
+ self._logger = logger
223
+ self._on_open = on_open
224
+ self._on_close = on_close
225
+
226
+ @property
227
+ def state(self) -> SessionState:
228
+ return self._shared.state
229
+
230
+ async def _close_previous_async(self, previous_state: SessionState) -> None:
231
+ token = previous_state.token
232
+ if not token:
233
+ return
234
+ try:
235
+ await self._backend.close_async(token)
236
+ self._logger.info("Closed previous async session for device=%s", self._config.device_name)
237
+ if self._on_close:
238
+ self._on_close(previous_state)
239
+ except Exception:
240
+ self._logger.warning(
241
+ "Failed to close previous async session for device=%s",
242
+ self._config.device_name,
243
+ exc_info=True,
244
+ )
245
+
246
+ async def ensure_async(self) -> SessionState:
247
+ while True:
248
+ # Hot path: in steady state most async calls only need to read
249
+ # the current token and skip lock/condition coordination.
250
+ current = self._shared.state
251
+ if not current.is_expired(max_age=self._config.max_session_age):
252
+ return current
253
+
254
+ with self._shared.lock:
255
+ if self._shared.is_fresh():
256
+ return self._shared.state
257
+ if self._shared.refreshing:
258
+ should_refresh = False
259
+ else:
260
+ self._shared.refreshing = True
261
+ previous_state = self._shared.state
262
+ should_refresh = True
263
+
264
+ if not should_refresh:
265
+ await self._shared.wait_for_refresh_async()
266
+ continue
267
+
268
+ try:
269
+ await self._close_previous_async(previous_state)
270
+ token = await self._backend.open_async(self._config.device_name)
271
+ except Exception:
272
+ self._shared.fail_refresh()
273
+ raise
274
+
275
+ new_state = self._shared.commit_refresh(token)
276
+ self._logger.info("Opened async session for device=%s", self._config.device_name)
277
+ if self._on_open:
278
+ self._on_open(new_state)
279
+ return new_state
280
+
281
+ async def close_async(self) -> None:
282
+ await self._shared.wait_for_refresh_async()
283
+ with self._shared.lock:
284
+ if not self._shared.state.token:
285
+ return
286
+ token = self._shared.state.token
287
+ prev_state = self._shared.state
288
+ self._shared.state = SessionState()
289
+ self._shared.condition.notify_all()
290
+
291
+ try:
292
+ await self._backend.close_async(token)
293
+ self._logger.info("Closed async session for device=%s", self._config.device_name)
294
+ finally:
295
+ if self._on_close:
296
+ self._on_close(prev_state)
297
+
298
+
299
+ class SessionManager:
300
+ """Backward-compatible facade coordinating sync and async session managers."""
301
+
302
+ def __init__(
303
+ self,
304
+ config: ClientConfig,
305
+ backend: SessionBackend,
306
+ *,
307
+ on_open: Optional[Callable[[SessionState], None]] = None,
308
+ on_close: Optional[Callable[[SessionState], None]] = None,
309
+ on_invalidate: Optional[Callable[[SessionState], None]] = None,
310
+ ):
311
+ logger = logging.getLogger(__name__)
312
+ shared_state = _SharedSessionState(config)
313
+ self._sync = SyncSessionManager(
314
+ config,
315
+ backend,
316
+ shared_state,
317
+ logger=logger,
318
+ on_open=on_open,
319
+ on_close=on_close,
320
+ on_invalidate=on_invalidate,
321
+ )
322
+ self._async = AsyncSessionManager(
323
+ config,
324
+ backend,
325
+ shared_state,
326
+ logger=logger,
327
+ on_open=on_open,
328
+ on_close=on_close,
329
+ )
330
+
331
+ @property
332
+ def state(self) -> SessionState:
333
+ return self._sync.state
334
+
335
+ async def ensure_async(self) -> SessionState:
336
+ return await self._async.ensure_async()
337
+
338
+ def ensure_sync(self) -> SessionState:
339
+ return self._sync.ensure_sync()
340
+
341
+ async def close_async(self) -> None:
342
+ await self._async.close_async()
343
+
344
+ def close_sync(self) -> None:
345
+ self._sync.close_sync()
346
+
347
+ def invalidate(self) -> None:
348
+ """Czyści lokalny token – użytkownik może wywołać po błędzie 401."""
349
+ self._sync.invalidate()
@@ -0,0 +1,9 @@
1
+ """HTTP transport implementations."""
2
+
3
+ from .httpx_async import AsyncHttpxTransport
4
+ from .httpx_sync import SyncHttpxTransport
5
+
6
+ __all__ = [
7
+ "AsyncHttpxTransport",
8
+ "SyncHttpxTransport",
9
+ ]
@@ -0,0 +1,77 @@
1
+ """Async HTTP transport using httpx."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any, Dict, Optional
6
+
7
+ import httpx
8
+
9
+ from ..config import ClientConfig
10
+ from ..errors import TransportError
11
+ from ..session import SessionBackend
12
+
13
+
14
+ class AsyncHttpxTransport(SessionBackend):
15
+ def __init__(self, config: ClientConfig, *, client: httpx.AsyncClient | None = None) -> None:
16
+ self._config = config
17
+ self._client = client or httpx.AsyncClient(
18
+ base_url=config.base_url,
19
+ timeout=config.request_timeout,
20
+ )
21
+
22
+ async def open_async(self, device_name: str) -> str:
23
+ path = "/api/Sessions/OpenNewSession"
24
+ try:
25
+ response = await self._client.get(
26
+ path,
27
+ params={"deviceName": device_name},
28
+ headers={"Authorization": f"Application {self._config.application_key}"},
29
+ )
30
+ response.raise_for_status()
31
+ return response.text.strip('"')
32
+ except httpx.HTTPError as exc:
33
+ raise TransportError(f"open session failed: {exc}", endpoint=path) from exc
34
+
35
+ def open_sync(self, device_name: str) -> str: # pragma: no cover - async backend
36
+ raise NotImplementedError("Użyj SyncHttpxTransport dla trybu sync")
37
+
38
+ async def close_async(self, token: str) -> None:
39
+ path = "/api/Sessions/CloseSession"
40
+ try:
41
+ response = await self._client.get(
42
+ path,
43
+ headers={"Authorization": f"Session {token}"},
44
+ )
45
+ response.raise_for_status()
46
+ except httpx.HTTPError as exc:
47
+ raise TransportError(f"close session failed: {exc}", endpoint=path) from exc
48
+
49
+ def close_sync(self, token: str) -> None: # pragma: no cover - async backend
50
+ raise NotImplementedError("Użyj SyncHttpxTransport dla trybu sync")
51
+
52
+ async def request(
53
+ self,
54
+ method: str,
55
+ path: str,
56
+ *,
57
+ token: str,
58
+ params: Optional[Dict[str, Any]] = None,
59
+ data: Any = None,
60
+ ) -> httpx.Response:
61
+ headers = {"Authorization": f"Session {token}"}
62
+ request_kwargs: Dict[str, Any] = {"params": params, "headers": headers}
63
+ if data is not None:
64
+ if isinstance(data, (str, bytes, bytearray, memoryview)):
65
+ request_kwargs["content"] = data
66
+ if isinstance(data, str):
67
+ headers["Content-Type"] = "application/json"
68
+ else:
69
+ request_kwargs["json"] = data
70
+ try:
71
+ response = await self._client.request(method, path, **request_kwargs)
72
+ return response
73
+ except httpx.HTTPError as exc:
74
+ raise TransportError(f"request failed: {exc}", endpoint=path) from exc
75
+
76
+ async def aclose(self) -> None:
77
+ await self._client.aclose()
@@ -0,0 +1,78 @@
1
+ """Synchronous HTTP transport oparty o httpx.Client."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Any, Dict, Optional
6
+
7
+ import httpx
8
+
9
+ from ..config import ClientConfig
10
+ from ..errors import TransportError
11
+ from ..session import SessionBackend
12
+
13
+
14
+ class SyncHttpxTransport(SessionBackend):
15
+ """Backend dla SyncAPI bazujący na httpx.Client."""
16
+
17
+ def __init__(self, config: ClientConfig, *, client: httpx.Client | None = None) -> None:
18
+ self._config = config
19
+ self._client = client or httpx.Client(
20
+ base_url=config.base_url,
21
+ timeout=config.request_timeout,
22
+ )
23
+
24
+ async def open_async(self, device_name: str) -> str: # pragma: no cover - sync backend
25
+ raise NotImplementedError("Użyj AsyncHttpxTransport dla trybu async")
26
+
27
+ def open_sync(self, device_name: str) -> str:
28
+ path = "/api/Sessions/OpenNewSession"
29
+ try:
30
+ response = self._client.get(
31
+ path,
32
+ params={"deviceName": device_name},
33
+ headers={"Authorization": f"Application {self._config.application_key}"},
34
+ )
35
+ response.raise_for_status()
36
+ return response.text.strip('"')
37
+ except httpx.HTTPError as exc:
38
+ raise TransportError(f"open session failed: {exc}", endpoint=path) from exc
39
+
40
+ async def close_async(self, token: str) -> None: # pragma: no cover - sync backend
41
+ raise NotImplementedError("Użyj AsyncHttpxTransport dla trybu async")
42
+
43
+ def close_sync(self, token: str) -> None:
44
+ path = "/api/Sessions/CloseSession"
45
+ try:
46
+ response = self._client.get(
47
+ path,
48
+ headers={"Authorization": f"Session {token}"},
49
+ )
50
+ response.raise_for_status()
51
+ except httpx.HTTPError as exc:
52
+ raise TransportError(f"close session failed: {exc}", endpoint=path) from exc
53
+
54
+ def request(
55
+ self,
56
+ method: str,
57
+ path: str,
58
+ *,
59
+ token: str,
60
+ params: Optional[Dict[str, Any]] = None,
61
+ data: Any = None,
62
+ ) -> httpx.Response:
63
+ headers = {"Authorization": f"Session {token}"}
64
+ request_kwargs: Dict[str, Any] = {"params": params, "headers": headers}
65
+ if data is not None:
66
+ if isinstance(data, (str, bytes, bytearray, memoryview)):
67
+ request_kwargs["content"] = data
68
+ if isinstance(data, str):
69
+ headers["Content-Type"] = "application/json"
70
+ else:
71
+ request_kwargs["json"] = data
72
+ try:
73
+ return self._client.request(method, path, **request_kwargs)
74
+ except httpx.HTTPError as exc:
75
+ raise TransportError(f"request failed: {exc}", endpoint=path) from exc
76
+
77
+ def close(self) -> None:
78
+ self._client.close()
@@ -0,0 +1,78 @@
1
+ Metadata-Version: 2.4
2
+ Name: SymfWebAPI
3
+ Version: 1.26.10.1
4
+ Summary: Python client for Symfonia WebAPI (sync + async).
5
+ Author: Maciej Pondo
6
+ Maintainer: Maciej Pondo
7
+ License-Expression: BSD-3-Clause
8
+ Project-URL: Homepage, https://github.com/maku2903/symf-webapi-py
9
+ Project-URL: Repository, https://github.com/maku2903/symf-webapi-py
10
+ Requires-Python: >=3.11
11
+ Description-Content-Type: text/markdown
12
+ License-File: LICENSE
13
+ Requires-Dist: httpx<0.29,>=0.27
14
+ Requires-Dist: pydantic<3.0,>=2.6
15
+ Provides-Extra: dev
16
+ Requires-Dist: pytest<9.0,>=8.0; extra == "dev"
17
+ Requires-Dist: ruff<0.5,>=0.3.0; extra == "dev"
18
+ Requires-Dist: build<2.0,>=1.2; extra == "dev"
19
+ Dynamic: license-file
20
+
21
+ # SymfWebAPI
22
+
23
+ [![CI](https://github.com/maku2903/symf-webapi-py/actions/workflows/public-ci-release.yml/badge.svg)](https://github.com/maku2903/symf-webapi-py/actions/workflows/public-ci-release.yml)
24
+ [![PyPI version](https://img.shields.io/pypi/v/SymfWebAPI.svg)](https://pypi.org/project/SymfWebAPI/)
25
+ [![Python versions](https://img.shields.io/pypi/pyversions/SymfWebAPI.svg)](https://pypi.org/project/SymfWebAPI/)
26
+ [![License](https://img.shields.io/pypi/l/SymfWebAPI.svg)](https://github.com/maku2903/symf-webapi-py/blob/main/LICENSE)
27
+
28
+ Pythonowa biblioteka kliencka do Symfonia WebAPI (sync + async) z typowanymi modelami i wygenerowanymi kontrolerami.
29
+
30
+ ## Instalacja
31
+
32
+ ```bash
33
+ pip install SymfWebAPI
34
+ ```
35
+
36
+ ## Szybki start
37
+
38
+ ```python
39
+ from SymfWebAPI import ClientConfig, WebAPI, build_async_client
40
+
41
+ config = ClientConfig(
42
+ domain="host:9000",
43
+ application_key="00000000-0000-0000-0000-000000000000",
44
+ device_name="integration-client",
45
+ )
46
+
47
+ async with build_async_client(config) as api:
48
+ resp = await WebAPI.Interface.Products.Interfaces.IProductsController.Get(api, salePrices=False)
49
+ products = resp.unwrap()
50
+ print(len(products))
51
+ ```
52
+
53
+ ## Dokumentacja
54
+
55
+ - Omówienie biblioteki: `docs/overview.md`
56
+ - Przykłady: `examples/`
57
+
58
+ ## Benchmark bez sekretów
59
+
60
+ Przykład benchmarku znajduje się w:
61
+ - `examples/benchmark_order_details.py`
62
+
63
+ Konfiguracja przez zmienne środowiskowe (brak hardcode klucza):
64
+ - `SYMFWEBAPI_DOMAIN`
65
+ - `SYMFWEBAPI_APP_KEY`
66
+ - `SYMFWEBAPI_DEVICE_NAME` (opcjonalnie)
67
+ - `SYMFWEBAPI_HTTPS` (opcjonalnie, np. `true`/`false`)
68
+
69
+ ## Wersjonowanie
70
+
71
+ Wersja paczki ma format `X.WM.Wm.I`, np. `1.26.10.3`:
72
+ - `X` - major SDK,
73
+ - `WM.Wm` - docelowa wersja Symfonia WebAPI,
74
+ - `I` - iteracja SDK dla tej samej wersji WebAPI.
75
+
76
+ ## Licencja
77
+
78
+ BSD-3-Clause.