b1sl-python 0.1.0__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 (579) hide show
  1. b1sl/__init__.py +5 -0
  2. b1sl/b1sl/__init__.py +56 -0
  3. b1sl/b1sl/_types.py +28 -0
  4. b1sl/b1sl/adapter.py +40 -0
  5. b1sl/b1sl/adapter_protocol.py +28 -0
  6. b1sl/b1sl/async_client.py +268 -0
  7. b1sl/b1sl/async_rest_adapter.py +347 -0
  8. b1sl/b1sl/base_adapter.py +394 -0
  9. b1sl/b1sl/client.py +112 -0
  10. b1sl/b1sl/config.py +138 -0
  11. b1sl/b1sl/config_manager.py +77 -0
  12. b1sl/b1sl/contrib/__init__.py +14 -0
  13. b1sl/b1sl/contrib/django/__init__.py +13 -0
  14. b1sl/b1sl/contrib/django/middleware/__init__.py +27 -0
  15. b1sl/b1sl/contrib/django/middleware/base.py +89 -0
  16. b1sl/b1sl/contrib/django/middleware/odata_decode_middleware.py +20 -0
  17. b1sl/b1sl/contrib/django/middleware/odata_transform_url_middleware.py +20 -0
  18. b1sl/b1sl/entities/__init__.py +2209 -0
  19. b1sl/b1sl/environment.py +36 -0
  20. b1sl/b1sl/exceptions/exceptions.py +142 -0
  21. b1sl/b1sl/fields/__init__.py +2020 -0
  22. b1sl/b1sl/fields/_generated/__init__.py +0 -0
  23. b1sl/b1sl/fields/_generated/complex_types.py +6926 -0
  24. b1sl/b1sl/fields/_generated/entities/__init__.py +0 -0
  25. b1sl/b1sl/fields/_generated/entities/businesspartners.py +544 -0
  26. b1sl/b1sl/fields/_generated/entities/finance.py +451 -0
  27. b1sl/b1sl/fields/_generated/entities/general.py +4587 -0
  28. b1sl/b1sl/fields/_generated/entities/inventory.py +761 -0
  29. b1sl/b1sl/fields/_generated/entities/production.py +256 -0
  30. b1sl/b1sl/fields/_generated/entities/purchasing.py +53 -0
  31. b1sl/b1sl/fields/_generated/entities/sales.py +244 -0
  32. b1sl/b1sl/logging_utils.py +119 -0
  33. b1sl/b1sl/models/__init__.py +13 -0
  34. b1sl/b1sl/models/_generated/__init__.py +0 -0
  35. b1sl/b1sl/models/_generated/_types.py +5 -0
  36. b1sl/b1sl/models/_generated/complex_types.py +6929 -0
  37. b1sl/b1sl/models/_generated/entities/__init__.py +581 -0
  38. b1sl/b1sl/models/_generated/entities/businesspartners.py +565 -0
  39. b1sl/b1sl/models/_generated/entities/finance.py +472 -0
  40. b1sl/b1sl/models/_generated/entities/general.py +4831 -0
  41. b1sl/b1sl/models/_generated/entities/inventory.py +786 -0
  42. b1sl/b1sl/models/_generated/entities/production.py +272 -0
  43. b1sl/b1sl/models/_generated/entities/purchasing.py +64 -0
  44. b1sl/b1sl/models/_generated/entities/sales.py +263 -0
  45. b1sl/b1sl/models/_generated/enums.py +3501 -0
  46. b1sl/b1sl/models/_generated/resources/__init__.py +0 -0
  47. b1sl/b1sl/models/_overrides/inventory.py +24 -0
  48. b1sl/b1sl/models/base.py +209 -0
  49. b1sl/b1sl/models/odata_query_model.py +50 -0
  50. b1sl/b1sl/models/paginated_result.py +85 -0
  51. b1sl/b1sl/models/result.py +17 -0
  52. b1sl/b1sl/resources/__init__.py +11 -0
  53. b1sl/b1sl/resources/_generated/__init__.py +0 -0
  54. b1sl/b1sl/resources/_generated/account_category.py +15 -0
  55. b1sl/b1sl/resources/_generated/account_category_service.py +21 -0
  56. b1sl/b1sl/resources/_generated/account_segmentation_categories.py +15 -0
  57. b1sl/b1sl/resources/_generated/account_segmentations.py +15 -0
  58. b1sl/b1sl/resources/_generated/accounts_service.py +33 -0
  59. b1sl/b1sl/resources/_generated/accrual_types.py +15 -0
  60. b1sl/b1sl/resources/_generated/accrual_types_service.py +21 -0
  61. b1sl/b1sl/resources/_generated/activities.py +15 -0
  62. b1sl/b1sl/resources/_generated/activities_service.py +109 -0
  63. b1sl/b1sl/resources/_generated/activity_locations.py +15 -0
  64. b1sl/b1sl/resources/_generated/activity_recipient_lists.py +15 -0
  65. b1sl/b1sl/resources/_generated/activity_recipient_lists_service.py +21 -0
  66. b1sl/b1sl/resources/_generated/activity_statuses.py +15 -0
  67. b1sl/b1sl/resources/_generated/activity_types.py +15 -0
  68. b1sl/b1sl/resources/_generated/additional_expenses.py +15 -0
  69. b1sl/b1sl/resources/_generated/address_service.py +38 -0
  70. b1sl/b1sl/resources/_generated/alert_managements.py +16 -0
  71. b1sl/b1sl/resources/_generated/alternate_cat_num.py +15 -0
  72. b1sl/b1sl/resources/_generated/alternative_items_service.py +113 -0
  73. b1sl/b1sl/resources/_generated/approval_requests.py +15 -0
  74. b1sl/b1sl/resources/_generated/approval_requests_service.py +33 -0
  75. b1sl/b1sl/resources/_generated/approval_stages.py +15 -0
  76. b1sl/b1sl/resources/_generated/approval_stages_service.py +21 -0
  77. b1sl/b1sl/resources/_generated/approval_templates.py +15 -0
  78. b1sl/b1sl/resources/_generated/approval_templates_service.py +21 -0
  79. b1sl/b1sl/resources/_generated/asset_capitalization.py +15 -0
  80. b1sl/b1sl/resources/_generated/asset_capitalization_credit_memo.py +15 -0
  81. b1sl/b1sl/resources/_generated/asset_capitalization_credit_memo_service.py +37 -0
  82. b1sl/b1sl/resources/_generated/asset_capitalization_service.py +37 -0
  83. b1sl/b1sl/resources/_generated/asset_classes.py +15 -0
  84. b1sl/b1sl/resources/_generated/asset_classes_service.py +21 -0
  85. b1sl/b1sl/resources/_generated/asset_depreciation_groups.py +15 -0
  86. b1sl/b1sl/resources/_generated/asset_depreciation_groups_service.py +21 -0
  87. b1sl/b1sl/resources/_generated/asset_groups.py +15 -0
  88. b1sl/b1sl/resources/_generated/asset_groups_service.py +21 -0
  89. b1sl/b1sl/resources/_generated/asset_manual_depreciation.py +15 -0
  90. b1sl/b1sl/resources/_generated/asset_manual_depreciation_service.py +37 -0
  91. b1sl/b1sl/resources/_generated/asset_retirement.py +15 -0
  92. b1sl/b1sl/resources/_generated/asset_retirement_service.py +37 -0
  93. b1sl/b1sl/resources/_generated/asset_transfer.py +15 -0
  94. b1sl/b1sl/resources/_generated/asset_transfer_service.py +37 -0
  95. b1sl/b1sl/resources/_generated/attachments2.py +15 -0
  96. b1sl/b1sl/resources/_generated/attribute_groups.py +15 -0
  97. b1sl/b1sl/resources/_generated/attribute_groups_service.py +21 -0
  98. b1sl/b1sl/resources/_generated/bank_charges_allocation_codes.py +15 -0
  99. b1sl/b1sl/resources/_generated/bank_charges_allocation_codes_service.py +21 -0
  100. b1sl/b1sl/resources/_generated/bank_pages.py +15 -0
  101. b1sl/b1sl/resources/_generated/bank_statements.py +15 -0
  102. b1sl/b1sl/resources/_generated/bank_statements_service.py +32 -0
  103. b1sl/b1sl/resources/_generated/banks.py +15 -0
  104. b1sl/b1sl/resources/_generated/bar_codes.py +15 -0
  105. b1sl/b1sl/resources/_generated/bar_codes_service.py +21 -0
  106. b1sl/b1sl/resources/_generated/batch_number_details.py +15 -0
  107. b1sl/b1sl/resources/_generated/bill_of_exchange_transactions.py +15 -0
  108. b1sl/b1sl/resources/_generated/bin_location_attributes.py +15 -0
  109. b1sl/b1sl/resources/_generated/bin_location_attributes_service.py +21 -0
  110. b1sl/b1sl/resources/_generated/bin_location_fields.py +15 -0
  111. b1sl/b1sl/resources/_generated/bin_location_fields_service.py +21 -0
  112. b1sl/b1sl/resources/_generated/bin_locations.py +15 -0
  113. b1sl/b1sl/resources/_generated/bin_locations_service.py +21 -0
  114. b1sl/b1sl/resources/_generated/blanket_agreements.py +15 -0
  115. b1sl/b1sl/resources/_generated/blanket_agreements_service.py +21 -0
  116. b1sl/b1sl/resources/_generated/boe_document_types.py +15 -0
  117. b1sl/b1sl/resources/_generated/boe_document_types_service.py +21 -0
  118. b1sl/b1sl/resources/_generated/boe_instructions.py +15 -0
  119. b1sl/b1sl/resources/_generated/boe_instructions_service.py +21 -0
  120. b1sl/b1sl/resources/_generated/boe_lines_service.py +30 -0
  121. b1sl/b1sl/resources/_generated/boe_portfolios.py +15 -0
  122. b1sl/b1sl/resources/_generated/boe_portfolios_service.py +21 -0
  123. b1sl/b1sl/resources/_generated/bp_fiscal_registry_id.py +15 -0
  124. b1sl/b1sl/resources/_generated/bp_opening_balance_service.py +41 -0
  125. b1sl/b1sl/resources/_generated/bp_priorities.py +15 -0
  126. b1sl/b1sl/resources/_generated/branches.py +15 -0
  127. b1sl/b1sl/resources/_generated/branches_service.py +21 -0
  128. b1sl/b1sl/resources/_generated/brazil_beverage_indexers.py +15 -0
  129. b1sl/b1sl/resources/_generated/brazil_beverage_indexers_service.py +21 -0
  130. b1sl/b1sl/resources/_generated/brazil_fuel_indexers.py +15 -0
  131. b1sl/b1sl/resources/_generated/brazil_fuel_indexers_service.py +21 -0
  132. b1sl/b1sl/resources/_generated/brazil_multi_indexers.py +15 -0
  133. b1sl/b1sl/resources/_generated/brazil_numeric_indexers.py +15 -0
  134. b1sl/b1sl/resources/_generated/brazil_string_indexers.py +15 -0
  135. b1sl/b1sl/resources/_generated/budget_distributions.py +15 -0
  136. b1sl/b1sl/resources/_generated/budget_scenarios.py +15 -0
  137. b1sl/b1sl/resources/_generated/budgets.py +15 -0
  138. b1sl/b1sl/resources/_generated/business_partner_groups.py +15 -0
  139. b1sl/b1sl/resources/_generated/business_partner_properties.py +15 -0
  140. b1sl/b1sl/resources/_generated/business_partner_properties_service.py +21 -0
  141. b1sl/b1sl/resources/_generated/business_partners.py +15 -0
  142. b1sl/b1sl/resources/_generated/business_partners_service.py +47 -0
  143. b1sl/b1sl/resources/_generated/business_places.py +15 -0
  144. b1sl/b1sl/resources/_generated/campaign_response_type.py +15 -0
  145. b1sl/b1sl/resources/_generated/campaign_response_type_service.py +21 -0
  146. b1sl/b1sl/resources/_generated/campaigns.py +15 -0
  147. b1sl/b1sl/resources/_generated/campaigns_service.py +21 -0
  148. b1sl/b1sl/resources/_generated/cash_discounts.py +15 -0
  149. b1sl/b1sl/resources/_generated/cash_discounts_service.py +21 -0
  150. b1sl/b1sl/resources/_generated/cash_flow_line_items.py +15 -0
  151. b1sl/b1sl/resources/_generated/cash_flow_line_items_service.py +21 -0
  152. b1sl/b1sl/resources/_generated/certificate_series.py +15 -0
  153. b1sl/b1sl/resources/_generated/certificate_series_service.py +21 -0
  154. b1sl/b1sl/resources/_generated/change_logs_service.py +51 -0
  155. b1sl/b1sl/resources/_generated/chart_of_accounts.py +15 -0
  156. b1sl/b1sl/resources/_generated/check_lines_service.py +38 -0
  157. b1sl/b1sl/resources/_generated/checksfor_payment.py +15 -0
  158. b1sl/b1sl/resources/_generated/choose_from_list.py +15 -0
  159. b1sl/b1sl/resources/_generated/client_mixin.py +3920 -0
  160. b1sl/b1sl/resources/_generated/closing_date_procedure.py +15 -0
  161. b1sl/b1sl/resources/_generated/cockpits.py +15 -0
  162. b1sl/b1sl/resources/_generated/cockpits_service.py +46 -0
  163. b1sl/b1sl/resources/_generated/commission_groups.py +15 -0
  164. b1sl/b1sl/resources/_generated/company_service.py +410 -0
  165. b1sl/b1sl/resources/_generated/contacts.py +15 -0
  166. b1sl/b1sl/resources/_generated/contract_templates.py +15 -0
  167. b1sl/b1sl/resources/_generated/correction_invoice.py +15 -0
  168. b1sl/b1sl/resources/_generated/correction_invoice_reversal.py +15 -0
  169. b1sl/b1sl/resources/_generated/correction_invoice_reversal_service.py +65 -0
  170. b1sl/b1sl/resources/_generated/correction_invoice_service.py +78 -0
  171. b1sl/b1sl/resources/_generated/correction_purchase_invoice.py +15 -0
  172. b1sl/b1sl/resources/_generated/correction_purchase_invoice_reversal.py +15 -0
  173. b1sl/b1sl/resources/_generated/correction_purchase_invoice_reversal_service.py +65 -0
  174. b1sl/b1sl/resources/_generated/correction_purchase_invoice_service.py +78 -0
  175. b1sl/b1sl/resources/_generated/cost_center_types.py +15 -0
  176. b1sl/b1sl/resources/_generated/cost_center_types_service.py +21 -0
  177. b1sl/b1sl/resources/_generated/cost_element_service.py +21 -0
  178. b1sl/b1sl/resources/_generated/cost_elements.py +15 -0
  179. b1sl/b1sl/resources/_generated/counties.py +15 -0
  180. b1sl/b1sl/resources/_generated/counties_service.py +21 -0
  181. b1sl/b1sl/resources/_generated/countries.py +15 -0
  182. b1sl/b1sl/resources/_generated/countries_service.py +21 -0
  183. b1sl/b1sl/resources/_generated/credit_card_payments.py +15 -0
  184. b1sl/b1sl/resources/_generated/credit_cards.py +15 -0
  185. b1sl/b1sl/resources/_generated/credit_lines_service.py +38 -0
  186. b1sl/b1sl/resources/_generated/credit_notes.py +15 -0
  187. b1sl/b1sl/resources/_generated/credit_notes_service.py +100 -0
  188. b1sl/b1sl/resources/_generated/credit_payment_methods.py +15 -0
  189. b1sl/b1sl/resources/_generated/currencies.py +15 -0
  190. b1sl/b1sl/resources/_generated/customer_equipment_cards.py +15 -0
  191. b1sl/b1sl/resources/_generated/customs_declaration.py +15 -0
  192. b1sl/b1sl/resources/_generated/customs_groups.py +15 -0
  193. b1sl/b1sl/resources/_generated/cycle_count_determinations.py +15 -0
  194. b1sl/b1sl/resources/_generated/cycle_count_determinations_service.py +21 -0
  195. b1sl/b1sl/resources/_generated/dashboard_packages_service.py +28 -0
  196. b1sl/b1sl/resources/_generated/deductible_tax_service.py +21 -0
  197. b1sl/b1sl/resources/_generated/deductible_taxes.py +15 -0
  198. b1sl/b1sl/resources/_generated/deduction_tax_groups.py +15 -0
  199. b1sl/b1sl/resources/_generated/deduction_tax_hierarchies.py +15 -0
  200. b1sl/b1sl/resources/_generated/deduction_tax_sub_groups.py +15 -0
  201. b1sl/b1sl/resources/_generated/deduction_tax_sub_groups_service.py +21 -0
  202. b1sl/b1sl/resources/_generated/delivery_notes.py +15 -0
  203. b1sl/b1sl/resources/_generated/delivery_notes_service.py +85 -0
  204. b1sl/b1sl/resources/_generated/departments.py +15 -0
  205. b1sl/b1sl/resources/_generated/departments_service.py +21 -0
  206. b1sl/b1sl/resources/_generated/deposits.py +15 -0
  207. b1sl/b1sl/resources/_generated/deposits_service.py +53 -0
  208. b1sl/b1sl/resources/_generated/depreciation_areas.py +15 -0
  209. b1sl/b1sl/resources/_generated/depreciation_areas_service.py +21 -0
  210. b1sl/b1sl/resources/_generated/depreciation_type_pools.py +15 -0
  211. b1sl/b1sl/resources/_generated/depreciation_type_pools_service.py +21 -0
  212. b1sl/b1sl/resources/_generated/depreciation_types.py +15 -0
  213. b1sl/b1sl/resources/_generated/depreciation_types_service.py +21 -0
  214. b1sl/b1sl/resources/_generated/determination_criterias.py +15 -0
  215. b1sl/b1sl/resources/_generated/determination_criterias_service.py +21 -0
  216. b1sl/b1sl/resources/_generated/dimensions.py +15 -0
  217. b1sl/b1sl/resources/_generated/dimensions_service.py +21 -0
  218. b1sl/b1sl/resources/_generated/distribution_rules.py +15 -0
  219. b1sl/b1sl/resources/_generated/distribution_rules_service.py +21 -0
  220. b1sl/b1sl/resources/_generated/dnf_code_setup.py +15 -0
  221. b1sl/b1sl/resources/_generated/dnf_code_setup_service.py +21 -0
  222. b1sl/b1sl/resources/_generated/down_payments.py +15 -0
  223. b1sl/b1sl/resources/_generated/down_payments_service.py +68 -0
  224. b1sl/b1sl/resources/_generated/drafts.py +15 -0
  225. b1sl/b1sl/resources/_generated/drafts_service.py +86 -0
  226. b1sl/b1sl/resources/_generated/dunning_letters.py +15 -0
  227. b1sl/b1sl/resources/_generated/dunning_terms.py +15 -0
  228. b1sl/b1sl/resources/_generated/dunning_terms_service.py +21 -0
  229. b1sl/b1sl/resources/_generated/dynamic_system_strings.py +15 -0
  230. b1sl/b1sl/resources/_generated/electronic_communication_action_service.py +122 -0
  231. b1sl/b1sl/resources/_generated/electronic_communication_actions_service.py +119 -0
  232. b1sl/b1sl/resources/_generated/electronic_file_formats.py +15 -0
  233. b1sl/b1sl/resources/_generated/electronic_file_formats_service.py +21 -0
  234. b1sl/b1sl/resources/_generated/email_groups.py +15 -0
  235. b1sl/b1sl/resources/_generated/email_groups_service.py +21 -0
  236. b1sl/b1sl/resources/_generated/employee_id_type.py +15 -0
  237. b1sl/b1sl/resources/_generated/employee_id_type_service.py +21 -0
  238. b1sl/b1sl/resources/_generated/employee_position.py +15 -0
  239. b1sl/b1sl/resources/_generated/employee_position_service.py +21 -0
  240. b1sl/b1sl/resources/_generated/employee_roles_setup.py +15 -0
  241. b1sl/b1sl/resources/_generated/employee_roles_setup_service.py +21 -0
  242. b1sl/b1sl/resources/_generated/employee_status.py +15 -0
  243. b1sl/b1sl/resources/_generated/employee_status_service.py +21 -0
  244. b1sl/b1sl/resources/_generated/employee_transfers.py +15 -0
  245. b1sl/b1sl/resources/_generated/employee_transfers_service.py +21 -0
  246. b1sl/b1sl/resources/_generated/employees_info.py +15 -0
  247. b1sl/b1sl/resources/_generated/employment_category_service.py +21 -0
  248. b1sl/b1sl/resources/_generated/employment_categorys.py +15 -0
  249. b1sl/b1sl/resources/_generated/enhanced_discount_groups.py +15 -0
  250. b1sl/b1sl/resources/_generated/enhanced_discount_groups_service.py +21 -0
  251. b1sl/b1sl/resources/_generated/exceptional_event_service.py +21 -0
  252. b1sl/b1sl/resources/_generated/exceptional_events.py +15 -0
  253. b1sl/b1sl/resources/_generated/extended_translations.py +15 -0
  254. b1sl/b1sl/resources/_generated/extended_translations_service.py +21 -0
  255. b1sl/b1sl/resources/_generated/external_calls_service.py +54 -0
  256. b1sl/b1sl/resources/_generated/external_reconciliations_service.py +104 -0
  257. b1sl/b1sl/resources/_generated/fa_account_determinations.py +15 -0
  258. b1sl/b1sl/resources/_generated/fa_account_determinations_service.py +21 -0
  259. b1sl/b1sl/resources/_generated/factoring_indicators.py +15 -0
  260. b1sl/b1sl/resources/_generated/financial_years.py +15 -0
  261. b1sl/b1sl/resources/_generated/financial_years_service.py +21 -0
  262. b1sl/b1sl/resources/_generated/fiscal_printer.py +15 -0
  263. b1sl/b1sl/resources/_generated/fiscal_printer_service.py +21 -0
  264. b1sl/b1sl/resources/_generated/fixed_asset_items_service.py +55 -0
  265. b1sl/b1sl/resources/_generated/form_preferences.py +15 -0
  266. b1sl/b1sl/resources/_generated/formatted_searches.py +15 -0
  267. b1sl/b1sl/resources/_generated/forms1099.py +15 -0
  268. b1sl/b1sl/resources/_generated/gl_account_advanced_rules.py +15 -0
  269. b1sl/b1sl/resources/_generated/gl_account_advanced_rules_service.py +21 -0
  270. b1sl/b1sl/resources/_generated/goods_return_request.py +15 -0
  271. b1sl/b1sl/resources/_generated/goods_return_request_service.py +69 -0
  272. b1sl/b1sl/resources/_generated/gov_pay_codes.py +15 -0
  273. b1sl/b1sl/resources/_generated/gov_pay_codes_service.py +21 -0
  274. b1sl/b1sl/resources/_generated/gt_is_service.py +28 -0
  275. b1sl/b1sl/resources/_generated/holidays.py +15 -0
  276. b1sl/b1sl/resources/_generated/house_bank_accounts.py +15 -0
  277. b1sl/b1sl/resources/_generated/incoming_payments.py +15 -0
  278. b1sl/b1sl/resources/_generated/india_hsn.py +15 -0
  279. b1sl/b1sl/resources/_generated/india_hsn_service.py +21 -0
  280. b1sl/b1sl/resources/_generated/industries.py +15 -0
  281. b1sl/b1sl/resources/_generated/integration_packages_configure.py +15 -0
  282. b1sl/b1sl/resources/_generated/integration_packages_configure_service.py +21 -0
  283. b1sl/b1sl/resources/_generated/internal_reconciliations.py +15 -0
  284. b1sl/b1sl/resources/_generated/internal_reconciliations_service.py +51 -0
  285. b1sl/b1sl/resources/_generated/intrastat_configuration.py +15 -0
  286. b1sl/b1sl/resources/_generated/intrastat_configuration_service.py +21 -0
  287. b1sl/b1sl/resources/_generated/inventory_countings.py +15 -0
  288. b1sl/b1sl/resources/_generated/inventory_countings_service.py +21 -0
  289. b1sl/b1sl/resources/_generated/inventory_cycles.py +15 -0
  290. b1sl/b1sl/resources/_generated/inventory_gen_entries.py +15 -0
  291. b1sl/b1sl/resources/_generated/inventory_gen_entry_service.py +67 -0
  292. b1sl/b1sl/resources/_generated/inventory_gen_exit_service.py +66 -0
  293. b1sl/b1sl/resources/_generated/inventory_gen_exits.py +15 -0
  294. b1sl/b1sl/resources/_generated/inventory_opening_balances.py +15 -0
  295. b1sl/b1sl/resources/_generated/inventory_opening_balances_service.py +21 -0
  296. b1sl/b1sl/resources/_generated/inventory_postings.py +15 -0
  297. b1sl/b1sl/resources/_generated/inventory_postings_service.py +34 -0
  298. b1sl/b1sl/resources/_generated/inventory_transfer_requests.py +15 -0
  299. b1sl/b1sl/resources/_generated/inventory_transfer_requests_service.py +43 -0
  300. b1sl/b1sl/resources/_generated/invoices.py +15 -0
  301. b1sl/b1sl/resources/_generated/invoices_service.py +100 -0
  302. b1sl/b1sl/resources/_generated/item_groups.py +15 -0
  303. b1sl/b1sl/resources/_generated/item_properties.py +15 -0
  304. b1sl/b1sl/resources/_generated/items.py +15 -0
  305. b1sl/b1sl/resources/_generated/journal_entries.py +15 -0
  306. b1sl/b1sl/resources/_generated/journal_entry_document_type_service.py +21 -0
  307. b1sl/b1sl/resources/_generated/journal_entry_document_types.py +15 -0
  308. b1sl/b1sl/resources/_generated/journal_vouchers_service.py +45 -0
  309. b1sl/b1sl/resources/_generated/knowledge_base_solutions.py +15 -0
  310. b1sl/b1sl/resources/_generated/kp_is.py +15 -0
  311. b1sl/b1sl/resources/_generated/kp_is_service.py +21 -0
  312. b1sl/b1sl/resources/_generated/landed_costs.py +15 -0
  313. b1sl/b1sl/resources/_generated/landed_costs_codes.py +15 -0
  314. b1sl/b1sl/resources/_generated/landed_costs_service.py +21 -0
  315. b1sl/b1sl/resources/_generated/legal_data.py +15 -0
  316. b1sl/b1sl/resources/_generated/length_measures.py +15 -0
  317. b1sl/b1sl/resources/_generated/license_service.py +21 -0
  318. b1sl/b1sl/resources/_generated/local_era.py +15 -0
  319. b1sl/b1sl/resources/_generated/manufacturers.py +15 -0
  320. b1sl/b1sl/resources/_generated/material_groups.py +15 -0
  321. b1sl/b1sl/resources/_generated/material_groups_service.py +21 -0
  322. b1sl/b1sl/resources/_generated/material_revaluation.py +15 -0
  323. b1sl/b1sl/resources/_generated/material_revaluation_fifo_service.py +33 -0
  324. b1sl/b1sl/resources/_generated/material_revaluation_snb_service.py +33 -0
  325. b1sl/b1sl/resources/_generated/messages.py +15 -0
  326. b1sl/b1sl/resources/_generated/messages_service.py +35 -0
  327. b1sl/b1sl/resources/_generated/mobile_add_on_setting.py +15 -0
  328. b1sl/b1sl/resources/_generated/mobile_add_on_setting_service.py +21 -0
  329. b1sl/b1sl/resources/_generated/mobile_app_service.py +240 -0
  330. b1sl/b1sl/resources/_generated/multi_language_translations.py +15 -0
  331. b1sl/b1sl/resources/_generated/nature_of_assessees.py +15 -0
  332. b1sl/b1sl/resources/_generated/nature_of_assessees_service.py +21 -0
  333. b1sl/b1sl/resources/_generated/ncm_codes_setup.py +15 -0
  334. b1sl/b1sl/resources/_generated/ncm_codes_setup_service.py +21 -0
  335. b1sl/b1sl/resources/_generated/nf_models.py +15 -0
  336. b1sl/b1sl/resources/_generated/nf_models_service.py +21 -0
  337. b1sl/b1sl/resources/_generated/nf_tax_categories.py +15 -0
  338. b1sl/b1sl/resources/_generated/nf_tax_categories_service.py +21 -0
  339. b1sl/b1sl/resources/_generated/nota_fiscal_cfop.py +15 -0
  340. b1sl/b1sl/resources/_generated/nota_fiscal_cst.py +15 -0
  341. b1sl/b1sl/resources/_generated/nota_fiscal_usage.py +15 -0
  342. b1sl/b1sl/resources/_generated/occurrence_codes.py +15 -0
  343. b1sl/b1sl/resources/_generated/occurrence_codes_service.py +21 -0
  344. b1sl/b1sl/resources/_generated/orders.py +15 -0
  345. b1sl/b1sl/resources/_generated/orders_service.py +94 -0
  346. b1sl/b1sl/resources/_generated/packages_types.py +15 -0
  347. b1sl/b1sl/resources/_generated/partners_setups.py +15 -0
  348. b1sl/b1sl/resources/_generated/partners_setups_service.py +21 -0
  349. b1sl/b1sl/resources/_generated/payment_blocks.py +15 -0
  350. b1sl/b1sl/resources/_generated/payment_blocks_service.py +21 -0
  351. b1sl/b1sl/resources/_generated/payment_calculation_service.py +37 -0
  352. b1sl/b1sl/resources/_generated/payment_drafts.py +15 -0
  353. b1sl/b1sl/resources/_generated/payment_reason_code_service.py +21 -0
  354. b1sl/b1sl/resources/_generated/payment_reason_codes.py +15 -0
  355. b1sl/b1sl/resources/_generated/payment_run_export.py +15 -0
  356. b1sl/b1sl/resources/_generated/payment_terms_types.py +15 -0
  357. b1sl/b1sl/resources/_generated/payment_terms_types_service.py +28 -0
  358. b1sl/b1sl/resources/_generated/pick_lists.py +15 -0
  359. b1sl/b1sl/resources/_generated/pick_lists_service.py +78 -0
  360. b1sl/b1sl/resources/_generated/pos_daily_summary.py +15 -0
  361. b1sl/b1sl/resources/_generated/predefined_texts.py +15 -0
  362. b1sl/b1sl/resources/_generated/predefined_texts_service.py +21 -0
  363. b1sl/b1sl/resources/_generated/price_lists.py +15 -0
  364. b1sl/b1sl/resources/_generated/product_trees.py +15 -0
  365. b1sl/b1sl/resources/_generated/production_orders.py +15 -0
  366. b1sl/b1sl/resources/_generated/profit_centers.py +15 -0
  367. b1sl/b1sl/resources/_generated/profit_centers_service.py +21 -0
  368. b1sl/b1sl/resources/_generated/project_management_configuration_service.py +333 -0
  369. b1sl/b1sl/resources/_generated/project_management_service.py +104 -0
  370. b1sl/b1sl/resources/_generated/project_management_time_sheet.py +15 -0
  371. b1sl/b1sl/resources/_generated/project_managements.py +15 -0
  372. b1sl/b1sl/resources/_generated/projects.py +15 -0
  373. b1sl/b1sl/resources/_generated/projects_service.py +21 -0
  374. b1sl/b1sl/resources/_generated/purchase_credit_notes.py +15 -0
  375. b1sl/b1sl/resources/_generated/purchase_credit_notes_service.py +85 -0
  376. b1sl/b1sl/resources/_generated/purchase_delivery_notes.py +15 -0
  377. b1sl/b1sl/resources/_generated/purchase_delivery_notes_service.py +85 -0
  378. b1sl/b1sl/resources/_generated/purchase_down_payments.py +15 -0
  379. b1sl/b1sl/resources/_generated/purchase_down_payments_service.py +70 -0
  380. b1sl/b1sl/resources/_generated/purchase_invoices.py +15 -0
  381. b1sl/b1sl/resources/_generated/purchase_invoices_service.py +85 -0
  382. b1sl/b1sl/resources/_generated/purchase_orders.py +15 -0
  383. b1sl/b1sl/resources/_generated/purchase_orders_service.py +69 -0
  384. b1sl/b1sl/resources/_generated/purchase_quotations.py +15 -0
  385. b1sl/b1sl/resources/_generated/purchase_quotations_service.py +70 -0
  386. b1sl/b1sl/resources/_generated/purchase_request_service.py +68 -0
  387. b1sl/b1sl/resources/_generated/purchase_requests.py +15 -0
  388. b1sl/b1sl/resources/_generated/purchase_returns.py +15 -0
  389. b1sl/b1sl/resources/_generated/purchase_returns_service.py +85 -0
  390. b1sl/b1sl/resources/_generated/purchase_tax_invoices.py +15 -0
  391. b1sl/b1sl/resources/_generated/qr_code_service.py +33 -0
  392. b1sl/b1sl/resources/_generated/query_auth_groups.py +15 -0
  393. b1sl/b1sl/resources/_generated/query_categories.py +15 -0
  394. b1sl/b1sl/resources/_generated/query_service.py +29 -0
  395. b1sl/b1sl/resources/_generated/queue.py +15 -0
  396. b1sl/b1sl/resources/_generated/quotations.py +15 -0
  397. b1sl/b1sl/resources/_generated/quotations_service.py +69 -0
  398. b1sl/b1sl/resources/_generated/recurring_transaction_service.py +67 -0
  399. b1sl/b1sl/resources/_generated/relationships.py +15 -0
  400. b1sl/b1sl/resources/_generated/report_filter.py +15 -0
  401. b1sl/b1sl/resources/_generated/report_filter_service.py +30 -0
  402. b1sl/b1sl/resources/_generated/report_layouts_service.py +237 -0
  403. b1sl/b1sl/resources/_generated/report_types.py +15 -0
  404. b1sl/b1sl/resources/_generated/report_types_service.py +21 -0
  405. b1sl/b1sl/resources/_generated/resource_capacities.py +15 -0
  406. b1sl/b1sl/resources/_generated/resource_capacities_service.py +34 -0
  407. b1sl/b1sl/resources/_generated/resource_groups.py +15 -0
  408. b1sl/b1sl/resources/_generated/resource_groups_service.py +21 -0
  409. b1sl/b1sl/resources/_generated/resource_properties.py +15 -0
  410. b1sl/b1sl/resources/_generated/resource_properties_service.py +21 -0
  411. b1sl/b1sl/resources/_generated/resources.py +15 -0
  412. b1sl/b1sl/resources/_generated/resources_service.py +21 -0
  413. b1sl/b1sl/resources/_generated/retorno_codes.py +15 -0
  414. b1sl/b1sl/resources/_generated/retorno_codes_service.py +21 -0
  415. b1sl/b1sl/resources/_generated/return_request.py +15 -0
  416. b1sl/b1sl/resources/_generated/return_request_service.py +69 -0
  417. b1sl/b1sl/resources/_generated/returns.py +15 -0
  418. b1sl/b1sl/resources/_generated/returns_service.py +85 -0
  419. b1sl/b1sl/resources/_generated/route_stages.py +15 -0
  420. b1sl/b1sl/resources/_generated/route_stages_service.py +21 -0
  421. b1sl/b1sl/resources/_generated/sales_forecast.py +15 -0
  422. b1sl/b1sl/resources/_generated/sales_opportunities.py +15 -0
  423. b1sl/b1sl/resources/_generated/sales_opportunity_competitors_setup.py +15 -0
  424. b1sl/b1sl/resources/_generated/sales_opportunity_competitors_setup_service.py +21 -0
  425. b1sl/b1sl/resources/_generated/sales_opportunity_interests_setup.py +15 -0
  426. b1sl/b1sl/resources/_generated/sales_opportunity_interests_setup_service.py +21 -0
  427. b1sl/b1sl/resources/_generated/sales_opportunity_reasons_setup.py +15 -0
  428. b1sl/b1sl/resources/_generated/sales_opportunity_reasons_setup_service.py +21 -0
  429. b1sl/b1sl/resources/_generated/sales_opportunity_sources_setup.py +15 -0
  430. b1sl/b1sl/resources/_generated/sales_opportunity_sources_setup_service.py +21 -0
  431. b1sl/b1sl/resources/_generated/sales_persons.py +15 -0
  432. b1sl/b1sl/resources/_generated/sales_stages.py +15 -0
  433. b1sl/b1sl/resources/_generated/sales_tax_authorities.py +15 -0
  434. b1sl/b1sl/resources/_generated/sales_tax_authorities_types.py +15 -0
  435. b1sl/b1sl/resources/_generated/sales_tax_codes.py +15 -0
  436. b1sl/b1sl/resources/_generated/sales_tax_invoices.py +15 -0
  437. b1sl/b1sl/resources/_generated/sbo_bob_service.py +89 -0
  438. b1sl/b1sl/resources/_generated/sections.py +15 -0
  439. b1sl/b1sl/resources/_generated/sections_service.py +21 -0
  440. b1sl/b1sl/resources/_generated/self_credit_memo_service.py +69 -0
  441. b1sl/b1sl/resources/_generated/self_credit_memos.py +15 -0
  442. b1sl/b1sl/resources/_generated/self_invoice_service.py +69 -0
  443. b1sl/b1sl/resources/_generated/self_invoices.py +15 -0
  444. b1sl/b1sl/resources/_generated/serial_number_details.py +15 -0
  445. b1sl/b1sl/resources/_generated/series_service.py +305 -0
  446. b1sl/b1sl/resources/_generated/service_call_origins.py +15 -0
  447. b1sl/b1sl/resources/_generated/service_call_origins_service.py +21 -0
  448. b1sl/b1sl/resources/_generated/service_call_problem_sub_types.py +15 -0
  449. b1sl/b1sl/resources/_generated/service_call_problem_sub_types_service.py +21 -0
  450. b1sl/b1sl/resources/_generated/service_call_problem_types.py +15 -0
  451. b1sl/b1sl/resources/_generated/service_call_problem_types_service.py +21 -0
  452. b1sl/b1sl/resources/_generated/service_call_solution_status.py +15 -0
  453. b1sl/b1sl/resources/_generated/service_call_solution_status_service.py +21 -0
  454. b1sl/b1sl/resources/_generated/service_call_status.py +15 -0
  455. b1sl/b1sl/resources/_generated/service_call_status_service.py +21 -0
  456. b1sl/b1sl/resources/_generated/service_call_types.py +15 -0
  457. b1sl/b1sl/resources/_generated/service_call_types_service.py +21 -0
  458. b1sl/b1sl/resources/_generated/service_calls.py +15 -0
  459. b1sl/b1sl/resources/_generated/service_contracts.py +15 -0
  460. b1sl/b1sl/resources/_generated/service_groups.py +15 -0
  461. b1sl/b1sl/resources/_generated/service_groups_service.py +21 -0
  462. b1sl/b1sl/resources/_generated/service_tax_posting_service.py +36 -0
  463. b1sl/b1sl/resources/_generated/shipping_types.py +15 -0
  464. b1sl/b1sl/resources/_generated/short_link_mappings_service.py +26 -0
  465. b1sl/b1sl/resources/_generated/special_prices.py +15 -0
  466. b1sl/b1sl/resources/_generated/states.py +15 -0
  467. b1sl/b1sl/resources/_generated/states_service.py +21 -0
  468. b1sl/b1sl/resources/_generated/stock_takings.py +15 -0
  469. b1sl/b1sl/resources/_generated/stock_transfer_draft_service.py +34 -0
  470. b1sl/b1sl/resources/_generated/stock_transfer_drafts.py +15 -0
  471. b1sl/b1sl/resources/_generated/stock_transfer_service.py +43 -0
  472. b1sl/b1sl/resources/_generated/stock_transfers.py +15 -0
  473. b1sl/b1sl/resources/_generated/target_groups.py +15 -0
  474. b1sl/b1sl/resources/_generated/target_groups_service.py +21 -0
  475. b1sl/b1sl/resources/_generated/tax_code_determinations.py +15 -0
  476. b1sl/b1sl/resources/_generated/tax_code_determinations_service.py +21 -0
  477. b1sl/b1sl/resources/_generated/tax_code_determinations_tcd.py +15 -0
  478. b1sl/b1sl/resources/_generated/tax_code_determinations_tcd_service.py +21 -0
  479. b1sl/b1sl/resources/_generated/tax_invoice_report.py +15 -0
  480. b1sl/b1sl/resources/_generated/tax_web_sites.py +15 -0
  481. b1sl/b1sl/resources/_generated/tax_web_sites_service.py +27 -0
  482. b1sl/b1sl/resources/_generated/teams.py +15 -0
  483. b1sl/b1sl/resources/_generated/termination_reason.py +15 -0
  484. b1sl/b1sl/resources/_generated/termination_reason_service.py +21 -0
  485. b1sl/b1sl/resources/_generated/territories.py +15 -0
  486. b1sl/b1sl/resources/_generated/tracking_notes.py +15 -0
  487. b1sl/b1sl/resources/_generated/tracking_notes_service.py +21 -0
  488. b1sl/b1sl/resources/_generated/transaction_codes.py +15 -0
  489. b1sl/b1sl/resources/_generated/transaction_codes_service.py +21 -0
  490. b1sl/b1sl/resources/_generated/transportation_document.py +15 -0
  491. b1sl/b1sl/resources/_generated/tsr_exceptional_event_service.py +21 -0
  492. b1sl/b1sl/resources/_generated/tsr_exceptional_events.py +15 -0
  493. b1sl/b1sl/resources/_generated/unit_of_measurement_groups.py +15 -0
  494. b1sl/b1sl/resources/_generated/unit_of_measurement_groups_service.py +21 -0
  495. b1sl/b1sl/resources/_generated/unit_of_measurements.py +15 -0
  496. b1sl/b1sl/resources/_generated/unit_of_measurements_service.py +21 -0
  497. b1sl/b1sl/resources/_generated/user_default_groups.py +15 -0
  498. b1sl/b1sl/resources/_generated/user_fields_md.py +15 -0
  499. b1sl/b1sl/resources/_generated/user_keys_md.py +15 -0
  500. b1sl/b1sl/resources/_generated/user_languages.py +15 -0
  501. b1sl/b1sl/resources/_generated/user_menu_service.py +103 -0
  502. b1sl/b1sl/resources/_generated/user_objects_md.py +15 -0
  503. b1sl/b1sl/resources/_generated/user_permission_tree.py +15 -0
  504. b1sl/b1sl/resources/_generated/user_queries.py +15 -0
  505. b1sl/b1sl/resources/_generated/user_tables_md.py +15 -0
  506. b1sl/b1sl/resources/_generated/users.py +15 -0
  507. b1sl/b1sl/resources/_generated/users_service.py +21 -0
  508. b1sl/b1sl/resources/_generated/value_mapping.py +15 -0
  509. b1sl/b1sl/resources/_generated/value_mapping_communication.py +15 -0
  510. b1sl/b1sl/resources/_generated/value_mapping_service.py +64 -0
  511. b1sl/b1sl/resources/_generated/vat_groups.py +15 -0
  512. b1sl/b1sl/resources/_generated/vendor_payments.py +15 -0
  513. b1sl/b1sl/resources/_generated/w_tax_type_code_service.py +21 -0
  514. b1sl/b1sl/resources/_generated/w_tax_type_codes.py +15 -0
  515. b1sl/b1sl/resources/_generated/warehouse_locations.py +15 -0
  516. b1sl/b1sl/resources/_generated/warehouse_sublevel_codes.py +15 -0
  517. b1sl/b1sl/resources/_generated/warehouse_sublevel_codes_service.py +21 -0
  518. b1sl/b1sl/resources/_generated/warehouses.py +15 -0
  519. b1sl/b1sl/resources/_generated/web_client_bookmark_tile_service.py +21 -0
  520. b1sl/b1sl/resources/_generated/web_client_bookmark_tiles.py +15 -0
  521. b1sl/b1sl/resources/_generated/web_client_dashboard_service.py +21 -0
  522. b1sl/b1sl/resources/_generated/web_client_dashboards.py +15 -0
  523. b1sl/b1sl/resources/_generated/web_client_form_setting_service.py +21 -0
  524. b1sl/b1sl/resources/_generated/web_client_form_settings.py +15 -0
  525. b1sl/b1sl/resources/_generated/web_client_launchpad_service.py +21 -0
  526. b1sl/b1sl/resources/_generated/web_client_launchpads.py +15 -0
  527. b1sl/b1sl/resources/_generated/web_client_listview_filter_service.py +21 -0
  528. b1sl/b1sl/resources/_generated/web_client_listview_filters.py +15 -0
  529. b1sl/b1sl/resources/_generated/web_client_notification_service.py +21 -0
  530. b1sl/b1sl/resources/_generated/web_client_notifications.py +15 -0
  531. b1sl/b1sl/resources/_generated/web_client_preference_service.py +21 -0
  532. b1sl/b1sl/resources/_generated/web_client_preferences.py +15 -0
  533. b1sl/b1sl/resources/_generated/web_client_recent_activities.py +15 -0
  534. b1sl/b1sl/resources/_generated/web_client_recent_activity_service.py +21 -0
  535. b1sl/b1sl/resources/_generated/web_client_variant_group_service.py +21 -0
  536. b1sl/b1sl/resources/_generated/web_client_variant_groups.py +15 -0
  537. b1sl/b1sl/resources/_generated/web_client_variant_service.py +21 -0
  538. b1sl/b1sl/resources/_generated/web_client_variants.py +15 -0
  539. b1sl/b1sl/resources/_generated/weight_measures.py +15 -0
  540. b1sl/b1sl/resources/_generated/withholding_tax_codes.py +15 -0
  541. b1sl/b1sl/resources/_generated/witholding_tax_definition.py +15 -0
  542. b1sl/b1sl/resources/_generated/wizard_payment_methods.py +15 -0
  543. b1sl/b1sl/resources/_generated/workflow_task_service.py +47 -0
  544. b1sl/b1sl/resources/async_base.py +60 -0
  545. b1sl/b1sl/resources/base.py +159 -0
  546. b1sl/b1sl/resources/udo.py +78 -0
  547. b1sl/b1sl/rest_adapter.py +351 -0
  548. b1sl/b1sl/testing.py +24 -0
  549. b1sl/b1sl/tests/__init__.py +0 -0
  550. b1sl/b1sl/tests/test_01_settings.py +60 -0
  551. b1sl/b1sl/tests/test_02_rest_adapter.py +177 -0
  552. b1sl/b1sl/tests/test_03_items_endpoint.py +172 -0
  553. b1sl/b1sl/tests/test_04_serialnumberdetails_endpoint.py +181 -0
  554. b1sl/b1sl/tests/test_observability.py +153 -0
  555. b1sl/b1sl/tests/test_utils.py +24 -0
  556. b1sl/contrib/__init__.py +0 -0
  557. b1sl/contrib/django/__init__.py +15 -0
  558. b1sl/contrib/django/base.py +89 -0
  559. b1sl/contrib/django/odata_decode_middleware.py +14 -0
  560. b1sl/contrib/django/odata_transform_url_middleware.py +15 -0
  561. b1sl/py.typed +0 -0
  562. b1sl/saphdb/__init__.py +19 -0
  563. b1sl/saphdb/adapter.py +24 -0
  564. b1sl/saphdb/client.py +50 -0
  565. b1sl/saphdb/config.py +68 -0
  566. b1sl/saphdb/endpoints/serialnumberdetailodbc.py +100 -0
  567. b1sl/saphdb/exceptions/exceptions.py +19 -0
  568. b1sl/saphdb/main.py +18 -0
  569. b1sl/saphdb/models/result.py +18 -0
  570. b1sl/saphdb/models/serial.py +37 -0
  571. b1sl/saphdb/odbc_adapter.py +220 -0
  572. b1sl/saphdb/tests/__init__.py +0 -0
  573. b1sl/saphdb/tests/test_01_settings.py +37 -0
  574. b1sl/saphdb/tests/test_02_odbc_adapter.py +96 -0
  575. b1sl/saphdb/tests/test_04_serialnumberdetails_endpoint.py +131 -0
  576. b1sl_python-0.1.0.dist-info/METADATA +169 -0
  577. b1sl_python-0.1.0.dist-info/RECORD +579 -0
  578. b1sl_python-0.1.0.dist-info/WHEEL +4 -0
  579. b1sl_python-0.1.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,347 @@
1
+ from __future__ import annotations
2
+
3
+ import asyncio
4
+ import logging
5
+ import time
6
+ from datetime import datetime, timedelta
7
+ from typing import Optional
8
+ from urllib.parse import urlencode
9
+
10
+ import httpx
11
+
12
+ from b1sl.b1sl.base_adapter import BaseRestAdapter, HookContext, ObservabilityConfig
13
+ from b1sl.b1sl.config import B1Config
14
+ from b1sl.b1sl.exceptions.exceptions import (
15
+ B1AuthError,
16
+ B1Exception,
17
+ B1NotFoundError,
18
+ B1ValidationError,
19
+ SAPConcurrencyError,
20
+ )
21
+ from b1sl.b1sl.models.result import Result
22
+
23
+ _HTTP_STATUS_TO_EXC: dict[int, type] = {
24
+ 400: B1ValidationError,
25
+ 401: B1AuthError,
26
+ 404: B1NotFoundError,
27
+ }
28
+
29
+
30
+ class AsyncRestAdapter(BaseRestAdapter):
31
+ """
32
+ Asynchronous HTTP adapter for SAP B1 Service Layer using httpx.
33
+
34
+ This adapter provides high-concurrency support with thread-safe (async-safe)
35
+ session management via an internal asyncio.Lock. It handles automatic
36
+ re-authentication and structured logging.
37
+
38
+ AI Role: Recommended for FastAPI, Temporal, or bulk async tasks.
39
+ Prevents race conditions when multiple concurrent tasks hit the session.
40
+ """
41
+
42
+
43
+
44
+ def __init__(self, *args, session_id: str | None = None, **kwargs):
45
+ """
46
+ Initializes the async httpx client and session lock.
47
+
48
+ Args:
49
+ session_id (str, optional): An existing B1SESSION cookie to reuse.
50
+ Prevents a full login if already authenticated.
51
+ """
52
+ super().__init__(*args, **kwargs)
53
+ self._initial_session_id = session_id
54
+ self._client: httpx.AsyncClient | None = None
55
+ self._lock: asyncio.Lock | None = None
56
+
57
+ async def _get_lock(self) -> asyncio.Lock:
58
+ if self._lock is None:
59
+ self._lock = asyncio.Lock()
60
+ return self._lock
61
+
62
+ @property
63
+ def session_id(self) -> str | None:
64
+ """
65
+ Retrieves the current SAP session ID from the httpx cookie jar.
66
+
67
+ Returns:
68
+ str: The B1SESSION cookie value or None.
69
+ """
70
+ if not self._client:
71
+ return None
72
+ return self._client.cookies.get("B1SESSION")
73
+
74
+ async def connect(self) -> None:
75
+ """
76
+ Initializes the underlying HTTP client and logs in.
77
+ Must be called if not using the async context manager.
78
+ """
79
+ if not self._client:
80
+ self._client = httpx.AsyncClient(
81
+ verify=self._ssl_verify,
82
+ timeout=httpx.Timeout(
83
+ self._connect_timeout,
84
+ read=self._read_timeout,
85
+ write=self._read_timeout,
86
+ pool=self._connect_timeout,
87
+ ),
88
+ follow_redirects=True,
89
+ )
90
+ # Hydrate session if provided
91
+ if self._initial_session_id:
92
+ self._client.cookies.set("B1SESSION", self._initial_session_id)
93
+ self.is_session_active = True
94
+ # We don't have an expiry date, so we set it to None, which
95
+ # forces the 401-retry logic to handle it if it's already expired.
96
+ self.token_expiry = None
97
+ self._is_closed = False
98
+ await self.ensure_session()
99
+
100
+ async def aclose(self) -> None:
101
+ """
102
+ Logs out and closes the underlying HTTP client pool.
103
+ Must be called to ensure clean shutdown if not using the context manager.
104
+ """
105
+ if getattr(self, "_is_closed", False):
106
+ return
107
+
108
+ if self.is_session_active:
109
+ try:
110
+ await self.logout()
111
+ except Exception as e:
112
+ self._logger.warning(
113
+ f"[{self._username}] Failed to logout during cleanup: {e}"
114
+ )
115
+ if self._client:
116
+ await self._client.aclose()
117
+ self._client = None
118
+
119
+ self._is_closed = True
120
+
121
+ async def __aenter__(self) -> AsyncRestAdapter:
122
+ """
123
+ Async context manager entry point. Initialises the HTTP client.
124
+
125
+ Returns:
126
+ AsyncRestAdapter: The initialised instance.
127
+ """
128
+ await self.connect()
129
+ return self
130
+
131
+ async def __aexit__(self, exc_type, exc_val, exc_tb) -> None:
132
+ """
133
+ Async context manager exit point. Performs logout and closes the client.
134
+ """
135
+ await self.aclose()
136
+
137
+ async def ensure_session(self, force_refresh_if_expiry: Optional[datetime] = None) -> None:
138
+ """
139
+ Ensures a valid SAP session exists before a request.
140
+
141
+ Uses an internal asyncio.Lock to prevent multiple concurrent login
142
+ attempts when many tasks start simultaneously. If force_refresh_if_expiry
143
+ is provided, it will forcefully invalidate the session ONLY if the token
144
+ hasn't been refreshed by another task in the meantime.
145
+ """
146
+ if not self._client:
147
+ raise B1Exception("AsyncRestAdapter not initialized. Call connect() first.")
148
+ lock = await self._get_lock()
149
+ async with lock:
150
+ if force_refresh_if_expiry is not None and self.token_expiry == force_refresh_if_expiry:
151
+ self.is_session_active = False
152
+
153
+ if (
154
+ not self.is_session_active
155
+ or not self.token_expiry
156
+ or datetime.now() >= self.token_expiry
157
+ ):
158
+ await self.login()
159
+
160
+ async def login(self) -> Result:
161
+ """
162
+ Asynchronously authenticates with the SAP B1 Service Layer.
163
+ """
164
+ data = {
165
+ "UserName": self._username,
166
+ "Password": self._password,
167
+ "CompanyDB": self._db,
168
+ }
169
+ self._logger.info(f"Logging in to SAP B1 at {self.raw_base_url}...")
170
+
171
+ try:
172
+ # We call _do which handles its own timing and logging
173
+ return await self._do(
174
+ http_method="POST", endpoint="Login", data=data, _is_login=True
175
+ )
176
+ except Exception as e:
177
+ self._logger.error(f"Login failed: {e}")
178
+ raise B1AuthError(f"Login failed: {e}") from e
179
+
180
+ async def logout(self) -> Result:
181
+ """
182
+ Asynchronously releases the SAP B1 session license.
183
+
184
+ Returns:
185
+ Result: Current logout state.
186
+ """
187
+ if not self._client:
188
+ return Result(status_code=200, message="Closed")
189
+ try:
190
+ response = await self._client.post(f"{self.raw_base_url}/Logout")
191
+ self.is_session_active = False
192
+ self.token_expiry = None
193
+ return Result(
194
+ status_code=response.status_code, message=response.reason_phrase
195
+ )
196
+ except Exception as e:
197
+ self._logger.warning(f"[{self._username}] Logout failed: {e}")
198
+ return Result(status_code=500, message=str(e))
199
+
200
+ @staticmethod
201
+ def _parse_sap_error(response: httpx.Response) -> tuple[str, str]:
202
+ """Parses error information from an Httpx response object."""
203
+ try:
204
+ body = response.json()
205
+ except Exception:
206
+ body = None
207
+ return AsyncRestAdapter._parse_sap_error_shared(
208
+ response.status_code, response.reason_phrase, body
209
+ )
210
+
211
+ async def _do(
212
+ self,
213
+ http_method: str,
214
+ endpoint: str,
215
+ ep_params=None,
216
+ data=None,
217
+ _is_login: bool = False,
218
+ _retry_once=True,
219
+ ) -> Result:
220
+ """
221
+ Dispatches an asynchronous HTTP request to SAP SL.
222
+ Implements Senior Observability (Timing + Structured Logging + Async Hooks).
223
+ """
224
+ # Removed redundant imports moved to module level
225
+ if not _is_login:
226
+ await self.ensure_session()
227
+
228
+ req_id = self._generate_req_id()
229
+ endpoint_path = endpoint if endpoint.startswith("/") else f"/{endpoint}"
230
+ full_url = self.raw_base_url + endpoint_path
231
+
232
+ log_data = self._redact_data(data)
233
+ self._logger.debug(f"[{req_id}] data={log_data}")
234
+
235
+ start_time = time.perf_counter()
236
+ exc_captured: Exception | None = None
237
+ response: httpx.Response | None = None
238
+ is_success = False
239
+
240
+ try:
241
+ # ── ETag: inject If-None-Match (GET) or If-Match (PATCH/DELETE/POST) ──
242
+ headers = self._build_headers(http_method, endpoint_path)
243
+ response = await self._client.request(
244
+ method=http_method, url=full_url, params=ep_params, json=data,
245
+ headers=headers,
246
+ )
247
+
248
+ if response.status_code == 401 and _retry_once and not _is_login:
249
+ self._logger.warning(f"[{req_id}] 401 Unauthorized - retrying login...")
250
+ await self.ensure_session(force_refresh_if_expiry=self.token_expiry)
251
+ # Recursive call will handle its own finally block,
252
+ # but we need to return here to avoid double-logging/hooking.
253
+ return await self._do(
254
+ http_method, endpoint, ep_params, data, _is_login, _retry_once=False
255
+ )
256
+
257
+ response.raise_for_status()
258
+ is_success = True
259
+ except httpx.HTTPStatusError as e:
260
+ exc_captured = e
261
+ sap_code, sap_msg = self._parse_sap_error(e.response)
262
+ # ── Raise specialised exception before falling back to B1Exception ──
263
+ try:
264
+ body = e.response.json() if e.response.content else None
265
+ except Exception:
266
+ body = None
267
+ self._raise_if_concurrency_error(
268
+ e.response.status_code, sap_code, sap_msg, endpoint_path, body
269
+ )
270
+ raise B1Exception(f"SAP Error {sap_code}: {sap_msg}") from e
271
+ except Exception as e:
272
+ exc_captured = e
273
+ raise B1Exception(f"Request failed: {e}") from e
274
+ finally:
275
+ # Only log/hook if this is not the first attempt of a 401 retry
276
+ if not (
277
+ response is not None
278
+ and response.status_code == 401
279
+ and _retry_once
280
+ and not _is_login
281
+ ):
282
+ duration_ms = (time.perf_counter() - start_time) * 1000
283
+ status_code = response.status_code if response is not None else None
284
+
285
+ ctx = HookContext(
286
+ req_id=req_id,
287
+ http_method=http_method,
288
+ base_url=self.raw_base_url,
289
+ endpoint=endpoint_path,
290
+ query_params=urlencode(ep_params) if ep_params else "",
291
+ db=self._db,
292
+ user=self._username,
293
+ status_code=status_code,
294
+ duration_ms=duration_ms,
295
+ extra=dict(self._obs.context_extras),
296
+ exc=exc_captured,
297
+ )
298
+
299
+ self._log_response(ctx)
300
+ await self._hooks.adispatch(
301
+ "on_error" if exc_captured else "on_response", ctx, self._logger
302
+ )
303
+
304
+ if _is_login and is_success and response is not None:
305
+ data_out = response.json()
306
+ timeout_min = data_out.get("SessionTimeout", 30)
307
+ self.token_expiry = datetime.now() + timedelta(minutes=timeout_min - 2)
308
+ self.is_session_active = True
309
+
310
+ if is_success and response is not None:
311
+ data_out = response.json() if response.content else None
312
+ # ── ETag: extract from header (preferred) or body fallback ──
313
+ self._extract_etag(endpoint_path, dict(response.headers), data_out)
314
+ return Result(
315
+ status_code=response.status_code,
316
+ message=response.reason_phrase,
317
+ data=data_out,
318
+ next_link=data_out.get("odata.nextLink")
319
+ if isinstance(data_out, dict)
320
+ else None,
321
+ next_params=self._get_ep_params(data_out.get("odata.nextLink"))
322
+ if isinstance(data_out, dict) and data_out.get("odata.nextLink")
323
+ else None,
324
+ metadata=data_out.get("odata.metadata")
325
+ if isinstance(data_out, dict)
326
+ else None,
327
+ )
328
+ else:
329
+ raise B1Exception(
330
+ f"HTTP Error {response.status_code if response else 'Unknown'}"
331
+ )
332
+
333
+ async def get(self, endpoint, ep_params=None, data=None):
334
+ """Execute an asynchronous GET request."""
335
+ return await self._do("GET", endpoint, ep_params, data)
336
+
337
+ async def post(self, endpoint, ep_params=None, data=None):
338
+ """Execute an asynchronous POST request."""
339
+ return await self._do("POST", endpoint, ep_params, data)
340
+
341
+ async def patch(self, endpoint, ep_params=None, data=None):
342
+ """Execute an asynchronous PATCH request."""
343
+ return await self._do("PATCH", endpoint, ep_params, data)
344
+
345
+ async def delete(self, endpoint, ep_params=None, data=None):
346
+ """Execute an asynchronous DELETE request."""
347
+ return await self._do("DELETE", endpoint, ep_params, data)