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
b1sl/saphdb/adapter.py ADDED
@@ -0,0 +1,24 @@
1
+ from typing import Optional
2
+
3
+ from b1sl.saphdb.config import SapHDBConfig
4
+ from b1sl.saphdb.odbc_adapter import HDBCliAdapter
5
+
6
+ # This module provides a shared odbc_adapter instance for Django users.
7
+ # It uses settings.SAPODBCLIENT_* vars from the Django environment.
8
+ # Avoid importing this if not in a Django context.
9
+
10
+ _odbc_adapter: Optional[HDBCliAdapter] = None
11
+
12
+
13
+ def get_odbc_adapter() -> HDBCliAdapter:
14
+ global _odbc_adapter
15
+ if _odbc_adapter is None:
16
+ _odbc_adapter = HDBCliAdapter.from_config(SapHDBConfig.from_django_settings())
17
+ return _odbc_adapter
18
+
19
+
20
+ # Legacy support for direct access
21
+ try:
22
+ odbc_adapter = get_odbc_adapter()
23
+ except Exception:
24
+ odbc_adapter = None
b1sl/saphdb/client.py ADDED
@@ -0,0 +1,50 @@
1
+ """
2
+ SapHDBClient — Framework-agnostic entry point for SAP HANA ODBC SDK.
3
+
4
+ Usage (standalone / scripts):
5
+ from b1sl.saphdb import SapHDBClient, SapHDBConfig
6
+ config = SapHDBConfig.from_env()
7
+ client = SapHDBClient(config)
8
+
9
+ Usage (Django — in service layer only):
10
+ from b1sl.saphdb import SapHDBClient, SapHDBConfig
11
+ config = SapHDBConfig.from_django_settings()
12
+ client = SapHDBClient(config)
13
+ """
14
+
15
+ from __future__ import annotations
16
+
17
+ import logging
18
+
19
+ from b1sl.saphdb.config import SapHDBConfig
20
+ from b1sl.saphdb.odbc_adapter import HDBCliAdapter
21
+
22
+
23
+ class SapHDBClient:
24
+ """
25
+ Public interface for the SAP HANA ODBC SDK.
26
+ """
27
+
28
+ def __init__(
29
+ self,
30
+ config: SapHDBConfig,
31
+ logger: logging.Logger | None = None,
32
+ ) -> None:
33
+ self._logger = logger or logging.getLogger(__name__)
34
+ self._adapter = HDBCliAdapter.from_config(config, logger=self._logger)
35
+
36
+ # Lazy resources
37
+ self._serial_numbers = None
38
+
39
+ @property
40
+ def serial_numbers(self):
41
+ """Access the SerialNumberDetails ODBC resource."""
42
+ if self._serial_numbers is None:
43
+ from b1sl.saphdb.endpoints.serialnumberdetailodbc import (
44
+ SerialNumberDetailsODBCEndpoint,
45
+ )
46
+
47
+ self._serial_numbers = SerialNumberDetailsODBCEndpoint(
48
+ adapter=self._adapter
49
+ )
50
+ return self._serial_numbers
b1sl/saphdb/config.py ADDED
@@ -0,0 +1,68 @@
1
+ from __future__ import annotations
2
+
3
+ import os
4
+ from dataclasses import dataclass, field
5
+ from datetime import timedelta
6
+
7
+
8
+ @dataclass
9
+ class SapHDBConfig:
10
+ address: str
11
+ port: int
12
+ user: str
13
+ password: str
14
+ schema: str
15
+ reuse_connection: bool = False
16
+ connection_timeout: timedelta = field(
17
+ default_factory=lambda: timedelta(seconds=900)
18
+ )
19
+
20
+ @classmethod
21
+ def from_env(cls) -> "SapHDBConfig":
22
+ """Load config from environment variables (no Django dependency)."""
23
+ missing = []
24
+ required = {
25
+ "address": "SAPODBCLIENT_ADDRESS",
26
+ "port": "SAPODBCLIENT_PORT",
27
+ "user": "SAPODBCLIENT_USER",
28
+ "password": "SAPODBCLIENT_PASSWORD",
29
+ "schema": "SAPODBCLIENT_COMPANY_DB",
30
+ }
31
+ kwargs = {}
32
+ for attr, env_key in required.items():
33
+ val = os.environ.get(env_key)
34
+ if not val:
35
+ missing.append(env_key)
36
+ kwargs[attr] = val
37
+
38
+ if missing:
39
+ raise EnvironmentError(
40
+ f"Missing required SAP HDB config env vars: {missing}"
41
+ )
42
+
43
+ kwargs["port"] = int(kwargs["port"])
44
+ # Standard pythonic way to parse boolean environment variables
45
+ env_reuse = os.environ.get("SAPODBCLIENT_REUSE_CONNECTION", "False").lower()
46
+ kwargs["reuse_connection"] = env_reuse in ("true", "1", "t", "y", "yes")
47
+
48
+ kwargs["connection_timeout"] = timedelta(
49
+ seconds=int(os.environ.get("SAPODBCLIENT_CONNECTION_TIMEOUT", 900))
50
+ )
51
+ return cls(**kwargs)
52
+
53
+ @classmethod
54
+ def from_django_settings(cls) -> "SapHDBConfig":
55
+ """Load from django.conf.settings — only call this inside a Django app."""
56
+ from django.conf import settings
57
+
58
+ return cls(
59
+ address=settings.SAPODBCLIENT_ADDRESS,
60
+ port=int(settings.SAPODBCLIENT_PORT),
61
+ user=settings.SAPODBCLIENT_USER,
62
+ password=settings.SAPODBCLIENT_PASSWORD,
63
+ schema=settings.SAPODBCLIENT_COMPANY_DB,
64
+ reuse_connection=getattr(settings, "SAPODBCLIENT_REUSE_CONNECTION", False),
65
+ connection_timeout=timedelta(
66
+ seconds=int(getattr(settings, "SAPODBCLIENT_CONNECTION_TIMEOUT", 900))
67
+ ),
68
+ )
@@ -0,0 +1,100 @@
1
+ from b1sl.saphdb.exceptions.exceptions import SapHAClientException
2
+ from b1sl.saphdb.models.serial import SerialNumberList
3
+ from b1sl.saphdb.odbc_adapter import HDBCliAdapter
4
+
5
+
6
+ class SerialNumberDetailsODBCEndpoint:
7
+ """
8
+ Provides methods for interacting with SerialNumberDetails in an SAP B1 system.
9
+ """
10
+
11
+ def __init__(self, adapter: HDBCliAdapter):
12
+ """
13
+ Initializes the SerialNumberDetailsEndpoint with a RestAdapter instance.
14
+ """
15
+ self.adapter = adapter
16
+
17
+ @staticmethod
18
+ def _format_payload_for_api(payload: dict) -> dict:
19
+ """Converts internal representation to the format expected by the API."""
20
+ # Converts boolean values to the format expected by the API.
21
+ # if 'Valid' in payload:
22
+ # payload['Valid'] = 'tYES' if payload.get('valid', True) else 'tNO'
23
+ # payload['Frozen'] = 'tNO' if payload.get('valid', True) else 'tYES'
24
+
25
+ return payload
26
+
27
+ @staticmethod
28
+ def _parse_api_response(data: dict) -> dict:
29
+ """Converts API response to internal representation."""
30
+ # Converts 'tYES'/'tNO' values to booleans in the API response.
31
+ # if 'Valid' in data:
32
+ # data['Valid'] = True if data['Valid'] == 'tYES' else False
33
+
34
+ return data
35
+
36
+ # TODO: AGREGAR MANEJO DE ERRORES EN ELEMENTOS SQL-SL
37
+ def get_by_id(self, doc_entry: int) -> SerialNumberList:
38
+ """Consulta un ítem en el sistema."""
39
+ try:
40
+ query = """
41
+ SELECT TOP 10 T0."AbsEntry", T0."Quantity", T0."QuantOut", T1."WhsCode"
42
+ FROM OSRN T0 INNER JOIN OSRI T1 ON (T0."ItemCode" = T1."ItemCode") AND (T1."SuppSerial" = T0."MnfSerial") AND (T0."SysNumber" = T1."SysSerial")
43
+ WHERE T0."AbsEntry" = ?
44
+ """
45
+ result = self.adapter.execute_query(query=query, params=(doc_entry,))
46
+
47
+ response = SerialNumberDetailsODBCEndpoint._parse_api_response(
48
+ data=result.data
49
+ )
50
+
51
+ if response and len(response) > 0:
52
+ serialnumberdetails_list = response[0]
53
+ print(f"serialnumberdetail_list: {serialnumberdetails_list}")
54
+ return SerialNumberList(**serialnumberdetails_list)
55
+ else:
56
+ raise ValueError(f"No serial number found with doc entry {doc_entry}")
57
+
58
+ except SapHAClientException as e:
59
+ raise ValueError(
60
+ f"Error retrieving serial number with doc entry {doc_entry}: {e}"
61
+ )
62
+
63
+ def get_by_ids(self, doc_entries: list[int]) -> list[SerialNumberList]:
64
+ """Consulta ítems en el sistema para una lista de IDs."""
65
+ if not doc_entries:
66
+ raise ValueError("La lista de IDs está vacía.")
67
+
68
+ try:
69
+ # Construir dinámicamente los placeholders para el IN
70
+ placeholders = ", ".join(["?"] * len(doc_entries))
71
+ query = f"""
72
+ SELECT T0."AbsEntry", T0."Quantity", T0."QuantOut", T1."WhsCode"
73
+ FROM OSRN T0
74
+ INNER JOIN OSRI T1
75
+ ON (T0."ItemCode" = T1."ItemCode") AND (T1."SuppSerial" = T0."MnfSerial") AND (T0."SysNumber" = T1."SysSerial")
76
+ WHERE T0."AbsEntry" IN ({placeholders})
77
+ """
78
+
79
+ result = self.adapter.execute_query(query=query, params=tuple(doc_entries))
80
+
81
+ # Parsear la respuesta
82
+ response = SerialNumberDetailsODBCEndpoint._parse_api_response(
83
+ data=result.data
84
+ )
85
+
86
+ if response:
87
+ serialnumberdetails_list = [
88
+ SerialNumberList(**item) for item in response
89
+ ]
90
+ print(f"serialnumberdetails_list: {serialnumberdetails_list}")
91
+ return serialnumberdetails_list
92
+ else:
93
+ raise ValueError(
94
+ "No se encontraron números de serie para los IDs proporcionados."
95
+ )
96
+
97
+ except SapHAClientException as e:
98
+ raise ValueError(
99
+ f"Error al recuperar números de serie para los IDs proporcionados: {e}"
100
+ )
@@ -0,0 +1,19 @@
1
+ class SapHAClientException(Exception):
2
+ """Base exception for all SAP HANA client errors."""
3
+
4
+ def __init__(self, message, details=None):
5
+ super().__init__(message)
6
+ self.details = details
7
+
8
+
9
+ class SapHAClientConnectionError(SapHAClientException):
10
+ pass
11
+
12
+
13
+ class SapHAClientResponseError(SapHAClientException):
14
+ pass
15
+
16
+
17
+ # Legacy aliases
18
+ B1ClientConnectionError = SapHAClientConnectionError
19
+ B1ClientResponseError = SapHAClientResponseError
b1sl/saphdb/main.py ADDED
@@ -0,0 +1,18 @@
1
+ from b1sl.saphdb.adapter import odbc_adapter
2
+
3
+ if __name__ == "__main__":
4
+ # Ejecución de una consulta
5
+ try:
6
+ adapter = odbc_adapter
7
+ query = """
8
+ SELECT TOP 2 T0."ItemName"
9
+ FROM OITM T0
10
+ """
11
+ result = adapter.execute_query(query=query)
12
+ print(result) # Muestra el resultado en formato JSON
13
+ except Exception as e:
14
+ print(f"Error al ejecutar la consulta: {e}")
15
+ # logger.error(f"Error al ejecutar la consulta: {e}")
16
+ finally:
17
+ # Cierra la conexión explícitamente si no es reutilizable
18
+ adapter.close()
@@ -0,0 +1,18 @@
1
+ from typing import Dict, List, Optional
2
+
3
+ from pydantic import BaseModel, ConfigDict
4
+
5
+
6
+ class Result(BaseModel):
7
+ status_code: int
8
+ message: str = ""
9
+ # data: Optional[Dict] = None
10
+ data: Optional[List[Dict]] = None # Cambiado para aceptar listas de diccionarios
11
+ next_link: Optional[str] = None
12
+ next_params: Optional[Dict] = None
13
+ metadata: Optional[str] = None
14
+
15
+ # Actualiza la configuración para Pydantic V2
16
+ model_config = ConfigDict(
17
+ extra="allow" # Permite campos adicionales no definidos
18
+ )
@@ -0,0 +1,37 @@
1
+ from decimal import Decimal
2
+ from typing import Optional
3
+
4
+ from pydantic import BaseModel, ConfigDict, Field
5
+
6
+
7
+ class BaseSerialNumberDetailModel(BaseModel):
8
+ # active: Optional[bool] = Field(default=True, alias="Valid")
9
+
10
+ def to_api_payload(self) -> dict:
11
+ """Convierte el modelo a un formato compatible con la API."""
12
+ payload = self.model_dump(by_alias=True)
13
+ # payload['Valid'] = 'tYES' if payload.get('Valid', False) else 'tNO'
14
+ return payload
15
+
16
+ model_config = ConfigDict(
17
+ populate_by_name=True, # Reemplaza a 'allow_population_by_field_name'
18
+ extra="allow", # Permite campos adicionales no definidos
19
+ )
20
+
21
+
22
+ class SerialNumberList(BaseSerialNumberDetailModel):
23
+ doc_entry: int = Field(alias="AbsEntry")
24
+ warehouse: Optional[str] = Field(alias="WhsCode", default=None)
25
+ quantity_out: Optional[Decimal] = Field(alias="QuantOut", default=None)
26
+ quantity: Optional[Decimal] = Field(alias="Quantity", default=None)
27
+
28
+ # in_stock: Optional[bool] = None # Campo derivado
29
+
30
+ # @model_validator(mode='before')
31
+ # def calculate_in_stock(cls, values):
32
+ # quantity_out = values.get('quantity_out')
33
+ # if quantity_out >= 1:
34
+ # values['in_stock'] = False
35
+ # else:
36
+ # values['in_stock'] = True
37
+ # return values
@@ -0,0 +1,220 @@
1
+ import logging
2
+ import threading
3
+ from contextlib import contextmanager
4
+ from datetime import datetime, timedelta
5
+ from typing import Any, Dict, List, Optional, Tuple
6
+
7
+ from hdbcli import dbapi
8
+ from pydantic import BaseModel
9
+
10
+ from b1sl.saphdb.models.result import Result
11
+
12
+
13
+ class QueryResult(BaseModel):
14
+ data: List[Dict[str, Any]]
15
+
16
+
17
+ class HDBCliAdapter:
18
+ @classmethod
19
+ def from_config(
20
+ cls, config, logger: Optional[logging.Logger] = None
21
+ ) -> "HDBCliAdapter":
22
+ return cls(
23
+ address=config.address,
24
+ port=config.port,
25
+ user=config.user,
26
+ password=config.password,
27
+ schema=config.schema,
28
+ logger=logger,
29
+ reuse_connection=config.reuse_connection,
30
+ connection_timeout=config.connection_timeout,
31
+ )
32
+
33
+ def __init__(
34
+ self,
35
+ address: str,
36
+ port: int,
37
+ user: str,
38
+ password: str,
39
+ schema: str,
40
+ logger: Optional[logging.Logger] = None,
41
+ reuse_connection: bool = False,
42
+ connection_timeout: timedelta = timedelta(seconds=900),
43
+ ):
44
+ self._lock = threading.RLock()
45
+ self.address = address
46
+ self.port = port
47
+ self.user = user
48
+ self.password = password
49
+ self.schema = schema
50
+ self.logger = logger or logging.getLogger(__name__)
51
+
52
+ self.connection = None
53
+ self.reuse_connection = reuse_connection
54
+ self.connection_timeout = connection_timeout
55
+ self.connection_expiry = None
56
+
57
+ def connect(self):
58
+ """Idempotent and thread-safe connection establishment with liveness check."""
59
+ with self._lock:
60
+ if self.connection is None or self._is_connection_expired():
61
+ # Close the dead socket gracefully if possible
62
+ if self.connection is not None:
63
+ try:
64
+ self.connection.close()
65
+ except Exception:
66
+ pass
67
+ finally:
68
+ self.connection = None
69
+
70
+ try:
71
+ self.connection = dbapi.connect(
72
+ address=self.address,
73
+ port=self.port,
74
+ user=self.user,
75
+ password=self.password,
76
+ )
77
+ self.connection_expiry = datetime.now() + self.connection_timeout
78
+ self.logger.info("Connected to HANA database")
79
+ except dbapi.Error as e:
80
+ self.logger.error(
81
+ f"Failed to connect to HANA database: {e.errortext} (Code: {e.errorcode})"
82
+ )
83
+ raise
84
+ except Exception as e:
85
+ self.logger.error(
86
+ f"Failed to connect to HANA (Network/OS Error): {e}"
87
+ )
88
+ raise
89
+
90
+ def _is_connection_expired(self) -> bool:
91
+ """Checks both clock-based timeout and actual socket liveness."""
92
+ if self.connection_expiry is None or self.connection is None:
93
+ return True
94
+ if datetime.now() >= self.connection_expiry:
95
+ return True
96
+
97
+ # Real Liveness Check (hdbcli specific)
98
+ try:
99
+ if hasattr(self.connection, "isconnected"):
100
+ if not self.connection.isconnected():
101
+ self.logger.warning("HANA socket is natively reported as dead.")
102
+ return True
103
+ else:
104
+ # Fallback if driver version lacks isconnected(): ping via dummy execute
105
+ cursor = self.connection.cursor()
106
+ cursor.execute("SELECT 1 FROM DUMMY")
107
+ cursor.close()
108
+ except dbapi.Error:
109
+ self.logger.warning("HANA socket is dead (failed liveness ping).")
110
+ return True
111
+ return False
112
+
113
+ @contextmanager
114
+ def transaction(self):
115
+ """
116
+ Transactional Context Manager.
117
+ Ensures atomic execution: COMMIT on success, ROLLBACK on error.
118
+ """
119
+ with self._lock:
120
+ self.connect()
121
+ try:
122
+ yield self.connection
123
+ self.connection.commit()
124
+ self.logger.debug("Transaction committed.")
125
+ except dbapi.Error as e:
126
+ try:
127
+ self.connection.rollback()
128
+ except Exception:
129
+ pass
130
+ self.logger.error(
131
+ f"Transaction rolled back due to HANA error: {e.errortext} (Code: {e.errorcode})"
132
+ )
133
+ raise
134
+ except Exception as e:
135
+ try:
136
+ self.connection.rollback()
137
+ except Exception:
138
+ pass
139
+ self.logger.error(f"Transaction rolled back due to Runtime Error: {e}")
140
+ raise
141
+
142
+ def execute_query(
143
+ self,
144
+ query: str,
145
+ params: Optional[Tuple[Any, ...]] = None,
146
+ schema: Optional[str] = None,
147
+ ) -> Result:
148
+ """
149
+ Executes a query safely using bind variables.
150
+ """
151
+ with self._lock:
152
+ cursor = None
153
+ try:
154
+ # Use transactional scope for query execution
155
+ with self.transaction() as conn:
156
+ cursor = conn.cursor()
157
+
158
+ # Sanitize schema name (SQL injection prevention for identifiers)
159
+ active_schema = schema or self.schema
160
+ if active_schema:
161
+ # Add double quotes to prevent identifier injection
162
+ cursor.execute(f'SET SCHEMA "{active_schema}"')
163
+ self.logger.debug(f"Schema set to: {active_schema}")
164
+
165
+ # Execute safely with bind variables
166
+ if params:
167
+ cursor.execute(query, params)
168
+ else:
169
+ cursor.execute(query)
170
+
171
+ self.logger.info("Query executed successfully.")
172
+
173
+ if cursor.description:
174
+ columns = [col[0] for col in cursor.description]
175
+ results = [dict(zip(columns, row)) for row in cursor.fetchall()]
176
+ else:
177
+ results = []
178
+
179
+ return Result(
180
+ status_code=200,
181
+ message="Query executed successfully.",
182
+ data=results,
183
+ )
184
+ except dbapi.Error as e:
185
+ self.logger.error(
186
+ f"HANA Query error: {e.errortext} (Code: {e.errorcode})"
187
+ )
188
+ return Result(
189
+ status_code=500,
190
+ message=f"SAP HANA Error [{e.errorcode}]: {e.errortext}",
191
+ )
192
+ except Exception as e:
193
+ self.logger.error(f"Runtime query execution error: {e}")
194
+ return Result(status_code=500, message=f"Runtime query error: {str(e)}")
195
+ finally:
196
+ if cursor:
197
+ cursor.close()
198
+ if not self.reuse_connection:
199
+ self.close()
200
+
201
+ def close(self):
202
+ """Idempotent closure of resources."""
203
+ with self._lock:
204
+ if self.connection is not None:
205
+ try:
206
+ self.connection.close()
207
+ except Exception:
208
+ pass
209
+ finally:
210
+ self.connection = None
211
+ self.connection_expiry = None
212
+ self.logger.info("Connection closed.")
213
+
214
+ # Support for simple 'with adapter:' usage
215
+ def __enter__(self):
216
+ self.connect()
217
+ return self
218
+
219
+ def __exit__(self, exc_type, exc_val, exc_tb):
220
+ self.close()
File without changes
@@ -0,0 +1,37 @@
1
+ from django.conf import settings
2
+ from django.test import TestCase
3
+
4
+
5
+ class SettingsTestCase(TestCase):
6
+ def test_assert_is_working(self):
7
+ self.assertTrue(True)
8
+
9
+ def test_load_settings(self):
10
+ self.assertIsNotNone(
11
+ settings.SAPODBCLIENT_ADDRESS, "SAPODBCLIENT_ADDRESS should not be None"
12
+ )
13
+ self.assertIsNotNone(
14
+ settings.SAPODBCLIENT_PORT, "SAPODBCLIENT_PORT should not be None"
15
+ )
16
+ self.assertIsNotNone(
17
+ settings.SAPODBCLIENT_USER, "SAPODBCLIENT_USER should not be None"
18
+ )
19
+ self.assertIsNotNone(
20
+ settings.SAPODBCLIENT_PASSWORD, "SAPODBCLIENT_PASSWORD should not be None"
21
+ )
22
+ self.assertIsNotNone(
23
+ settings.SAPODBCLIENT_COMPANY_DB,
24
+ "SAPODBCLIENT_COMPANY_DB should not be None",
25
+ )
26
+ self.assertIsNotNone(
27
+ settings.SAPODBCLIENT_REUSE_CONNECTION,
28
+ "SAPODBCLIENT_REUSE_CONNECTION should not be None",
29
+ )
30
+ self.assertIsNotNone(
31
+ settings.SAPODBCLIENT_CONNECTION_TIMEOUT,
32
+ "SAPODBCLIENT_CONNECTION_TIMEOUT should not be None",
33
+ )
34
+ self.assertTrue(
35
+ settings.SAPODBCLIENT_IS_CONFIGURED,
36
+ "SAPODBCLIENT_IS_CONFIGURED should be True",
37
+ )