From be712fbb226dfa3c160292fb23af253d7db59179 Mon Sep 17 00:00:00 2001 From: Wilmer Martinez <44853160+wilmerm@users.noreply.github.com> Date: Sun, 21 Sep 2025 16:37:13 -0400 Subject: [PATCH 1/3] =?UTF-8?q?docs:=20agregar=20nuevos=20m=C3=A9todos=20y?= =?UTF-8?q?=20tipos=20para=20reportes=20de=20documentos=20en=20l=E2=80=A6?= =?UTF-8?q?=20(#23)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * docs: agregar nuevos métodos y tipos para reportes de documentos en la API de Alanube * docs: refactor métodos de reporte en AlanubeAPI para usar 'cls' en lugar de 'self' y simplificar la definición de Companies * Update alanube/do/api.py * docs: actualizar formato de cadenas en propiedades de APIConfig para usar f-strings --- alanube/do/__init__.py | 17 ++++ alanube/do/api.py | 183 +++++++++++++++++++++++++++++++++++++++-- alanube/do/types.py | 72 +++++++++++++++- 3 files changed, 266 insertions(+), 6 deletions(-) diff --git a/alanube/do/__init__.py b/alanube/do/__init__.py index 703e636..8f16aae 100644 --- a/alanube/do/__init__.py +++ b/alanube/do/__init__.py @@ -41,6 +41,15 @@ class Alanube: - `send_document`: Send an electronic document of the specified type. - `get_document`: Retrieve the status of an electronic document of the specified type. - `get_documents`: Retrieve a list of electronic documents of the specified type. + - `get_document_status`: (Deprecated) Retrieve the status of an electronic document. + - `get_report_companies_documents_total`: Get a report of total documents for companies. + - `get_report_users_documents_total`: Get a report of total documents for users. + - `get_report_company_emitted_documents`: Get total emitted documents for a specific company. + - `get_company_emitted_documents_monthly`: Get monthly emitted documents for a specific company. + - `get_company_emitted_documents_15_days`: Get emitted documents for a specific company in the last 15 days. + - `get_company_accepted_documents`: Get total accepted documents for a specific company. + - `get_company_accepted_documents_monthly`: Get monthly accepted documents for a specific company. + - `get_company_accepted_documents_15_days`: Get accepted documents for a specific company in the last 15 days. """ exceptions = exceptions create_company = AlanubeAPI.create_company @@ -53,6 +62,14 @@ class Alanube: get_cancellation = AlanubeAPI.get_cancellation get_cancellations = AlanubeAPI.get_cancellations send_cancellation = AlanubeAPI.send_cancellation + get_report_companies_documents_total = AlanubeAPI.get_report_companies_documents_total + get_report_users_documents_total = AlanubeAPI.get_report_users_documents_total + get_report_company_emitted_documents = AlanubeAPI.get_report_company_emitted_documents + get_report_company_emitted_documents_monthly = AlanubeAPI.get_report_company_emitted_documents_monthly + get_report_company_emitted_documents_15_days = AlanubeAPI.get_report_company_emitted_documents_15_days + get_report_company_accepted_documents = AlanubeAPI.get_report_company_accepted_documents + get_report_company_accepted_documents_monthly = AlanubeAPI.get_report_company_accepted_documents_monthly + get_report_company_accepted_documents_15_days = AlanubeAPI.get_report_company_accepted_documents_15_days send_document_func_map = { 31: AlanubeAPI.send_fiscal_invoice, diff --git a/alanube/do/api.py b/alanube/do/api.py index 1de2257..8bbcd1d 100644 --- a/alanube/do/api.py +++ b/alanube/do/api.py @@ -12,6 +12,11 @@ ListDocumentResponse, ListReceivedDocumentsResponse, ReceivedDocumentsResponse, + ReportCompaniesDocumentsTotalData, + ReportCompaniesDocumentsTotalResponse, + ReportDocumentsStatsDaily, + ReportDocumentsStatsMonthly, + ReportUsersDocumentsTotalResponse, ) @@ -127,6 +132,38 @@ def endpoint_check_dgii_status(self): """ return f"{self.api_url}/check-dgii-status" + @property + def endpoint_reports_companies_documents_total(self): + return f"{self.api_url}/reports/companies/{{idCompany}}/documents/total" + + @property + def endpoint_reports_users_documents_total(self): + return f"{self.api_url}/reports/users/documents/total" + + @property + def endpoint_reports_companies_emitted_documents(self): + return f"{self.api_url}/companies/{{id}}/emitted-documents" + + @property + def endpoint_reports_companies_emitted_documents_monthly(self): + return f"{self.endpoint_reports_companies_emitted_documents}/monthly" + + @property + def endpoint_reports_companies_emitted_documents_15_days(self): + return f"{self.endpoint_reports_companies_emitted_documents}/15-days" + + @property + def endpoint_reports_companies_accepted_documents(self): + return f"{self.api_url}/companies/{{id}}/accepted-documents" + + @property + def endpoint_reports_companies_accepted_documents_monthly(self): + return f"{self.endpoint_reports_companies_accepted_documents}/monthly" + + @property + def endpoint_reports_companies_accepted_documents_15_days(self): + return f"{self.endpoint_reports_companies_accepted_documents}/15-days" + class AlanubeAPI: config: APIConfig = None @@ -766,11 +803,11 @@ def get_received_document(cls, id_: str, company_id: str = None) -> ReceivedDocu @classmethod def get_received_documents( cls, - company_id=None, - limit=25, - page=1, - start=None, - end=None, + company_id: str = None, + limit: int = 25, + page: int = 1, + start: str = None, + end: str = None, ) -> ListReceivedDocumentsResponse: """ Consultar varios 'documentos recibidos' @@ -785,6 +822,10 @@ def get_received_documents( - `end`: Fecha de fin de la consulta basada en la fecha de emisión del documento(s). Formato: YYYY-MM-DD. Si no se envía, se tomará la fecha actual en zona horaria UTC. + + Retorna: + - response (ListReceivedDocumentsResponse): La respuesta de la API con + la lista de documentos recibidos. """ url = cls.config.endpoint_received_documents url = build_url(url, company_id=company_id, limit=limit, page=page, start=start, end=end) @@ -835,9 +876,141 @@ def check_dgii_status( mantenimiento para los servicios de factura electrónica de la DGII. Si también se proporciona el parámetro 'environment', este tiene prioridad sobre este parámetro. + + Retorna: + - data (dict o list): El estado del servicio o las ventanas de + mantenimiento de la DGII. """ url = cls.config.endpoint_check_dgii_status url = build_url(url, company_id, environment=environment, maintenance=maintenance) response = cls.get(url, expected_response_code=200) data = response.json() return data + + @classmethod + def get_report_companies_documents_total( + cls, + company_id: str, + legal_status: str, + date_from: str = None, + date_until: str = None, + ) -> ReportCompaniesDocumentsTotalResponse: + """ + Obtiene el total de documentos electrónicos emitidos por una compañía + específica en un rango de fechas y estados legales determinados. + + Parámetros: + ----------- + - company_id (str): Id de la compañía para la cual se desean consultar los totales. + - legal_status (str): Lista de estados legales de los documentos emitidos separados por comas. + - date_from (str, opcional): Fecha de inicio del rango de fechas. + Si no se especifica, se toma la fecha actual menos 30 días + - date_until (str, opcional): Fecha de fin del rango de fechas. + Si no se especifica, se toma la fecha actual. + """ + url = cls.config.endpoint_reports_companies_documents_total.format(idCompany=company_id) + url = build_url(url, legal_status=legal_status, date_from=date_from, date_until=date_until) + response = cls.get(url, expected_response_code=200) + return response.json() + + @classmethod + def get_report_users_documents_total( + cls, + legal_status: str = None, + date_from: str = None, + date_until: str = None, + ) -> ReportUsersDocumentsTotalResponse: + """ + Obtiene el total de documentos electrónicos emitidos por el usuario + autenticado en un rango de fechas y estados legales determinados. + + Parámetros: + ----------- + - legal_status (str, opcional): Lista de estados legales de los + documentos emitidos separados por comas. + - date_from (str, opcional): Fecha de inicio del rango de fechas. + Si no se especifica, se toma la fecha actual menos 30 días. + - date_until (str, opcional): Fecha de fin del rango de fechas. + Si no se especifica, se toma la fecha actual. + """ + url = cls.config.endpoint_reports_users_documents_total + url = build_url(url, legal_status=legal_status, date_from=date_from, date_until=date_until) + response = cls.get(url, expected_response_code=200) + return response.json() + + @classmethod + def get_report_company_emitted_documents( + cls, + company_id: str, + ) -> ReportCompaniesDocumentsTotalData: + """ + Consulta el total de documentos electrónicos emitidos por una compañía específica. + """ + url = cls.config.endpoint_reports_companies_emitted_documents.format(id=company_id) + response = cls.get(url, expected_response_code=200) + return response.json() + + @classmethod + def get_report_company_emitted_documents_monthly( + cls, + company_id: str, + ) -> ReportDocumentsStatsMonthly: + """ + Consulta el total de documentos electrónicos emitidos por una compañía + específica durante los últimos 12 meses. + """ + url = cls.config.endpoint_reports_companies_emitted_documents_monthly.format(id=company_id) + response = cls.get(url, expected_response_code=200) + return response.json() + + @classmethod + def get_report_company_emitted_documents_15_days( + cls, + company_id: str, + ) -> ReportDocumentsStatsDaily: + """ + Consulta el total de documentos electrónicos emitidos por una compañía + específica durante los últimos 15 días. + """ + url = cls.config.endpoint_reports_companies_emitted_documents_15_days.format(id=company_id) + response = cls.get(url, expected_response_code=200) + return response.json() + + @classmethod + def get_report_company_accepted_documents( + cls, + company_id: str, + ) -> ReportCompaniesDocumentsTotalData: + """ + Consulta el total de documentos electrónicos aceptados por la DGII + para una compañía específica. + """ + url = cls.config.endpoint_reports_companies_accepted_documents.format(id=company_id) + response = cls.get(url, expected_response_code=200) + return response.json() + + @classmethod + def get_report_company_accepted_documents_monthly( + cls, + company_id: str, + ) -> ReportDocumentsStatsMonthly: + """ + Consulta el total de documentos electrónicos aceptados por la DGII + para una compañía específica durante los últimos 12 meses. + """ + url = cls.config.endpoint_reports_companies_accepted_documents_monthly.format(id=company_id) + response = cls.get(url, expected_response_code=200) + return response.json() + + @classmethod + def get_report_company_accepted_documents_15_days( + cls, + company_id: str, + ) -> ReportDocumentsStatsDaily: + """ + Consulta el total de documentos electrónicos aceptados por la DGII + para una compañía específica durante los últimos 15 días. + """ + url = cls.config.endpoint_reports_companies_accepted_documents_15_days.format(id=company_id) + response = cls.get(url, expected_response_code=200) + return response.json() diff --git a/alanube/do/types.py b/alanube/do/types.py index 13ac659..8746a50 100644 --- a/alanube/do/types.py +++ b/alanube/do/types.py @@ -1,4 +1,4 @@ -from typing import TypedDict, List, Literal +from typing import Dict, TypedDict, List, Literal class Metadata(TypedDict): @@ -71,3 +71,73 @@ class ReceivedDocumentsResponse(TypedDict): class ListReceivedDocumentsResponse(TypedDict): metadata: Metadata documents: List[ReceivedDocumentsResponse] + + +class ReportCompaniesDocumentsTotalData(TypedDict): + totalEmittedDocuments: int + fiscalInvoices: int + invoices: int + creditNotes: int + debitNotes: int + exportSupports: int + gubernamentals: int + minorExpenses: int + paymentAbroadSupports: int + purchases: int + specialRegimes: int + + +class ReportCompaniesDocumentsTotalResponse(TypedDict): + data: ReportCompaniesDocumentsTotalData + + +Companies = Dict[str, ReportCompaniesDocumentsTotalData] # El key es el company_id + + +class ReportUsersDocumentsTotalData(TypedDict): + totalEmittedDocuments: int + companies: Dict[str, ReportCompaniesDocumentsTotalData] + + +class ReportUsersDocumentsTotalResponse(TypedDict): + data: ReportUsersDocumentsTotalData + + +class MonthlyQuantity(TypedDict): + year: int + month: int + quantity: int + + +class ReportDocumentsStatsMonthly(TypedDict): + totalEmittedDocuments: List[MonthlyQuantity] + fiscalInvoices: List[MonthlyQuantity] + invoices: List[MonthlyQuantity] + creditNotes: List[MonthlyQuantity] + debitNotes: List[MonthlyQuantity] + exportSupports: List[MonthlyQuantity] + gubernamentals: List[MonthlyQuantity] + minorExpenses: List[MonthlyQuantity] + paymentAbroadSupports: List[MonthlyQuantity] + purchases: List[MonthlyQuantity] + specialRegimes: List[MonthlyQuantity] + + +class DailyQuantity(TypedDict): + month: int + day: int + quantity: int + + +class ReportDocumentsStatsDaily(TypedDict): + totalEmittedDocuments: List[DailyQuantity] + fiscalInvoices: List[DailyQuantity] + invoices: List[DailyQuantity] + creditNotes: List[DailyQuantity] + debitNotes: List[DailyQuantity] + exportSupports: List[DailyQuantity] + gubernamentals: List[DailyQuantity] + minorExpenses: List[DailyQuantity] + paymentAbroadSupports: List[DailyQuantity] + purchases: List[DailyQuantity] + specialRegimes: List[DailyQuantity] From 5b9543cc8431b70e2a0980cb6b351efc10463bab Mon Sep 17 00:00:00 2001 From: Wilmer Martinez Date: Mon, 22 Sep 2025 10:31:44 -0400 Subject: [PATCH 2/3] Refactor documentation: Remove API reference section, update usage examples, and enhance contributing guidelines - Removed API Reference link from navigation and layout files. - Updated usage examples in index.md to reflect new payload structure and methods. - Revised contributing.md to remove references to API documentation and streamline contribution process. - Cleaned up countries.md by removing unnecessary whitespace and clarifying guidelines. - Deleted troubleshooting.md as it was deemed unnecessary. - Adjusted installation.md to remove references to the deleted troubleshooting guide. - Updated default.html layout to reflect changes in navigation. --- DOCUMENTATION_SETUP.md | 385 -------------------------- README.md | 54 +++- docs/README.md | 22 +- docs/_config.yml | 1 - docs/_layouts/default.html | 3 - docs/contributing.md | 15 +- docs/countries.md | 9 +- docs/index.md | 311 +++++++++++++++++++-- docs/installation.md | 5 +- docs/troubleshooting.md | 544 ------------------------------------- docs/usage.md | 487 ++++----------------------------- 11 files changed, 422 insertions(+), 1414 deletions(-) delete mode 100644 DOCUMENTATION_SETUP.md delete mode 100644 docs/troubleshooting.md diff --git a/DOCUMENTATION_SETUP.md b/DOCUMENTATION_SETUP.md deleted file mode 100644 index f5b6e70..0000000 --- a/DOCUMENTATION_SETUP.md +++ /dev/null @@ -1,385 +0,0 @@ -# Alanube Python API - Documentation Setup Guide - -This document provides a complete overview of the documentation setup for the Alanube Python API project, including installation, usage, and deployment instructions. - -## 📋 Overview - -The documentation for the Alanube Python API has been set up using: - -- **Jekyll** - Static site generator -- **GitHub Pages** - Hosting platform -- **Bootstrap 5** - CSS framework -- **GitHub Actions** - Automated deployment - -## 🏗️ Documentation Structure - -``` -docs/ -├── _config.yml # Jekyll site configuration -├── _layouts/ -│ └── default.html # Main page layout template -├── assets/ -│ └── favicon.ico # Site favicon (placeholder) -├── index.md # Home page with overview -├── installation.md # Installation guide -├── usage.md # Usage examples and tutorials -├── api-reference.md # Complete API reference -├── countries.md # Country-specific features -├── contributing.md # Contributing guidelines -├── troubleshooting.md # Common issues and solutions -├── README.md # Documentation development guide -└── Gemfile # Jekyll dependencies - -.github/workflows/ -└── docs.yml # GitHub Actions deployment workflow -``` - -## 🚀 Quick Start - -### 1. Enable GitHub Pages - -1. Go to your repository on GitHub -2. Navigate to **Settings** → **Pages** -3. Under **Source**, select **GitHub Actions** -4. The workflow will automatically deploy when you push to main branch - -### 2. Local Development - -```bash -# Install Ruby and Jekyll -# On macOS: -brew install ruby -gem install jekyll bundler - -# On Ubuntu/Debian: -sudo apt install ruby-full build-essential -gem install jekyll bundler - -# On Windows: -# Download Ruby from rubyinstaller.org -gem install jekyll bundler - -# Install dependencies -cd docs -bundle install - -# Serve locally -bundle exec jekyll serve -``` - -3. Open http://localhost:4000 in your browser - -## 📚 Documentation Content - -### 1. Home Page (`index.md`) -- Project overview and quick start -- Feature highlights -- Supported countries -- Document types table -- Links to all sections - -### 2. Installation Guide (`installation.md`) -- Prerequisites -- Installation methods (PyPI, source) -- Environment setup -- API token configuration -- Troubleshooting common installation issues - -### 3. Usage Examples (`usage.md`) -- Basic setup and connection -- Company management -- Document sending (all types) -- Document retrieval and listing -- Cancellations and received documents -- Status checking -- Error handling examples -- Best practices - -### 4. API Reference (`api-reference.md`) -- Complete method documentation -- Parameter descriptions -- Return types -- Error handling -- Data types -- Rate limiting information -- Best practices - -### 5. Country Support (`countries.md`) -- Detailed country-specific information -- Dominican Republic (DGII) implementation -- Planned countries (Panama, Costa Rica, Peru, Bolivia) -- Tax systems and requirements -- Document numbering systems -- Implementation guidelines - -### 6. Contributing Guide (`contributing.md`) -- Development setup -- Code style guidelines -- Testing procedures -- Documentation standards -- Pull request process -- Issue reporting templates - -### 7. Troubleshooting (`troubleshooting.md`) -- Common installation issues -- Authentication problems -- API connection issues -- Validation errors -- Performance problems -- Country-specific issues -- Getting help - -## 🎨 Customization - -### Styling - -The documentation uses a custom Bootstrap 5 theme with: - -- **Color Scheme:** - - Primary: Blue (#2563eb) - - Secondary: Gray (#64748b) - - Accent: Orange (#f59e0b) - - Text: Dark gray (#1e293b) - -- **Features:** - - Responsive design - - Syntax highlighting - - Copy-to-clipboard buttons - - Search functionality - - Mobile-friendly navigation - -### Configuration - -Edit `docs/_config.yml` to customize: - -```yaml -# Site information -title: "Alanube Python API Documentation" -description: "Comprehensive documentation for the Alanube Python API client" -url: "https://wilmerm.github.io/alanube-python" - -# Navigation -nav: - - title: Home - url: / - - title: Installation - url: /installation/ - -# Social links -social: - github: wilmerm/alanube-python - twitter: AlanubeRD -``` - -## 🔧 Deployment - -### Automatic Deployment - -The documentation is automatically deployed via GitHub Actions: - -1. **Trigger:** Push to main/master branch -2. **Build:** Jekyll builds the site -3. **Deploy:** Site is deployed to GitHub Pages -4. **URL:** https://wilmerm.github.io/alanube-python/ - -### Manual Deployment - -```bash -# Build the site -cd docs -bundle exec jekyll build - -# The built site is in _site/ -# Upload to your hosting provider -``` - -### Custom Domain - -To use a custom domain: - -1. **Add CNAME file:** - ```bash - echo "docs.alanube.co" > docs/CNAME - ``` - -2. **Update configuration:** - ```yaml - # In _config.yml - url: "https://docs.alanube.co" - baseurl: "" - ``` - -3. **Configure DNS:** - Point your domain to GitHub Pages - -## 📊 Analytics and SEO - -### Google Analytics - -Add analytics tracking: - -```yaml -# In _config.yml -google_analytics: UA-XXXXXXXXX-X -``` - -### SEO Optimization - -The site includes: - -- Meta tags for social sharing -- Open Graph tags -- Twitter Card tags -- Sitemap generation -- Structured data - -## 🐛 Troubleshooting - -### Common Issues - -1. **Build Failures:** - ```bash - # Check Jekyll version - jekyll --version - - # Clean and rebuild - bundle exec jekyll clean - bundle exec jekyll build - ``` - -2. **Missing Dependencies:** - ```bash - # Install missing gems - bundle install - ``` - -3. **Local Server Issues:** - ```bash - # Use different port - bundle exec jekyll serve --port 4001 - ``` - -### Debug Mode - -```bash -# Enable verbose output -bundle exec jekyll serve --verbose -``` - -## 🤝 Contributing to Documentation - -### Adding New Content - -1. **Create new page:** - ```bash - touch docs/new-page.md - ``` - -2. **Add front matter:** - ```markdown - --- - title: Page Title - description: Page description - --- - ``` - -3. **Update navigation:** - Edit `docs/_config.yml` nav section - -### Documentation Standards - -- Use clear, concise language -- Include code examples -- Test all code snippets -- Use proper Markdown formatting -- Add links to related pages -- Include screenshots when helpful - -### Review Process - -1. Create a feature branch -2. Make your changes -3. Test locally -4. Submit a pull request -5. Wait for review and approval - -## 📈 Maintenance - -### Regular Tasks - -1. **Update Dependencies:** - ```bash - bundle update - ``` - -2. **Check for Broken Links:** - ```bash - bundle exec htmlproofer _site - ``` - -3. **Update Content:** - - Keep examples current - - Update API documentation - - Add new features - - Fix reported issues - -### Version Updates - -When updating the library: - -1. Update installation instructions -2. Review and update examples -3. Update API reference -4. Test all code snippets -5. Update version numbers - -## 🎯 Best Practices - -### Content Organization - -- Use clear, descriptive headings -- Group related information -- Provide navigation between sections -- Include table of contents for long pages - -### Code Examples - -- Use realistic examples -- Include error handling -- Show both simple and complex use cases -- Test all code before committing - -### User Experience - -- Make information easy to find -- Use consistent formatting -- Provide multiple ways to access content -- Include search functionality - -## 📞 Support - -For documentation issues: - -1. **Check existing issues** on GitHub -2. **Create a new issue** with details -3. **Contact maintainers** if urgent - -## 🎉 Success Metrics - -Track documentation success with: - -- **Page views** and **time on page** -- **Search queries** and **click-through rates** -- **User feedback** and **issue reports** -- **Contribution frequency** -- **Support ticket reduction** - -## 📄 License - -This documentation is licensed under the MIT License, same as the main project. - ---- - -**The documentation is now ready to help users effectively use the Alanube Python API! 🚀** - -For questions or improvements, please open an issue or submit a pull request. \ No newline at end of file diff --git a/README.md b/README.md index e138aed..895b03a 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,59 @@ data = Alanube.send_document(encf_type=31, payload) Now you can easily and efficiently use the Alanube API with this Python library! +### Dominican Republic API Methods + +| Method | Description | +|--------|-------------| +| `create_company` | Create a new company. | +| `update_company` | Update company information. | +| `get_company` | Retrieve company info. | +| `send_fiscal_invoice` | Issue Fiscal Credit Invoice (31). | +| `get_fiscal_invoice` | Get status of a Fiscal Credit Invoice. | +| `get_fiscal_invoices` | List Fiscal Credit Invoices. | +| `send_invoice` | Issue Consumption Invoice (32). | +| `get_invoice` | Get status of a Consumption Invoice. | +| `get_invoices` | List Consumption Invoices. | +| `send_debit_note` | Issue Debit Note (33). | +| `get_debit_note` | Get status of a Debit Note. | +| `get_debit_notes` | List Debit Notes. | +| `send_credit_note` | Issue Credit Note (34). | +| `get_credit_note` | Get status of a Credit Note. | +| `get_credit_notes` | List Credit Notes. | +| `send_purchase` | Issue Purchase Document (41). | +| `get_purchase` | Get status of a Purchase Document. | +| `get_purchases` | List Purchase Documents. | +| `send_minor_expense` | Issue Minor Expense Document (43). | +| `get_minor_expense` | Get status of a Minor Expense Document. | +| `get_minor_expenses` | List Minor Expense Documents. | +| `send_special_regime` | Issue Special Regime Document (44). | +| `get_special_regime` | Get status of a Special Regime Document. | +| `get_special_regimes` | List Special Regime Documents. | +| `send_gubernamental` | Issue Government Document (45). | +| `get_gubernamental` | Get status of a Government Document. | +| `get_gubernamentals` | List Government Documents. | +| `send_export_support` | Issue Export Support Document (46). | +| `get_export_support` | Get status of an Export Support Document. | +| `get_export_supports` | List Export Support Documents. | +| `send_payment_abroad_support` | Issue Payment Abroad Support Document (47). | +| `get_payment_abroad_support` | Get status of a Payment Abroad Support Document. | +| `get_payment_abroad_supports` | List Payment Abroad Support Documents. | +| `send_cancellation` | Issue a cancellation document. | +| `get_cancellation` | Get status of a cancellation. | +| `get_cancellations` | List cancellations. | +| `get_received_document` | Retrieve a received document. | +| `get_received_documents` | List received documents. | +| `check_directory` | Check active companies in directory. | +| `check_dgii_status` | Check DGII service status and maintenance. | +| `get_report_companies_documents_total` | Get total documents issued by a company. | +| `get_report_users_documents_total` | Get total documents issued by the authenticated user. | +| `get_report_company_emitted_documents` | Get total documents emitted by a company. | +| `get_report_company_emitted_documents_monthly` | Monthly totals of emitted documents (12 months). | +| `get_report_company_emitted_documents_15_days` | Daily totals of emitted documents (last 15 days). | +| `get_report_company_accepted_documents` | Total documents accepted by DGII for a company. | +| `get_report_company_accepted_documents_monthly` | Monthly totals of accepted documents (12 months). | +| `get_report_company_accepted_documents_15_days` | Daily totals of accepted documents (last 15 days). | + ## Contents - `do`: Fully implemented for the Dominican Republic (DGII). @@ -83,7 +136,6 @@ This library is trusted and used in production by: If your company uses this library and would like to be listed here, feel free to [open a pull request](https://github.com/wilmerm/alanube-python/pulls) or [create an issue](https://github.com/wilmerm/alanube-python/issues). - ## Developers If you're contributing to the development of this library, here are the steps to set up your environment and run the tests: diff --git a/docs/README.md b/docs/README.md index d427cbf..7b295a6 100644 --- a/docs/README.md +++ b/docs/README.md @@ -14,10 +14,8 @@ docs/ ├── index.md # Home page ├── installation.md # Installation guide ├── usage.md # Usage examples -├── api-reference.md # API reference ├── countries.md # Country support guide ├── contributing.md # Contributing guide -├── troubleshooting.md # Troubleshooting guide └── README.md # This file ``` @@ -30,11 +28,11 @@ docs/ # On macOS brew install ruby gem install jekyll bundler - + # On Ubuntu/Debian sudo apt install ruby-full build-essential gem install jekyll bundler - + # On Windows # Download Ruby from rubyinstaller.org gem install jekyll bundler @@ -73,9 +71,9 @@ The built site will be in `docs/_site/`. title: New Page Title description: Brief description of the page --- - + # New Page Title - + Your content here... ``` @@ -100,7 +98,7 @@ The built site will be in `docs/_site/`. ```markdown ```python from alanube.do import Alanube - + Alanube.connect("token", developer_mode=True) ``` ``` @@ -115,9 +113,9 @@ The built site will be in `docs/_site/`. 4. **Use Alerts for Important Information:** ```markdown > **Note:** Important information here. - + > **Warning:** Warning message here. - + > **Tip:** Helpful tip here. ``` @@ -199,7 +197,7 @@ To add Google Analytics: ```bash # Check Jekyll version jekyll --version - + # Clean and rebuild jekyll clean jekyll build @@ -215,7 +213,7 @@ To add Google Analytics: ```bash # Use different port jekyll serve --port 4001 - + # Bind to all interfaces jekyll serve --host 0.0.0.0 ``` @@ -266,4 +264,4 @@ This documentation is licensed under the same license as the main project (MIT). --- -**Happy documenting! 📚✨** \ No newline at end of file +**Happy documenting! 📚✨** \ No newline at end of file diff --git a/docs/_config.yml b/docs/_config.yml index 834a0fc..de145d9 100644 --- a/docs/_config.yml +++ b/docs/_config.yml @@ -40,7 +40,6 @@ nav: - title: Usage url: /usage/ - title: API Reference - url: /api-reference/ - title: Countries url: /countries/ - title: Contributing diff --git a/docs/_layouts/default.html b/docs/_layouts/default.html index a3a9d68..165e63c 100644 --- a/docs/_layouts/default.html +++ b/docs/_layouts/default.html @@ -253,9 +253,6 @@ Usage Examples - - API Reference - Country Support diff --git a/docs/contributing.md b/docs/contributing.md index 8683a76..4580ed4 100644 --- a/docs/contributing.md +++ b/docs/contributing.md @@ -246,10 +246,10 @@ def send_document(self, encf_type: int, payload: dict) -> dict: AlanubeException: For other API errors. Example: - >>> payload = {"company_id": "123", "customer": {...}} - >>> response = Alanube.send_document(31, payload) - >>> print(response["document_number"]) - 'B0100000001' + >>> payload = {"company": {...}, "idDoc": {...}, "sender": {...}, "buyer": {...}, ...} + >>> data = Alanube.send_document(31, payload) + >>> print(data['encf']) + 'E310000000000001' """ pass ``` @@ -260,7 +260,6 @@ When adding new features or changing existing ones: 1. **Update docstrings** for all modified methods 2. **Update README.md** if adding new features -3. **Update API reference** in `docs/api-reference.md` 4. **Add usage examples** in `docs/usage.md` 5. **Update installation guide** if needed @@ -363,12 +362,6 @@ Closes #(issue number) ```markdown ## Bug Report -### Environment -- Python version: 3.10.0 -- Alanube version: 1.0.0 -- Operating system: Windows 10 -- Country: Dominican Republic - ### Description Clear and concise description of the bug. diff --git a/docs/countries.md b/docs/countries.md index d30f280..58e8399 100644 --- a/docs/countries.md +++ b/docs/countries.md @@ -234,7 +234,7 @@ To add support for a new country, follow these guidelines: ```python # alanube/pa/__init__.py (for Panama) from .api import AlanubeAPI - + class Alanube: # Implement country-specific methods pass @@ -269,7 +269,7 @@ To add support for a new country, follow these guidelines: ```python # alanube/pa/types.py from dataclasses import dataclass - + @dataclass class DocumentResponse: # Country-specific response structure @@ -280,7 +280,7 @@ To add support for a new country, follow these guidelines: ```python # alanube/pa/tests/test_api.py import unittest - + class TestPanamaAPI(unittest.TestCase): def test_send_document(self): # Test implementation @@ -338,7 +338,6 @@ For each new country implementation: 2. **Installation Guide** - Country-specific setup instructions - Configuration requirements - - Troubleshooting guide 3. **Usage Examples** - Common use cases @@ -394,4 +393,4 @@ To contribute to country implementations: 5. Update documentation 6. Submit a pull request -For more information about contributing, see the [Contributing Guide](contributing.md). \ No newline at end of file +For more information about contributing, see the [Contributing Guide](contributing.md). \ No newline at end of file diff --git a/docs/index.md b/docs/index.md index ff26892..a478574 100644 --- a/docs/index.md +++ b/docs/index.md @@ -16,24 +16,304 @@ Alanube.connect("your_api_token", developer_mode=True) # Send a fiscal invoice payload = { - "company_id": "your_company_id", - "customer": { - "rnc": "123456789", - "name": "Customer Name", - "address": "Customer Address" - }, - "items": [ + "company": { + "id": "FAKE-01FV0123456789000000" + }, + "idDoc": { + "encf": "E310000000001", + "sequenceDueDate": "1990-12-31", + "deferredDeliveryIndicator": 1, + "taxAmountIndicator": 1, + "incomeType": 1, + "paymentType": 1, + "paymentDeadline": "1990-12-31", + "paymentTerm": "72 horas", + "paymentFormsTable": [ + { + "paymentMethod": 1, + "paymentAmount": 24300 + } + ], + "paymentAccountType": "CT", + "paymentAccountNumber": 1212453611324, + "bankPayment": "Banco estatal", + "dateFrom": "1990-12-31", + "dateUntil": "1990-12-31", + "totalPages": 3 + }, + "sender": { + "rnc": "133109124", + "companyName": "Mi compañía", + "tradename": "Mi compañía S.A.", + "branchOffice": "Mi sucursal", + "address": "30 De Marzo 9 Sd", + "municipality": "020101", + "province": "020000", + "phoneNumber": [ + [ + "809-123-4567", + "809-123-4570" + ] + ], + "mail": "user@example.com", + "webSite": "example.com", + "economicActivity": "Componenetes electrónicos", + "sellerCode": "A10002121", + "internalInvoiceNumber": "2023", + "internalOrderNumber": "202", + "saleArea": "Ventas", + "saleRoute": "Principal", + "additionalInformationIssuer": "Información adicional de emisor...", + "stampDate": "1990-12-31" + }, + "buyer": { + "rnc": "133109124", + "companyName": "Su compañía", + "contact": "David Pérez", + "mail": "user@example.com", + "address": "30 De Marzo 9 Sd", + "municipality": "020101", + "province": "020000", + "deliverDate": "1990-12-31", + "contactDelivery": "30 De Marzo 9 Sd", + "deliveryAddress": "30 De Marzo 9 Sd", + "additionalPhone": "333-222-2454", + "purchaseOrderDate": "1990-12-31", + "purchaseOrderNumber": 420, + "internalCode": "A0001212", + "responsibleForPayment": 101215465, + "additionalInformation": "Informacion adicional del comprador..." + }, + "additionalInformation": { + "shippingDate": "1990-12-31", + "shipmentNumber": "A24000000126", + "containerNumber": 1000025, + "referenceNumber": 1234, + "grossWeight": 228, + "netWeight": 227, + "grossWeightUnit": 10, + "unitNetWeight": 10, + "bulkQuantity": 1000, + "bulkUnit": 10, + "bulkVolume": 1000, + "unitVolume": 10 + }, + "transport": { + "driver": "A20020", + "transportDocument": 20020, + "file": "AZ100200", + "licensePlate": "ED00168", + "transportationRoute": "Principal", + "transportationZone": "Zona de transporte", + "albaranNumber": 20023 + }, + "totals": { + "totalTaxedAmount": 4000, + "i1AmountTaxed": 1000, + "i2AmountTaxed": 1000, + "i3AmountTaxed": 1000, + "exemptAmount": 1000, + "itbisS1": 18, + "itbisS2": 16, + "itbisS3": 0, + "itbisTotal": 340, + "itbis1Total": 180, + "itbis2Total": 160, + "itbis3Total": 0, + "additionalTaxAmount": 270, + "additionalTaxes": [ + { + "taxType": 6, + "additionalTaxRate": 632.58, + "selectiveTaxAmountSpecificConsumption": 24300, + "amountSelectiveConsumptionTaxAdvalorem": 24300, + "otherAdditionalTaxes": 24300 + } + ], + "totalAmount": 88757.68, + "nonBillableAmount": 88757.68, + "amountPeriod": 88757.68, + "previousBalance": 88757.68, + "amountAdvancePayment": 88757.68, + "payValue": 2000, + "itbisTotalRetained": 2000, + "isrTotalRetention": 2000, + "itbisTotalPerception": 2000, + "isrTotalPerception": 2000 + }, + "otherCurrency": { + "currencyType": "USD", + "exchangeRate": 100.8, + "totalTaxedAmountOtherCurrency": 2000, + "amountTaxed1OtherCurrency": 2000, + "amountTaxed2OtherCurrency": 2000, + "amountTaxed3OtherCurrency": 2000, + "exemptAmountOtherCurrency": 2000, + "itbisTotalOtherCurrency": 2000, + "itbis1TotalOtherCurrency": 2000, + "itbis2TotalOtherCurrency": 2000, + "itbis3TotalOtherCurrency": 2000, + "additionalTaxAmountOtherCurrency": 2000, + "additionalTaxesOtherCurrency": [ + { + "taxTypeOtherCurrency": 6, + "additionalTaxRateOtherCurrency": 632.58, + "selectiveTaxAmountSpecificConsumptionOtherCurrency": 24300, + "amountSelectiveConsumptionTaxAdvaloremOtherCurrency": 24300, + "otherAdditionalTaxesOtherCurrency": 24300 + } + ], + "totalAmountOtherCurrency": 24300 + }, + "itemDetails": [ + { + "lineNumber": 1, + "itemCodeTable": [ { - "description": "Product Description", - "quantity": 1, - "unit_price": 100.00, - "tax_rate": 18.00 + "codeType": "Interna", + "itemCode": "A001212" } - ] + ], + "billingIndicator": 0, + "retention": { + "indicatorAgentWithholdingPerception": 1, + "itbisAmountWithheld": 24300, + "isrAmountWithheld": 24300 + }, + "itemName": "Caja de madera", + "goodServiceIndicator": 1, + "itemDescription": "Fabricado con madera de arce canadience", + "quantityItem": 24300, + "unitMeasure": 0, + "quantityReference": 24300, + "referenceUnit": 4, + "subquantityTable": [ + { + "subquantity": 24300, + "codeSubquantity": 3 + } + ], + "degreesAlcohol": 0, + "unitPriceReference": 24300, + "elaborationDate": "1990-12-31", + "expirationDateItem": "1990-12-31", + "unitPriceItem": 24300, + "discountAmount": 24300, + "subDiscounts": [ + { + "subDiscountRate": "$", + "subDiscountPercentage": 0, + "subDiscountAmount": 24300 + } + ], + "surchargeAmount": 24300, + "subSurcharge": [ + { + "subSurchargeType": "$", + "subSurchargePercentage": 0, + "subSurchargeAmount": 24300 + } + ], + "additionalTaxes": [ + { + "taxType": 6 + } + ], + "otherCurrencyDetail": { + "priceOtherCurrency": 24300, + "discountOtherCurrency": 24300, + "surchargeAnotherCurrency": 24300, + "amountItemOtherCurrency": 24300 + }, + "itemAmount": 24300 + } + ], + "subtotals": [ + { + "subTotalNumber": 1, + "subtotalDescription": "Subtotal 1", + "order": 1, + "subTotalAmountTaxedTotal": 24300, + "subTotalAmountTaxedI1": 24300, + "subTotalAmountTaxedI2": 24300, + "subTotalAmountTaxedI3": 24300, + "itbisSubTotal": 24300, + "itbis1SubTotal": 24300, + "itbis2SubTotal": 24300, + "itbis3SubTotal": 24300, + "subTotalAdditionalTax": 24300, + "subTotalExempt": 24300, + "subTotalAmount": 24300, + "lines": 1 + } + ], + "discountsOrSurcharges": [ + { + "lineNumber": 1, + "fitType": "D", + "norma1007Indicator": 1, + "descriptionDiscountOrSurcharge": "Descuendo por el día de la madre", + "typeValue": "%", + "discountValueOrSurcharge": 0, + "discountAmountOrSurcharge": 24300, + "discountAmountOrSurchargeOtherCurrency": 24300, + "indicatorBillingDiscountOrSurcharge": 1 + } + ], + "pagination": [ + { + "pageNo": 1, + "noLineFrom": 1, + "noLineUntil": 1, + "subtotalAmountTaxedPage": 24300, + "subtotalAmountTaxed1Page": 24300, + "subtotalAmountTaxed2Page": 24300, + "subtotalAmountTaxed3Page": 24300, + "exemptSubtotalPage": 24300, + "itbisSubtotalPage": 24300, + "itbis1SubtotalPage": 24300, + "itbis2SubtotalPage": 24300, + "itbis3SubtotalPage": 24300, + "subtotalAdditionalTaxPage": 24300, + "subtotalAdditionalTax": { + "subtotalSelectiveTaxForSpecificConsumptionPage": 24300, + "subtotalOtherTax": 24300 + }, + "subtotalAmountPage": 24300, + "subtotalNonBillableAmountPage": 24300 + } + ], + "informationReference": { + "ncfModified": 1090012500, + "rncOtherTaxpayer": "101212154", + "ncfModifiedDate": "1990-12-31", + "modificationCode": 4 + }, + "config": { + "pdf": { + "type": "generic", + "note": "Nota de prueba" + } + } } -response = Alanube.send_document(encf_type=31, payload=payload) -print(response) +data = Alanube.send_document(encf_type=31, payload=payload) +print(data) + +# Output +{ + "id": "01G021Z3QSRZ58GSTBH7TPGD2J", + "stampDate": "1990-12-31", + "status": "REGISTERED", + "companyIdentification": 132109122, + "encf": "E310000000001", + "xml": "https://api-alanube-e-provider-dom-test.s3.amazonaws.com/users/...", + "pdf": "https://api-alanube-e-provider-dom-test.s3.amazonaws.com/users/...", + "documentStampUrl": "https://ecf.dgii.gov.do/testecf/ConsultaTimbre?...", + "signatureDate": "2025-09-22T13:46:23.350Z", + "securityCode": "MYUVCT", + "sequenceConsumed": False +} ``` ## 📚 Documentation Sections @@ -44,9 +324,6 @@ Complete setup instructions for getting started with the Alanube Python API. ### [Usage Examples](usage.md) Practical examples showing how to use the library for common tasks. -### [API Reference](api-reference.md) -Comprehensive documentation of all available methods and parameters. - ### [Country Support](countries.md) Information about supported countries and their specific features. diff --git a/docs/installation.md b/docs/installation.md index 3701408..67f34bf 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -89,7 +89,6 @@ Alanube.connect(token, developer_mode=developer_mode) ## Next Steps - Read the [Usage Examples](usage.md) to learn how to use the library -- Check the [API Reference](api-reference.md) for detailed method documentation - Explore [Country Support](countries.md) to see what features are available ## Troubleshooting @@ -109,6 +108,4 @@ Alanube.connect(token, developer_mode=developer_mode) **Network Issues** - Check your internet connection - Verify firewall settings -- Try using a different network if available - -For more help, see our [troubleshooting guide](troubleshooting.md) or [open an issue](https://github.com/wilmerm/alanube-python/issues) on GitHub. \ No newline at end of file +- Try using a different network if available \ No newline at end of file diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md deleted file mode 100644 index c990dc6..0000000 --- a/docs/troubleshooting.md +++ /dev/null @@ -1,544 +0,0 @@ -# Troubleshooting Guide - -This guide helps you resolve common issues when using the Alanube Python API. - -## Table of Contents - -- [Installation Issues](#installation-issues) -- [Authentication Issues](#authentication-issues) -- [API Connection Issues](#api-connection-issues) -- [Document Sending Issues](#document-sending-issues) -- [Validation Issues](#validation-issues) -- [Performance Issues](#performance-issues) -- [Country-Specific Issues](#country-specific-issues) -- [Getting Help](#getting-help) - -## Installation Issues - -### Import Error: No module named 'alanube' - -**Symptoms:** -```python -ImportError: No module named 'alanube' -``` - -**Solutions:** - -1. **Verify Installation:** - ```bash - pip list | grep alanube - ``` - -2. **Reinstall the Package:** - ```bash - pip uninstall alanube - pip install alanube - ``` - -3. **Check Python Environment:** - ```bash - python --version - which python - pip --version - ``` - -4. **Use Virtual Environment:** - ```bash - python -m venv venv - source venv/bin/activate # On Windows: venv\Scripts\activate - pip install alanube - ``` - -### Version Compatibility Issues - -**Symptoms:** -```python -TypeError: 'module' object is not callable -``` - -**Solutions:** - -1. **Check Python Version:** - - Ensure you're using Python 3.10 or higher - - The library requires Python 3.10+ - -2. **Update Python:** - ```bash - # On Ubuntu/Debian - sudo apt update - sudo apt install python3.10 - - # On macOS with Homebrew - brew install python@3.10 - - # On Windows, download from python.org - ``` - -## Authentication Issues - -### Invalid Token Error - -**Symptoms:** -```python -alanube.do.exceptions.AuthenticationError: Invalid API token -``` - -**Solutions:** - -1. **Verify Token:** - - Check your API token in the Alanube dashboard - - Ensure the token is copied correctly (no extra spaces) - - Verify the token hasn't expired - -2. **Regenerate Token:** - - Log into your Alanube account - - Go to API settings - - Generate a new token - - Update your code with the new token - -3. **Check Environment Variables:** - ```python - import os - print(os.getenv('ALANUBE_TOKEN')) # Should not be None - ``` - -### Token Expired - -**Symptoms:** -```python -alanube.do.exceptions.AuthenticationError: Token expired -``` - -**Solutions:** - -1. **Generate New Token:** - - Log into Alanube dashboard - - Navigate to API settings - - Generate a new token - -2. **Update Your Code:** - ```python - # Update your token - Alanube.connect("new_token_here", developer_mode=True) - ``` - -3. **Use Environment Variables:** - ```python - import os - from dotenv import load_dotenv - - load_dotenv() - token = os.getenv('ALANUBE_TOKEN') - Alanube.connect(token, developer_mode=True) - ``` - -## API Connection Issues - -### Connection Timeout - -**Symptoms:** -```python -requests.exceptions.ConnectTimeout: HTTPSConnectionPool -``` - -**Solutions:** - -1. **Check Internet Connection:** - ```bash - ping api.alanube.co - ``` - -2. **Increase Timeout:** - ```python - import requests - from alanube.do import Alanube - - # Set longer timeout - requests.adapters.DEFAULT_RETRIES = 5 - ``` - -3. **Use Retry Logic:** - ```python - import time - from alanube.do.exceptions import AlanubeException - - def send_with_retry(payload, max_retries=3): - for attempt in range(max_retries): - try: - return Alanube.send_document(encf_type=31, payload=payload) - except AlanubeException as e: - if "timeout" in str(e).lower() and attempt < max_retries - 1: - time.sleep(2 ** attempt) # Exponential backoff - continue - raise - ``` - -### SSL Certificate Issues - -**Symptoms:** -```python -requests.exceptions.SSLError: SSL certificate verification failed -``` - -**Solutions:** - -1. **Update Certificates:** - ```bash - # On Ubuntu/Debian - sudo apt update - sudo apt install ca-certificates - - # On macOS - brew install ca-certificates - ``` - -2. **Update Python:** - ```bash - pip install --upgrade certifi - ``` - -3. **Temporary Workaround (Not Recommended for Production):** - ```python - import ssl - import requests - - # Disable SSL verification (use only for testing) - ssl._create_default_https_context = ssl._create_unverified_context - ``` - -## Document Sending Issues - -### Validation Errors - -**Symptoms:** -```python -alanube.do.exceptions.ValidationError: Missing required field 'company_id' -``` - -**Solutions:** - -1. **Check Payload Structure:** - ```python - # Ensure all required fields are present - payload = { - "company_id": "your_company_id", # Required - "customer": { - "name": "Customer Name", # Required - "address": "Customer Address" # Required - }, - "items": [ # Required - { - "description": "Product", # Required - "quantity": 1, # Required - "unit_price": 100.00, # Required - "tax_rate": 18.00 # Required - } - ] - } - ``` - -2. **Validate Data Types:** - ```python - # Ensure correct data types - payload = { - "company_id": str(company_id), # Must be string - "items": [ - { - "quantity": float(quantity), # Must be float - "unit_price": float(price), # Must be float - "tax_rate": float(tax_rate) # Must be float - } - ] - } - ``` - -### Document Type Not Supported - -**Symptoms:** -```python -NotImplementedError: No implementation for eNCF type: 99 -``` - -**Solutions:** - -1. **Check Supported Types:** - ```python - # Supported document types - SUPPORTED_TYPES = { - 31: "Fiscal Invoice", - 32: "Invoice", - 33: "Debit Note", - 34: "Credit Note", - 41: "Purchase", - 43: "Minor Expense", - 44: "Special Regime", - 45: "Governmental", - 46: "Export Support", - 47: "Payment Abroad Support" - } - ``` - -2. **Use Correct Type:** - ```python - # Use the correct document type - response = Alanube.send_document(encf_type=31, payload=payload) # Fiscal Invoice - ``` - -## Validation Issues - -### RNC Validation Failed - -**Symptoms:** -```python -alanube.do.exceptions.ValidationError: Invalid RNC format -``` - -**Solutions:** - -1. **Check RNC Format:** - ```python - # RNC must be 9 or 11 digits - rnc = "123456789" # 9 digits - rnc = "12345678901" # 11 digits - ``` - -2. **Validate RNC:** - ```python - import re - - def validate_rnc(rnc): - # Remove any non-digit characters - rnc_clean = re.sub(r'\D', '', str(rnc)) - - # Check length - if len(rnc_clean) not in [9, 11]: - raise ValueError("RNC must be 9 or 11 digits") - - return rnc_clean - ``` - -### Tax Rate Validation - -**Symptoms:** -```python -alanube.do.exceptions.ValidationError: Invalid tax rate -``` - -**Solutions:** - -1. **Use Valid Tax Rates:** - ```python - # Valid tax rates for Dominican Republic - VALID_TAX_RATES = [0.0, 18.0] # 0% and 18% - - # Check tax rate - if tax_rate not in VALID_TAX_RATES: - raise ValueError(f"Tax rate must be one of {VALID_TAX_RATES}") - ``` - -2. **Format Tax Rate:** - ```python - # Ensure tax rate is a float - tax_rate = float(tax_rate) - ``` - -## Performance Issues - -### Slow Response Times - -**Symptoms:** -- API calls taking longer than expected -- Timeout errors - -**Solutions:** - -1. **Optimize Payload Size:** - ```python - # Remove unnecessary fields - payload = { - "company_id": company_id, - "customer": { - "name": customer_name, - "address": customer_address - # Only include required fields - }, - "items": items - } - ``` - -2. **Use Connection Pooling:** - ```python - import requests - - # Create a session for connection pooling - session = requests.Session() - session.mount('https://', requests.adapters.HTTPAdapter( - pool_connections=10, - pool_maxsize=10 - )) - ``` - -3. **Implement Caching:** - ```python - import functools - - @functools.lru_cache(maxsize=128) - def get_company_info(company_id): - return Alanube.get_company(company_id) - ``` - -### Rate Limiting - -**Symptoms:** -```python -alanube.do.exceptions.RateLimitError: Rate limit exceeded -``` - -**Solutions:** - -1. **Implement Exponential Backoff:** - ```python - import time - import random - - def send_with_backoff(payload, max_retries=5): - for attempt in range(max_retries): - try: - return Alanube.send_document(encf_type=31, payload=payload) - except RateLimitError: - if attempt < max_retries - 1: - wait_time = (2 ** attempt) + random.uniform(0, 1) - time.sleep(wait_time) - continue - raise - ``` - -2. **Batch Requests:** - ```python - # Instead of sending multiple requests quickly - # Batch them or add delays - import time - - for payload in payloads: - response = Alanube.send_document(encf_type=31, payload=payload) - time.sleep(1) # Add delay between requests - ``` - -## Country-Specific Issues - -### Dominican Republic (DGII) Issues - -**RNC Directory Issues:** -```python -# If RNC is not found in directory -try: - Alanube.check_directory(rnc="123456789") -except AlanubeException as e: - if "not found" in str(e).lower(): - print("RNC not found in DGII directory") - # Handle accordingly -``` - -**NCF Generation Issues:** -```python -# If NCF generation fails -try: - response = Alanube.send_document(encf_type=31, payload=payload) - ncf = response['document_number'] -except AlanubeException as e: - if "ncf" in str(e).lower(): - print("NCF generation failed") - # Check company configuration -``` - -### Environment Issues - -**Production vs Sandbox:** -```python -# Use sandbox for testing -Alanube.connect(token, developer_mode=True) # Sandbox - -# Use production for live data -Alanube.connect(token, developer_mode=False) # Production -``` - -## Getting Help - -### Before Asking for Help - -1. **Check the Documentation:** - - Review the [API Reference](api-reference.md) - - Check [Usage Examples](usage.md) - - Read [Installation Guide](installation.md) - -2. **Search Existing Issues:** - - Check [GitHub Issues](https://github.com/wilmerm/alanube-python/issues) - - Search for similar problems - -3. **Reproduce the Issue:** - - Create a minimal example - - Include error messages - - Specify your environment - -### Creating a Good Bug Report - -```markdown -## Environment -- Python version: 3.10.0 -- Alanube version: 1.0.0 -- Operating system: Windows 10 -- Country: Dominican Republic - -## Issue Description -Brief description of the problem - -## Steps to Reproduce -1. Step 1 -2. Step 2 -3. Step 3 - -## Expected Behavior -What should happen - -## Actual Behavior -What actually happens - -## Error Messages -``` -Traceback (most recent call last): - File "", line 1, in - ... -``` - -## Code Example -```python -from alanube.do import Alanube - -Alanube.connect("your_token", developer_mode=True) -# Your code here -``` - -## Additional Context -Any other relevant information -``` - -### Support Channels - -1. **GitHub Issues:** [Create an issue](https://github.com/wilmerm/alanube-python/issues) -2. **Documentation:** Check this troubleshooting guide -3. **Alanube Support:** [Contact Alanube](https://www.alanube.co/) -4. **Community:** Check discussions and existing issues - -### Common Solutions Summary - -| Issue | Quick Fix | -|-------|-----------| -| Import Error | `pip install alanube` | -| Authentication | Check/regenerate API token | -| Validation | Verify payload structure | -| Timeout | Check internet connection | -| Rate Limit | Add delays between requests | -| SSL Issues | Update certificates | -| RNC Issues | Validate RNC format | - -Remember to always test in sandbox mode first before using production! \ No newline at end of file diff --git a/docs/usage.md b/docs/usage.md index 53167c8..5eeda67 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -24,434 +24,59 @@ from alanube.do import Alanube Alanube.connect("your_api_token", developer_mode=True) ``` -## Company Management - -### Create a Company - -```python -company_payload = { - "rnc": "123456789", - "name": "My Company Name", - "commercial_name": "My Company", - "address": "123 Main Street", - "city": "Santo Domingo", - "state": "Distrito Nacional", - "country": "DO", - "phone": "+1-809-555-0123", - "email": "contact@mycompany.com", - "tax_regime": "General", - "economic_activity": "Software Development" -} - -response = Alanube.create_company(company_payload) -print(f"Company created with ID: {response['id']}") -``` - -### Update a Company - -```python -update_payload = { - "name": "Updated Company Name", - "phone": "+1-809-555-0124" -} - -response = Alanube.update_company(update_payload, company_id="your_company_id") -print("Company updated successfully") -``` - -### Get Company Details - -```python -company = Alanube.get_company("your_company_id") -print(f"Company: {company['name']}") -print(f"RNC: {company['rnc']}") -``` - -## Sending Documents - -### Send a Fiscal Invoice (NCF-E) - -```python -invoice_payload = { - "company_id": "your_company_id", - "customer": { - "rnc": "123456789", - "name": "Customer Name", - "address": "Customer Address", - "city": "Santo Domingo", - "state": "Distrito Nacional", - "country": "DO", - "phone": "+1-809-555-0000", - "email": "customer@example.com" - }, - "items": [ - { - "description": "Software Development Services", - "quantity": 1, - "unit_price": 1000.00, - "tax_rate": 18.00, - "discount": 0.00 - }, - { - "description": "Consulting Services", - "quantity": 2, - "unit_price": 500.00, - "tax_rate": 18.00, - "discount": 50.00 - } - ], - "payment_method": "Cash", - "payment_terms": "Immediate", - "notes": "Thank you for your business!" -} - -response = Alanube.send_document(encf_type=31, payload=invoice_payload) -print(f"Fiscal Invoice sent successfully: {response['document_number']}") -``` - -### Send a Regular Invoice - -```python -regular_invoice_payload = { - "company_id": "your_company_id", - "customer": { - "name": "Customer Name", - "address": "Customer Address", - "email": "customer@example.com" - }, - "items": [ - { - "description": "Product Description", - "quantity": 5, - "unit_price": 25.00, - "tax_rate": 18.00 - } - ] -} - -response = Alanube.send_document(encf_type=32, payload=regular_invoice_payload) -print(f"Invoice sent successfully: {response['document_number']}") -``` - -### Send a Credit Note - -```python -credit_note_payload = { - "company_id": "your_company_id", - "original_document": "B0100000001", # Original invoice number - "customer": { - "rnc": "123456789", - "name": "Customer Name", - "address": "Customer Address" - }, - "items": [ - { - "description": "Returned Product", - "quantity": 1, - "unit_price": 100.00, - "tax_rate": 18.00, - "reason": "Customer return" - } - ] -} - -response = Alanube.send_document(encf_type=34, payload=credit_note_payload) -print(f"Credit Note sent successfully: {response['document_number']}") -``` - -### Send a Debit Note - -```python -debit_note_payload = { - "company_id": "your_company_id", - "original_document": "B0100000001", # Original invoice number - "customer": { - "rnc": "123456789", - "name": "Customer Name", - "address": "Customer Address" - }, - "items": [ - { - "description": "Additional Services", - "quantity": 1, - "unit_price": 50.00, - "tax_rate": 18.00, - "reason": "Additional work performed" - } - ] -} - -response = Alanube.send_document(encf_type=33, payload=debit_note_payload) -print(f"Debit Note sent successfully: {response['document_number']}") -``` - -## Retrieving Documents - -### Get a Specific Document - -```python -# Get a fiscal invoice -invoice = Alanube.get_document(encf_type=31, document_id="document_id_here") -print(f"Document Status: {invoice['status']}") -print(f"Document Number: {invoice['document_number']}") - -# Get a credit note -credit_note = Alanube.get_document(encf_type=34, document_id="credit_note_id_here") -print(f"Credit Note Status: {credit_note['status']}") -``` - -### List Documents with Filters - -```python -# Get all fiscal invoices for a company -invoices = Alanube.get_documents( - encf_type=31, - company_id="your_company_id", - status="approved", - limit=50, - page=1 -) - -for invoice in invoices['documents']: - print(f"Invoice: {invoice['document_number']} - Status: {invoice['status']}") - -# Get documents within a date range -from datetime import datetime - -start_date = int(datetime(2024, 1, 1).timestamp()) -end_date = int(datetime(2024, 12, 31).timestamp()) - -documents = Alanube.get_documents( - encf_type=31, - company_id="your_company_id", - start=start_date, - end=end_date, - limit=100 -) -``` - -## Document Cancellations - -### Send a Cancellation Request - -```python -cancellation_payload = { - "company_id": "your_company_id", - "document_number": "B0100000001", - "reason": "Customer request", - "document_type": 31 # Fiscal invoice -} - -response = Alanube.send_cancellation(cancellation_payload) -print(f"Cancellation request sent: {response['id']}") -``` - -### Get Cancellation Details - -```python -cancellation = Alanube.get_cancellation("cancellation_id_here") -print(f"Cancellation Status: {cancellation['status']}") -``` - -### List Cancellations - -```python -cancellations = Alanube.get_cancellations( - company_id="your_company_id", - limit=25, - page=1 -) - -for cancellation in cancellations['cancellations']: - print(f"Cancellation: {cancellation['document_number']} - Status: {cancellation['status']}") -``` - -## Received Documents - -### Get Received Document Details - -```python -received_doc = Alanube.get_received_document("received_document_id_here") -print(f"Received Document: {received_doc['document_number']}") -print(f"Sender: {received_doc['sender']['name']}") -``` - -### List Received Documents - -```python -received_docs = Alanube.get_received_documents( - company_id="your_company_id", - limit=25, - page=1 -) - -for doc in received_docs['documents']: - print(f"Received: {doc['document_number']} from {doc['sender']['name']}") -``` - -## Status Checking - -### Check DGII Status - -```python -dgii_status = Alanube.check_dgii_status(company_id="your_company_id") -print(f"DGII Status: {dgii_status['status']}") -``` - -### Check Directory Status - -```python -directory_status = Alanube.check_directory( - rnc="123456789", - company_id="your_company_id" -) -print(f"Directory Status: {directory_status['status']}") -``` - -## Error Handling - -The library provides comprehensive error handling. Here's how to handle common errors: - -```python -from alanube.do import Alanube -from alanube.do.exceptions import AlanubeException, AuthenticationError, ValidationError - -try: - response = Alanube.send_document(encf_type=31, payload=invoice_payload) - print("Document sent successfully!") - -except AuthenticationError as e: - print(f"Authentication failed: {e}") - # Check your API token - -except ValidationError as e: - print(f"Validation error: {e}") - # Check your payload format - -except AlanubeException as e: - print(f"Alanube API error: {e}") - # Handle other API errors - -except Exception as e: - print(f"Unexpected error: {e}") - # Handle unexpected errors -``` - -### Common Error Scenarios - -```python -# Handle missing required fields -try: - incomplete_payload = { - "company_id": "your_company_id", - # Missing customer and items - } - Alanube.send_document(encf_type=31, payload=incomplete_payload) -except ValidationError as e: - print(f"Missing required fields: {e}") - -# Handle invalid document type -try: - Alanube.send_document(encf_type=99, payload=payload) # Invalid type -except NotImplementedError as e: - print(f"Unsupported document type: {e}") - -# Handle network issues -try: - Alanube.get_document(encf_type=31, document_id="invalid_id") -except AlanubeException as e: - if "404" in str(e): - print("Document not found") - elif "500" in str(e): - print("Server error, try again later") -``` - -## Best Practices - -1. **Always use try-catch blocks** for error handling -2. **Store your API token securely** (use environment variables) -3. **Use developer_mode=True** for testing -4. **Validate your data** before sending -5. **Handle pagination** when retrieving large lists -6. **Cache responses** when appropriate -7. **Log important operations** for debugging - -## Complete Example - -Here's a complete example that demonstrates the full workflow: - -```python -import os -from datetime import datetime -from alanube.do import Alanube -from alanube.do.exceptions import AlanubeException - -# Load environment variables -from dotenv import load_dotenv -load_dotenv() - -# Connect to API -token = os.getenv('ALANUBE_TOKEN') -Alanube.connect(token, developer_mode=True) - -try: - # Create a company - company_payload = { - "rnc": "123456789", - "name": "Example Company", - "address": "123 Main St", - "city": "Santo Domingo", - "state": "Distrito Nacional", - "country": "DO", - "email": "contact@example.com" - } - - company = Alanube.create_company(company_payload) - company_id = company['id'] - print(f"Company created: {company_id}") - - # Send a fiscal invoice - invoice_payload = { - "company_id": company_id, - "customer": { - "rnc": "987654321", - "name": "Customer Company", - "address": "456 Customer St", - "city": "Santo Domingo", - "state": "Distrito Nacional", - "country": "DO" - }, - "items": [ - { - "description": "Consulting Services", - "quantity": 10, - "unit_price": 100.00, - "tax_rate": 18.00 - } - ] - } - - invoice = Alanube.send_document(encf_type=31, payload=invoice_payload) - document_id = invoice['id'] - print(f"Fiscal invoice sent: {invoice['document_number']}") - - # Check document status - status = Alanube.get_document(encf_type=31, document_id=document_id) - print(f"Document status: {status['status']}") - - # List all documents - documents = Alanube.get_documents( - encf_type=31, - company_id=company_id, - limit=10 - ) - - print(f"Total documents: {documents['total']}") - for doc in documents['documents']: - print(f"- {doc['document_number']}: {doc['status']}") - -except AlanubeException as e: - print(f"Error: {e}") -``` - -This example shows the complete workflow from creating a company to sending documents and checking their status. \ No newline at end of file +### Dominican Republic API Methods + +| Method | Description | +|--------|-------------| +| `create_company` | Create a new company. | +| `update_company` | Update company information. | +| `get_company` | Retrieve company info. | +| `send_fiscal_invoice` | Issue Fiscal Credit Invoice (31). | +| `get_fiscal_invoice` | Get status of a Fiscal Credit Invoice. | +| `get_fiscal_invoices` | List Fiscal Credit Invoices. | +| `send_invoice` | Issue Consumption Invoice (32). | +| `get_invoice` | Get status of a Consumption Invoice. | +| `get_invoices` | List Consumption Invoices. | +| `send_debit_note` | Issue Debit Note (33). | +| `get_debit_note` | Get status of a Debit Note. | +| `get_debit_notes` | List Debit Notes. | +| `send_credit_note` | Issue Credit Note (34). | +| `get_credit_note` | Get status of a Credit Note. | +| `get_credit_notes` | List Credit Notes. | +| `send_purchase` | Issue Purchase Document (41). | +| `get_purchase` | Get status of a Purchase Document. | +| `get_purchases` | List Purchase Documents. | +| `send_minor_expense` | Issue Minor Expense Document (43). | +| `get_minor_expense` | Get status of a Minor Expense Document. | +| `get_minor_expenses` | List Minor Expense Documents. | +| `send_special_regime` | Issue Special Regime Document (44). | +| `get_special_regime` | Get status of a Special Regime Document. | +| `get_special_regimes` | List Special Regime Documents. | +| `send_gubernamental` | Issue Government Document (45). | +| `get_gubernamental` | Get status of a Government Document. | +| `get_gubernamentals` | List Government Documents. | +| `send_export_support` | Issue Export Support Document (46). | +| `get_export_support` | Get status of an Export Support Document. | +| `get_export_supports` | List Export Support Documents. | +| `send_payment_abroad_support` | Issue Payment Abroad Support Document (47). | +| `get_payment_abroad_support` | Get status of a Payment Abroad Support Document. | +| `get_payment_abroad_supports` | List Payment Abroad Support Documents. | +| `send_cancellation` | Issue a cancellation document. | +| `get_cancellation` | Get status of a cancellation. | +| `get_cancellations` | List cancellations. | +| `get_received_document` | Retrieve a received document. | +| `get_received_documents` | List received documents. | +| `check_directory` | Check active companies in directory. | +| `check_dgii_status` | Check DGII service status and maintenance. | +| `get_report_companies_documents_total` | Get total documents issued by a company. | +| `get_report_users_documents_total` | Get total documents issued by the authenticated user. | +| `get_report_company_emitted_documents` | Get total documents emitted by a company. | +| `get_report_company_emitted_documents_monthly` | Monthly totals of emitted documents (12 months). | +| `get_report_company_emitted_documents_15_days` | Daily totals of emitted documents (last 15 days). | +| `get_report_company_accepted_documents` | Total documents accepted by DGII for a company. | +| `get_report_company_accepted_documents_monthly` | Monthly totals of accepted documents (12 months). | +| `get_report_company_accepted_documents_15_days` | Daily totals of accepted documents (last 15 days). | + +--- + +For detailed information on each endpoint, refer to the official [Alanube API Documentation](https://developer.alanube.co/). \ No newline at end of file From 1a8118cdbf67a36d8a1f46966c87a1b4b5ed5b6e Mon Sep 17 00:00:00 2001 From: Wilmer Martinez Date: Mon, 22 Sep 2025 10:32:32 -0400 Subject: [PATCH 3/3] =?UTF-8?q?docs:=20actualizar=20versi=C3=B3n=20a=201.1?= =?UTF-8?q?.0=20en=20=5F=5Finit=5F=5F.py=20y=20pyproject.toml?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- alanube/__init__.py | 2 +- alanube/do/__init__.py | 2 +- pyproject.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/alanube/__init__.py b/alanube/__init__.py index ac19082..5862313 100644 --- a/alanube/__init__.py +++ b/alanube/__init__.py @@ -15,6 +15,6 @@ - `bo`: Implementation for Bolivia (future) """ -__version__ = "1.0.0" +__version__ = "1.1.0" __author__ = "Wilmer Martínez" __license__ = "MIT" diff --git a/alanube/do/__init__.py b/alanube/do/__init__.py index 8f16aae..517ab59 100644 --- a/alanube/do/__init__.py +++ b/alanube/do/__init__.py @@ -7,7 +7,7 @@ Alanube: Main class to interact with the Alanube API. """ -__version__ = "1.0.0" +__version__ = "1.1.0" import warnings diff --git a/pyproject.toml b/pyproject.toml index 71d16fc..f8df3b2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "alanube" -version = "1.0.1" +version = "1.1.0" authors = [ { name = "Wilmer Martinez" }, ]