forked from mindsdb/mindshub
-
Notifications
You must be signed in to change notification settings - Fork 0
Feat/add xero connector #14
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 26 commits
Commits
Show all changes
36 commits
Select commit
Hold shift + click to select a range
9350094
Add Xero integration handler and associated tables
gabrielbressan-tfy d37c317
Enhance XeroHandler to support token injection for OAuth2 authenticatβ¦
gabrielbressan-tfy 09f303e
Enhance XeroHandler token management; add client credentials validatiβ¦
gabrielbressan-tfy e977e6b
Enhance XeroTable classes to support optimized API queries; implementβ¦
gabrielbressan-tfy 3b2c9c2
Enhance XeroHandler with race condition protection for token refresh;β¦
gabrielbressan-tfy aa65dad
Refactor XeroHandler to register AccountsTable correctly; remove duplβ¦
gabrielbressan-tfy b770363
Increase default result limit in SELECTQueryParser from 20 to 1000 foβ¦
gabrielbressan-tfy 693b8ef
Enhance QuotesTable to support additional filters and update parameteβ¦
gabrielbressan-tfy 188c2ab
Enhance XeroTable to support BETWEEN operator in condition parsing; uβ¦
gabrielbressan-tfy 251d275
Add AccountsTable, BankTransactionsTable, and QuotesTable implementatβ¦
gabrielbressan-tfy 1f71d1d
Refactor XeroHandler to register new tables (BudgetsTable, ContactGroβ¦
gabrielbressan-tfy 7aaec9d
Add CreditNotesTable implementation and register it in XeroHandler; rβ¦
gabrielbressan-tfy 3b0d93b
Add InvoicesTable and ItemsTable implementations; update ContactsTablβ¦
gabrielbressan-tfy b710cc9
Add JournalsTable and ManualJournalsTable implementations; register tβ¦
gabrielbressan-tfy 6cd603e
Add OrganisationsTable implementation and register it in XeroHandler β¦
gabrielbressan-tfy c3e1165
Add OverpaymentsTable implementation and register it in XeroHandler fβ¦
gabrielbressan-tfy a3a2c20
Refactor InvoicesTable and OverpaymentsTable to remove debug print stβ¦
gabrielbressan-tfy c1b043a
Add PaymentServicesTable implementation for handling payment servicesβ¦
gabrielbressan-tfy d649895
Add contact_id support to CreditNotesTable, OverpaymentsTable, Paymenβ¦
gabrielbressan-tfy 107b7e7
Implement custom JSON serialization in XeroTable for Decimal, datetimβ¦
gabrielbressan-tfy 5edd256
Add RepeatingInvoicesTable implementation and register it in XeroHandβ¦
gabrielbressan-tfy 4def82b
Implement pagination and result limit parsing for Xero API tables to β¦
gabrielbressan-tfy 2d0db86
Increase page size to 1000 for PaymentsTable to enhance data retrievaβ¦
gabrielbressan-tfy 2adeaa1
Add report table implementations for Xero API: BalanceSheet, BankSummβ¦
gabrielbressan-tfy 1418298
Enhance SQL condition handling by unwrapping TypeCast in extract_compβ¦
gabrielbressan-tfy b905b26
Add snake_case conversion for keys in XeroTable class to improve consβ¦
gabrielbressan-tfy 5147614
Set default date parameters for BankSummary and ProfitLoss report tabβ¦
gabrielbressan-tfy 00b84bd
Update mindsdb/integrations/handlers/xero_handler/tables/items_table.py
gabrielbressan-tfy f015ef2
Update mindsdb/integrations/handlers/xero_handler/tables/journals_tabβ¦
gabrielbressan-tfy 3990222
Update mindsdb/integrations/handlers/xero_handler/tables/bank_transacβ¦
gabrielbressan-tfy 38f3789
Update mindsdb/integrations/handlers/xero_handler/tables/bank_transfeβ¦
gabrielbressan-tfy 3f75fb1
Remove obsolete config.json file
gabrielbressan-tfy 79d30dd
Merge branch 'feat/add-xero-connector' of https://github.com/Talentifβ¦
gabrielbressan-tfy 223f236
Update mindsdb/integrations/handlers/xero_handler/xero_handler.py
gabrielbressan-tfy 175abc7
Update mindsdb/integrations/handlers/xero_handler/tables/invoices_tabβ¦
gabrielbressan-tfy 3e14890
Merge branch 'feat/add-xero-connector' of https://github.com/Talentifβ¦
gabrielbressan-tfy File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| { | ||
| "gui": { | ||
| "autoupdate": true, | ||
| "open_on_start": false | ||
| }, | ||
| "api": { | ||
| "http": { | ||
| "host": "127.0.0.1", | ||
| "port": "47334", | ||
| "restart_on_failure": true, | ||
| "max_restart_count": 1, | ||
| "max_restart_interval_seconds": 60 | ||
| }, | ||
| "mysql": { | ||
| "host": "127.0.0.1", | ||
| "port": "47335", | ||
| "database": "mindsdb", | ||
| "ssl": true, | ||
| "restart_on_failure": true, | ||
| "max_restart_count": 1, | ||
| "max_restart_interval_seconds": 60 | ||
| } | ||
| },"data_catalog": { | ||
| "enabled": true | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -52,6 +52,7 @@ twillio | |
| web | ||
| youtube | ||
| xero | ||
| zendesk | ||
| zipcodebase | ||
| zotero | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,294 @@ | ||
| # Xero Handler for MindsDB | ||
|
|
||
| This handler provides read-only access to Xero Accounting API data through MindsDB. It supports OAuth2 authentication with automatic token refresh and exposes 10 key accounting endpoints as queryable tables. | ||
|
|
||
| ## Installation | ||
|
|
||
| The Xero handler is automatically installed with MindsDB. If you need to install it manually: | ||
|
|
||
| ```bash | ||
| pip install xero-python requests | ||
| ``` | ||
|
|
||
| ## Supported Tables | ||
|
|
||
| The handler provides access to the following Xero Accounting API endpoints: | ||
|
|
||
| 1. **budgets** - Budget information | ||
| 2. **contacts** - Customer and supplier contacts | ||
| 3. **invoices** - Invoice records | ||
| 4. **items** - Products and services | ||
| 5. **overpayments** - Overpayment records | ||
| 6. **payments** - Payment records | ||
| 7. **purchase_orders** - Purchase order records | ||
| 8. **quotes** - Sales quote records | ||
| 9. **repeating_invoices** - Repeating invoice templates | ||
| 10. **accounts** - Chart of accounts | ||
|
|
||
| All tables support SELECT queries with WHERE, ORDER BY, and LIMIT clauses. | ||
|
|
||
| ## Connection Setup | ||
|
|
||
| ### 1. Create a Xero App | ||
|
|
||
| 1. Go to [Xero Developer Portal](https://developer.xero.com) | ||
| 2. Sign in with your Xero account | ||
| 3. Click "My Apps" and create a new app | ||
| 4. Choose "Web" as the app type | ||
| 5. Fill in the app details: | ||
| - App Name | ||
| - Company URL | ||
| - Redirect URI (e.g., `http://localhost:3000/callback`) | ||
| 6. Note your Client ID and Client Secret | ||
|
|
||
| ### 2. Configure the Connection in MindsDB | ||
|
|
||
| #### Initial Connection (First Time) | ||
|
|
||
| ```sql | ||
| CREATE DATABASE xero_connection | ||
| WITH ENGINE = 'xero', | ||
| PARAMETERS = { | ||
| 'client_id': 'your_client_id', | ||
| 'client_secret': 'your_client_secret', | ||
| 'redirect_uri': 'http://localhost:3000/callback' | ||
| }; | ||
| ``` | ||
|
|
||
| When you run this for the first time, MindsDB will return an authorization URL. Visit this URL and authorize the application. You'll receive an authorization code. | ||
|
|
||
| #### With Authorization Code | ||
|
|
||
| After authorizing, provide the authorization code to complete the setup: | ||
|
|
||
| ```sql | ||
| CREATE DATABASE xero_connection | ||
| WITH ENGINE = 'xero', | ||
| PARAMETERS = { | ||
| 'client_id': 'your_client_id', | ||
| 'client_secret': 'your_client_secret', | ||
| 'redirect_uri': 'http://localhost:3000/callback', | ||
| 'code': 'your_authorization_code' | ||
| }; | ||
| ``` | ||
|
|
||
| #### Specifying Tenant (Organization) | ||
|
|
||
| If you have access to multiple Xero organizations, you can specify which one to use: | ||
|
|
||
| ```sql | ||
| CREATE DATABASE xero_connection | ||
| WITH ENGINE = 'xero', | ||
| PARAMETERS = { | ||
| 'client_id': 'your_client_id', | ||
| 'client_secret': 'your_client_secret', | ||
| 'redirect_uri': 'http://localhost:3000/callback', | ||
| 'code': 'your_authorization_code', | ||
| 'tenant_id': 'your_tenant_id' | ||
| }; | ||
| ``` | ||
|
|
||
| If not specified, the handler will use the first accessible organization. | ||
|
|
||
| ## Token Injection (Backend Integration) | ||
|
|
||
| For backend systems that manage OAuth2 tokens centrally, you can inject tokens directly without going through the authorization flow: | ||
|
|
||
| ### Basic Token Injection | ||
|
|
||
| If you have a valid access token: | ||
|
|
||
| ```sql | ||
| CREATE DATABASE xero_backend | ||
| WITH ENGINE = 'xero', | ||
| PARAMETERS = { | ||
| 'client_id': 'your_client_id', | ||
| 'client_secret': 'your_client_secret', | ||
| 'access_token': 'xero_access_token', | ||
| 'tenant_id': 'xero_tenant_id' | ||
| }; | ||
| ``` | ||
|
|
||
| ### Token Injection with Refresh | ||
|
|
||
| For better reliability, provide both access and refresh tokens. The handler will automatically refresh the access token when needed: | ||
|
|
||
| ```sql | ||
| CREATE DATABASE xero_backend | ||
| WITH ENGINE = 'xero', | ||
| PARAMETERS = { | ||
| 'client_id': 'your_client_id', | ||
| 'client_secret': 'your_client_secret', | ||
| 'access_token': 'xero_access_token', | ||
| 'refresh_token': 'xero_refresh_token', | ||
| 'expires_at': '2024-11-30T12:00:00', -- Optional: ISO 8601 format or Unix timestamp | ||
| 'tenant_id': 'xero_tenant_id' | ||
| }; | ||
| ``` | ||
|
|
||
| ### How Token Injection Works | ||
|
|
||
| 1. **Token Validation**: The handler checks if the provided access token is expired or expiring soon (within 5 minutes) | ||
| 2. **Automatic Refresh**: If expired and a refresh_token is provided, the handler automatically refreshes the token | ||
| 3. **Token Storage**: Refreshed tokens are stored for future use | ||
| 4. **Grace Period**: Tokens are considered expired if they expire within 5 minutes, allowing proactive refresh | ||
|
|
||
| **Note:** Token refresh requires valid `client_id` and `client_secret` in the connection parameters, even when using token injection. | ||
|
|
||
| ## Usage Examples | ||
|
|
||
| ### Select All Contacts | ||
|
|
||
| ```sql | ||
| SELECT * FROM xero_connection.contacts LIMIT 10; | ||
| ``` | ||
|
|
||
| ### Find Recent Invoices | ||
|
|
||
| ```sql | ||
| SELECT invoice_number, contact_name, total, invoice_date | ||
| FROM xero_connection.invoices | ||
| WHERE status = 'DRAFT' | ||
| ORDER BY invoice_date DESC | ||
| LIMIT 20; | ||
| ``` | ||
|
|
||
| ### Get All Active Accounts | ||
|
|
||
| ```sql | ||
| SELECT code, name, type, currency_code | ||
| FROM xero_connection.accounts | ||
| WHERE status = 'ACTIVE' | ||
| ORDER BY code; | ||
| ``` | ||
|
|
||
| ### View Purchase Orders | ||
|
|
||
| ```sql | ||
| SELECT purchase_order_number, contact_name, total, order_date | ||
| FROM xero_connection.purchase_orders | ||
| WHERE status = 'AUTHORISED' | ||
| LIMIT 50; | ||
| ``` | ||
|
|
||
| ### Check Available Items | ||
|
|
||
| ```sql | ||
| SELECT code, description, is_tracked_as_inventory | ||
| FROM xero_connection.items | ||
| LIMIT 30; | ||
| ``` | ||
|
|
||
| ### Get Payments Summary | ||
|
|
||
| ```sql | ||
| SELECT invoice_id, amount, payment_type, reference | ||
| FROM xero_connection.payments | ||
| WHERE amount > 100 | ||
| ORDER BY updated_utc DESC; | ||
| ``` | ||
|
|
||
| ### View Quotes | ||
|
|
||
| ```sql | ||
| SELECT quote_number, contact_name, total, quote_date, expiry_date | ||
| FROM xero_connection.quotes | ||
| WHERE status = 'DRAFT' | ||
| ORDER BY quote_date DESC; | ||
| ``` | ||
|
|
||
| ## Authentication Details | ||
|
|
||
| ### OAuth2 Flow | ||
|
|
||
| This handler implements the OAuth2 Authorization Code flow as documented in the [Xero OAuth2 Guide](https://developer.xero.com/documentation/guides/oauth2/auth-flow). | ||
|
|
||
| 1. **Authorization**: User is directed to Xero's authorization endpoint | ||
| 2. **Code Exchange**: Authorization code is exchanged for access and refresh tokens | ||
| 3. **Token Storage**: Tokens are stored securely in MindsDB's encrypted storage | ||
| 4. **Token Refresh**: Access tokens are automatically refreshed when expired (Xero tokens expire every 30 minutes) | ||
|
|
||
| ### Scopes | ||
|
|
||
| The handler requests the following OAuth2 scopes: | ||
| - `openid` - OpenID Connect | ||
| - `profile` - User profile information | ||
| - `email` - User email | ||
| - `accounting.transactions` - Read access to transactions | ||
| - `accounting.settings` - Read access to settings | ||
| - `offline_access` - Refresh token access | ||
|
|
||
| ## Limitations | ||
|
|
||
| - **Read-only**: This handler provides read-only access to the Xero API. Create, update, and delete operations are not supported. | ||
| - **Rate Limiting**: Xero API has rate limits. Be mindful of the number of queries you execute. | ||
| - **Token Expiration**: Access tokens expire after 30 minutes. The handler automatically refreshes them as needed. | ||
| - **Tenant Selection**: If you have access to multiple Xero organizations, you must specify the `tenant_id` or the handler will use the first available organization. | ||
|
|
||
| ## Troubleshooting | ||
|
|
||
| ### "Authorization required" Error | ||
|
|
||
| If you see this error during connection, you need to provide an authorization code: | ||
| 1. Visit the URL provided in the error message | ||
| 2. Authorize the application | ||
| 3. Copy the authorization code | ||
| 4. Update your connection parameters with the code | ||
|
|
||
| ### "No Xero tenants found" Error | ||
|
|
||
| This typically means: | ||
| 1. The user account has no Xero organizations/tenants | ||
| 2. The user needs to create a Xero organization first | ||
| 3. The user account permissions are restricted | ||
|
|
||
| ### Token Refresh Failures | ||
|
|
||
| If token refresh fails: | ||
| 1. Delete the current connection and create a new one | ||
| 2. Go through the authorization flow again | ||
| 3. This will generate new tokens | ||
|
|
||
| ## Advanced Usage | ||
|
|
||
| ### Query Filtering | ||
|
|
||
| You can use WHERE clauses to filter data: | ||
|
|
||
| ```sql | ||
| SELECT * FROM xero_connection.invoices | ||
| WHERE invoice_date >= '2024-01-01' | ||
| AND status = 'DRAFT' | ||
| AND total > 1000; | ||
| ``` | ||
|
|
||
| ### Ordering and Limiting | ||
|
|
||
| ```sql | ||
| SELECT contact_name, total | ||
| FROM xero_connection.payments | ||
| ORDER BY total DESC | ||
| LIMIT 5; | ||
| ``` | ||
|
|
||
| ### Column Selection | ||
|
|
||
| Only select the columns you need for better performance: | ||
|
|
||
| ```sql | ||
| SELECT invoice_number, total, due_date | ||
| FROM xero_connection.invoices; | ||
| ``` | ||
|
|
||
| ## API Reference | ||
|
|
||
| For detailed information about the Xero Accounting API, visit: | ||
| - [Xero API Documentation](https://developer.xero.com/documentation/api/accounting/overview) | ||
| - [Xero Python SDK](https://github.com/XeroAPI/xero-python) | ||
|
|
||
| ## Support | ||
|
|
||
| For issues or questions: | ||
| 1. Check the [Xero Developer Community](https://community.xero.com/developer) | ||
| 2. Review the [xero-python SDK documentation](https://github.com/XeroAPI/xero-python) | ||
| 3. Check MindsDB documentation for handler-specific issues |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| __title__ = 'MindsDB Xero handler' | ||
| __package_name__ = 'mindsdb_xero_handler' | ||
| __version__ = '0.0.1' | ||
| __description__ = "MindsDB handler for the Xero Accounting API" | ||
| __author__ = 'MindsDB' | ||
| __github__ = 'https://github.com/mindsdb/mindsdb' | ||
| __pypi__ = 'https://pypi.org/project/mindsdb/' | ||
| __license__ = 'MIT' | ||
| __copyright__ = 'Copyright 2025 - mindsdb' |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| from mindsdb.integrations.libs.const import HANDLER_TYPE | ||
| from .__about__ import __version__ as version, __description__ as description | ||
|
|
||
| try: | ||
| from .xero_handler import XeroHandler as Handler | ||
| import_error = None | ||
| except Exception as e: | ||
| Handler = None | ||
| import_error = e | ||
|
|
||
| title = "Xero" | ||
| name = "xero" | ||
| type = HANDLER_TYPE.DATA | ||
| icon_path = "icon.svg" | ||
|
|
||
| __all__ = [ | ||
| "Handler", | ||
| "version", | ||
| "name", | ||
| "type", | ||
| "title", | ||
| "description", | ||
| "import_error", | ||
| "icon_path", | ||
| ] |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.