mirror of
https://github.com/bringout/oca-ocb-l10n_me-africa.git
synced 2026-04-28 03:02:06 +02:00
19.0 vanilla
This commit is contained in:
parent
c5006a6999
commit
80293571e7
420 changed files with 21812 additions and 44297 deletions
|
|
@ -1,7 +1,7 @@
|
|||
# Kenya Tremol Device EDI Integration
|
||||
|
||||
|
||||
This module integrates with the Kenyan G03 Tremol control unit device to the KRA through TIMS.
|
||||
This module integrates with the Kenyan G03 Tremol control unit device to the KRA through TIMS.
|
||||
|
||||
|
||||
## Installation
|
||||
|
|
@ -12,37 +12,14 @@ pip install odoo-bringout-oca-ocb-l10n_ke_edi_tremol
|
|||
|
||||
## Dependencies
|
||||
|
||||
This addon depends on:
|
||||
- l10n_ke
|
||||
|
||||
## Manifest Information
|
||||
|
||||
- **Name**: Kenya Tremol Device EDI Integration
|
||||
- **Version**: 1.0
|
||||
- **Category**: Accounting/Localizations/EDI
|
||||
- **License**: LGPL-3
|
||||
- **Installable**: False
|
||||
|
||||
## Source
|
||||
|
||||
Based on [OCA/OCB](https://github.com/OCA/OCB) branch 16.0, addon `l10n_ke_edi_tremol`.
|
||||
- Repository: https://github.com/OCA/OCB
|
||||
- Branch: 19.0
|
||||
- Path: addons/l10n_ke_edi_tremol
|
||||
|
||||
## License
|
||||
|
||||
This package maintains the original LGPL-3 license from the upstream Odoo project.
|
||||
|
||||
## Documentation
|
||||
|
||||
- Overview: doc/OVERVIEW.md
|
||||
- Architecture: doc/ARCHITECTURE.md
|
||||
- Models: doc/MODELS.md
|
||||
- Controllers: doc/CONTROLLERS.md
|
||||
- Wizards: doc/WIZARDS.md
|
||||
- Reports: doc/REPORTS.md
|
||||
- Security: doc/SECURITY.md
|
||||
- Install: doc/INSTALL.md
|
||||
- Usage: doc/USAGE.md
|
||||
- Configuration: doc/CONFIGURATION.md
|
||||
- Dependencies: doc/DEPENDENCIES.md
|
||||
- Troubleshooting: doc/TROUBLESHOOTING.md
|
||||
- FAQ: doc/FAQ.md
|
||||
This package preserves the original LGPL-3 license.
|
||||
|
|
|
|||
|
|
@ -1 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
#
|
||||
from . import models
|
||||
from . import wizard
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
{
|
||||
'name': "Kenya Tremol Device EDI Integration",
|
||||
'summary': """
|
||||
Kenya Tremol Device EDI Integration
|
||||
""",
|
||||
'countries': ['ke'],
|
||||
'summary': "Kenya Tremol Device EDI Integration",
|
||||
'description': """
|
||||
This module integrates with the Kenyan G03 Tremol control unit device to the KRA through TIMS.
|
||||
This module integrates with the Kenyan G03 Tremol control unit device to the KRA through TIMS.
|
||||
""",
|
||||
'author': 'Odoo',
|
||||
'category': 'Accounting/Localizations/EDI',
|
||||
|
|
@ -14,14 +13,13 @@
|
|||
'depends': ['l10n_ke'],
|
||||
'data': [
|
||||
'views/account_move_view.xml',
|
||||
'views/product_view.xml',
|
||||
'views/report_invoice.xml',
|
||||
'views/res_config_settings_view.xml',
|
||||
'views/res_partner_views.xml',
|
||||
],
|
||||
'assets': {
|
||||
'web.assets_backend': [
|
||||
'l10n_ke_edi_tremol/static/src/js/send_invoice.js',
|
||||
'l10n_ke_edi_tremol/static/src/components/*',
|
||||
],
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,10 +4,10 @@
|
|||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Odoo Server 15.0+e\n"
|
||||
"Project-Id-Version: Odoo Server 19.0+e\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-01-08 23:34+0000\n"
|
||||
"PO-Revision-Date: 2023-01-08 23:34+0000\n"
|
||||
"POT-Creation-Date: 2025-12-30 19:07+0000\n"
|
||||
"PO-Revision-Date: 2025-12-30 19:07+0000\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
|
@ -35,46 +35,59 @@ msgstr ""
|
|||
msgid "<b>Serial Number: </b><br/>"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#: model_terms:ir.ui.view,arch_db:l10n_ke_edi_tremol.res_config_settings_view_form
|
||||
msgid ""
|
||||
"<span class=\"o_form_label\">Tremol Device Settings</span>\n"
|
||||
" <span class=\"fa fa-lg fa-building-o\" title=\"Values set here are company-specific.\" aria-label=\"Values set here are company-specific.\" groups=\"base.group_multi_company\" role=\"img\"/>"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#: model_terms:ir.ui.view,arch_db:l10n_ke_edi_tremol.l10n_ke_invoice
|
||||
msgid "<strong class=\"text-center\">TIMS URL</strong><br/><br/>"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#: model:ir.model,name:l10n_ke_edi_tremol.model_account_move_send
|
||||
msgid "Account Move Send"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#: model:ir.model,name:l10n_ke_edi_tremol.model_account_move_send_wizard
|
||||
msgid "Account Move Send Wizard"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#. odoo-python
|
||||
#: code:addons/l10n_ke_edi_tremol/models/account_move.py:0
|
||||
msgid ""
|
||||
"An OSCU has been initialized for this company. Please send the e-invoice via"
|
||||
" Send and Print -> Send to eTIMS instead."
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#: model:ir.model.fields,field_description:l10n_ke_edi_tremol.field_account_bank_statement_line__l10n_ke_cu_invoice_number
|
||||
#: model:ir.model.fields,field_description:l10n_ke_edi_tremol.field_account_move__l10n_ke_cu_invoice_number
|
||||
#: model:ir.model.fields,field_description:l10n_ke_edi_tremol.field_account_payment__l10n_ke_cu_invoice_number
|
||||
msgid "CU Invoice Number"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#: model:ir.model.fields,field_description:l10n_ke_edi_tremol.field_account_bank_statement_line__l10n_ke_cu_qrcode
|
||||
#: model:ir.model.fields,field_description:l10n_ke_edi_tremol.field_account_move__l10n_ke_cu_qrcode
|
||||
#: model:ir.model.fields,field_description:l10n_ke_edi_tremol.field_account_payment__l10n_ke_cu_qrcode
|
||||
msgid "CU QR Code"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#: model:ir.model.fields,field_description:l10n_ke_edi_tremol.field_account_bank_statement_line__l10n_ke_cu_serial_number
|
||||
#: model:ir.model.fields,field_description:l10n_ke_edi_tremol.field_account_move__l10n_ke_cu_serial_number
|
||||
#: model:ir.model.fields,field_description:l10n_ke_edi_tremol.field_account_payment__l10n_ke_cu_serial_number
|
||||
msgid "CU Serial Number"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#: model:ir.model.fields,field_description:l10n_ke_edi_tremol.field_account_bank_statement_line__l10n_ke_cu_datetime
|
||||
#: model:ir.model.fields,field_description:l10n_ke_edi_tremol.field_account_move__l10n_ke_cu_datetime
|
||||
#: model:ir.model.fields,field_description:l10n_ke_edi_tremol.field_account_payment__l10n_ke_cu_datetime
|
||||
msgid "CU Signing Date and Time"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#. odoo-python
|
||||
#: code:addons/l10n_ke_edi_tremol/models/account_move_send.py:0
|
||||
msgid "Check Invoice(s)"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#: model:ir.model,name:l10n_ke_edi_tremol.model_res_company
|
||||
msgid "Companies"
|
||||
|
|
@ -85,23 +98,46 @@ msgstr ""
|
|||
msgid "Config Settings"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#. odoo-javascript
|
||||
#: code:addons/l10n_ke_edi_tremol/static/src/components/ke_proxy_hook.js:0
|
||||
msgid "Connection lost, please try again later."
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#: model:ir.model,name:l10n_ke_edi_tremol.model_res_partner
|
||||
msgid "Contact"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#. openerp-web
|
||||
#: code:addons/l10n_ke_edi_tremol/static/src/js/send_invoice.js:0
|
||||
#, python-format
|
||||
msgid "Error trying to connect to Odoo. Check your internet connection"
|
||||
#: model:ir.model,website_form_label:l10n_ke_edi_tremol.model_res_partner
|
||||
msgid "Create a Customer"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#. openerp-web
|
||||
#: code:addons/l10n_ke_edi_tremol/static/src/js/send_invoice.js:0
|
||||
#, python-format
|
||||
msgid "Error trying to connect to the middleware. Is the middleware running?"
|
||||
#: model:ir.model.fields,field_description:l10n_ke_edi_tremol.field_account_move__display_name
|
||||
#: model:ir.model.fields,field_description:l10n_ke_edi_tremol.field_account_move_send__display_name
|
||||
#: model:ir.model.fields,field_description:l10n_ke_edi_tremol.field_account_move_send_wizard__display_name
|
||||
#: model:ir.model.fields,field_description:l10n_ke_edi_tremol.field_res_company__display_name
|
||||
#: model:ir.model.fields,field_description:l10n_ke_edi_tremol.field_res_config_settings__display_name
|
||||
#: model:ir.model.fields,field_description:l10n_ke_edi_tremol.field_res_partner__display_name
|
||||
msgid "Display Name"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#. odoo-javascript
|
||||
#: code:addons/l10n_ke_edi_tremol/static/src/components/ke_proxy_hook.js:0
|
||||
msgid ""
|
||||
"Error trying to connect to Odoo. Check your internet connection. Error "
|
||||
"message: %s"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#. odoo-javascript
|
||||
#: code:addons/l10n_ke_edi_tremol/static/src/components/ke_proxy_hook.js:0
|
||||
msgid ""
|
||||
"Error trying to connect to the middleware. Is the middleware running? \n"
|
||||
" Error message: %s"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
|
|
@ -117,16 +153,21 @@ msgid "Fiscal Device Proxy Address"
|
|||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#: model_terms:ir.ui.view,arch_db:l10n_ke_edi_tremol.l10n_ke_inherit_product_template_form_view
|
||||
msgid "HS Code"
|
||||
#: model:ir.model.fields,field_description:l10n_ke_edi_tremol.field_account_move__id
|
||||
#: model:ir.model.fields,field_description:l10n_ke_edi_tremol.field_account_move_send__id
|
||||
#: model:ir.model.fields,field_description:l10n_ke_edi_tremol.field_account_move_send_wizard__id
|
||||
#: model:ir.model.fields,field_description:l10n_ke_edi_tremol.field_res_company__id
|
||||
#: model:ir.model.fields,field_description:l10n_ke_edi_tremol.field_res_config_settings__id
|
||||
#: model:ir.model.fields,field_description:l10n_ke_edi_tremol.field_res_partner__id
|
||||
msgid "ID"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#. odoo-python
|
||||
#: code:addons/l10n_ke_edi_tremol/models/account_move.py:0
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Invalid invoice configuration on %s:\n"
|
||||
"%s\n"
|
||||
"Invalid invoice configuration on %(invoice)s:\n"
|
||||
"%(error_list)s\n"
|
||||
"\n"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -135,19 +176,6 @@ msgstr ""
|
|||
msgid "Journal Entry"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#: model:ir.model.fields,field_description:l10n_ke_edi_tremol.field_product_product__l10n_ke_hsn_code
|
||||
#: model:ir.model.fields,field_description:l10n_ke_edi_tremol.field_product_template__l10n_ke_hsn_code
|
||||
#: model_terms:ir.ui.view,arch_db:l10n_ke_edi_tremol.l10n_ke_inherit_product_product_form_view
|
||||
msgid "KRA Item Code"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#: model:ir.model.fields,field_description:l10n_ke_edi_tremol.field_product_product__l10n_ke_hsn_name
|
||||
#: model:ir.model.fields,field_description:l10n_ke_edi_tremol.field_product_template__l10n_ke_hsn_name
|
||||
msgid "KRA Item Description"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#: model_terms:ir.ui.view,arch_db:l10n_ke_edi_tremol.res_partner_view_form
|
||||
msgid "Kenya Accounting Details"
|
||||
|
|
@ -164,41 +192,37 @@ msgid "Kenya TIMS Integration"
|
|||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#. odoo-javascript
|
||||
#: code:addons/l10n_ke_edi_tremol/static/src/components/ke_proxy_dialog.xml:0
|
||||
msgid "OK"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#. odoo-python
|
||||
#: code:addons/l10n_ke_edi_tremol/models/account_move.py:0
|
||||
#, python-format
|
||||
msgid ""
|
||||
"On line %s, a product with a HS Code and HS Name must be selected, since the"
|
||||
" tax is 0%% or exempt."
|
||||
"On line %s, a tax with a KRA item code must be selected, since the tax is "
|
||||
"0%% or exempt."
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#. odoo-python
|
||||
#: code:addons/l10n_ke_edi_tremol/models/account_move.py:0
|
||||
#, python-format
|
||||
msgid "On line %s, you must select one and only one tax."
|
||||
msgid "On line %s, you must select one and only one VAT tax."
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#. openerp-web
|
||||
#: code:addons/l10n_ke_edi_tremol/static/src/js/send_invoice.js:0
|
||||
#, python-format
|
||||
msgid "Posting an invoice has failed, with the message: \n"
|
||||
#. odoo-javascript
|
||||
#: code:addons/l10n_ke_edi_tremol/static/src/components/ke_proxy_hook.js:0
|
||||
msgid "Posting invoice: %s"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#: model:ir.model,name:l10n_ke_edi_tremol.model_product_template
|
||||
msgid "Product Template"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#: model:ir.model.fields,help:l10n_ke_edi_tremol.field_product_product__l10n_ke_hsn_name
|
||||
#: model:ir.model.fields,help:l10n_ke_edi_tremol.field_product_template__l10n_ke_hsn_name
|
||||
msgid "Product code description needed when not 16% VAT rated. "
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#: model:ir.model.fields,help:l10n_ke_edi_tremol.field_product_product__l10n_ke_hsn_code
|
||||
#: model:ir.model.fields,help:l10n_ke_edi_tremol.field_product_template__l10n_ke_hsn_code
|
||||
msgid "Product code needed when not 16% VAT rated. "
|
||||
#. odoo-javascript
|
||||
#: code:addons/l10n_ke_edi_tremol/static/src/components/ke_proxy_hook.js:0
|
||||
msgid ""
|
||||
"Posting the invoice %s has failed with the message: \n"
|
||||
" %s"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
|
|
@ -217,18 +241,15 @@ msgid "Send to fiscal device"
|
|||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#: code:addons/l10n_ke_edi_tremol/models/account_move.py:0
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Tax '%s' is used, but only taxes of 16%%, 8%%, 0%% or Exempt can be sent. "
|
||||
"Please reconfigure or change the tax."
|
||||
#. odoo-javascript
|
||||
#: code:addons/l10n_ke_edi_tremol/static/src/components/ke_proxy_dialog.xml:0
|
||||
msgid "Sending Invoices to Fiscal Device"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#: code:addons/l10n_ke_edi_tremol/models/account_move.py:0
|
||||
#, python-format
|
||||
msgid ""
|
||||
"Tax exempt report line cannot be found, please update the l10n_ke module."
|
||||
#: model:ir.model.fields,field_description:l10n_ke_edi_tremol.field_account_bank_statement_line__l10n_ke_cu_show_send_button
|
||||
#: model:ir.model.fields,field_description:l10n_ke_edi_tremol.field_account_move__l10n_ke_cu_show_send_button
|
||||
msgid "Show Send to Tremol button"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
|
|
@ -238,16 +259,16 @@ msgid "The address of the proxy server for the fiscal device."
|
|||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#. odoo-python
|
||||
#: code:addons/l10n_ke_edi_tremol/models/account_move.py:0
|
||||
#, python-format
|
||||
msgid ""
|
||||
"The document already has details related to the fiscal device. Please make "
|
||||
"sure that the invoice has not already been sent."
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#. odoo-python
|
||||
#: code:addons/l10n_ke_edi_tremol/models/account_move.py:0
|
||||
#, python-format
|
||||
msgid "The document being sent should be an invoice or credit note."
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -259,39 +280,54 @@ msgid ""
|
|||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#: model_terms:ir.ui.view,arch_db:l10n_ke_edi_tremol.res_config_settings_view_form
|
||||
msgid ""
|
||||
"The tremol device makes use of a proxy server, which can be running locally on your computer or on an IoT Box.\n"
|
||||
" The proxy server must be on the same network as the fiscal device."
|
||||
#. odoo-python
|
||||
#: code:addons/l10n_ke_edi_tremol/models/account_move_send.py:0
|
||||
msgid "The following documents have no details related to the fiscal device."
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#: model_terms:ir.ui.view,arch_db:l10n_ke_edi_tremol.res_config_settings_view_form
|
||||
msgid ""
|
||||
"The tremol device makes use of a proxy server, which can be running locally "
|
||||
"on your computer or on an IoT Box. The proxy server must be on the same "
|
||||
"network as the fiscal device."
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#. odoo-python
|
||||
#: code:addons/l10n_ke_edi_tremol/models/account_move.py:0
|
||||
#, python-format
|
||||
msgid ""
|
||||
"This credit note must reference the previous invoice, and this previous "
|
||||
"invoice must have already been submitted."
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#. odoo-python
|
||||
#: code:addons/l10n_ke_edi_tremol/models/account_move_send.py:0
|
||||
msgid ""
|
||||
"This document does not have details related to the fiscal device, a proforma"
|
||||
" invoice will be used."
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#. odoo-python
|
||||
#: code:addons/l10n_ke_edi_tremol/models/account_move.py:0
|
||||
#, python-format
|
||||
msgid ""
|
||||
"This invoice is not a Kenyan invoice and therefore can not be sent to the "
|
||||
"device."
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#. odoo-python
|
||||
#: code:addons/l10n_ke_edi_tremol/models/account_move.py:0
|
||||
#, python-format
|
||||
msgid ""
|
||||
"This invoice's company currency is not in Kenyan Shillings, conversion to "
|
||||
"KES is not possible."
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#. odoo-python
|
||||
#: code:addons/l10n_ke_edi_tremol/models/account_move.py:0
|
||||
#, python-format
|
||||
msgid ""
|
||||
"This invoice/credit note has not been posted. Please confirm it to continue."
|
||||
msgstr ""
|
||||
|
|
@ -301,7 +337,26 @@ msgstr ""
|
|||
msgid "To Send to TIMS"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#: model_terms:ir.ui.view,arch_db:l10n_ke_edi_tremol.res_config_settings_view_form
|
||||
msgid "Tremol Device Settings"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#: model_terms:ir.ui.view,arch_db:l10n_ke_edi_tremol.l10n_ke_inherit_account_move_form
|
||||
msgid "Tremol GO3 Fiscal Device"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#. odoo-javascript
|
||||
#: code:addons/l10n_ke_edi_tremol/static/src/components/ke_proxy_hook.js:0
|
||||
msgid ""
|
||||
"Unexpected Error:\n"
|
||||
" %s"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#. odoo-python
|
||||
#: code:addons/l10n_ke_edi_tremol/models/account_move_send.py:0
|
||||
msgid "View Invoice(s)"
|
||||
msgstr ""
|
||||
|
|
|
|||
|
|
@ -0,0 +1,362 @@
|
|||
# Translation of Odoo Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * l10n_ke_edi_tremol
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Odoo Server 19.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-12-30 19:07+0000\n"
|
||||
"PO-Revision-Date: 2025-11-13 14:26+0000\n"
|
||||
"Last-Translator: Automatically generated\n"
|
||||
"Language-Team: none\n"
|
||||
"Language: sw\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#: model_terms:ir.ui.view,arch_db:l10n_ke_edi_tremol.l10n_ke_invoice
|
||||
msgid "<b>Date and Time of Signing: </b><br/>"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#: model_terms:ir.ui.view,arch_db:l10n_ke_edi_tremol.l10n_ke_invoice
|
||||
msgid "<b>Invoice Number: </b><br/>"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#: model_terms:ir.ui.view,arch_db:l10n_ke_edi_tremol.l10n_ke_invoice
|
||||
msgid "<b>Kenyan Fiscal Device Info</b>"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#: model_terms:ir.ui.view,arch_db:l10n_ke_edi_tremol.l10n_ke_invoice
|
||||
msgid "<b>Serial Number: </b><br/>"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#: model_terms:ir.ui.view,arch_db:l10n_ke_edi_tremol.l10n_ke_invoice
|
||||
msgid "<strong class=\"text-center\">TIMS URL</strong><br/><br/>"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#: model:ir.model,name:l10n_ke_edi_tremol.model_account_move_send
|
||||
msgid "Account Move Send"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#: model:ir.model,name:l10n_ke_edi_tremol.model_account_move_send_wizard
|
||||
msgid "Account Move Send Wizard"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#. odoo-python
|
||||
#: code:addons/l10n_ke_edi_tremol/models/account_move.py:0
|
||||
msgid ""
|
||||
"An OSCU has been initialized for this company. Please send the e-invoice via "
|
||||
"Send and Print -> Send to eTIMS instead."
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#: model:ir.model.fields,field_description:l10n_ke_edi_tremol.field_account_bank_statement_line__l10n_ke_cu_invoice_number
|
||||
#: model:ir.model.fields,field_description:l10n_ke_edi_tremol.field_account_move__l10n_ke_cu_invoice_number
|
||||
msgid "CU Invoice Number"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#: model:ir.model.fields,field_description:l10n_ke_edi_tremol.field_account_bank_statement_line__l10n_ke_cu_qrcode
|
||||
#: model:ir.model.fields,field_description:l10n_ke_edi_tremol.field_account_move__l10n_ke_cu_qrcode
|
||||
msgid "CU QR Code"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#: model:ir.model.fields,field_description:l10n_ke_edi_tremol.field_account_bank_statement_line__l10n_ke_cu_serial_number
|
||||
#: model:ir.model.fields,field_description:l10n_ke_edi_tremol.field_account_move__l10n_ke_cu_serial_number
|
||||
msgid "CU Serial Number"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#: model:ir.model.fields,field_description:l10n_ke_edi_tremol.field_account_bank_statement_line__l10n_ke_cu_datetime
|
||||
#: model:ir.model.fields,field_description:l10n_ke_edi_tremol.field_account_move__l10n_ke_cu_datetime
|
||||
msgid "CU Signing Date and Time"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#. odoo-python
|
||||
#: code:addons/l10n_ke_edi_tremol/models/account_move_send.py:0
|
||||
msgid "Check Invoice(s)"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#: model:ir.model,name:l10n_ke_edi_tremol.model_res_company
|
||||
msgid "Companies"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#: model:ir.model,name:l10n_ke_edi_tremol.model_res_config_settings
|
||||
msgid "Config Settings"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#. odoo-javascript
|
||||
#: code:addons/l10n_ke_edi_tremol/static/src/components/ke_proxy_hook.js:0
|
||||
msgid "Connection lost, please try again later."
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#: model:ir.model,name:l10n_ke_edi_tremol.model_res_partner
|
||||
msgid "Contact"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#: model:ir.model,website_form_label:l10n_ke_edi_tremol.model_res_partner
|
||||
msgid "Create a Customer"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#: model:ir.model.fields,field_description:l10n_ke_edi_tremol.field_account_move__display_name
|
||||
#: model:ir.model.fields,field_description:l10n_ke_edi_tremol.field_account_move_send__display_name
|
||||
#: model:ir.model.fields,field_description:l10n_ke_edi_tremol.field_account_move_send_wizard__display_name
|
||||
#: model:ir.model.fields,field_description:l10n_ke_edi_tremol.field_res_company__display_name
|
||||
#: model:ir.model.fields,field_description:l10n_ke_edi_tremol.field_res_config_settings__display_name
|
||||
#: model:ir.model.fields,field_description:l10n_ke_edi_tremol.field_res_partner__display_name
|
||||
msgid "Display Name"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#. odoo-javascript
|
||||
#: code:addons/l10n_ke_edi_tremol/static/src/components/ke_proxy_hook.js:0
|
||||
msgid ""
|
||||
"Error trying to connect to Odoo. Check your internet connection. Error "
|
||||
"message: %s"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#. odoo-javascript
|
||||
#: code:addons/l10n_ke_edi_tremol/static/src/components/ke_proxy_hook.js:0
|
||||
msgid ""
|
||||
"Error trying to connect to the middleware. Is the middleware running? \n"
|
||||
" Error message: %s"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#: model:ir.model.fields,field_description:l10n_ke_edi_tremol.field_res_partner__l10n_ke_exemption_number
|
||||
#: model:ir.model.fields,field_description:l10n_ke_edi_tremol.field_res_users__l10n_ke_exemption_number
|
||||
msgid "Exemption Number"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#: model:ir.model.fields,field_description:l10n_ke_edi_tremol.field_res_company__l10n_ke_cu_proxy_address
|
||||
#: model:ir.model.fields,field_description:l10n_ke_edi_tremol.field_res_config_settings__l10n_ke_cu_proxy_address
|
||||
msgid "Fiscal Device Proxy Address"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#: model:ir.model.fields,field_description:l10n_ke_edi_tremol.field_account_move__id
|
||||
#: model:ir.model.fields,field_description:l10n_ke_edi_tremol.field_account_move_send__id
|
||||
#: model:ir.model.fields,field_description:l10n_ke_edi_tremol.field_account_move_send_wizard__id
|
||||
#: model:ir.model.fields,field_description:l10n_ke_edi_tremol.field_res_company__id
|
||||
#: model:ir.model.fields,field_description:l10n_ke_edi_tremol.field_res_config_settings__id
|
||||
#: model:ir.model.fields,field_description:l10n_ke_edi_tremol.field_res_partner__id
|
||||
msgid "ID"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#. odoo-python
|
||||
#: code:addons/l10n_ke_edi_tremol/models/account_move.py:0
|
||||
msgid ""
|
||||
"Invalid invoice configuration on %(invoice)s:\n"
|
||||
"%(error_list)s\n"
|
||||
"\n"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#: model:ir.model,name:l10n_ke_edi_tremol.model_account_move
|
||||
msgid "Journal Entry"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#: model_terms:ir.ui.view,arch_db:l10n_ke_edi_tremol.res_partner_view_form
|
||||
msgid "Kenya Accounting Details"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#: model_terms:ir.ui.view,arch_db:l10n_ke_edi_tremol.l10n_ke_inherit_account_move_search_view
|
||||
msgid "Kenya CU Invoice Number"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#: model_terms:ir.ui.view,arch_db:l10n_ke_edi_tremol.res_config_settings_view_form
|
||||
msgid "Kenya TIMS Integration"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#. odoo-javascript
|
||||
#: code:addons/l10n_ke_edi_tremol/static/src/components/ke_proxy_dialog.xml:0
|
||||
msgid "OK"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#. odoo-python
|
||||
#: code:addons/l10n_ke_edi_tremol/models/account_move.py:0
|
||||
msgid ""
|
||||
"On line %s, a tax with a KRA item code must be selected, since the tax is 0%"
|
||||
"% or exempt."
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#. odoo-python
|
||||
#: code:addons/l10n_ke_edi_tremol/models/account_move.py:0
|
||||
msgid "On line %s, you must select one and only one VAT tax."
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#. odoo-javascript
|
||||
#: code:addons/l10n_ke_edi_tremol/static/src/components/ke_proxy_hook.js:0
|
||||
msgid "Posting invoice: %s"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#. odoo-javascript
|
||||
#: code:addons/l10n_ke_edi_tremol/static/src/components/ke_proxy_hook.js:0
|
||||
msgid ""
|
||||
"Posting the invoice %s has failed with the message: \n"
|
||||
" %s"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#: model_terms:ir.ui.view,arch_db:l10n_ke_edi_tremol.l10n_ke_invoice
|
||||
msgid "QR Code"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#: model_terms:ir.ui.view,arch_db:l10n_ke_edi_tremol.l10n_ke_inherit_account_move_form
|
||||
msgid "Send To Fiscal Device"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#: model:ir.actions.server,name:l10n_ke_edi_tremol.action_send_invoices_to_device
|
||||
msgid "Send to fiscal device"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#. odoo-javascript
|
||||
#: code:addons/l10n_ke_edi_tremol/static/src/components/ke_proxy_dialog.xml:0
|
||||
msgid "Sending Invoices to Fiscal Device"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#: model:ir.model.fields,field_description:l10n_ke_edi_tremol.field_account_bank_statement_line__l10n_ke_cu_show_send_button
|
||||
#: model:ir.model.fields,field_description:l10n_ke_edi_tremol.field_account_move__l10n_ke_cu_show_send_button
|
||||
msgid "Show Send to Tremol button"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#: model:ir.model.fields,help:l10n_ke_edi_tremol.field_res_company__l10n_ke_cu_proxy_address
|
||||
#: model:ir.model.fields,help:l10n_ke_edi_tremol.field_res_config_settings__l10n_ke_cu_proxy_address
|
||||
msgid "The address of the proxy server for the fiscal device."
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#. odoo-python
|
||||
#: code:addons/l10n_ke_edi_tremol/models/account_move.py:0
|
||||
msgid ""
|
||||
"The document already has details related to the fiscal device. Please make "
|
||||
"sure that the invoice has not already been sent."
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#. odoo-python
|
||||
#: code:addons/l10n_ke_edi_tremol/models/account_move.py:0
|
||||
msgid "The document being sent should be an invoice or credit note."
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#: model:ir.model.fields,help:l10n_ke_edi_tremol.field_res_partner__l10n_ke_exemption_number
|
||||
#: model:ir.model.fields,help:l10n_ke_edi_tremol.field_res_users__l10n_ke_exemption_number
|
||||
msgid "The exemption number of the partner. Provided by the Kenyan government."
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#. odoo-python
|
||||
#: code:addons/l10n_ke_edi_tremol/models/account_move_send.py:0
|
||||
msgid "The following documents have no details related to the fiscal device."
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#: model_terms:ir.ui.view,arch_db:l10n_ke_edi_tremol.res_config_settings_view_form
|
||||
msgid ""
|
||||
"The tremol device makes use of a proxy server, which can be running locally "
|
||||
"on your computer or on an IoT Box. The proxy server must be on the same "
|
||||
"network as the fiscal device."
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#. odoo-python
|
||||
#: code:addons/l10n_ke_edi_tremol/models/account_move.py:0
|
||||
msgid ""
|
||||
"This credit note must reference the previous invoice, and this previous "
|
||||
"invoice must have already been submitted."
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#. odoo-python
|
||||
#: code:addons/l10n_ke_edi_tremol/models/account_move_send.py:0
|
||||
msgid ""
|
||||
"This document does not have details related to the fiscal device, a proforma "
|
||||
"invoice will be used."
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#. odoo-python
|
||||
#: code:addons/l10n_ke_edi_tremol/models/account_move.py:0
|
||||
msgid ""
|
||||
"This invoice is not a Kenyan invoice and therefore can not be sent to the "
|
||||
"device."
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#. odoo-python
|
||||
#: code:addons/l10n_ke_edi_tremol/models/account_move.py:0
|
||||
msgid ""
|
||||
"This invoice's company currency is not in Kenyan Shillings, conversion to "
|
||||
"KES is not possible."
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#. odoo-python
|
||||
#: code:addons/l10n_ke_edi_tremol/models/account_move.py:0
|
||||
msgid ""
|
||||
"This invoice/credit note has not been posted. Please confirm it to continue."
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#: model_terms:ir.ui.view,arch_db:l10n_ke_edi_tremol.l10n_ke_inherit_account_move_search_view
|
||||
msgid "To Send to TIMS"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#: model_terms:ir.ui.view,arch_db:l10n_ke_edi_tremol.res_config_settings_view_form
|
||||
msgid "Tremol Device Settings"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#: model_terms:ir.ui.view,arch_db:l10n_ke_edi_tremol.l10n_ke_inherit_account_move_form
|
||||
msgid "Tremol GO3 Fiscal Device"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#. odoo-javascript
|
||||
#: code:addons/l10n_ke_edi_tremol/static/src/components/ke_proxy_hook.js:0
|
||||
msgid ""
|
||||
"Unexpected Error:\n"
|
||||
" %s"
|
||||
msgstr ""
|
||||
|
||||
#. module: l10n_ke_edi_tremol
|
||||
#. odoo-python
|
||||
#: code:addons/l10n_ke_edi_tremol/models/account_move_send.py:0
|
||||
msgid "View Invoice(s)"
|
||||
msgstr ""
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
from . import account_move
|
||||
from . import product
|
||||
from . import account_move_send
|
||||
from . import res_company
|
||||
from . import res_config_settings
|
||||
from . import res_partner
|
||||
|
|
|
|||
|
|
@ -5,11 +5,12 @@ import json
|
|||
import re
|
||||
from datetime import datetime
|
||||
|
||||
from odoo import models, fields, _
|
||||
from odoo import models, fields, _, api
|
||||
from odoo.exceptions import UserError
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class AccountMove(models.Model):
|
||||
_inherit = 'account.move'
|
||||
|
||||
|
|
@ -17,6 +18,18 @@ class AccountMove(models.Model):
|
|||
l10n_ke_cu_serial_number = fields.Char(string='CU Serial Number', copy=False)
|
||||
l10n_ke_cu_invoice_number = fields.Char(string='CU Invoice Number', copy=False)
|
||||
l10n_ke_cu_qrcode = fields.Char(string='CU QR Code', copy=False)
|
||||
l10n_ke_cu_show_send_button = fields.Boolean(string='Show Send to Tremol button', compute='_compute_l10n_ke_cu_show_send_button')
|
||||
|
||||
@api.depends('country_code', 'l10n_ke_cu_qrcode', 'state', 'move_type', 'company_id')
|
||||
def _compute_l10n_ke_cu_show_send_button(self):
|
||||
for move in self:
|
||||
move.l10n_ke_cu_show_send_button = (
|
||||
move.country_code == 'KE'
|
||||
and not move.l10n_ke_cu_qrcode
|
||||
and move.state == 'posted'
|
||||
and move.move_type in ['out_invoice', 'out_refund']
|
||||
and not move.company_id.l10n_ke_oscu_is_active
|
||||
)
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# HELPERS
|
||||
|
|
@ -72,14 +85,27 @@ class AccountMove(models.Model):
|
|||
if not vat_taxes or len(vat_taxes) > 1:
|
||||
move_errors.append(_("On line %s, you must select one and only one VAT tax.", line.name))
|
||||
else:
|
||||
if vat_taxes[0].amount == 0 and not (line.product_id and line.product_id.l10n_ke_hsn_code and line.product_id.l10n_ke_hsn_name):
|
||||
move_errors.append(_("On line %s, a product with a HS Code and HS Name must be selected, since the tax is 0%% or exempt.", line.name))
|
||||
if vat_taxes[0].amount == 0 and not line.tax_ids[0].l10n_ke_item_code_id:
|
||||
move_errors.append(_("On line %s, a tax with a KRA item code must be selected, since the tax is 0%% or exempt.", line.name))
|
||||
|
||||
if move_errors:
|
||||
errors.append((move.name, move_errors))
|
||||
|
||||
return errors
|
||||
|
||||
def _l10n_ke_fiscal_device_details_filled(self):
|
||||
self.ensure_one()
|
||||
# If the company is configured for OSCU, don't block the Send & Print.
|
||||
if self.company_id.l10n_ke_oscu_is_active:
|
||||
return True
|
||||
return all([
|
||||
self.country_code == 'KE',
|
||||
self.l10n_ke_cu_invoice_number,
|
||||
self.l10n_ke_cu_serial_number,
|
||||
self.l10n_ke_cu_qrcode,
|
||||
self.l10n_ke_cu_datetime,
|
||||
])
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# SERIALISERS
|
||||
# -------------------------------------------------------------------------
|
||||
|
|
@ -163,45 +189,30 @@ class AccountMove(models.Model):
|
|||
discount_dict[candidate.id] += rest_to_discount
|
||||
break
|
||||
|
||||
vat_class = {16.0: 'A', 8.0: 'B'}
|
||||
msgs = []
|
||||
tax_details = self._prepare_invoice_aggregated_taxes()
|
||||
for line in self.invoice_line_ids.filtered(lambda l: l.display_type == 'product' and l.quantity and l.price_total > 0 and not discount_dict.get(l.id) >= 100):
|
||||
# Here we use the original discount of the line, since it the distributed discount has not been applied in the price_total
|
||||
price_total = 0
|
||||
percentage = 0
|
||||
item_code = line.tax_ids[0].l10n_ke_item_code_id
|
||||
for tax in tax_details['tax_details_per_record'][line]['tax_details']:
|
||||
if tax['tax'].amount in (16, 8, 0): # This should only occur once
|
||||
if tax.amount in (16, 8, 0): # This should only occur once
|
||||
line_tax_details = tax_details['tax_details_per_record'][line]['tax_details'][tax]
|
||||
price_total = abs(line_tax_details['base_amount_currency']) + abs(line_tax_details['tax_amount_currency'])
|
||||
percentage = tax['tax'].amount
|
||||
|
||||
percentage = tax.amount
|
||||
price = round(price_total / abs(line.quantity) * 100 / (100 - line.discount), line.currency_id.decimal_places) * currency_rate
|
||||
price = ('%.5f' % price).rstrip('0').rstrip('.')
|
||||
|
||||
# Letter to classify tax, 0% taxes are handled conditionally, as the tax can be zero-rated or exempt
|
||||
letter = ''
|
||||
if percentage in vat_class:
|
||||
letter = vat_class[percentage]
|
||||
else:
|
||||
report_line_ids = line.tax_ids.invoice_repartition_line_ids.tag_ids._get_related_tax_report_expressions().report_line_id.ids
|
||||
try:
|
||||
exempt_report_line = self.env.ref('l10n_ke.tax_report_line_exempt_sales')
|
||||
except ValueError:
|
||||
raise UserError(_("Tax exempt report line cannot be found, please update the l10n_ke module."))
|
||||
letter = 'E' if exempt_report_line.id in report_line_ids else 'C'
|
||||
|
||||
uom = line.product_uom_id and line.product_uom_id.name or ''
|
||||
hscode = re.sub('[^0-9.]+', '', line.product_id.l10n_ke_hsn_code)[:10].ljust(10).encode('cp1251') if letter not in ('A', 'B') else b''.ljust(10)
|
||||
hsname = self._l10n_ke_fmt(line.product_id.l10n_ke_hsn_name, 20) if letter not in ('A', 'B') else b''.ljust(20)
|
||||
|
||||
line_data = b';'.join([
|
||||
self._l10n_ke_fmt(line.name, 36), # 36 symbols for the article's name
|
||||
self._l10n_ke_fmt(letter, 1), # 1 symbol for article's vat class ('A', 'B', 'C', 'D', or 'E')
|
||||
self._l10n_ke_fmt(line.name, 36), # 36 symbols for the article's name
|
||||
self._l10n_ke_fmt(item_code.tax_rate or 'A', 1), # 1 symbol for article's vat class ('A', 'B', 'C', 'D', or 'E')
|
||||
price[:15].encode('cp1251'), # 1 to 15 symbols for article's price with up to 5 digits after decimal point
|
||||
self._l10n_ke_fmt(uom, 3), # 3 symbols for unit of measure
|
||||
hscode, # 10 symbols for HS code in the format xxxx.xx.xx (can be empty)
|
||||
hsname, # 20 symbols for the HS name (can be empty)
|
||||
str(percentage).encode('cp1251')[:5] # up to 5 symbols for vat rate
|
||||
self._l10n_ke_fmt(uom, 3), # 3 symbols for unit of measure
|
||||
(item_code.code or '').ljust(10).encode('cp1251'), # 10 symbols for KRA item code in the format xxxx.xx.xx (can be empty)
|
||||
self._l10n_ke_fmt(item_code.description or '', 20), # 20 symbols for KRA item code description (can be empty)
|
||||
str(percentage).encode('cp1251')[:5] # up to 5 symbols for vat rate
|
||||
])
|
||||
# 1 to 10 symbols for quantity
|
||||
line_data += b'*' + str(abs(line.quantity)).encode('cp1251')[:10]
|
||||
|
|
@ -235,41 +246,48 @@ class AccountMove(models.Model):
|
|||
|
||||
def l10n_ke_action_cu_post(self):
|
||||
""" Returns the client action descriptor dictionary for sending the
|
||||
invoice(s) to the fiscal device.
|
||||
invoice(s) to the control unit (the fiscal device).
|
||||
"""
|
||||
# If l10n_ke_edi_oscu is configured for the company, disable sending via TREMOL.
|
||||
if self.company_id.l10n_ke_oscu_is_active:
|
||||
raise UserError(
|
||||
_('An OSCU has been initialized for this company. Please send the e-invoice via Send and Print -> Send to eTIMS instead.')
|
||||
)
|
||||
# Check the configuration of the invoice
|
||||
errors = self._l10n_ke_validate_move()
|
||||
if errors:
|
||||
error_msg = ""
|
||||
for move, error_list in errors:
|
||||
error_list = '\n'.join(error_list)
|
||||
error_msg += _("Invalid invoice configuration on %s:\n%s\n\n", move, error_list)
|
||||
error_msg += _("Invalid invoice configuration on %(invoice)s:\n%(error_list)s\n\n", invoice=move, error_list=error_list)
|
||||
raise UserError(error_msg)
|
||||
return {
|
||||
'type': 'ir.actions.client',
|
||||
'tag': 'post_send',
|
||||
'params': {
|
||||
'invoices': {
|
||||
move.id: {
|
||||
'messages': json.dumps([msg.decode('cp1251') for msg in move._l10n_ke_get_cu_messages()]),
|
||||
'proxy_address': move.company_id.l10n_ke_cu_proxy_address,
|
||||
'company_vat': move.company_id.vat
|
||||
} for move in self
|
||||
}
|
||||
}
|
||||
'tag': 'l10n_ke_post_send',
|
||||
'params': [
|
||||
{
|
||||
'move_id': move.id,
|
||||
'messages': json.dumps([msg.decode('cp1251') for msg in move._l10n_ke_get_cu_messages()]),
|
||||
'proxy_address': move.company_id.l10n_ke_cu_proxy_address,
|
||||
'company_vat': move.company_id.vat,
|
||||
'name': move.name,
|
||||
} for move in self
|
||||
]
|
||||
}
|
||||
|
||||
def l10n_ke_cu_response(self, response):
|
||||
def l10n_ke_cu_responses(self, responses):
|
||||
""" Set the fields related to the fiscal device on the invoice.
|
||||
|
||||
This is intended to be utilized by an RPC call from the javascript
|
||||
client action.
|
||||
client action. The fields are prefixed with l10n_ke_cu_*, which refers
|
||||
to the fact that they originate from the control unit.
|
||||
"""
|
||||
move = self.browse(int(response['move_id']))
|
||||
replies = [msg for msg in response['replies']]
|
||||
move.update({
|
||||
'l10n_ke_cu_serial_number': response['serial_number'],
|
||||
'l10n_ke_cu_invoice_number': replies[-2].split(';')[0],
|
||||
'l10n_ke_cu_qrcode': replies[-2].split(';')[1].strip(),
|
||||
'l10n_ke_cu_datetime': datetime.strptime(replies[-1], '%d-%m-%Y %H:%M'),
|
||||
})
|
||||
for response in responses:
|
||||
move = self.browse(int(response['move_id']))
|
||||
replies = [msg for msg in response['replies']]
|
||||
move.update({
|
||||
'l10n_ke_cu_serial_number': response['serial_number'],
|
||||
'l10n_ke_cu_invoice_number': replies[-2].split(';')[0],
|
||||
'l10n_ke_cu_qrcode': replies[-2].split(';')[1].strip(),
|
||||
'l10n_ke_cu_datetime': datetime.strptime(replies[-1], '%d-%m-%Y %H:%M'),
|
||||
})
|
||||
|
|
|
|||
|
|
@ -0,0 +1,45 @@
|
|||
from odoo import _, models, api
|
||||
|
||||
|
||||
class AccountMoveSend(models.AbstractModel):
|
||||
_inherit = 'account.move.send'
|
||||
|
||||
@api.model
|
||||
def _get_l10n_ke_edi_tremol_warning_moves(self, moves):
|
||||
return moves.filtered(lambda m: m.country_code == 'KE' and not m._l10n_ke_fiscal_device_details_filled())
|
||||
|
||||
@api.model
|
||||
def _get_l10n_ke_edi_tremol_warning_message(self, warning_moves):
|
||||
return '\n'.join([
|
||||
_("The following documents have no details related to the fiscal device."),
|
||||
*(warning_moves.mapped('name'))
|
||||
])
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# ALERTS
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
def _get_alerts(self, moves, moves_data):
|
||||
# EXTENDS 'account'
|
||||
alerts = super()._get_alerts(moves, moves_data)
|
||||
if warning_moves := self._get_l10n_ke_edi_tremol_warning_moves(moves):
|
||||
alerts['l10n_ke_edi_tremol_warning_moves'] = {
|
||||
'message': self._get_l10n_ke_edi_tremol_warning_message(warning_moves),
|
||||
'action_text': _("View Invoice(s)"),
|
||||
'action': warning_moves._get_records_action(name=_("Check Invoice(s)")),
|
||||
}
|
||||
return alerts
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# SENDING METHODS
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
def _hook_invoice_document_before_pdf_report_render(self, invoice, invoice_data):
|
||||
# EXTENDS account
|
||||
super()._hook_invoice_document_before_pdf_report_render(invoice, invoice_data)
|
||||
if invoice.country_code == 'KE' and not invoice._l10n_ke_fiscal_device_details_filled():
|
||||
invoice_data['error'] = {
|
||||
'error_title': _(
|
||||
"This document does not have details related to the fiscal device, a proforma invoice will be used."
|
||||
)
|
||||
}
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
from odoo import fields, models
|
||||
|
||||
|
||||
class ProductTemplate(models.Model):
|
||||
_inherit = "product.template"
|
||||
|
||||
l10n_ke_hsn_code = fields.Char(
|
||||
string='KRA Item Code',
|
||||
help='Product code needed when not 16% VAT rated. ',
|
||||
)
|
||||
l10n_ke_hsn_name = fields.Char(
|
||||
string='KRA Item Description',
|
||||
help='Product code description needed when not 16% VAT rated. ',
|
||||
)
|
||||
|
||||
class ProductProduct(models.Model):
|
||||
_inherit = "product.product"
|
||||
|
||||
l10n_ke_hsn_code = fields.Char(
|
||||
string='HSN code',
|
||||
related='product_tmpl_id.l10n_ke_hsn_code',
|
||||
help="Product code needed in case of not 16%. ",
|
||||
readonly=False,
|
||||
)
|
||||
l10n_ke_hsn_name = fields.Char(
|
||||
string='HSN description',
|
||||
related='product_tmpl_id.l10n_ke_hsn_name',
|
||||
help="Product code description needed in case of not 16%. ",
|
||||
readonly=False,
|
||||
)
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
import { registry } from "@web/core/registry";
|
||||
import { KEProxyDialog } from "./ke_proxy_dialog";
|
||||
|
||||
export function KESendInvoiceClientAction(env, action) {
|
||||
return new Promise((resolve) => {
|
||||
env.services.dialog.add(
|
||||
KEProxyDialog,
|
||||
{
|
||||
invoices: action.params,
|
||||
},
|
||||
{
|
||||
onClose: () => {
|
||||
resolve({ type: "ir.actions.act_window_close" });
|
||||
},
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
registry.category("actions").add("l10n_ke_post_send", KESendInvoiceClientAction);
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
import { Dialog } from "@web/core/dialog/dialog";
|
||||
import { useService } from "@web/core/utils/hooks";
|
||||
import { useHotkey } from "@web/core/hotkeys/hotkey_hook";
|
||||
import { useKEProxy } from "./ke_proxy_hook";
|
||||
import { Component } from "@odoo/owl";
|
||||
|
||||
|
||||
export class KEProxyDialog extends Component {
|
||||
static template = "l10n_ke_edi_tremol.KEProxyDialog";
|
||||
static components = { Dialog };
|
||||
static props = {
|
||||
invoices: Object,
|
||||
close: Function,
|
||||
};
|
||||
|
||||
setup() {
|
||||
// prevent the escape key from exiting the dialog
|
||||
useHotkey("escape", () => {});
|
||||
this.action = useService("action");
|
||||
this.sender = useKEProxy({ onAllSent: this.props.close });
|
||||
this.state = this.sender.state;
|
||||
this.sender.postInvoices(this.props.invoices);
|
||||
};
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<templates>
|
||||
<t t-name="l10n_ke_edi_tremol.KEProxyDialog">
|
||||
<Dialog>
|
||||
<t t-set-slot="header">
|
||||
<h4 class="modal-title text-break">
|
||||
Sending Invoices to Fiscal Device
|
||||
</h4>
|
||||
</t>
|
||||
<t t-set-slot="default">
|
||||
<div t-att-class="{'alert alert-danger': state.error}">
|
||||
<p t-esc="state.message"/>
|
||||
<t t-if="!state.error">
|
||||
<div t-attf-class="o_progressbar align-items-center w-100 d-flex">
|
||||
<div class="o_progress w-100 flex-fill"
|
||||
aria-valuemin="0"
|
||||
t-att-aria-valuemax="props.invoices.length"
|
||||
t-att-aria-valuenow="state.successfullySent">
|
||||
<div class="bg-primary h-100"
|
||||
t-att-style="'width: min(' + 100 * state.successfullySent / props.invoices.length + '%, 100%)'"/>
|
||||
</div>
|
||||
<div class="o_progressbar_value flex-shrink-0 ms-2"
|
||||
t-esc="state.successfullySent + ' / ' + props.invoices.length"/>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
</t>
|
||||
<t t-set-slot="footer">
|
||||
<button t-if="state.error"
|
||||
class="btn btn-primary o-default-button"
|
||||
t-on-click="props.close">
|
||||
OK
|
||||
</button>
|
||||
</t>
|
||||
</Dialog>
|
||||
</t>
|
||||
|
||||
</templates>
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
import { useState } from "@odoo/owl";
|
||||
import { rpc } from "@web/core/network/rpc";
|
||||
import { useService } from "@web/core/utils/hooks";
|
||||
import { _t } from "@web/core/l10n/translation";
|
||||
|
||||
export function useKEProxy({onAllSent}) {
|
||||
onAllSent = onAllSent || (() => {});
|
||||
const state = useState({
|
||||
successfullySent: 0,
|
||||
error: false,
|
||||
message: "",
|
||||
});
|
||||
const orm = useService("orm");
|
||||
const http = useService("http");
|
||||
|
||||
/**
|
||||
* Send each of the invoices provided to the proxy connected to the fiscal device. The proxy should return
|
||||
* details, from each successfully posted invoice, which are propagated back to the account move using the orm
|
||||
* service. Alternatively, the proxy can return an error, in which case the execution of this function should
|
||||
* halt, though the successfully posted invoices are still updated as above.
|
||||
*
|
||||
* @param Array<Object> invoices array representing serialised invoice data and the proxy address to send each invoice to.
|
||||
*/
|
||||
async function postInvoices(invoices) {
|
||||
|
||||
// Ping the server to prevent posting to the device when there is no connection to the odoo server
|
||||
try {
|
||||
await rpc("/web/webclient/version_info", {});
|
||||
} catch (e) {
|
||||
// Allow the default error handler to execute after displaying an error message in the dialog
|
||||
state.message = _t("Connection lost, please try again later.");
|
||||
state.error = true;
|
||||
throw e;
|
||||
}
|
||||
let progress; // keep track of when an error occurs
|
||||
for (const index in invoices) {
|
||||
let { move_id, messages, proxy_address, company_vat, name } = invoices[index];
|
||||
state.message = _t("Posting invoice: %s", name);
|
||||
try {
|
||||
progress = 'postToDevice';
|
||||
let deviceResponse = await http.post(
|
||||
proxy_address + '/hw_proxy/l10n_ke_cu_send', {
|
||||
messages: messages,
|
||||
company_vat: company_vat,
|
||||
},
|
||||
);
|
||||
progress = 'parseResponse';
|
||||
if (deviceResponse.status === "ok") {
|
||||
progress = 'updateInvoice'
|
||||
deviceResponse.move_id = move_id;
|
||||
await orm.call("account.move", "l10n_ke_cu_responses", [[], [deviceResponse]]);
|
||||
state.successfullySent++;
|
||||
} else {
|
||||
throw new Error(deviceResponse.status)
|
||||
}
|
||||
} catch (e) {
|
||||
state.error = true;
|
||||
switch (progress) {
|
||||
case 'postToDevice':
|
||||
state.message = _t("Error trying to connect to the middleware. Is the middleware running? \n Error message: %s", e.message);
|
||||
break;
|
||||
case 'parseResponse':
|
||||
state.message = _t("Posting the invoice %s has failed with the message: \n %s", name, e.message);
|
||||
break;
|
||||
case 'updateInvoice':
|
||||
state.message = _t("Error trying to connect to Odoo. Check your internet connection. Error message: %s", e.message);
|
||||
break;
|
||||
default:
|
||||
state.message = _t("Unexpected Error:\n %s", e.message);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (state.successfullySent == invoices.length) {
|
||||
onAllSent();
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
postInvoices,
|
||||
state,
|
||||
};
|
||||
}
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
odoo.define('l10n_ke_edi_tremol.action_post_send_invoice', function (require) {
|
||||
const core = require('web.core');
|
||||
const ajax = require('web.ajax');
|
||||
const Dialog = require('web.Dialog');
|
||||
var rpc = require('web.rpc');
|
||||
var _t = core._t;
|
||||
|
||||
async function post_send(parent, {params}) {
|
||||
let refresh = false;
|
||||
for (let move_id in params.invoices) {
|
||||
try {
|
||||
const res = await ajax.post(
|
||||
params.invoices[move_id].proxy_address + '/hw_proxy/l10n_ke_cu_send', {
|
||||
messages: params.invoices[move_id].messages,
|
||||
company_vat: params.invoices[move_id].company_vat
|
||||
}
|
||||
);
|
||||
const res_obj = JSON.parse(res);
|
||||
if (res_obj.status === "ok") {
|
||||
try {
|
||||
await rpc.query({
|
||||
model: 'account.move',
|
||||
method: 'l10n_ke_cu_response',
|
||||
args: [[], {'replies': res_obj.replies, 'serial_number': res_obj.serial_number, 'move_id': move_id}],
|
||||
});
|
||||
refresh = true;
|
||||
} catch (_e) {
|
||||
Dialog.alert(this, _t("Error trying to connect to Odoo. Check your internet connection"));
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
Dialog.alert(this, _t("Posting an invoice has failed, with the message: \n") + res_obj.status);
|
||||
break;
|
||||
}
|
||||
} catch(_e) {
|
||||
Dialog.alert(this, _t("Error trying to connect to the middleware. Is the middleware running?"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (refresh) {
|
||||
parent.services.action.doAction({
|
||||
'type': 'ir.actions.client',
|
||||
'tag': 'reload',
|
||||
});
|
||||
}
|
||||
}
|
||||
core.action_registry.add('post_send', post_send);
|
||||
return post_send;
|
||||
});
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
from .import test_move_export
|
||||
from . import test_account_move_send
|
||||
from . import test_move_export
|
||||
|
|
|
|||
|
|
@ -0,0 +1,50 @@
|
|||
from datetime import timedelta
|
||||
|
||||
from odoo import fields
|
||||
from odoo.exceptions import UserError
|
||||
from odoo.tests import tagged
|
||||
from odoo.addons.account.tests.test_account_move_send import TestAccountMoveSendCommon
|
||||
|
||||
|
||||
@tagged('post_install_l10n', 'post_install', '-at_install')
|
||||
class TestKEAccountMoveSend(TestAccountMoveSendCommon):
|
||||
|
||||
@classmethod
|
||||
@TestAccountMoveSendCommon.setup_country('ke')
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
|
||||
def test_sent_to_fiscal_device(self):
|
||||
invoice = self.init_invoice("out_invoice", amounts=[1000], post=True, partner=self.partner_a)
|
||||
# Write data as if the invoice was successfully sent to fiscal device
|
||||
invoice.write({
|
||||
'l10n_ke_cu_invoice_number': 'test_ke_invoice_number',
|
||||
'l10n_ke_cu_serial_number': 'test_ke_serial_number',
|
||||
'l10n_ke_cu_qrcode': 'test_ke_qrcode',
|
||||
'l10n_ke_cu_datetime': fields.Datetime.now() - timedelta(days=1),
|
||||
})
|
||||
|
||||
wizard = self.create_send_and_print(invoice)
|
||||
self.assertFalse(wizard.alerts)
|
||||
wizard.action_send_and_print()
|
||||
|
||||
self.assertTrue(invoice.invoice_pdf_report_id)
|
||||
|
||||
def test_not_sent_to_fiscal_device_but_allow_fallback(self):
|
||||
invoice = self.init_invoice("out_invoice", amounts=[1000], post=True, partner=self.partner_a)
|
||||
wizard = self.create_send_and_print(invoice)
|
||||
self.assertTrue('l10n_ke_edi_tremol_warning_moves' in wizard.alerts)
|
||||
wizard.action_send_and_print(allow_fallback_pdf=True)
|
||||
|
||||
# The PDF is not generated but a proforma.
|
||||
self.assertFalse(invoice.invoice_pdf_report_id)
|
||||
self.assertTrue(self.env['ir.attachment'].search([
|
||||
('name', '=', invoice._get_invoice_proforma_pdf_report_filename()),
|
||||
]))
|
||||
|
||||
def test_not_sent_to_fiscal_device_raises(self):
|
||||
invoice = self.init_invoice("out_invoice", amounts=[1000], post=True, partner=self.partner_a)
|
||||
wizard = self.create_send_and_print(invoice)
|
||||
self.assertTrue('l10n_ke_edi_tremol_warning_moves' in wizard.alerts)
|
||||
with self.assertRaisesRegex(UserError, wizard._get_l10n_ke_edi_tremol_warning_message(invoice)):
|
||||
wizard.action_send_and_print()
|
||||
|
|
@ -9,8 +9,9 @@ from freezegun import freeze_time
|
|||
class TestKeMoveExport(AccountTestInvoicingCommon):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls, chart_template_ref='l10n_ke.l10nke_chart_template'):
|
||||
super().setUpClass(chart_template_ref=chart_template_ref)
|
||||
@AccountTestInvoicingCommon.setup_country('ke')
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
|
||||
cls.partner_a.write({
|
||||
'name': 'Sirius Cybernetics Corporation',
|
||||
|
|
@ -24,14 +25,13 @@ class TestKeMoveExport(AccountTestInvoicingCommon):
|
|||
|
||||
cls.product_a.write({
|
||||
'name': 'Infinite Improbability Drive',
|
||||
'l10n_ke_hsn_code': '0039.11.53',
|
||||
'l10n_ke_hsn_name': 'Spacecraft including satellites and suborbital and spacecraft launch vehicles'
|
||||
})
|
||||
|
||||
cls.standard_rate_tax = cls.env['account.tax'].create({
|
||||
'name': '16% tax',
|
||||
'amount': 16.0,
|
||||
cls.spaceship_tax = cls.env['account.tax'].create({
|
||||
'name': 'Exempt Spaceship tax',
|
||||
'amount': 0,
|
||||
'amount_type': 'percent',
|
||||
'l10n_ke_item_code_id': cls.env.ref('l10n_ke.item_code_2023_00391153').id,
|
||||
})
|
||||
|
||||
@classmethod
|
||||
|
|
@ -66,7 +66,7 @@ class TestKeMoveExport(AccountTestInvoicingCommon):
|
|||
'product_id': self.product_a.id,
|
||||
'quantity': 10,
|
||||
'price_unit': 1234.56,
|
||||
'tax_ids': [(6, 0, [self.company_data['company'].account_sale_tax_id.id])],
|
||||
'tax_ids': [(6, 0, [self.spaceship_tax.id])],
|
||||
'discount': 25,
|
||||
}),
|
||||
],
|
||||
|
|
@ -75,9 +75,13 @@ class TestKeMoveExport(AccountTestInvoicingCommon):
|
|||
generated_messages = simple_invoice._l10n_ke_get_cu_messages()
|
||||
expected_sale_line = self.line_dict_to_bytes({
|
||||
'name': b'Infinite Improbability Drive ',
|
||||
'price': b'1432.09', # This is the unit price, tax included
|
||||
'price': b'1234.56', # This is the unit price, (though this is tax exempt)
|
||||
'item_code': b'0039.11.53',
|
||||
'item_desc': b'Spacecraft including',
|
||||
'quantity': b'10.0',
|
||||
'discount': b'-25.0%',
|
||||
'vat_rate': b'0.0',
|
||||
'vat_class': b'E',
|
||||
})
|
||||
expected_messages = [
|
||||
# open invoice
|
||||
|
|
|
|||
|
|
@ -8,17 +8,18 @@
|
|||
<field name="arch" type="xml">
|
||||
<xpath expr="//header/button[@name='action_post']" position="after">
|
||||
<field name="l10n_ke_cu_qrcode" invisible="1"/>
|
||||
<field name="l10n_ke_cu_show_send_button" invisible="1"/>
|
||||
<button name="l10n_ke_action_cu_post" type="object"
|
||||
class="oe_highlight"
|
||||
groups="account.group_account_manager"
|
||||
string="Send To Fiscal Device"
|
||||
attrs="{'invisible': ['|', '|', '|', ('country_code', '!=', 'KE'), ('l10n_ke_cu_qrcode', '!=', False), ('state', '!=', 'posted'), ('move_type', 'not in', ['out_invoice', 'out_refund'])]}"/>
|
||||
invisible="not l10n_ke_cu_show_send_button"/>
|
||||
</xpath>
|
||||
<xpath expr="//group[@id='header_right_group']" position="inside">
|
||||
<field name="l10n_ke_cu_invoice_number" attrs="{'invisible': [('country_code', '!=', 'KE')]}" readonly="1"/>
|
||||
<field name="l10n_ke_cu_invoice_number" readonly="1" invisible="country_code != 'KE'"/>
|
||||
</xpath>
|
||||
<notebook position="inside">
|
||||
<page string="Tremol GO3 Fiscal Device" attrs="{'invisible': [('country_code', '!=', 'KE')]}">
|
||||
<page string="Tremol GO3 Fiscal Device" name="page_tremol_go3_fiscal_device" invisible="country_code != 'KE'">
|
||||
<group>
|
||||
<group>
|
||||
<field name="l10n_ke_cu_qrcode" widget="url" readonly="1"/>
|
||||
|
|
@ -32,11 +33,11 @@
|
|||
</record>
|
||||
|
||||
<record id="l10n_ke_inherit_account_move_tree_view" model="ir.ui.view">
|
||||
<field name="name">l10n.ke.inherit.account.move.tree</field>
|
||||
<field name="name">l10n.ke.inherit.account.move.list</field>
|
||||
<field name="model">account.move</field>
|
||||
<field name="inherit_id" ref="account.view_out_invoice_tree" />
|
||||
<field name="arch" type="xml">
|
||||
<field name="state" position="after">
|
||||
<field name="status_in_payment" position="after">
|
||||
<field name="l10n_ke_cu_invoice_number" optional="hide"/>
|
||||
</field>
|
||||
</field>
|
||||
|
|
@ -46,7 +47,7 @@
|
|||
<field name="name">Send to fiscal device</field>
|
||||
<field name="model_id" ref="account.model_account_move"/>
|
||||
<field name="binding_model_id" ref="account.model_account_move"/>
|
||||
<field name="binding_view_types">list</field>
|
||||
<field name="binding_view_types">list,kanban</field>
|
||||
<field name="state">code</field>
|
||||
<field name="code">
|
||||
action = records.l10n_ke_action_cu_post()
|
||||
|
|
@ -69,5 +70,3 @@
|
|||
</record>
|
||||
</data>
|
||||
</odoo>
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,33 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<record id="l10n_ke_inherit_product_template_form_view" model="ir.ui.view">
|
||||
|
||||
<field name="name">l10n.ke.inherit.product.template.form.inherit</field>
|
||||
<field name="model">product.template</field>
|
||||
<field name="inherit_id" ref="account.product_template_form_view"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//page[@name='invoicing']//group[@name='accounting']" position="inside">
|
||||
<group name="HS Code" string="HS Code" attrs="{'invisible': [('product_variant_count', '>', 1), ('is_product_variant', '=', False)]}">
|
||||
<field name="l10n_ke_hsn_code"/>
|
||||
<field name="l10n_ke_hsn_name"/>
|
||||
</group>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="l10n_ke_inherit_product_product_form_view" model="ir.ui.view">
|
||||
<field name="name">l10n.ke.inherit.product.product.form</field>
|
||||
<field name="model">product.product</field>
|
||||
<field name="inherit_id" ref="product.product_variant_easy_edit_view"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//sheet" position="inside">
|
||||
<group>
|
||||
<group name="KRA Item Code" string="KRA Item Code">
|
||||
<field name="l10n_ke_hsn_code"/>
|
||||
<field name="l10n_ke_hsn_name"/>
|
||||
</group>
|
||||
</group>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
</odoo>
|
||||
|
|
@ -2,10 +2,10 @@
|
|||
<odoo>
|
||||
<template id="l10n_ke_invoice" inherit_id="account.report_invoice_document">
|
||||
<xpath expr="//div[@id='qrcode']" position="before">
|
||||
<div t-if="o.country_code == 'KE'" id="l10n_ke_control_unit_information" style="page-break-inside:avoid;">
|
||||
<div t-if="o.country_code == 'KE' and o.l10n_ke_cu_invoice_number" id="l10n_ke_control_unit_information" style="page-break-inside:avoid;">
|
||||
<b>Kenyan Fiscal Device Info</b>
|
||||
<div class="row mt-4 mb-4">
|
||||
<div class="col-auto col-3 mw-100 mb-2">
|
||||
<div class="col">
|
||||
<p>
|
||||
<b>Invoice Number: </b><br></br>
|
||||
<span t-field="o.l10n_ke_cu_invoice_number"/>
|
||||
|
|
@ -19,10 +19,10 @@
|
|||
<span t-field="o.l10n_ke_cu_datetime"/>
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-auto col-3 mw-100 mb-2">
|
||||
<div class="col">
|
||||
<p t-if="o.l10n_ke_cu_qrcode">
|
||||
<strong class="text-center">TIMS URL</strong><br/><br/>
|
||||
<img style="display:block;" t-att-src="'/report/barcode/?barcode_type=%s&value=%s&width=%s&height=%s' % ('QR', quote_plus(o.l10n_ke_cu_qrcode), 130, 130)" alt="QR Code"/>
|
||||
<img style="display:block;" t-att-src="'/report/barcode/?barcode_type=%s&value=%s&width=%s&height=%s&quiet=%s' % ('QR', quote_plus(o.l10n_ke_cu_qrcode), 130, 130, 0)" alt="QR Code"/>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -5,27 +5,21 @@
|
|||
<field name="model">res.config.settings</field>
|
||||
<field name="inherit_id" ref="account.res_config_settings_view_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//div[@id='account_vendor_bills']" position="after">
|
||||
<div attrs="{'invisible':[('country_code', '!=', 'KE')]}">
|
||||
<h2>Kenya TIMS Integration</h2>
|
||||
<div class="row mt16 o_settings_container" id="l10n_ke_cu_details">
|
||||
<div class="col-12 col-lg-6 o_setting_box">
|
||||
<div class="o_setting_right_pane">
|
||||
<span class="o_form_label">Tremol Device Settings</span>
|
||||
<span class="fa fa-lg fa-building-o" title="Values set here are company-specific." aria-label="Values set here are company-specific." groups="base.group_multi_company" role="img"/>
|
||||
<div class="text-muted">
|
||||
The tremol device makes use of a proxy server, which can be running locally on your computer or on an IoT Box.
|
||||
The proxy server must be on the same network as the fiscal device.
|
||||
</div>
|
||||
<xpath expr="//block[@id='account_vendor_bills']" position="after">
|
||||
<div invisible="country_code != 'KE'">
|
||||
<block title="Kenya TIMS Integration" id="l10n_ke_cu_details">
|
||||
<setting
|
||||
string="Tremol Device Settings"
|
||||
help="The tremol device makes use of a proxy server, which can be running locally on your computer or on an IoT Box. The proxy server must be on the same network as the fiscal device."
|
||||
company_dependent="1">
|
||||
<div class="content-group">
|
||||
<div class="row mt8">
|
||||
<label for="l10n_ke_cu_proxy_address" class="col-lg-5 o_light_label"/>
|
||||
<field name="l10n_ke_cu_proxy_address"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</setting>
|
||||
</block>
|
||||
</div>
|
||||
</xpath>
|
||||
</field>
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
<field name="model">res.partner</field>
|
||||
<field name="inherit_id" ref="account.view_partner_property_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<group name="accounting_entries" position="after">
|
||||
<group name="general" position="after">
|
||||
<group string="Kenya Accounting Details" name="l10n_ke_details">
|
||||
<field name="l10n_ke_exemption_number"/>
|
||||
</group>
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
from . import account_move_send_wizard
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
from odoo import models
|
||||
from odoo.exceptions import UserError
|
||||
|
||||
|
||||
class AccountMoveSendWizard(models.TransientModel):
|
||||
_inherit = 'account.move.send.wizard'
|
||||
|
||||
def action_send_and_print(self, allow_fallback_pdf=False):
|
||||
# EXTENDS account - prevent Send & Print if KE invoices aren't validated and no fallback is allowed.
|
||||
self.ensure_one()
|
||||
if not allow_fallback_pdf:
|
||||
if warning_moves := self._get_l10n_ke_edi_tremol_warning_moves(self.move_id):
|
||||
raise UserError(self._get_l10n_ke_edi_tremol_warning_message(warning_moves))
|
||||
return super().action_send_and_print(allow_fallback_pdf=allow_fallback_pdf)
|
||||
|
|
@ -2,13 +2,13 @@
|
|||
name = "odoo-bringout-oca-ocb-l10n_ke_edi_tremol"
|
||||
version = "16.0.0"
|
||||
description = "Kenya Tremol Device EDI Integration -
|
||||
Kenya Tremol Device EDI Integration
|
||||
Kenya Tremol Device EDI Integration
|
||||
"
|
||||
authors = [
|
||||
{ name = "Ernad Husremovic", email = "hernad@bring.out.ba" }
|
||||
]
|
||||
dependencies = [
|
||||
"odoo-bringout-oca-ocb-l10n_ke>=16.0.0",
|
||||
"odoo-bringout-oca-ocb-l10n_ke>=19.0.0",
|
||||
"requests>=2.25.1"
|
||||
]
|
||||
readme = "README.md"
|
||||
|
|
@ -18,7 +18,7 @@ classifiers = [
|
|||
"Intended Audience :: Developers",
|
||||
"License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
"Topic :: Office/Business",
|
||||
]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue