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.
- b1sl/__init__.py +5 -0
- b1sl/b1sl/__init__.py +56 -0
- b1sl/b1sl/_types.py +28 -0
- b1sl/b1sl/adapter.py +40 -0
- b1sl/b1sl/adapter_protocol.py +28 -0
- b1sl/b1sl/async_client.py +268 -0
- b1sl/b1sl/async_rest_adapter.py +347 -0
- b1sl/b1sl/base_adapter.py +394 -0
- b1sl/b1sl/client.py +112 -0
- b1sl/b1sl/config.py +138 -0
- b1sl/b1sl/config_manager.py +77 -0
- b1sl/b1sl/contrib/__init__.py +14 -0
- b1sl/b1sl/contrib/django/__init__.py +13 -0
- b1sl/b1sl/contrib/django/middleware/__init__.py +27 -0
- b1sl/b1sl/contrib/django/middleware/base.py +89 -0
- b1sl/b1sl/contrib/django/middleware/odata_decode_middleware.py +20 -0
- b1sl/b1sl/contrib/django/middleware/odata_transform_url_middleware.py +20 -0
- b1sl/b1sl/entities/__init__.py +2209 -0
- b1sl/b1sl/environment.py +36 -0
- b1sl/b1sl/exceptions/exceptions.py +142 -0
- b1sl/b1sl/fields/__init__.py +2020 -0
- b1sl/b1sl/fields/_generated/__init__.py +0 -0
- b1sl/b1sl/fields/_generated/complex_types.py +6926 -0
- b1sl/b1sl/fields/_generated/entities/__init__.py +0 -0
- b1sl/b1sl/fields/_generated/entities/businesspartners.py +544 -0
- b1sl/b1sl/fields/_generated/entities/finance.py +451 -0
- b1sl/b1sl/fields/_generated/entities/general.py +4587 -0
- b1sl/b1sl/fields/_generated/entities/inventory.py +761 -0
- b1sl/b1sl/fields/_generated/entities/production.py +256 -0
- b1sl/b1sl/fields/_generated/entities/purchasing.py +53 -0
- b1sl/b1sl/fields/_generated/entities/sales.py +244 -0
- b1sl/b1sl/logging_utils.py +119 -0
- b1sl/b1sl/models/__init__.py +13 -0
- b1sl/b1sl/models/_generated/__init__.py +0 -0
- b1sl/b1sl/models/_generated/_types.py +5 -0
- b1sl/b1sl/models/_generated/complex_types.py +6929 -0
- b1sl/b1sl/models/_generated/entities/__init__.py +581 -0
- b1sl/b1sl/models/_generated/entities/businesspartners.py +565 -0
- b1sl/b1sl/models/_generated/entities/finance.py +472 -0
- b1sl/b1sl/models/_generated/entities/general.py +4831 -0
- b1sl/b1sl/models/_generated/entities/inventory.py +786 -0
- b1sl/b1sl/models/_generated/entities/production.py +272 -0
- b1sl/b1sl/models/_generated/entities/purchasing.py +64 -0
- b1sl/b1sl/models/_generated/entities/sales.py +263 -0
- b1sl/b1sl/models/_generated/enums.py +3501 -0
- b1sl/b1sl/models/_generated/resources/__init__.py +0 -0
- b1sl/b1sl/models/_overrides/inventory.py +24 -0
- b1sl/b1sl/models/base.py +209 -0
- b1sl/b1sl/models/odata_query_model.py +50 -0
- b1sl/b1sl/models/paginated_result.py +85 -0
- b1sl/b1sl/models/result.py +17 -0
- b1sl/b1sl/resources/__init__.py +11 -0
- b1sl/b1sl/resources/_generated/__init__.py +0 -0
- b1sl/b1sl/resources/_generated/account_category.py +15 -0
- b1sl/b1sl/resources/_generated/account_category_service.py +21 -0
- b1sl/b1sl/resources/_generated/account_segmentation_categories.py +15 -0
- b1sl/b1sl/resources/_generated/account_segmentations.py +15 -0
- b1sl/b1sl/resources/_generated/accounts_service.py +33 -0
- b1sl/b1sl/resources/_generated/accrual_types.py +15 -0
- b1sl/b1sl/resources/_generated/accrual_types_service.py +21 -0
- b1sl/b1sl/resources/_generated/activities.py +15 -0
- b1sl/b1sl/resources/_generated/activities_service.py +109 -0
- b1sl/b1sl/resources/_generated/activity_locations.py +15 -0
- b1sl/b1sl/resources/_generated/activity_recipient_lists.py +15 -0
- b1sl/b1sl/resources/_generated/activity_recipient_lists_service.py +21 -0
- b1sl/b1sl/resources/_generated/activity_statuses.py +15 -0
- b1sl/b1sl/resources/_generated/activity_types.py +15 -0
- b1sl/b1sl/resources/_generated/additional_expenses.py +15 -0
- b1sl/b1sl/resources/_generated/address_service.py +38 -0
- b1sl/b1sl/resources/_generated/alert_managements.py +16 -0
- b1sl/b1sl/resources/_generated/alternate_cat_num.py +15 -0
- b1sl/b1sl/resources/_generated/alternative_items_service.py +113 -0
- b1sl/b1sl/resources/_generated/approval_requests.py +15 -0
- b1sl/b1sl/resources/_generated/approval_requests_service.py +33 -0
- b1sl/b1sl/resources/_generated/approval_stages.py +15 -0
- b1sl/b1sl/resources/_generated/approval_stages_service.py +21 -0
- b1sl/b1sl/resources/_generated/approval_templates.py +15 -0
- b1sl/b1sl/resources/_generated/approval_templates_service.py +21 -0
- b1sl/b1sl/resources/_generated/asset_capitalization.py +15 -0
- b1sl/b1sl/resources/_generated/asset_capitalization_credit_memo.py +15 -0
- b1sl/b1sl/resources/_generated/asset_capitalization_credit_memo_service.py +37 -0
- b1sl/b1sl/resources/_generated/asset_capitalization_service.py +37 -0
- b1sl/b1sl/resources/_generated/asset_classes.py +15 -0
- b1sl/b1sl/resources/_generated/asset_classes_service.py +21 -0
- b1sl/b1sl/resources/_generated/asset_depreciation_groups.py +15 -0
- b1sl/b1sl/resources/_generated/asset_depreciation_groups_service.py +21 -0
- b1sl/b1sl/resources/_generated/asset_groups.py +15 -0
- b1sl/b1sl/resources/_generated/asset_groups_service.py +21 -0
- b1sl/b1sl/resources/_generated/asset_manual_depreciation.py +15 -0
- b1sl/b1sl/resources/_generated/asset_manual_depreciation_service.py +37 -0
- b1sl/b1sl/resources/_generated/asset_retirement.py +15 -0
- b1sl/b1sl/resources/_generated/asset_retirement_service.py +37 -0
- b1sl/b1sl/resources/_generated/asset_transfer.py +15 -0
- b1sl/b1sl/resources/_generated/asset_transfer_service.py +37 -0
- b1sl/b1sl/resources/_generated/attachments2.py +15 -0
- b1sl/b1sl/resources/_generated/attribute_groups.py +15 -0
- b1sl/b1sl/resources/_generated/attribute_groups_service.py +21 -0
- b1sl/b1sl/resources/_generated/bank_charges_allocation_codes.py +15 -0
- b1sl/b1sl/resources/_generated/bank_charges_allocation_codes_service.py +21 -0
- b1sl/b1sl/resources/_generated/bank_pages.py +15 -0
- b1sl/b1sl/resources/_generated/bank_statements.py +15 -0
- b1sl/b1sl/resources/_generated/bank_statements_service.py +32 -0
- b1sl/b1sl/resources/_generated/banks.py +15 -0
- b1sl/b1sl/resources/_generated/bar_codes.py +15 -0
- b1sl/b1sl/resources/_generated/bar_codes_service.py +21 -0
- b1sl/b1sl/resources/_generated/batch_number_details.py +15 -0
- b1sl/b1sl/resources/_generated/bill_of_exchange_transactions.py +15 -0
- b1sl/b1sl/resources/_generated/bin_location_attributes.py +15 -0
- b1sl/b1sl/resources/_generated/bin_location_attributes_service.py +21 -0
- b1sl/b1sl/resources/_generated/bin_location_fields.py +15 -0
- b1sl/b1sl/resources/_generated/bin_location_fields_service.py +21 -0
- b1sl/b1sl/resources/_generated/bin_locations.py +15 -0
- b1sl/b1sl/resources/_generated/bin_locations_service.py +21 -0
- b1sl/b1sl/resources/_generated/blanket_agreements.py +15 -0
- b1sl/b1sl/resources/_generated/blanket_agreements_service.py +21 -0
- b1sl/b1sl/resources/_generated/boe_document_types.py +15 -0
- b1sl/b1sl/resources/_generated/boe_document_types_service.py +21 -0
- b1sl/b1sl/resources/_generated/boe_instructions.py +15 -0
- b1sl/b1sl/resources/_generated/boe_instructions_service.py +21 -0
- b1sl/b1sl/resources/_generated/boe_lines_service.py +30 -0
- b1sl/b1sl/resources/_generated/boe_portfolios.py +15 -0
- b1sl/b1sl/resources/_generated/boe_portfolios_service.py +21 -0
- b1sl/b1sl/resources/_generated/bp_fiscal_registry_id.py +15 -0
- b1sl/b1sl/resources/_generated/bp_opening_balance_service.py +41 -0
- b1sl/b1sl/resources/_generated/bp_priorities.py +15 -0
- b1sl/b1sl/resources/_generated/branches.py +15 -0
- b1sl/b1sl/resources/_generated/branches_service.py +21 -0
- b1sl/b1sl/resources/_generated/brazil_beverage_indexers.py +15 -0
- b1sl/b1sl/resources/_generated/brazil_beverage_indexers_service.py +21 -0
- b1sl/b1sl/resources/_generated/brazil_fuel_indexers.py +15 -0
- b1sl/b1sl/resources/_generated/brazil_fuel_indexers_service.py +21 -0
- b1sl/b1sl/resources/_generated/brazil_multi_indexers.py +15 -0
- b1sl/b1sl/resources/_generated/brazil_numeric_indexers.py +15 -0
- b1sl/b1sl/resources/_generated/brazil_string_indexers.py +15 -0
- b1sl/b1sl/resources/_generated/budget_distributions.py +15 -0
- b1sl/b1sl/resources/_generated/budget_scenarios.py +15 -0
- b1sl/b1sl/resources/_generated/budgets.py +15 -0
- b1sl/b1sl/resources/_generated/business_partner_groups.py +15 -0
- b1sl/b1sl/resources/_generated/business_partner_properties.py +15 -0
- b1sl/b1sl/resources/_generated/business_partner_properties_service.py +21 -0
- b1sl/b1sl/resources/_generated/business_partners.py +15 -0
- b1sl/b1sl/resources/_generated/business_partners_service.py +47 -0
- b1sl/b1sl/resources/_generated/business_places.py +15 -0
- b1sl/b1sl/resources/_generated/campaign_response_type.py +15 -0
- b1sl/b1sl/resources/_generated/campaign_response_type_service.py +21 -0
- b1sl/b1sl/resources/_generated/campaigns.py +15 -0
- b1sl/b1sl/resources/_generated/campaigns_service.py +21 -0
- b1sl/b1sl/resources/_generated/cash_discounts.py +15 -0
- b1sl/b1sl/resources/_generated/cash_discounts_service.py +21 -0
- b1sl/b1sl/resources/_generated/cash_flow_line_items.py +15 -0
- b1sl/b1sl/resources/_generated/cash_flow_line_items_service.py +21 -0
- b1sl/b1sl/resources/_generated/certificate_series.py +15 -0
- b1sl/b1sl/resources/_generated/certificate_series_service.py +21 -0
- b1sl/b1sl/resources/_generated/change_logs_service.py +51 -0
- b1sl/b1sl/resources/_generated/chart_of_accounts.py +15 -0
- b1sl/b1sl/resources/_generated/check_lines_service.py +38 -0
- b1sl/b1sl/resources/_generated/checksfor_payment.py +15 -0
- b1sl/b1sl/resources/_generated/choose_from_list.py +15 -0
- b1sl/b1sl/resources/_generated/client_mixin.py +3920 -0
- b1sl/b1sl/resources/_generated/closing_date_procedure.py +15 -0
- b1sl/b1sl/resources/_generated/cockpits.py +15 -0
- b1sl/b1sl/resources/_generated/cockpits_service.py +46 -0
- b1sl/b1sl/resources/_generated/commission_groups.py +15 -0
- b1sl/b1sl/resources/_generated/company_service.py +410 -0
- b1sl/b1sl/resources/_generated/contacts.py +15 -0
- b1sl/b1sl/resources/_generated/contract_templates.py +15 -0
- b1sl/b1sl/resources/_generated/correction_invoice.py +15 -0
- b1sl/b1sl/resources/_generated/correction_invoice_reversal.py +15 -0
- b1sl/b1sl/resources/_generated/correction_invoice_reversal_service.py +65 -0
- b1sl/b1sl/resources/_generated/correction_invoice_service.py +78 -0
- b1sl/b1sl/resources/_generated/correction_purchase_invoice.py +15 -0
- b1sl/b1sl/resources/_generated/correction_purchase_invoice_reversal.py +15 -0
- b1sl/b1sl/resources/_generated/correction_purchase_invoice_reversal_service.py +65 -0
- b1sl/b1sl/resources/_generated/correction_purchase_invoice_service.py +78 -0
- b1sl/b1sl/resources/_generated/cost_center_types.py +15 -0
- b1sl/b1sl/resources/_generated/cost_center_types_service.py +21 -0
- b1sl/b1sl/resources/_generated/cost_element_service.py +21 -0
- b1sl/b1sl/resources/_generated/cost_elements.py +15 -0
- b1sl/b1sl/resources/_generated/counties.py +15 -0
- b1sl/b1sl/resources/_generated/counties_service.py +21 -0
- b1sl/b1sl/resources/_generated/countries.py +15 -0
- b1sl/b1sl/resources/_generated/countries_service.py +21 -0
- b1sl/b1sl/resources/_generated/credit_card_payments.py +15 -0
- b1sl/b1sl/resources/_generated/credit_cards.py +15 -0
- b1sl/b1sl/resources/_generated/credit_lines_service.py +38 -0
- b1sl/b1sl/resources/_generated/credit_notes.py +15 -0
- b1sl/b1sl/resources/_generated/credit_notes_service.py +100 -0
- b1sl/b1sl/resources/_generated/credit_payment_methods.py +15 -0
- b1sl/b1sl/resources/_generated/currencies.py +15 -0
- b1sl/b1sl/resources/_generated/customer_equipment_cards.py +15 -0
- b1sl/b1sl/resources/_generated/customs_declaration.py +15 -0
- b1sl/b1sl/resources/_generated/customs_groups.py +15 -0
- b1sl/b1sl/resources/_generated/cycle_count_determinations.py +15 -0
- b1sl/b1sl/resources/_generated/cycle_count_determinations_service.py +21 -0
- b1sl/b1sl/resources/_generated/dashboard_packages_service.py +28 -0
- b1sl/b1sl/resources/_generated/deductible_tax_service.py +21 -0
- b1sl/b1sl/resources/_generated/deductible_taxes.py +15 -0
- b1sl/b1sl/resources/_generated/deduction_tax_groups.py +15 -0
- b1sl/b1sl/resources/_generated/deduction_tax_hierarchies.py +15 -0
- b1sl/b1sl/resources/_generated/deduction_tax_sub_groups.py +15 -0
- b1sl/b1sl/resources/_generated/deduction_tax_sub_groups_service.py +21 -0
- b1sl/b1sl/resources/_generated/delivery_notes.py +15 -0
- b1sl/b1sl/resources/_generated/delivery_notes_service.py +85 -0
- b1sl/b1sl/resources/_generated/departments.py +15 -0
- b1sl/b1sl/resources/_generated/departments_service.py +21 -0
- b1sl/b1sl/resources/_generated/deposits.py +15 -0
- b1sl/b1sl/resources/_generated/deposits_service.py +53 -0
- b1sl/b1sl/resources/_generated/depreciation_areas.py +15 -0
- b1sl/b1sl/resources/_generated/depreciation_areas_service.py +21 -0
- b1sl/b1sl/resources/_generated/depreciation_type_pools.py +15 -0
- b1sl/b1sl/resources/_generated/depreciation_type_pools_service.py +21 -0
- b1sl/b1sl/resources/_generated/depreciation_types.py +15 -0
- b1sl/b1sl/resources/_generated/depreciation_types_service.py +21 -0
- b1sl/b1sl/resources/_generated/determination_criterias.py +15 -0
- b1sl/b1sl/resources/_generated/determination_criterias_service.py +21 -0
- b1sl/b1sl/resources/_generated/dimensions.py +15 -0
- b1sl/b1sl/resources/_generated/dimensions_service.py +21 -0
- b1sl/b1sl/resources/_generated/distribution_rules.py +15 -0
- b1sl/b1sl/resources/_generated/distribution_rules_service.py +21 -0
- b1sl/b1sl/resources/_generated/dnf_code_setup.py +15 -0
- b1sl/b1sl/resources/_generated/dnf_code_setup_service.py +21 -0
- b1sl/b1sl/resources/_generated/down_payments.py +15 -0
- b1sl/b1sl/resources/_generated/down_payments_service.py +68 -0
- b1sl/b1sl/resources/_generated/drafts.py +15 -0
- b1sl/b1sl/resources/_generated/drafts_service.py +86 -0
- b1sl/b1sl/resources/_generated/dunning_letters.py +15 -0
- b1sl/b1sl/resources/_generated/dunning_terms.py +15 -0
- b1sl/b1sl/resources/_generated/dunning_terms_service.py +21 -0
- b1sl/b1sl/resources/_generated/dynamic_system_strings.py +15 -0
- b1sl/b1sl/resources/_generated/electronic_communication_action_service.py +122 -0
- b1sl/b1sl/resources/_generated/electronic_communication_actions_service.py +119 -0
- b1sl/b1sl/resources/_generated/electronic_file_formats.py +15 -0
- b1sl/b1sl/resources/_generated/electronic_file_formats_service.py +21 -0
- b1sl/b1sl/resources/_generated/email_groups.py +15 -0
- b1sl/b1sl/resources/_generated/email_groups_service.py +21 -0
- b1sl/b1sl/resources/_generated/employee_id_type.py +15 -0
- b1sl/b1sl/resources/_generated/employee_id_type_service.py +21 -0
- b1sl/b1sl/resources/_generated/employee_position.py +15 -0
- b1sl/b1sl/resources/_generated/employee_position_service.py +21 -0
- b1sl/b1sl/resources/_generated/employee_roles_setup.py +15 -0
- b1sl/b1sl/resources/_generated/employee_roles_setup_service.py +21 -0
- b1sl/b1sl/resources/_generated/employee_status.py +15 -0
- b1sl/b1sl/resources/_generated/employee_status_service.py +21 -0
- b1sl/b1sl/resources/_generated/employee_transfers.py +15 -0
- b1sl/b1sl/resources/_generated/employee_transfers_service.py +21 -0
- b1sl/b1sl/resources/_generated/employees_info.py +15 -0
- b1sl/b1sl/resources/_generated/employment_category_service.py +21 -0
- b1sl/b1sl/resources/_generated/employment_categorys.py +15 -0
- b1sl/b1sl/resources/_generated/enhanced_discount_groups.py +15 -0
- b1sl/b1sl/resources/_generated/enhanced_discount_groups_service.py +21 -0
- b1sl/b1sl/resources/_generated/exceptional_event_service.py +21 -0
- b1sl/b1sl/resources/_generated/exceptional_events.py +15 -0
- b1sl/b1sl/resources/_generated/extended_translations.py +15 -0
- b1sl/b1sl/resources/_generated/extended_translations_service.py +21 -0
- b1sl/b1sl/resources/_generated/external_calls_service.py +54 -0
- b1sl/b1sl/resources/_generated/external_reconciliations_service.py +104 -0
- b1sl/b1sl/resources/_generated/fa_account_determinations.py +15 -0
- b1sl/b1sl/resources/_generated/fa_account_determinations_service.py +21 -0
- b1sl/b1sl/resources/_generated/factoring_indicators.py +15 -0
- b1sl/b1sl/resources/_generated/financial_years.py +15 -0
- b1sl/b1sl/resources/_generated/financial_years_service.py +21 -0
- b1sl/b1sl/resources/_generated/fiscal_printer.py +15 -0
- b1sl/b1sl/resources/_generated/fiscal_printer_service.py +21 -0
- b1sl/b1sl/resources/_generated/fixed_asset_items_service.py +55 -0
- b1sl/b1sl/resources/_generated/form_preferences.py +15 -0
- b1sl/b1sl/resources/_generated/formatted_searches.py +15 -0
- b1sl/b1sl/resources/_generated/forms1099.py +15 -0
- b1sl/b1sl/resources/_generated/gl_account_advanced_rules.py +15 -0
- b1sl/b1sl/resources/_generated/gl_account_advanced_rules_service.py +21 -0
- b1sl/b1sl/resources/_generated/goods_return_request.py +15 -0
- b1sl/b1sl/resources/_generated/goods_return_request_service.py +69 -0
- b1sl/b1sl/resources/_generated/gov_pay_codes.py +15 -0
- b1sl/b1sl/resources/_generated/gov_pay_codes_service.py +21 -0
- b1sl/b1sl/resources/_generated/gt_is_service.py +28 -0
- b1sl/b1sl/resources/_generated/holidays.py +15 -0
- b1sl/b1sl/resources/_generated/house_bank_accounts.py +15 -0
- b1sl/b1sl/resources/_generated/incoming_payments.py +15 -0
- b1sl/b1sl/resources/_generated/india_hsn.py +15 -0
- b1sl/b1sl/resources/_generated/india_hsn_service.py +21 -0
- b1sl/b1sl/resources/_generated/industries.py +15 -0
- b1sl/b1sl/resources/_generated/integration_packages_configure.py +15 -0
- b1sl/b1sl/resources/_generated/integration_packages_configure_service.py +21 -0
- b1sl/b1sl/resources/_generated/internal_reconciliations.py +15 -0
- b1sl/b1sl/resources/_generated/internal_reconciliations_service.py +51 -0
- b1sl/b1sl/resources/_generated/intrastat_configuration.py +15 -0
- b1sl/b1sl/resources/_generated/intrastat_configuration_service.py +21 -0
- b1sl/b1sl/resources/_generated/inventory_countings.py +15 -0
- b1sl/b1sl/resources/_generated/inventory_countings_service.py +21 -0
- b1sl/b1sl/resources/_generated/inventory_cycles.py +15 -0
- b1sl/b1sl/resources/_generated/inventory_gen_entries.py +15 -0
- b1sl/b1sl/resources/_generated/inventory_gen_entry_service.py +67 -0
- b1sl/b1sl/resources/_generated/inventory_gen_exit_service.py +66 -0
- b1sl/b1sl/resources/_generated/inventory_gen_exits.py +15 -0
- b1sl/b1sl/resources/_generated/inventory_opening_balances.py +15 -0
- b1sl/b1sl/resources/_generated/inventory_opening_balances_service.py +21 -0
- b1sl/b1sl/resources/_generated/inventory_postings.py +15 -0
- b1sl/b1sl/resources/_generated/inventory_postings_service.py +34 -0
- b1sl/b1sl/resources/_generated/inventory_transfer_requests.py +15 -0
- b1sl/b1sl/resources/_generated/inventory_transfer_requests_service.py +43 -0
- b1sl/b1sl/resources/_generated/invoices.py +15 -0
- b1sl/b1sl/resources/_generated/invoices_service.py +100 -0
- b1sl/b1sl/resources/_generated/item_groups.py +15 -0
- b1sl/b1sl/resources/_generated/item_properties.py +15 -0
- b1sl/b1sl/resources/_generated/items.py +15 -0
- b1sl/b1sl/resources/_generated/journal_entries.py +15 -0
- b1sl/b1sl/resources/_generated/journal_entry_document_type_service.py +21 -0
- b1sl/b1sl/resources/_generated/journal_entry_document_types.py +15 -0
- b1sl/b1sl/resources/_generated/journal_vouchers_service.py +45 -0
- b1sl/b1sl/resources/_generated/knowledge_base_solutions.py +15 -0
- b1sl/b1sl/resources/_generated/kp_is.py +15 -0
- b1sl/b1sl/resources/_generated/kp_is_service.py +21 -0
- b1sl/b1sl/resources/_generated/landed_costs.py +15 -0
- b1sl/b1sl/resources/_generated/landed_costs_codes.py +15 -0
- b1sl/b1sl/resources/_generated/landed_costs_service.py +21 -0
- b1sl/b1sl/resources/_generated/legal_data.py +15 -0
- b1sl/b1sl/resources/_generated/length_measures.py +15 -0
- b1sl/b1sl/resources/_generated/license_service.py +21 -0
- b1sl/b1sl/resources/_generated/local_era.py +15 -0
- b1sl/b1sl/resources/_generated/manufacturers.py +15 -0
- b1sl/b1sl/resources/_generated/material_groups.py +15 -0
- b1sl/b1sl/resources/_generated/material_groups_service.py +21 -0
- b1sl/b1sl/resources/_generated/material_revaluation.py +15 -0
- b1sl/b1sl/resources/_generated/material_revaluation_fifo_service.py +33 -0
- b1sl/b1sl/resources/_generated/material_revaluation_snb_service.py +33 -0
- b1sl/b1sl/resources/_generated/messages.py +15 -0
- b1sl/b1sl/resources/_generated/messages_service.py +35 -0
- b1sl/b1sl/resources/_generated/mobile_add_on_setting.py +15 -0
- b1sl/b1sl/resources/_generated/mobile_add_on_setting_service.py +21 -0
- b1sl/b1sl/resources/_generated/mobile_app_service.py +240 -0
- b1sl/b1sl/resources/_generated/multi_language_translations.py +15 -0
- b1sl/b1sl/resources/_generated/nature_of_assessees.py +15 -0
- b1sl/b1sl/resources/_generated/nature_of_assessees_service.py +21 -0
- b1sl/b1sl/resources/_generated/ncm_codes_setup.py +15 -0
- b1sl/b1sl/resources/_generated/ncm_codes_setup_service.py +21 -0
- b1sl/b1sl/resources/_generated/nf_models.py +15 -0
- b1sl/b1sl/resources/_generated/nf_models_service.py +21 -0
- b1sl/b1sl/resources/_generated/nf_tax_categories.py +15 -0
- b1sl/b1sl/resources/_generated/nf_tax_categories_service.py +21 -0
- b1sl/b1sl/resources/_generated/nota_fiscal_cfop.py +15 -0
- b1sl/b1sl/resources/_generated/nota_fiscal_cst.py +15 -0
- b1sl/b1sl/resources/_generated/nota_fiscal_usage.py +15 -0
- b1sl/b1sl/resources/_generated/occurrence_codes.py +15 -0
- b1sl/b1sl/resources/_generated/occurrence_codes_service.py +21 -0
- b1sl/b1sl/resources/_generated/orders.py +15 -0
- b1sl/b1sl/resources/_generated/orders_service.py +94 -0
- b1sl/b1sl/resources/_generated/packages_types.py +15 -0
- b1sl/b1sl/resources/_generated/partners_setups.py +15 -0
- b1sl/b1sl/resources/_generated/partners_setups_service.py +21 -0
- b1sl/b1sl/resources/_generated/payment_blocks.py +15 -0
- b1sl/b1sl/resources/_generated/payment_blocks_service.py +21 -0
- b1sl/b1sl/resources/_generated/payment_calculation_service.py +37 -0
- b1sl/b1sl/resources/_generated/payment_drafts.py +15 -0
- b1sl/b1sl/resources/_generated/payment_reason_code_service.py +21 -0
- b1sl/b1sl/resources/_generated/payment_reason_codes.py +15 -0
- b1sl/b1sl/resources/_generated/payment_run_export.py +15 -0
- b1sl/b1sl/resources/_generated/payment_terms_types.py +15 -0
- b1sl/b1sl/resources/_generated/payment_terms_types_service.py +28 -0
- b1sl/b1sl/resources/_generated/pick_lists.py +15 -0
- b1sl/b1sl/resources/_generated/pick_lists_service.py +78 -0
- b1sl/b1sl/resources/_generated/pos_daily_summary.py +15 -0
- b1sl/b1sl/resources/_generated/predefined_texts.py +15 -0
- b1sl/b1sl/resources/_generated/predefined_texts_service.py +21 -0
- b1sl/b1sl/resources/_generated/price_lists.py +15 -0
- b1sl/b1sl/resources/_generated/product_trees.py +15 -0
- b1sl/b1sl/resources/_generated/production_orders.py +15 -0
- b1sl/b1sl/resources/_generated/profit_centers.py +15 -0
- b1sl/b1sl/resources/_generated/profit_centers_service.py +21 -0
- b1sl/b1sl/resources/_generated/project_management_configuration_service.py +333 -0
- b1sl/b1sl/resources/_generated/project_management_service.py +104 -0
- b1sl/b1sl/resources/_generated/project_management_time_sheet.py +15 -0
- b1sl/b1sl/resources/_generated/project_managements.py +15 -0
- b1sl/b1sl/resources/_generated/projects.py +15 -0
- b1sl/b1sl/resources/_generated/projects_service.py +21 -0
- b1sl/b1sl/resources/_generated/purchase_credit_notes.py +15 -0
- b1sl/b1sl/resources/_generated/purchase_credit_notes_service.py +85 -0
- b1sl/b1sl/resources/_generated/purchase_delivery_notes.py +15 -0
- b1sl/b1sl/resources/_generated/purchase_delivery_notes_service.py +85 -0
- b1sl/b1sl/resources/_generated/purchase_down_payments.py +15 -0
- b1sl/b1sl/resources/_generated/purchase_down_payments_service.py +70 -0
- b1sl/b1sl/resources/_generated/purchase_invoices.py +15 -0
- b1sl/b1sl/resources/_generated/purchase_invoices_service.py +85 -0
- b1sl/b1sl/resources/_generated/purchase_orders.py +15 -0
- b1sl/b1sl/resources/_generated/purchase_orders_service.py +69 -0
- b1sl/b1sl/resources/_generated/purchase_quotations.py +15 -0
- b1sl/b1sl/resources/_generated/purchase_quotations_service.py +70 -0
- b1sl/b1sl/resources/_generated/purchase_request_service.py +68 -0
- b1sl/b1sl/resources/_generated/purchase_requests.py +15 -0
- b1sl/b1sl/resources/_generated/purchase_returns.py +15 -0
- b1sl/b1sl/resources/_generated/purchase_returns_service.py +85 -0
- b1sl/b1sl/resources/_generated/purchase_tax_invoices.py +15 -0
- b1sl/b1sl/resources/_generated/qr_code_service.py +33 -0
- b1sl/b1sl/resources/_generated/query_auth_groups.py +15 -0
- b1sl/b1sl/resources/_generated/query_categories.py +15 -0
- b1sl/b1sl/resources/_generated/query_service.py +29 -0
- b1sl/b1sl/resources/_generated/queue.py +15 -0
- b1sl/b1sl/resources/_generated/quotations.py +15 -0
- b1sl/b1sl/resources/_generated/quotations_service.py +69 -0
- b1sl/b1sl/resources/_generated/recurring_transaction_service.py +67 -0
- b1sl/b1sl/resources/_generated/relationships.py +15 -0
- b1sl/b1sl/resources/_generated/report_filter.py +15 -0
- b1sl/b1sl/resources/_generated/report_filter_service.py +30 -0
- b1sl/b1sl/resources/_generated/report_layouts_service.py +237 -0
- b1sl/b1sl/resources/_generated/report_types.py +15 -0
- b1sl/b1sl/resources/_generated/report_types_service.py +21 -0
- b1sl/b1sl/resources/_generated/resource_capacities.py +15 -0
- b1sl/b1sl/resources/_generated/resource_capacities_service.py +34 -0
- b1sl/b1sl/resources/_generated/resource_groups.py +15 -0
- b1sl/b1sl/resources/_generated/resource_groups_service.py +21 -0
- b1sl/b1sl/resources/_generated/resource_properties.py +15 -0
- b1sl/b1sl/resources/_generated/resource_properties_service.py +21 -0
- b1sl/b1sl/resources/_generated/resources.py +15 -0
- b1sl/b1sl/resources/_generated/resources_service.py +21 -0
- b1sl/b1sl/resources/_generated/retorno_codes.py +15 -0
- b1sl/b1sl/resources/_generated/retorno_codes_service.py +21 -0
- b1sl/b1sl/resources/_generated/return_request.py +15 -0
- b1sl/b1sl/resources/_generated/return_request_service.py +69 -0
- b1sl/b1sl/resources/_generated/returns.py +15 -0
- b1sl/b1sl/resources/_generated/returns_service.py +85 -0
- b1sl/b1sl/resources/_generated/route_stages.py +15 -0
- b1sl/b1sl/resources/_generated/route_stages_service.py +21 -0
- b1sl/b1sl/resources/_generated/sales_forecast.py +15 -0
- b1sl/b1sl/resources/_generated/sales_opportunities.py +15 -0
- b1sl/b1sl/resources/_generated/sales_opportunity_competitors_setup.py +15 -0
- b1sl/b1sl/resources/_generated/sales_opportunity_competitors_setup_service.py +21 -0
- b1sl/b1sl/resources/_generated/sales_opportunity_interests_setup.py +15 -0
- b1sl/b1sl/resources/_generated/sales_opportunity_interests_setup_service.py +21 -0
- b1sl/b1sl/resources/_generated/sales_opportunity_reasons_setup.py +15 -0
- b1sl/b1sl/resources/_generated/sales_opportunity_reasons_setup_service.py +21 -0
- b1sl/b1sl/resources/_generated/sales_opportunity_sources_setup.py +15 -0
- b1sl/b1sl/resources/_generated/sales_opportunity_sources_setup_service.py +21 -0
- b1sl/b1sl/resources/_generated/sales_persons.py +15 -0
- b1sl/b1sl/resources/_generated/sales_stages.py +15 -0
- b1sl/b1sl/resources/_generated/sales_tax_authorities.py +15 -0
- b1sl/b1sl/resources/_generated/sales_tax_authorities_types.py +15 -0
- b1sl/b1sl/resources/_generated/sales_tax_codes.py +15 -0
- b1sl/b1sl/resources/_generated/sales_tax_invoices.py +15 -0
- b1sl/b1sl/resources/_generated/sbo_bob_service.py +89 -0
- b1sl/b1sl/resources/_generated/sections.py +15 -0
- b1sl/b1sl/resources/_generated/sections_service.py +21 -0
- b1sl/b1sl/resources/_generated/self_credit_memo_service.py +69 -0
- b1sl/b1sl/resources/_generated/self_credit_memos.py +15 -0
- b1sl/b1sl/resources/_generated/self_invoice_service.py +69 -0
- b1sl/b1sl/resources/_generated/self_invoices.py +15 -0
- b1sl/b1sl/resources/_generated/serial_number_details.py +15 -0
- b1sl/b1sl/resources/_generated/series_service.py +305 -0
- b1sl/b1sl/resources/_generated/service_call_origins.py +15 -0
- b1sl/b1sl/resources/_generated/service_call_origins_service.py +21 -0
- b1sl/b1sl/resources/_generated/service_call_problem_sub_types.py +15 -0
- b1sl/b1sl/resources/_generated/service_call_problem_sub_types_service.py +21 -0
- b1sl/b1sl/resources/_generated/service_call_problem_types.py +15 -0
- b1sl/b1sl/resources/_generated/service_call_problem_types_service.py +21 -0
- b1sl/b1sl/resources/_generated/service_call_solution_status.py +15 -0
- b1sl/b1sl/resources/_generated/service_call_solution_status_service.py +21 -0
- b1sl/b1sl/resources/_generated/service_call_status.py +15 -0
- b1sl/b1sl/resources/_generated/service_call_status_service.py +21 -0
- b1sl/b1sl/resources/_generated/service_call_types.py +15 -0
- b1sl/b1sl/resources/_generated/service_call_types_service.py +21 -0
- b1sl/b1sl/resources/_generated/service_calls.py +15 -0
- b1sl/b1sl/resources/_generated/service_contracts.py +15 -0
- b1sl/b1sl/resources/_generated/service_groups.py +15 -0
- b1sl/b1sl/resources/_generated/service_groups_service.py +21 -0
- b1sl/b1sl/resources/_generated/service_tax_posting_service.py +36 -0
- b1sl/b1sl/resources/_generated/shipping_types.py +15 -0
- b1sl/b1sl/resources/_generated/short_link_mappings_service.py +26 -0
- b1sl/b1sl/resources/_generated/special_prices.py +15 -0
- b1sl/b1sl/resources/_generated/states.py +15 -0
- b1sl/b1sl/resources/_generated/states_service.py +21 -0
- b1sl/b1sl/resources/_generated/stock_takings.py +15 -0
- b1sl/b1sl/resources/_generated/stock_transfer_draft_service.py +34 -0
- b1sl/b1sl/resources/_generated/stock_transfer_drafts.py +15 -0
- b1sl/b1sl/resources/_generated/stock_transfer_service.py +43 -0
- b1sl/b1sl/resources/_generated/stock_transfers.py +15 -0
- b1sl/b1sl/resources/_generated/target_groups.py +15 -0
- b1sl/b1sl/resources/_generated/target_groups_service.py +21 -0
- b1sl/b1sl/resources/_generated/tax_code_determinations.py +15 -0
- b1sl/b1sl/resources/_generated/tax_code_determinations_service.py +21 -0
- b1sl/b1sl/resources/_generated/tax_code_determinations_tcd.py +15 -0
- b1sl/b1sl/resources/_generated/tax_code_determinations_tcd_service.py +21 -0
- b1sl/b1sl/resources/_generated/tax_invoice_report.py +15 -0
- b1sl/b1sl/resources/_generated/tax_web_sites.py +15 -0
- b1sl/b1sl/resources/_generated/tax_web_sites_service.py +27 -0
- b1sl/b1sl/resources/_generated/teams.py +15 -0
- b1sl/b1sl/resources/_generated/termination_reason.py +15 -0
- b1sl/b1sl/resources/_generated/termination_reason_service.py +21 -0
- b1sl/b1sl/resources/_generated/territories.py +15 -0
- b1sl/b1sl/resources/_generated/tracking_notes.py +15 -0
- b1sl/b1sl/resources/_generated/tracking_notes_service.py +21 -0
- b1sl/b1sl/resources/_generated/transaction_codes.py +15 -0
- b1sl/b1sl/resources/_generated/transaction_codes_service.py +21 -0
- b1sl/b1sl/resources/_generated/transportation_document.py +15 -0
- b1sl/b1sl/resources/_generated/tsr_exceptional_event_service.py +21 -0
- b1sl/b1sl/resources/_generated/tsr_exceptional_events.py +15 -0
- b1sl/b1sl/resources/_generated/unit_of_measurement_groups.py +15 -0
- b1sl/b1sl/resources/_generated/unit_of_measurement_groups_service.py +21 -0
- b1sl/b1sl/resources/_generated/unit_of_measurements.py +15 -0
- b1sl/b1sl/resources/_generated/unit_of_measurements_service.py +21 -0
- b1sl/b1sl/resources/_generated/user_default_groups.py +15 -0
- b1sl/b1sl/resources/_generated/user_fields_md.py +15 -0
- b1sl/b1sl/resources/_generated/user_keys_md.py +15 -0
- b1sl/b1sl/resources/_generated/user_languages.py +15 -0
- b1sl/b1sl/resources/_generated/user_menu_service.py +103 -0
- b1sl/b1sl/resources/_generated/user_objects_md.py +15 -0
- b1sl/b1sl/resources/_generated/user_permission_tree.py +15 -0
- b1sl/b1sl/resources/_generated/user_queries.py +15 -0
- b1sl/b1sl/resources/_generated/user_tables_md.py +15 -0
- b1sl/b1sl/resources/_generated/users.py +15 -0
- b1sl/b1sl/resources/_generated/users_service.py +21 -0
- b1sl/b1sl/resources/_generated/value_mapping.py +15 -0
- b1sl/b1sl/resources/_generated/value_mapping_communication.py +15 -0
- b1sl/b1sl/resources/_generated/value_mapping_service.py +64 -0
- b1sl/b1sl/resources/_generated/vat_groups.py +15 -0
- b1sl/b1sl/resources/_generated/vendor_payments.py +15 -0
- b1sl/b1sl/resources/_generated/w_tax_type_code_service.py +21 -0
- b1sl/b1sl/resources/_generated/w_tax_type_codes.py +15 -0
- b1sl/b1sl/resources/_generated/warehouse_locations.py +15 -0
- b1sl/b1sl/resources/_generated/warehouse_sublevel_codes.py +15 -0
- b1sl/b1sl/resources/_generated/warehouse_sublevel_codes_service.py +21 -0
- b1sl/b1sl/resources/_generated/warehouses.py +15 -0
- b1sl/b1sl/resources/_generated/web_client_bookmark_tile_service.py +21 -0
- b1sl/b1sl/resources/_generated/web_client_bookmark_tiles.py +15 -0
- b1sl/b1sl/resources/_generated/web_client_dashboard_service.py +21 -0
- b1sl/b1sl/resources/_generated/web_client_dashboards.py +15 -0
- b1sl/b1sl/resources/_generated/web_client_form_setting_service.py +21 -0
- b1sl/b1sl/resources/_generated/web_client_form_settings.py +15 -0
- b1sl/b1sl/resources/_generated/web_client_launchpad_service.py +21 -0
- b1sl/b1sl/resources/_generated/web_client_launchpads.py +15 -0
- b1sl/b1sl/resources/_generated/web_client_listview_filter_service.py +21 -0
- b1sl/b1sl/resources/_generated/web_client_listview_filters.py +15 -0
- b1sl/b1sl/resources/_generated/web_client_notification_service.py +21 -0
- b1sl/b1sl/resources/_generated/web_client_notifications.py +15 -0
- b1sl/b1sl/resources/_generated/web_client_preference_service.py +21 -0
- b1sl/b1sl/resources/_generated/web_client_preferences.py +15 -0
- b1sl/b1sl/resources/_generated/web_client_recent_activities.py +15 -0
- b1sl/b1sl/resources/_generated/web_client_recent_activity_service.py +21 -0
- b1sl/b1sl/resources/_generated/web_client_variant_group_service.py +21 -0
- b1sl/b1sl/resources/_generated/web_client_variant_groups.py +15 -0
- b1sl/b1sl/resources/_generated/web_client_variant_service.py +21 -0
- b1sl/b1sl/resources/_generated/web_client_variants.py +15 -0
- b1sl/b1sl/resources/_generated/weight_measures.py +15 -0
- b1sl/b1sl/resources/_generated/withholding_tax_codes.py +15 -0
- b1sl/b1sl/resources/_generated/witholding_tax_definition.py +15 -0
- b1sl/b1sl/resources/_generated/wizard_payment_methods.py +15 -0
- b1sl/b1sl/resources/_generated/workflow_task_service.py +47 -0
- b1sl/b1sl/resources/async_base.py +60 -0
- b1sl/b1sl/resources/base.py +159 -0
- b1sl/b1sl/resources/udo.py +78 -0
- b1sl/b1sl/rest_adapter.py +351 -0
- b1sl/b1sl/testing.py +24 -0
- b1sl/b1sl/tests/__init__.py +0 -0
- b1sl/b1sl/tests/test_01_settings.py +60 -0
- b1sl/b1sl/tests/test_02_rest_adapter.py +177 -0
- b1sl/b1sl/tests/test_03_items_endpoint.py +172 -0
- b1sl/b1sl/tests/test_04_serialnumberdetails_endpoint.py +181 -0
- b1sl/b1sl/tests/test_observability.py +153 -0
- b1sl/b1sl/tests/test_utils.py +24 -0
- b1sl/contrib/__init__.py +0 -0
- b1sl/contrib/django/__init__.py +15 -0
- b1sl/contrib/django/base.py +89 -0
- b1sl/contrib/django/odata_decode_middleware.py +14 -0
- b1sl/contrib/django/odata_transform_url_middleware.py +15 -0
- b1sl/py.typed +0 -0
- b1sl/saphdb/__init__.py +19 -0
- b1sl/saphdb/adapter.py +24 -0
- b1sl/saphdb/client.py +50 -0
- b1sl/saphdb/config.py +68 -0
- b1sl/saphdb/endpoints/serialnumberdetailodbc.py +100 -0
- b1sl/saphdb/exceptions/exceptions.py +19 -0
- b1sl/saphdb/main.py +18 -0
- b1sl/saphdb/models/result.py +18 -0
- b1sl/saphdb/models/serial.py +37 -0
- b1sl/saphdb/odbc_adapter.py +220 -0
- b1sl/saphdb/tests/__init__.py +0 -0
- b1sl/saphdb/tests/test_01_settings.py +37 -0
- b1sl/saphdb/tests/test_02_odbc_adapter.py +96 -0
- b1sl/saphdb/tests/test_04_serialnumberdetails_endpoint.py +131 -0
- b1sl_python-0.1.0.dist-info/METADATA +169 -0
- b1sl_python-0.1.0.dist-info/RECORD +579 -0
- b1sl_python-0.1.0.dist-info/WHEEL +4 -0
- 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
|
+
)
|