Ecocentral/ecocentral#172: migrate purchase_rappel to 18.0
This commit is contained in:
parent
1d6747e703
commit
a754df3914
24 changed files with 1588 additions and 0 deletions
40
purchase_rappel/README.md
Normal file
40
purchase_rappel/README.md
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
# Purchase Rappel Commission
|
||||
|
||||
This module allows managing **rappel commission invoices** for vendors.
|
||||
|
||||
## Features
|
||||
|
||||
- Configure a rappel commission rate per vendor.
|
||||
- Automatically mark vendor bills as "pending commission".
|
||||
- Generate customer (sale) invoices from selected vendor bills via a wizard.
|
||||
- Group invoices by vendor and compute commission amounts based on the taxable base.
|
||||
|
||||
## Configuration
|
||||
|
||||
Go to **Purchase > Configuration > Settings > Invoicing** and set:
|
||||
|
||||
- **Rappel Journal**: Sales journal where rappel commission invoices will be posted.
|
||||
- **Commission Product**: Product used as invoice line in rappel commission invoices (should have an income account and taxes configured).
|
||||
|
||||
Open a vendor contact and go to the **Sales & Purchases** tab:
|
||||
|
||||
- Enable **Rappel Commission**.
|
||||
- Set the **Commission Rate (%)** (e.g., 5.00).
|
||||
|
||||
## Usage
|
||||
|
||||
When a vendor bill is created for a partner with rappel enabled, the bill is automatically marked as **Pending Commission**. This flag is visible in the vendor bill list and form views.
|
||||
|
||||
To generate rappel invoices:
|
||||
|
||||
1. Go to **Invoicing > Vendors > Bills**.
|
||||
2. Select one or more posted vendor bills with pending commission.
|
||||
3. Click **Action > Create Rappel Commission Invoice**.
|
||||
4. In the wizard, confirm the **Invoice Date**, **Journal**, and **Product**.
|
||||
5. Click **Create Rappel Invoice(s)**.
|
||||
|
||||
The system will create one sale invoice per vendor, with one line per original bill. The commission amount is computed as:
|
||||
|
||||
taxable_base × commission_rate / 100
|
||||
|
||||
The original vendor bills are automatically unmarked as pending.
|
||||
4
purchase_rappel/__init__.py
Normal file
4
purchase_rappel/__init__.py
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
# Copyright 2024 Criptomart
|
||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
||||
from . import models
|
||||
from . import wizard
|
||||
22
purchase_rappel/__manifest__.py
Normal file
22
purchase_rappel/__manifest__.py
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
# Copyright 2024 Criptomart
|
||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
||||
|
||||
{
|
||||
"name": "Purchase Rappel Commission",
|
||||
"version": "18.0.1.0.0",
|
||||
"summary": "Manage rappel commission invoices for vendors",
|
||||
"category": "Purchase",
|
||||
"author": "Criptomart",
|
||||
"website": "https://criptomart.net",
|
||||
"license": "AGPL-3",
|
||||
"depends": ["purchase", "account"],
|
||||
"data": [
|
||||
"security/ir.model.access.csv",
|
||||
"wizard/account_move_rappel_wizard_views.xml",
|
||||
"views/res_partner_views.xml",
|
||||
"views/res_config_settings_views.xml",
|
||||
"views/account_move_views.xml",
|
||||
],
|
||||
"installable": True,
|
||||
"application": False,
|
||||
}
|
||||
167
purchase_rappel/i18n/ca.po
Normal file
167
purchase_rappel/i18n/ca.po
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
# Translation of Odoo Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * purchase_rappel
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Odoo Server 17.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-06-12 10:00+0000\n"
|
||||
"PO-Revision-Date: 2024-06-12 10:00+0000\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: \n"
|
||||
"Language: ca\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: \n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model:ir.model.fields,field_description:purchase_rappel.field_res_company__rappel_journal_id
|
||||
#: model:ir.model.fields,field_description:purchase_rappel.field_res_config_settings__rappel_journal_id
|
||||
msgid "Rappel Journal"
|
||||
msgstr "Diari de Rappel"
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model:ir.model.fields,help:purchase_rappel.field_res_company__rappel_journal_id
|
||||
#: model:ir.model.fields,help:purchase_rappel.field_res_config_settings__rappel_journal_id
|
||||
msgid "Sales journal used to post rappel commission invoices."
|
||||
msgstr "Diari de vendes utilitzat per registrar les factures de comissió per rappel."
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model:ir.model.fields,field_description:purchase_rappel.field_res_company__rappel_product_id
|
||||
#: model:ir.model.fields,field_description:purchase_rappel.field_res_config_settings__rappel_product_id
|
||||
#: model:ir.model.fields,field_description:purchase_rappel.field_account_move_rappel_wizard__product_id
|
||||
msgid "Commission Product"
|
||||
msgstr "Producte de Comissió"
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model:ir.model.fields,help:purchase_rappel.field_res_company__rappel_product_id
|
||||
#: model:ir.model.fields,help:purchase_rappel.field_res_config_settings__rappel_product_id
|
||||
msgid "Product used as invoice line in rappel commission invoices."
|
||||
msgstr "Producte utilitzat com a línia de factura en les factures de comissió per rappel."
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model:ir.model.fields,field_description:purchase_rappel.field_res_partner__rappel_commission
|
||||
#: model_terms:ir.ui.view,arch_db:purchase_rappel.view_partner_form_rappel
|
||||
#: model_terms:ir.ui.view,arch_db:purchase_rappel.res_config_settings_view_form_rappel
|
||||
msgid "Rappel Commission"
|
||||
msgstr "Comissió per Rappel"
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model:ir.model.fields,help:purchase_rappel.field_res_partner__rappel_commission
|
||||
msgid "If enabled, vendor bills from this partner will be eligible for rappel commission invoicing."
|
||||
msgstr "Si està activat, les factures de proveïdor d'aquest contacte seran elegibles per a la facturació de comissió per rappel."
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model:ir.model.fields,field_description:purchase_rappel.field_res_partner__rappel_commission_rate
|
||||
msgid "Commission Rate (%)"
|
||||
msgstr "Taxa de Comissió (%)"
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model:ir.model.fields,help:purchase_rappel.field_res_partner__rappel_commission_rate
|
||||
msgid "Percentage applied on the taxable base of vendor bills to calculate the rappel commission amount."
|
||||
msgstr "Percentatge aplicat sobre la base imposable de les factures de proveïdor per calcular l'import de la comissió per rappel."
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model:ir.model.fields,field_description:purchase_rappel.field_account_move__rappel_pending
|
||||
#: model_terms:ir.ui.view,arch_db:purchase_rappel.view_account_invoice_filter_rappel
|
||||
msgid "Pending Commission"
|
||||
msgstr "Pendent de Comissió"
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model:ir.model.fields,help:purchase_rappel.field_account_move__rappel_pending
|
||||
msgid "Indicates that this vendor bill has not yet been included in a rappel commission invoice. Automatically set based on the vendor's configuration."
|
||||
msgstr "Indica que aquesta factura de proveïdor encara no ha estat inclosa en una factura de comissió per rappel. S'estableix automàticament segons la configuració del proveïdor."
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model:ir.model,name:purchase_rappel.model_account_move_rappel_wizard
|
||||
#: model_terms:ir.ui.view,arch_db:purchase_rappel.view_account_move_rappel_wizard_form
|
||||
msgid "Create Rappel Commission Invoice"
|
||||
msgstr "Crear Factura de Comissió per Rappel"
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model:ir.model.fields,field_description:purchase_rappel.field_account_move_rappel_wizard__move_ids
|
||||
#: model_terms:ir.ui.view,arch_db:purchase_rappel.view_account_move_rappel_wizard_form
|
||||
msgid "Vendor Bills"
|
||||
msgstr "Factures de Proveïdor"
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model:ir.model.fields,field_description:purchase_rappel.field_account_move_rappel_wizard__invoice_date
|
||||
msgid "Invoice Date"
|
||||
msgstr "Data de Factura"
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model:ir.model.fields,field_description:purchase_rappel.field_account_move_rappel_wizard__journal_id
|
||||
msgid "Journal"
|
||||
msgstr "Diari"
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: code:addons/purchase_rappel/wizard/account_move_rappel_wizard.py:0
|
||||
msgid "No posted vendor bills found in the selection. Only posted (validated) vendor bills can be used to create rappel commission invoices."
|
||||
msgstr "No s'han trobat factures de proveïdor comptabilitzades en la selecció. Només les factures de proveïdor comptabilitzades (validades) es poden fer servir per crear factures de comissió per rappel."
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: code:addons/purchase_rappel/wizard/account_move_rappel_wizard.py:0
|
||||
msgid "None of the selected vendor bills are pending commission. They may have already been commissioned."
|
||||
msgstr "Cap de les factures de proveïdor seleccionades està pendent de comissió. Pot ser que ja hagin estat comissionades."
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: code:addons/purchase_rappel/wizard/account_move_rappel_wizard.py:0
|
||||
msgid "None of the selected vendors have the rappel commission enabled. Please configure the commission rate on the vendor contact first."
|
||||
msgstr "Cap dels proveïdors seleccionats té la comissió per rappel activada. Configureu primer la taxa de comissió en el contacte del proveïdor."
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: code:addons/purchase_rappel/wizard/account_move_rappel_wizard.py:0
|
||||
msgid "Please select a journal for the rappel commission invoices, or configure a default one in Purchase Settings."
|
||||
msgstr "Seleccioneu un diari per a les factures de comissió per rappel, o configureu-ne un per defecte en els Ajustos de Compres."
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: code:addons/purchase_rappel/wizard/account_move_rappel_wizard.py:0
|
||||
msgid "Please select a product for the rappel commission invoices, or configure a default one in Purchase Settings."
|
||||
msgstr "Seleccioneu un producte per a les factures de comissió per rappel, o configureu-ne un per defecte en els Ajustos de Compres."
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: code:addons/purchase_rappel/wizard/account_move_rappel_wizard.py:0
|
||||
msgid "None of the selected vendor bills belong to vendors with a rappel commission rate configured."
|
||||
msgstr "Cap de les factures de proveïdor seleccionades pertany a proveïdors amb una taxa de comissió per rappel configurada."
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: code:addons/purchase_rappel/wizard/account_move_rappel_wizard.py:0
|
||||
msgid "Rappel commission %(rate)s%% — Bill %(bill)s (taxable base: %(base)s %(currency)s)"
|
||||
msgstr "Comissió per rappel %(rate)s%% — Factura %(bill)s (base imposable: %(base)s %(currency)s)"
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: code:addons/purchase_rappel/wizard/account_move_rappel_wizard.py:0
|
||||
msgid "Rappel commission invoice generated from %d vendor bill(s)."
|
||||
msgstr "Factura de comissió per rappel generada a partir de %d factura(es) de proveïdor."
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model:ir.actions.act_window,name:purchase_rappel.action_open_rappel_wizard
|
||||
msgid "Rappel Commission Invoices"
|
||||
msgstr "Factures de Comissió per Rappel"
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model_terms:ir.ui.view,arch_db:purchase_rappel.res_config_settings_view_form_rappel
|
||||
msgid "Configure the journal and product for rappel commission invoices"
|
||||
msgstr "Configureu el diari i el producte per a les factures de comissió per rappel"
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model_terms:ir.ui.view,arch_db:purchase_rappel.view_account_invoice_filter_rappel
|
||||
msgid "Vendor bills not yet included in a rappel commission invoice"
|
||||
msgstr "Factures de proveïdor que encara no estan incloses en una factura de comissió per rappel"
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model_terms:ir.ui.view,arch_db:purchase_rappel.view_account_move_rappel_wizard_form
|
||||
msgid "Taxable Base"
|
||||
msgstr "Base Imposable"
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model_terms:ir.ui.view,arch_db:purchase_rappel.view_account_move_rappel_wizard_form
|
||||
msgid "Create Rappel Invoice(s)"
|
||||
msgstr "Crear Factura(es) de Rappel"
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model_terms:ir.ui.view,arch_db:purchase_rappel.view_account_move_rappel_wizard_form
|
||||
msgid "Cancel"
|
||||
msgstr "Cancel·lar"
|
||||
167
purchase_rappel/i18n/es.po
Normal file
167
purchase_rappel/i18n/es.po
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
# Translation of Odoo Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * purchase_rappel
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Odoo Server 17.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-06-12 10:00+0000\n"
|
||||
"PO-Revision-Date: 2024-06-12 10:00+0000\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: \n"
|
||||
"Language: es\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: \n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model:ir.model.fields,field_description:purchase_rappel.field_res_company__rappel_journal_id
|
||||
#: model:ir.model.fields,field_description:purchase_rappel.field_res_config_settings__rappel_journal_id
|
||||
msgid "Rappel Journal"
|
||||
msgstr "Diario de Rappel"
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model:ir.model.fields,help:purchase_rappel.field_res_company__rappel_journal_id
|
||||
#: model:ir.model.fields,help:purchase_rappel.field_res_config_settings__rappel_journal_id
|
||||
msgid "Sales journal used to post rappel commission invoices."
|
||||
msgstr "Diario de ventas utilizado para registrar las facturas de comisión por rappel."
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model:ir.model.fields,field_description:purchase_rappel.field_res_company__rappel_product_id
|
||||
#: model:ir.model.fields,field_description:purchase_rappel.field_res_config_settings__rappel_product_id
|
||||
#: model:ir.model.fields,field_description:purchase_rappel.field_account_move_rappel_wizard__product_id
|
||||
msgid "Commission Product"
|
||||
msgstr "Producto de Comisión"
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model:ir.model.fields,help:purchase_rappel.field_res_company__rappel_product_id
|
||||
#: model:ir.model.fields,help:purchase_rappel.field_res_config_settings__rappel_product_id
|
||||
msgid "Product used as invoice line in rappel commission invoices."
|
||||
msgstr "Producto utilizado como línea de factura en las facturas de comisión por rappel."
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model:ir.model.fields,field_description:purchase_rappel.field_res_partner__rappel_commission
|
||||
#: model_terms:ir.ui.view,arch_db:purchase_rappel.view_partner_form_rappel
|
||||
#: model_terms:ir.ui.view,arch_db:purchase_rappel.res_config_settings_view_form_rappel
|
||||
msgid "Rappel Commission"
|
||||
msgstr "Comisión por Rappel"
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model:ir.model.fields,help:purchase_rappel.field_res_partner__rappel_commission
|
||||
msgid "If enabled, vendor bills from this partner will be eligible for rappel commission invoicing."
|
||||
msgstr "Si está activado, las facturas de proveedor de este contacto serán elegibles para la facturación de comisión por rappel."
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model:ir.model.fields,field_description:purchase_rappel.field_res_partner__rappel_commission_rate
|
||||
msgid "Commission Rate (%)"
|
||||
msgstr "Tasa de Comisión (%)"
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model:ir.model.fields,help:purchase_rappel.field_res_partner__rappel_commission_rate
|
||||
msgid "Percentage applied on the taxable base of vendor bills to calculate the rappel commission amount."
|
||||
msgstr "Porcentaje aplicado sobre la base imponible de las facturas de proveedor para calcular el importe de la comisión por rappel."
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model:ir.model.fields,field_description:purchase_rappel.field_account_move__rappel_pending
|
||||
#: model_terms:ir.ui.view,arch_db:purchase_rappel.view_account_invoice_filter_rappel
|
||||
msgid "Pending Commission"
|
||||
msgstr "Pendiente de Comisión"
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model:ir.model.fields,help:purchase_rappel.field_account_move__rappel_pending
|
||||
msgid "Indicates that this vendor bill has not yet been included in a rappel commission invoice. Automatically set based on the vendor's configuration."
|
||||
msgstr "Indica que esta factura de proveedor aún no ha sido incluida en una factura de comisión por rappel. Se establece automáticamente según la configuración del proveedor."
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model:ir.model,name:purchase_rappel.model_account_move_rappel_wizard
|
||||
#: model_terms:ir.ui.view,arch_db:purchase_rappel.view_account_move_rappel_wizard_form
|
||||
msgid "Create Rappel Commission Invoice"
|
||||
msgstr "Crear Factura de Comisión por Rappel"
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model:ir.model.fields,field_description:purchase_rappel.field_account_move_rappel_wizard__move_ids
|
||||
#: model_terms:ir.ui.view,arch_db:purchase_rappel.view_account_move_rappel_wizard_form
|
||||
msgid "Vendor Bills"
|
||||
msgstr "Facturas de Proveedor"
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model:ir.model.fields,field_description:purchase_rappel.field_account_move_rappel_wizard__invoice_date
|
||||
msgid "Invoice Date"
|
||||
msgstr "Fecha de Factura"
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model:ir.model.fields,field_description:purchase_rappel.field_account_move_rappel_wizard__journal_id
|
||||
msgid "Journal"
|
||||
msgstr "Diario"
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: code:addons/purchase_rappel/wizard/account_move_rappel_wizard.py:0
|
||||
msgid "No posted vendor bills found in the selection. Only posted (validated) vendor bills can be used to create rappel commission invoices."
|
||||
msgstr "No se encontraron facturas de proveedor contabilizadas en la selección. Solo las facturas de proveedor contabilizadas (validadas) pueden usarse para crear facturas de comisión por rappel."
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: code:addons/purchase_rappel/wizard/account_move_rappel_wizard.py:0
|
||||
msgid "None of the selected vendor bills are pending commission. They may have already been commissioned."
|
||||
msgstr "Ninguna de las facturas de proveedor seleccionadas está pendiente de comisión. Puede que ya hayan sido comisionadas."
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: code:addons/purchase_rappel/wizard/account_move_rappel_wizard.py:0
|
||||
msgid "None of the selected vendors have the rappel commission enabled. Please configure the commission rate on the vendor contact first."
|
||||
msgstr "Ninguno de los proveedores seleccionados tiene la comisión por rappel activada. Configure primero la tasa de comisión en el contacto del proveedor."
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: code:addons/purchase_rappel/wizard/account_move_rappel_wizard.py:0
|
||||
msgid "Please select a journal for the rappel commission invoices, or configure a default one in Purchase Settings."
|
||||
msgstr "Seleccione un diario para las facturas de comisión por rappel, o configure uno por defecto en los Ajustes de Compras."
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: code:addons/purchase_rappel/wizard/account_move_rappel_wizard.py:0
|
||||
msgid "Please select a product for the rappel commission invoices, or configure a default one in Purchase Settings."
|
||||
msgstr "Seleccione un producto para las facturas de comisión por rappel, o configure uno por defecto en los Ajustes de Compras."
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: code:addons/purchase_rappel/wizard/account_move_rappel_wizard.py:0
|
||||
msgid "None of the selected vendor bills belong to vendors with a rappel commission rate configured."
|
||||
msgstr "Ninguna de las facturas de proveedor seleccionadas pertenece a proveedores con una tasa de comisión por rappel configurada."
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: code:addons/purchase_rappel/wizard/account_move_rappel_wizard.py:0
|
||||
msgid "Rappel commission %(rate)s%% — Bill %(bill)s (taxable base: %(base)s %(currency)s)"
|
||||
msgstr "Comisión por rappel %(rate)s%% — Factura %(bill)s (base imponible: %(base)s %(currency)s)"
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: code:addons/purchase_rappel/wizard/account_move_rappel_wizard.py:0
|
||||
msgid "Rappel commission invoice generated from %d vendor bill(s)."
|
||||
msgstr "Factura de comisión por rappel generada a partir de %d factura(s) de proveedor."
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model:ir.actions.act_window,name:purchase_rappel.action_open_rappel_wizard
|
||||
msgid "Rappel Commission Invoices"
|
||||
msgstr "Facturas de Comisión por Rappel"
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model_terms:ir.ui.view,arch_db:purchase_rappel.res_config_settings_view_form_rappel
|
||||
msgid "Configure the journal and product for rappel commission invoices"
|
||||
msgstr "Configure el diario y el producto para las facturas de comisión por rappel"
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model_terms:ir.ui.view,arch_db:purchase_rappel.view_account_invoice_filter_rappel
|
||||
msgid "Vendor bills not yet included in a rappel commission invoice"
|
||||
msgstr "Facturas de proveedor que aún no están incluidas en una factura de comisión por rappel"
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model_terms:ir.ui.view,arch_db:purchase_rappel.view_account_move_rappel_wizard_form
|
||||
msgid "Taxable Base"
|
||||
msgstr "Base Imponible"
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model_terms:ir.ui.view,arch_db:purchase_rappel.view_account_move_rappel_wizard_form
|
||||
msgid "Create Rappel Invoice(s)"
|
||||
msgstr "Crear Factura(s) de Rappel"
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model_terms:ir.ui.view,arch_db:purchase_rappel.view_account_move_rappel_wizard_form
|
||||
msgid "Cancel"
|
||||
msgstr "Cancelar"
|
||||
167
purchase_rappel/i18n/gl.po
Normal file
167
purchase_rappel/i18n/gl.po
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
# Translation of Odoo Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * purchase_rappel
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Odoo Server 17.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-06-12 10:00+0000\n"
|
||||
"PO-Revision-Date: 2024-06-12 10:00+0000\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: \n"
|
||||
"Language: gl\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: \n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model:ir.model.fields,field_description:purchase_rappel.field_res_company__rappel_journal_id
|
||||
#: model:ir.model.fields,field_description:purchase_rappel.field_res_config_settings__rappel_journal_id
|
||||
msgid "Rappel Journal"
|
||||
msgstr "Diario de Rappel"
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model:ir.model.fields,help:purchase_rappel.field_res_company__rappel_journal_id
|
||||
#: model:ir.model.fields,help:purchase_rappel.field_res_config_settings__rappel_journal_id
|
||||
msgid "Sales journal used to post rappel commission invoices."
|
||||
msgstr "Diario de vendas utilizado para rexistrar as facturas de comisión por rappel."
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model:ir.model.fields,field_description:purchase_rappel.field_res_company__rappel_product_id
|
||||
#: model:ir.model.fields,field_description:purchase_rappel.field_res_config_settings__rappel_product_id
|
||||
#: model:ir.model.fields,field_description:purchase_rappel.field_account_move_rappel_wizard__product_id
|
||||
msgid "Commission Product"
|
||||
msgstr "Produto de Comisión"
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model:ir.model.fields,help:purchase_rappel.field_res_company__rappel_product_id
|
||||
#: model:ir.model.fields,help:purchase_rappel.field_res_config_settings__rappel_product_id
|
||||
msgid "Product used as invoice line in rappel commission invoices."
|
||||
msgstr "Produto utilizado como liña de factura nas facturas de comisión por rappel."
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model:ir.model.fields,field_description:purchase_rappel.field_res_partner__rappel_commission
|
||||
#: model_terms:ir.ui.view,arch_db:purchase_rappel.view_partner_form_rappel
|
||||
#: model_terms:ir.ui.view,arch_db:purchase_rappel.res_config_settings_view_form_rappel
|
||||
msgid "Rappel Commission"
|
||||
msgstr "Comisión por Rappel"
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model:ir.model.fields,help:purchase_rappel.field_res_partner__rappel_commission
|
||||
msgid "If enabled, vendor bills from this partner will be eligible for rappel commission invoicing."
|
||||
msgstr "Se está activado, as facturas de provedor deste contacto serán elixibles para a facturación de comisión por rappel."
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model:ir.model.fields,field_description:purchase_rappel.field_res_partner__rappel_commission_rate
|
||||
msgid "Commission Rate (%)"
|
||||
msgstr "Taxa de Comisión (%)"
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model:ir.model.fields,help:purchase_rappel.field_res_partner__rappel_commission_rate
|
||||
msgid "Percentage applied on the taxable base of vendor bills to calculate the rappel commission amount."
|
||||
msgstr "Porcentaxe aplicado sobre a base imponible das facturas de provedor para calcular o importe da comisión por rappel."
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model:ir.model.fields,field_description:purchase_rappel.field_account_move__rappel_pending
|
||||
#: model_terms:ir.ui.view,arch_db:purchase_rappel.view_account_invoice_filter_rappel
|
||||
msgid "Pending Commission"
|
||||
msgstr "Pendente de Comisión"
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model:ir.model.fields,help:purchase_rappel.field_account_move__rappel_pending
|
||||
msgid "Indicates that this vendor bill has not yet been included in a rappel commission invoice. Automatically set based on the vendor's configuration."
|
||||
msgstr "Indica que esta factura de provedor aínda non foi incluída nunha factura de comisión por rappel. Establécese automaticamente segundo a configuración do provedor."
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model:ir.model,name:purchase_rappel.model_account_move_rappel_wizard
|
||||
#: model_terms:ir.ui.view,arch_db:purchase_rappel.view_account_move_rappel_wizard_form
|
||||
msgid "Create Rappel Commission Invoice"
|
||||
msgstr "Crear Factura de Comisión por Rappel"
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model:ir.model.fields,field_description:purchase_rappel.field_account_move_rappel_wizard__move_ids
|
||||
#: model_terms:ir.ui.view,arch_db:purchase_rappel.view_account_move_rappel_wizard_form
|
||||
msgid "Vendor Bills"
|
||||
msgstr "Facturas de Provedor"
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model:ir.model.fields,field_description:purchase_rappel.field_account_move_rappel_wizard__invoice_date
|
||||
msgid "Invoice Date"
|
||||
msgstr "Data de Factura"
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model:ir.model.fields,field_description:purchase_rappel.field_account_move_rappel_wizard__journal_id
|
||||
msgid "Journal"
|
||||
msgstr "Diario"
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: code:addons/purchase_rappel/wizard/account_move_rappel_wizard.py:0
|
||||
msgid "No posted vendor bills found in the selection. Only posted (validated) vendor bills can be used to create rappel commission invoices."
|
||||
msgstr "Non se atoparon facturas de provedor contabilizadas na selección. Só as facturas de provedor contabilizadas (validadas) poden usarse para crear facturas de comisión por rappel."
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: code:addons/purchase_rappel/wizard/account_move_rappel_wizard.py:0
|
||||
msgid "None of the selected vendor bills are pending commission. They may have already been commissioned."
|
||||
msgstr "Ningunha das facturas de provedor seleccionadas está pendente de comisión. Pode que xa fosen comisionadas."
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: code:addons/purchase_rappel/wizard/account_move_rappel_wizard.py:0
|
||||
msgid "None of the selected vendors have the rappel commission enabled. Please configure the commission rate on the vendor contact first."
|
||||
msgstr "Ningún dos provedores seleccionados ten a comisión por rappel activada. Configure primeiro a taxa de comisión no contacto do provedor."
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: code:addons/purchase_rappel/wizard/account_move_rappel_wizard.py:0
|
||||
msgid "Please select a journal for the rappel commission invoices, or configure a default one in Purchase Settings."
|
||||
msgstr "Seleccione un diario para as facturas de comisión por rappel, ou configure un por defecto nos Axustes de Compras."
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: code:addons/purchase_rappel/wizard/account_move_rappel_wizard.py:0
|
||||
msgid "Please select a product for the rappel commission invoices, or configure a default one in Purchase Settings."
|
||||
msgstr "Seleccione un produto para as facturas de comisión por rappel, ou configure un por defecto nos Axustes de Compras."
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: code:addons/purchase_rappel/wizard/account_move_rappel_wizard.py:0
|
||||
msgid "None of the selected vendor bills belong to vendors with a rappel commission rate configured."
|
||||
msgstr "Ningunha das facturas de provedor seleccionadas pertence a provedores cunha taxa de comisión por rappel configurada."
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: code:addons/purchase_rappel/wizard/account_move_rappel_wizard.py:0
|
||||
msgid "Rappel commission %(rate)s%% — Bill %(bill)s (taxable base: %(base)s %(currency)s)"
|
||||
msgstr "Comisión por rappel %(rate)s%% — Factura %(bill)s (base imponible: %(base)s %(currency)s)"
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: code:addons/purchase_rappel/wizard/account_move_rappel_wizard.py:0
|
||||
msgid "Rappel commission invoice generated from %d vendor bill(s)."
|
||||
msgstr "Factura de comisión por rappel xerada a partir de %d factura(s) de provedor."
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model:ir.actions.act_window,name:purchase_rappel.action_open_rappel_wizard
|
||||
msgid "Rappel Commission Invoices"
|
||||
msgstr "Facturas de Comisión por Rappel"
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model_terms:ir.ui.view,arch_db:purchase_rappel.res_config_settings_view_form_rappel
|
||||
msgid "Configure the journal and product for rappel commission invoices"
|
||||
msgstr "Configure o diario e o produto para as facturas de comisión por rappel"
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model_terms:ir.ui.view,arch_db:purchase_rappel.view_account_invoice_filter_rappel
|
||||
msgid "Vendor bills not yet included in a rappel commission invoice"
|
||||
msgstr "Facturas de provedor que aínda non están incluídas nunha factura de comisión por rappel"
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model_terms:ir.ui.view,arch_db:purchase_rappel.view_account_move_rappel_wizard_form
|
||||
msgid "Taxable Base"
|
||||
msgstr "Base Imponible"
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model_terms:ir.ui.view,arch_db:purchase_rappel.view_account_move_rappel_wizard_form
|
||||
msgid "Create Rappel Invoice(s)"
|
||||
msgstr "Crear Factura(s) de Rappel"
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model_terms:ir.ui.view,arch_db:purchase_rappel.view_account_move_rappel_wizard_form
|
||||
msgid "Cancel"
|
||||
msgstr "Cancelar"
|
||||
166
purchase_rappel/i18n/purchase_rappel.pot
Normal file
166
purchase_rappel/i18n/purchase_rappel.pot
Normal file
|
|
@ -0,0 +1,166 @@
|
|||
# Translation of Odoo Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * purchase_rappel
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Odoo Server 17.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-06-12 10:00+0000\n"
|
||||
"PO-Revision-Date: 2024-06-12 10:00+0000\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: \n"
|
||||
"Plural-Forms: \n"
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model:ir.model.fields,field_description:purchase_rappel.field_res_company__rappel_journal_id
|
||||
#: model:ir.model.fields,field_description:purchase_rappel.field_res_config_settings__rappel_journal_id
|
||||
msgid "Rappel Journal"
|
||||
msgstr ""
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model:ir.model.fields,help:purchase_rappel.field_res_company__rappel_journal_id
|
||||
#: model:ir.model.fields,help:purchase_rappel.field_res_config_settings__rappel_journal_id
|
||||
msgid "Sales journal used to post rappel commission invoices."
|
||||
msgstr ""
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model:ir.model.fields,field_description:purchase_rappel.field_res_company__rappel_product_id
|
||||
#: model:ir.model.fields,field_description:purchase_rappel.field_res_config_settings__rappel_product_id
|
||||
#: model:ir.model.fields,field_description:purchase_rappel.field_account_move_rappel_wizard__product_id
|
||||
msgid "Commission Product"
|
||||
msgstr ""
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model:ir.model.fields,help:purchase_rappel.field_res_company__rappel_product_id
|
||||
#: model:ir.model.fields,help:purchase_rappel.field_res_config_settings__rappel_product_id
|
||||
msgid "Product used as invoice line in rappel commission invoices."
|
||||
msgstr ""
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model:ir.model.fields,field_description:purchase_rappel.field_res_partner__rappel_commission
|
||||
#: model_terms:ir.ui.view,arch_db:purchase_rappel.view_partner_form_rappel
|
||||
#: model_terms:ir.ui.view,arch_db:purchase_rappel.res_config_settings_view_form_rappel
|
||||
msgid "Rappel Commission"
|
||||
msgstr ""
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model:ir.model.fields,help:purchase_rappel.field_res_partner__rappel_commission
|
||||
msgid "If enabled, vendor bills from this partner will be eligible for rappel commission invoicing."
|
||||
msgstr ""
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model:ir.model.fields,field_description:purchase_rappel.field_res_partner__rappel_commission_rate
|
||||
msgid "Commission Rate (%)"
|
||||
msgstr ""
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model:ir.model.fields,help:purchase_rappel.field_res_partner__rappel_commission_rate
|
||||
msgid "Percentage applied on the taxable base of vendor bills to calculate the rappel commission amount."
|
||||
msgstr ""
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model:ir.model.fields,field_description:purchase_rappel.field_account_move__rappel_pending
|
||||
#: model_terms:ir.ui.view,arch_db:purchase_rappel.view_account_invoice_filter_rappel
|
||||
msgid "Pending Commission"
|
||||
msgstr ""
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model:ir.model.fields,help:purchase_rappel.field_account_move__rappel_pending
|
||||
msgid "Indicates that this vendor bill has not yet been included in a rappel commission invoice. Automatically set based on the vendor's configuration."
|
||||
msgstr ""
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model:ir.model,name:purchase_rappel.model_account_move_rappel_wizard
|
||||
#: model_terms:ir.ui.view,arch_db:purchase_rappel.view_account_move_rappel_wizard_form
|
||||
msgid "Create Rappel Commission Invoice"
|
||||
msgstr ""
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model:ir.model.fields,field_description:purchase_rappel.field_account_move_rappel_wizard__move_ids
|
||||
#: model_terms:ir.ui.view,arch_db:purchase_rappel.view_account_move_rappel_wizard_form
|
||||
msgid "Vendor Bills"
|
||||
msgstr ""
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model:ir.model.fields,field_description:purchase_rappel.field_account_move_rappel_wizard__invoice_date
|
||||
msgid "Invoice Date"
|
||||
msgstr ""
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model:ir.model.fields,field_description:purchase_rappel.field_account_move_rappel_wizard__journal_id
|
||||
msgid "Journal"
|
||||
msgstr ""
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: code:addons/purchase_rappel/wizard/account_move_rappel_wizard.py:0
|
||||
msgid "No posted vendor bills found in the selection. Only posted (validated) vendor bills can be used to create rappel commission invoices."
|
||||
msgstr ""
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: code:addons/purchase_rappel/wizard/account_move_rappel_wizard.py:0
|
||||
msgid "None of the selected vendor bills are pending commission. They may have already been commissioned."
|
||||
msgstr ""
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: code:addons/purchase_rappel/wizard/account_move_rappel_wizard.py:0
|
||||
msgid "None of the selected vendors have the rappel commission enabled. Please configure the commission rate on the vendor contact first."
|
||||
msgstr ""
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: code:addons/purchase_rappel/wizard/account_move_rappel_wizard.py:0
|
||||
msgid "Please select a journal for the rappel commission invoices, or configure a default one in Purchase Settings."
|
||||
msgstr ""
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: code:addons/purchase_rappel/wizard/account_move_rappel_wizard.py:0
|
||||
msgid "Please select a product for the rappel commission invoices, or configure a default one in Purchase Settings."
|
||||
msgstr ""
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: code:addons/purchase_rappel/wizard/account_move_rappel_wizard.py:0
|
||||
msgid "None of the selected vendor bills belong to vendors with a rappel commission rate configured."
|
||||
msgstr ""
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: code:addons/purchase_rappel/wizard/account_move_rappel_wizard.py:0
|
||||
msgid "Rappel commission %(rate)s%% — Bill %(bill)s (taxable base: %(base)s %(currency)s)"
|
||||
msgstr ""
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: code:addons/purchase_rappel/wizard/account_move_rappel_wizard.py:0
|
||||
msgid "Rappel commission invoice generated from %d vendor bill(s)."
|
||||
msgstr ""
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model:ir.actions.act_window,name:purchase_rappel.action_open_rappel_wizard
|
||||
msgid "Rappel Commission Invoices"
|
||||
msgstr ""
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model_terms:ir.ui.view,arch_db:purchase_rappel.res_config_settings_view_form_rappel
|
||||
msgid "Configure the journal and product for rappel commission invoices"
|
||||
msgstr ""
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model_terms:ir.ui.view,arch_db:purchase_rappel.view_account_invoice_filter_rappel
|
||||
msgid "Vendor bills not yet included in a rappel commission invoice"
|
||||
msgstr ""
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model_terms:ir.ui.view,arch_db:purchase_rappel.view_account_move_rappel_wizard_form
|
||||
msgid "Taxable Base"
|
||||
msgstr ""
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model_terms:ir.ui.view,arch_db:purchase_rappel.view_account_move_rappel_wizard_form
|
||||
msgid "Create Rappel Invoice(s)"
|
||||
msgstr ""
|
||||
|
||||
#. module: purchase_rappel
|
||||
#: model_terms:ir.ui.view,arch_db:purchase_rappel.view_account_move_rappel_wizard_form
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
6
purchase_rappel/models/__init__.py
Normal file
6
purchase_rappel/models/__init__.py
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
# Copyright 2024 Criptomart
|
||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
||||
from . import res_company
|
||||
from . import res_partner
|
||||
from . import res_config_settings
|
||||
from . import account_move
|
||||
32
purchase_rappel/models/account_move.py
Normal file
32
purchase_rappel/models/account_move.py
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
# Copyright 2024 Criptomart
|
||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
||||
from odoo import api, fields, models
|
||||
|
||||
|
||||
class AccountMove(models.Model):
|
||||
_inherit = "account.move"
|
||||
|
||||
rappel_pending = fields.Boolean(
|
||||
string="Pending Commission",
|
||||
copy=False,
|
||||
help="Indicates that this vendor bill has not yet been included in a rappel "
|
||||
"commission invoice. Automatically set based on the vendor's configuration.",
|
||||
)
|
||||
|
||||
@api.model_create_multi
|
||||
def create(self, vals_list):
|
||||
moves = super().create(vals_list)
|
||||
for move in moves:
|
||||
if (
|
||||
move.move_type in ("in_invoice", "in_refund")
|
||||
and move.partner_id.rappel_commission
|
||||
):
|
||||
move.rappel_pending = True
|
||||
return moves
|
||||
|
||||
@api.onchange("partner_id")
|
||||
def _onchange_partner_id_rappel(self):
|
||||
if self.move_type in ("in_invoice", "in_refund"):
|
||||
self.rappel_pending = bool(
|
||||
self.partner_id and self.partner_id.rappel_commission
|
||||
)
|
||||
19
purchase_rappel/models/res_company.py
Normal file
19
purchase_rappel/models/res_company.py
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
# Copyright 2024 Criptomart
|
||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
||||
from odoo import fields, models
|
||||
|
||||
|
||||
class ResCompany(models.Model):
|
||||
_inherit = "res.company"
|
||||
|
||||
rappel_journal_id = fields.Many2one(
|
||||
comodel_name="account.journal",
|
||||
string="Rappel Journal",
|
||||
domain="[('type', '=', 'sale'), ('company_id', '=', id)]",
|
||||
help="Sales journal used to post rappel commission invoices.",
|
||||
)
|
||||
rappel_product_id = fields.Many2one(
|
||||
comodel_name="product.product",
|
||||
string="Commission Product",
|
||||
help="Product used as invoice line in rappel commission invoices.",
|
||||
)
|
||||
23
purchase_rappel/models/res_config_settings.py
Normal file
23
purchase_rappel/models/res_config_settings.py
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
# Copyright 2024 Criptomart
|
||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
||||
from odoo import api, fields, models
|
||||
|
||||
|
||||
class ResConfigSettings(models.TransientModel):
|
||||
_inherit = "res.config.settings"
|
||||
|
||||
rappel_journal_id = fields.Many2one(
|
||||
comodel_name="account.journal",
|
||||
string="Rappel Journal",
|
||||
related="company_id.rappel_journal_id",
|
||||
domain=[("type", "=", "sale")],
|
||||
readonly=False,
|
||||
help="Sales journal used to post rappel commission invoices.",
|
||||
)
|
||||
rappel_product_id = fields.Many2one(
|
||||
comodel_name="product.product",
|
||||
string="Commission Product",
|
||||
related="company_id.rappel_product_id",
|
||||
readonly=False,
|
||||
help="Product used as invoice line in rappel commission invoices.",
|
||||
)
|
||||
19
purchase_rappel/models/res_partner.py
Normal file
19
purchase_rappel/models/res_partner.py
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
# Copyright 2024 Criptomart
|
||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
||||
from odoo import fields, models
|
||||
|
||||
|
||||
class ResPartner(models.Model):
|
||||
_inherit = "res.partner"
|
||||
|
||||
rappel_commission = fields.Boolean(
|
||||
string="Rappel Commission",
|
||||
help="If enabled, vendor bills from this partner will be eligible for rappel "
|
||||
"commission invoicing.",
|
||||
)
|
||||
rappel_commission_rate = fields.Float(
|
||||
string="Commission Rate (%)",
|
||||
digits=(5, 4),
|
||||
help="Percentage applied on the taxable base of vendor bills to calculate the "
|
||||
"rappel commission amount.",
|
||||
)
|
||||
13
purchase_rappel/readme/CONFIGURE.md
Normal file
13
purchase_rappel/readme/CONFIGURE.md
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
## Company Settings
|
||||
|
||||
Go to **Purchase > Configuration > Settings > Invoicing** and set:
|
||||
|
||||
- **Rappel Journal**: Sales journal where rappel commission invoices will be posted.
|
||||
- **Commission Product**: Product used as invoice line in rappel commission invoices (should have an income account and taxes configured).
|
||||
|
||||
## Vendor Configuration
|
||||
|
||||
Open a vendor contact and go to the **Sales & Purchases** tab:
|
||||
|
||||
- Enable **Rappel Commission**.
|
||||
- Set the **Commission Rate (%)** (e.g., 5.00).
|
||||
7
purchase_rappel/readme/DESCRIPTION.md
Normal file
7
purchase_rappel/readme/DESCRIPTION.md
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
This module allows managing **rappel commission invoices** for vendors.
|
||||
|
||||
Features:
|
||||
- Configure a rappel commission rate per vendor.
|
||||
- Automatically mark vendor bills as "pending commission".
|
||||
- Generate customer (sale) invoices from selected vendor bills via a wizard.
|
||||
- Group invoices by vendor and compute commission amounts based on the taxable base.
|
||||
15
purchase_rappel/readme/USAGE.md
Normal file
15
purchase_rappel/readme/USAGE.md
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
When a vendor bill is created for a partner with rappel enabled, the bill is automatically marked as **Pending Commission**. This flag is visible in the vendor bill list and form views.
|
||||
|
||||
To generate rappel invoices:
|
||||
|
||||
1. Go to **Invoicing > Vendors > Bills**.
|
||||
2. Select one or more posted vendor bills with pending commission.
|
||||
3. Click **Action > Create Rappel Commission Invoice**.
|
||||
4. In the wizard, confirm the **Invoice Date**, **Journal**, and **Product**.
|
||||
5. Click **Create Rappel Invoice(s)**.
|
||||
|
||||
The system will create one sale invoice per vendor, with one line per original bill. The commission amount is computed as:
|
||||
|
||||
taxable_base × commission_rate / 100
|
||||
|
||||
The original vendor bills are automatically unmarked as pending.
|
||||
2
purchase_rappel/security/ir.model.access.csv
Normal file
2
purchase_rappel/security/ir.model.access.csv
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_account_move_rappel_wizard_user,account.move.rappel.wizard user,model_account_move_rappel_wizard,account.group_account_invoice,1,1,1,1
|
||||
|
4
purchase_rappel/tests/__init__.py
Normal file
4
purchase_rappel/tests/__init__.py
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
# Copyright 2024 Criptomart
|
||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
||||
|
||||
from . import test_purchase_rappel
|
||||
333
purchase_rappel/tests/test_purchase_rappel.py
Normal file
333
purchase_rappel/tests/test_purchase_rappel.py
Normal file
|
|
@ -0,0 +1,333 @@
|
|||
# Copyright 2024 Criptomart
|
||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import fields
|
||||
from odoo.exceptions import UserError
|
||||
from odoo.tests import tagged
|
||||
from odoo.addons.account.tests.common import AccountTestInvoicingCommon
|
||||
|
||||
|
||||
@tagged("post_install", "-at_install")
|
||||
class TestPurchaseRappel(AccountTestInvoicingCommon):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
cls.vendor_rappel = cls.env["res.partner"].create(
|
||||
{
|
||||
"name": "Vendor with Rappel",
|
||||
"rappel_commission": True,
|
||||
"rappel_commission_rate": 5.0,
|
||||
"property_account_receivable_id": cls.company_data[
|
||||
"default_account_receivable"
|
||||
].id,
|
||||
"property_account_payable_id": cls.company_data[
|
||||
"default_account_payable"
|
||||
].id,
|
||||
}
|
||||
)
|
||||
cls.vendor_no_rappel = cls.env["res.partner"].create(
|
||||
{
|
||||
"name": "Vendor without Rappel",
|
||||
"rappel_commission": False,
|
||||
"property_account_receivable_id": cls.company_data[
|
||||
"default_account_receivable"
|
||||
].id,
|
||||
"property_account_payable_id": cls.company_data[
|
||||
"default_account_payable"
|
||||
].id,
|
||||
}
|
||||
)
|
||||
cls.vendor_zero_rate = cls.env["res.partner"].create(
|
||||
{
|
||||
"name": "Vendor Zero Rate",
|
||||
"rappel_commission": True,
|
||||
"rappel_commission_rate": 0.0,
|
||||
"property_account_receivable_id": cls.company_data[
|
||||
"default_account_receivable"
|
||||
].id,
|
||||
"property_account_payable_id": cls.company_data[
|
||||
"default_account_payable"
|
||||
].id,
|
||||
}
|
||||
)
|
||||
cls.rappel_product = cls.env["product.product"].create(
|
||||
{
|
||||
"name": "Rappel Commission Product",
|
||||
"type": "service",
|
||||
"list_price": 100.0,
|
||||
"property_account_income_id": cls.company_data[
|
||||
"default_account_revenue"
|
||||
].id,
|
||||
"taxes_id": [(6, 0, [cls.tax_sale_a.id])],
|
||||
}
|
||||
)
|
||||
cls.rappel_journal = cls.company_data["default_journal_sale"]
|
||||
cls.company_data["company"].write(
|
||||
{
|
||||
"rappel_journal_id": cls.rappel_journal.id,
|
||||
"rappel_product_id": cls.rappel_product.id,
|
||||
}
|
||||
)
|
||||
|
||||
def _create_vendor_bill(self, partner, amount=1000.0, post=True, ref=None):
|
||||
move = self.init_invoice(
|
||||
"in_invoice",
|
||||
partner=partner,
|
||||
products=self.product_a,
|
||||
post=False,
|
||||
)
|
||||
move.invoice_line_ids[0].price_unit = amount
|
||||
if ref is not None:
|
||||
move.ref = ref
|
||||
if post:
|
||||
move.action_post()
|
||||
return move
|
||||
|
||||
def _create_vendor_refund(self, partner, amount=200.0, post=True, ref=None):
|
||||
move = self.init_invoice(
|
||||
"in_refund",
|
||||
partner=partner,
|
||||
products=self.product_a,
|
||||
post=False,
|
||||
)
|
||||
move.invoice_line_ids[0].price_unit = amount
|
||||
if ref is not None:
|
||||
move.ref = ref
|
||||
if post:
|
||||
move.action_post()
|
||||
return move
|
||||
|
||||
def test_rappel_pending_on_create(self):
|
||||
bill_rappel = self._create_vendor_bill(self.vendor_rappel)
|
||||
self.assertTrue(bill_rappel.rappel_pending)
|
||||
|
||||
bill_no_rappel = self._create_vendor_bill(self.vendor_no_rappel)
|
||||
self.assertFalse(bill_no_rappel.rappel_pending)
|
||||
|
||||
def test_rappel_pending_onchange(self):
|
||||
move = self.env["account.move"].new(
|
||||
{
|
||||
"move_type": "in_invoice",
|
||||
"partner_id": self.vendor_no_rappel.id,
|
||||
"invoice_date": fields.Date.from_string("2019-01-01"),
|
||||
}
|
||||
)
|
||||
move._onchange_partner_id_rappel()
|
||||
self.assertFalse(move.rappel_pending)
|
||||
|
||||
move.partner_id = self.vendor_rappel
|
||||
move._onchange_partner_id_rappel()
|
||||
self.assertTrue(move.rappel_pending)
|
||||
|
||||
def test_wizard_default_get_valid(self):
|
||||
bill = self._create_vendor_bill(self.vendor_rappel)
|
||||
wizard = (
|
||||
self.env["account.move.rappel.wizard"]
|
||||
.with_context(active_ids=bill.ids)
|
||||
.create({})
|
||||
)
|
||||
self.assertIn(bill, wizard.move_ids)
|
||||
self.assertEqual(wizard.journal_id, self.rappel_journal)
|
||||
self.assertEqual(wizard.product_id, self.rappel_product)
|
||||
|
||||
def test_wizard_default_get_no_valid(self):
|
||||
bill = self._create_vendor_bill(self.vendor_rappel, post=False)
|
||||
with self.assertRaises(UserError):
|
||||
self.env["account.move.rappel.wizard"].with_context(
|
||||
active_ids=bill.ids
|
||||
).create({})
|
||||
|
||||
def test_wizard_default_get_no_rappel(self):
|
||||
bill = self._create_vendor_bill(self.vendor_no_rappel)
|
||||
with self.assertRaises(UserError):
|
||||
self.env["account.move.rappel.wizard"].with_context(
|
||||
active_ids=bill.ids
|
||||
).create({})
|
||||
|
||||
def test_wizard_default_get_not_pending(self):
|
||||
bill = self._create_vendor_bill(self.vendor_rappel)
|
||||
bill.rappel_pending = False
|
||||
with self.assertRaises(UserError):
|
||||
self.env["account.move.rappel.wizard"].with_context(
|
||||
active_ids=bill.ids
|
||||
).create({})
|
||||
|
||||
def test_wizard_create_invoice(self):
|
||||
bill = self._create_vendor_bill(self.vendor_rappel, amount=2000.0)
|
||||
self.assertTrue(bill.rappel_pending)
|
||||
|
||||
wizard = (
|
||||
self.env["account.move.rappel.wizard"]
|
||||
.with_context(active_ids=bill.ids)
|
||||
.create({})
|
||||
)
|
||||
action = wizard.action_create_rappel_invoices()
|
||||
|
||||
rappel_invoice = self.env["account.move"].browse(action["res_id"])
|
||||
self.assertEqual(rappel_invoice.move_type, "out_invoice")
|
||||
self.assertEqual(rappel_invoice.partner_id, self.vendor_rappel)
|
||||
self.assertEqual(len(rappel_invoice.invoice_line_ids), 1)
|
||||
|
||||
expected_amount = 2000.0 * 5.0 / 100.0
|
||||
self.assertEqual(rappel_invoice.invoice_line_ids[0].price_unit, expected_amount)
|
||||
|
||||
self.assertFalse(bill.rappel_pending)
|
||||
|
||||
def test_wizard_grouping(self):
|
||||
bill1 = self._create_vendor_bill(self.vendor_rappel, amount=1000.0)
|
||||
vendor_rappel_2 = self.env["res.partner"].create(
|
||||
{
|
||||
"name": "Vendor Rappel 2",
|
||||
"rappel_commission": True,
|
||||
"rappel_commission_rate": 10.0,
|
||||
"property_account_receivable_id": self.company_data[
|
||||
"default_account_receivable"
|
||||
].id,
|
||||
"property_account_payable_id": self.company_data[
|
||||
"default_account_payable"
|
||||
].id,
|
||||
}
|
||||
)
|
||||
bill2 = self._create_vendor_bill(vendor_rappel_2, amount=2000.0)
|
||||
|
||||
wizard = (
|
||||
self.env["account.move.rappel.wizard"]
|
||||
.with_context(active_ids=(bill1 + bill2).ids)
|
||||
.create({})
|
||||
)
|
||||
action = wizard.action_create_rappel_invoices()
|
||||
|
||||
invoices = self.env["account.move"].search(action.get("domain", []))
|
||||
self.assertEqual(len(invoices), 2)
|
||||
|
||||
invoice_vendor_1 = invoices.filtered(
|
||||
lambda m: m.partner_id == self.vendor_rappel
|
||||
)
|
||||
self.assertEqual(
|
||||
invoice_vendor_1.invoice_line_ids[0].price_unit,
|
||||
1000.0 * 5.0 / 100.0,
|
||||
)
|
||||
|
||||
invoice_vendor_2 = invoices.filtered(lambda m: m.partner_id == vendor_rappel_2)
|
||||
self.assertEqual(
|
||||
invoice_vendor_2.invoice_line_ids[0].price_unit,
|
||||
2000.0 * 10.0 / 100.0,
|
||||
)
|
||||
|
||||
self.assertFalse(bill1.rappel_pending)
|
||||
self.assertFalse(bill2.rappel_pending)
|
||||
|
||||
def test_wizard_no_journal(self):
|
||||
bill = self._create_vendor_bill(self.vendor_rappel)
|
||||
wizard = self.env["account.move.rappel.wizard"].new(
|
||||
{
|
||||
"move_ids": [(6, 0, bill.ids)],
|
||||
"journal_id": False,
|
||||
"product_id": self.rappel_product.id,
|
||||
"company_id": self.env.company.id,
|
||||
}
|
||||
)
|
||||
with self.assertRaises(UserError):
|
||||
wizard.action_create_rappel_invoices()
|
||||
|
||||
def test_wizard_no_product(self):
|
||||
bill = self._create_vendor_bill(self.vendor_rappel)
|
||||
wizard = self.env["account.move.rappel.wizard"].new(
|
||||
{
|
||||
"move_ids": [(6, 0, bill.ids)],
|
||||
"journal_id": self.rappel_journal.id,
|
||||
"product_id": False,
|
||||
"company_id": self.env.company.id,
|
||||
}
|
||||
)
|
||||
with self.assertRaises(UserError):
|
||||
wizard.action_create_rappel_invoices()
|
||||
|
||||
def test_wizard_zero_rate(self):
|
||||
bill = self._create_vendor_bill(self.vendor_zero_rate, amount=1000.0)
|
||||
wizard = (
|
||||
self.env["account.move.rappel.wizard"]
|
||||
.with_context(active_ids=bill.ids)
|
||||
.create({})
|
||||
)
|
||||
with self.assertRaises(UserError):
|
||||
wizard.action_create_rappel_invoices()
|
||||
|
||||
def test_wizard_vendor_ref_in_description(self):
|
||||
bill_with_ref = self._create_vendor_bill(
|
||||
self.vendor_rappel, amount=1000.0, ref="VENDOR-REF-001"
|
||||
)
|
||||
wizard = (
|
||||
self.env["account.move.rappel.wizard"]
|
||||
.with_context(active_ids=bill_with_ref.ids)
|
||||
.create({})
|
||||
)
|
||||
action = wizard.action_create_rappel_invoices()
|
||||
rappel_invoice = self.env["account.move"].browse(action["res_id"])
|
||||
line_name = rappel_invoice.invoice_line_ids[0].name
|
||||
self.assertIn("VENDOR-REF-001", line_name)
|
||||
self.assertNotIn(bill_with_ref.name, line_name)
|
||||
|
||||
bill_without_ref = self._create_vendor_bill(
|
||||
self.vendor_rappel, amount=1000.0, ref=None
|
||||
)
|
||||
wizard2 = (
|
||||
self.env["account.move.rappel.wizard"]
|
||||
.with_context(active_ids=bill_without_ref.ids)
|
||||
.create({})
|
||||
)
|
||||
action2 = wizard2.action_create_rappel_invoices()
|
||||
rappel_invoice2 = self.env["account.move"].browse(action2["res_id"])
|
||||
line_name2 = rappel_invoice2.invoice_line_ids[0].name
|
||||
self.assertIn(bill_without_ref.name, line_name2)
|
||||
|
||||
def test_wizard_includes_in_refund(self):
|
||||
bill = self._create_vendor_bill(self.vendor_rappel, amount=1000.0)
|
||||
refund = self._create_vendor_refund(self.vendor_rappel, amount=200.0)
|
||||
self.assertTrue(refund.rappel_pending)
|
||||
|
||||
wizard = (
|
||||
self.env["account.move.rappel.wizard"]
|
||||
.with_context(active_ids=(bill + refund).ids)
|
||||
.create({})
|
||||
)
|
||||
action = wizard.action_create_rappel_invoices()
|
||||
rappel_invoice = self.env["account.move"].browse(action["res_id"])
|
||||
|
||||
self.assertEqual(len(rappel_invoice.invoice_line_ids), 2)
|
||||
amounts = sorted(rappel_invoice.invoice_line_ids.mapped("price_unit"))
|
||||
self.assertEqual(amounts, [-10.0, 50.0])
|
||||
self.assertFalse(bill.rappel_pending)
|
||||
self.assertFalse(refund.rappel_pending)
|
||||
|
||||
def test_wizard_refund_subtracts_commission(self):
|
||||
bill = self._create_vendor_bill(self.vendor_rappel, amount=1000.0)
|
||||
refund = self._create_vendor_refund(self.vendor_rappel, amount=200.0)
|
||||
|
||||
wizard = (
|
||||
self.env["account.move.rappel.wizard"]
|
||||
.with_context(active_ids=(bill + refund).ids)
|
||||
.create({})
|
||||
)
|
||||
action = wizard.action_create_rappel_invoices()
|
||||
rappel_invoice = self.env["account.move"].browse(action["res_id"])
|
||||
|
||||
self.assertEqual(len(rappel_invoice.invoice_line_ids), 2)
|
||||
line_by_sign = {
|
||||
line.price_unit > 0: line for line in rappel_invoice.invoice_line_ids
|
||||
}
|
||||
self.assertEqual(line_by_sign[True].price_unit, 50.0)
|
||||
self.assertEqual(line_by_sign[False].price_unit, -10.0)
|
||||
self.assertEqual(rappel_invoice.amount_untaxed, 40.0)
|
||||
self.assertIn("Refund", line_by_sign[False].name)
|
||||
|
||||
def test_rappel_pending_set_on_refund_create(self):
|
||||
refund = self._create_vendor_refund(
|
||||
self.vendor_rappel, amount=200.0, post=False
|
||||
)
|
||||
self.assertTrue(refund.rappel_pending)
|
||||
|
||||
refund_no_rappel = self._create_vendor_refund(
|
||||
self.vendor_no_rappel, amount=200.0, post=False
|
||||
)
|
||||
self.assertFalse(refund_no_rappel.rappel_pending)
|
||||
51
purchase_rappel/views/account_move_views.xml
Normal file
51
purchase_rappel/views/account_move_views.xml
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<!-- Extend vendor bills list view to show rappel_pending column -->
|
||||
<record id="view_in_invoice_bill_tree_rappel" model="ir.ui.view">
|
||||
<field name="name">account.move.tree.rappel</field>
|
||||
<field name="model">account.move</field>
|
||||
<field name="inherit_id" ref="account.view_invoice_tree"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="checked" position="after">
|
||||
<field name="rappel_pending"
|
||||
optional="show"
|
||||
readonly="1"
|
||||
widget="boolean_toggle"
|
||||
column_invisible="context.get('default_move_type') not in ('in_invoice', 'in_refund')"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Extend the invoice search view to add the "Pending Commission" filter -->
|
||||
<record id="view_account_invoice_filter_rappel" model="ir.ui.view">
|
||||
<field name="name">account.invoice.select.rappel</field>
|
||||
<field name="model">account.move</field>
|
||||
<field name="inherit_id" ref="account.view_account_invoice_filter"/>
|
||||
<field name="arch" type="xml">
|
||||
<filter name="to_check" position="after">
|
||||
<separator/>
|
||||
<filter name="rappel_pending"
|
||||
string="Pending Commission"
|
||||
domain="[('rappel_pending', '=', True)]"
|
||||
help="Vendor bills not yet included in a rappel commission invoice"/>
|
||||
</filter>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Extend vendor bill form view to show rappel_pending field -->
|
||||
<record id="view_move_form_rappel" model="ir.ui.view">
|
||||
<field name="name">account.move.form.rappel</field>
|
||||
<field name="model">account.move</field>
|
||||
<field name="inherit_id" ref="account.view_move_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//group[@name='accounting_info_group']/field[@name='checked']" position="after">
|
||||
<field name="rappel_pending"
|
||||
invisible="move_type not in ('in_invoice', 'in_refund')"
|
||||
readonly="1"
|
||||
widget="boolean_toggle"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
26
purchase_rappel/views/res_config_settings_views.xml
Normal file
26
purchase_rappel/views/res_config_settings_views.xml
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<record id="res_config_settings_view_form_rappel" model="ir.ui.view">
|
||||
<field name="name">res.config.settings.view.form.inherit.purchase.rappel</field>
|
||||
<field name="model">res.config.settings</field>
|
||||
<field name="inherit_id" ref="purchase.res_config_settings_view_form_purchase"/>
|
||||
<field name="arch" type="xml">
|
||||
<block name="invoicing_settings_container" position="inside">
|
||||
<setting
|
||||
id="rappel_commission_settings"
|
||||
string="Rappel Commission"
|
||||
help="Configure the journal and product for rappel commission invoices">
|
||||
<field name="rappel_journal_id"/>
|
||||
<div class="content-group">
|
||||
<div class="row mt8">
|
||||
<label for="rappel_product_id" class="col-lg-4 o_light_label"/>
|
||||
<field name="rappel_product_id"/>
|
||||
</div>
|
||||
</div>
|
||||
</setting>
|
||||
</block>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
20
purchase_rappel/views/res_partner_views.xml
Normal file
20
purchase_rappel/views/res_partner_views.xml
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<record id="view_partner_form_rappel" model="ir.ui.view">
|
||||
<field name="name">res.partner.form.rappel</field>
|
||||
<field name="model">res.partner</field>
|
||||
<field name="inherit_id" ref="base.view_partner_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<page name="sales_purchases" position="inside">
|
||||
<group string="Rappel Commission" name="rappel_commission_group">
|
||||
<field name="rappel_commission"/>
|
||||
<field name="rappel_commission_rate"
|
||||
invisible="not rappel_commission"
|
||||
required="rappel_commission"/>
|
||||
</group>
|
||||
</page>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
3
purchase_rappel/wizard/__init__.py
Normal file
3
purchase_rappel/wizard/__init__.py
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# Copyright 2024 Criptomart
|
||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
||||
from . import account_move_rappel_wizard
|
||||
220
purchase_rappel/wizard/account_move_rappel_wizard.py
Normal file
220
purchase_rappel/wizard/account_move_rappel_wizard.py
Normal file
|
|
@ -0,0 +1,220 @@
|
|||
# Copyright 2024 Criptomart
|
||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
||||
from collections import defaultdict
|
||||
|
||||
from odoo import _, api, fields, models
|
||||
from odoo.exceptions import UserError
|
||||
|
||||
|
||||
class AccountMoveRappelWizard(models.TransientModel):
|
||||
"""Wizard to generate rappel commission (sale) invoices from selected vendor bills.
|
||||
|
||||
One sale invoice is created per vendor. Each original bill becomes one invoice
|
||||
line whose amount is computed as: taxable_base × commission_rate / 100.
|
||||
"""
|
||||
|
||||
_name = "account.move.rappel.wizard"
|
||||
_description = "Create Rappel Commission Invoice"
|
||||
|
||||
move_ids = fields.Many2many(
|
||||
comodel_name="account.move",
|
||||
string="Vendor Bills",
|
||||
readonly=True,
|
||||
)
|
||||
invoice_date = fields.Date(
|
||||
string="Invoice Date",
|
||||
default=fields.Date.context_today,
|
||||
required=True,
|
||||
)
|
||||
company_id = fields.Many2one(
|
||||
comodel_name="res.company",
|
||||
default=lambda self: self.env.company,
|
||||
required=True,
|
||||
)
|
||||
journal_id = fields.Many2one(
|
||||
comodel_name="account.journal",
|
||||
string="Journal",
|
||||
domain="[('type', '=', 'sale'), ('company_id', '=', company_id)]",
|
||||
required=True,
|
||||
)
|
||||
product_id = fields.Many2one(
|
||||
comodel_name="product.product",
|
||||
string="Commission Product",
|
||||
required=True,
|
||||
)
|
||||
|
||||
@api.model
|
||||
def default_get(self, fields_list):
|
||||
res = super().default_get(fields_list)
|
||||
company = self.env.company
|
||||
active_ids = self.env.context.get("active_ids", [])
|
||||
moves = self.env["account.move"].browse(active_ids)
|
||||
|
||||
# Filter only posted vendor bills and refunds
|
||||
valid_moves = moves.filtered(
|
||||
lambda m: m.move_type in ("in_invoice", "in_refund")
|
||||
and m.state == "posted"
|
||||
)
|
||||
if not valid_moves:
|
||||
raise UserError(
|
||||
_(
|
||||
"No posted vendor bills or refunds found in the selection. "
|
||||
"Only posted (validated) vendor bills and refunds can be used to "
|
||||
"create rappel commission invoices."
|
||||
)
|
||||
)
|
||||
|
||||
# Filter only pending bills
|
||||
pending_moves = valid_moves.filtered(lambda m: m.rappel_pending)
|
||||
if not pending_moves:
|
||||
raise UserError(
|
||||
_(
|
||||
"None of the selected vendor bills are pending commission. "
|
||||
"They may have already been commissioned."
|
||||
)
|
||||
)
|
||||
|
||||
# Warn about bills whose partner has no rappel configured
|
||||
no_rappel = pending_moves.filtered(lambda m: not m.partner_id.rappel_commission)
|
||||
if no_rappel and len(no_rappel) == len(pending_moves):
|
||||
raise UserError(
|
||||
_(
|
||||
"None of the selected vendors have the rappel commission enabled. "
|
||||
"Please configure the commission rate on the vendor contact first."
|
||||
)
|
||||
)
|
||||
|
||||
res.update(
|
||||
{
|
||||
"move_ids": [(6, 0, pending_moves.ids)],
|
||||
"journal_id": company.rappel_journal_id.id or False,
|
||||
"product_id": company.rappel_product_id.id or False,
|
||||
}
|
||||
)
|
||||
return res
|
||||
|
||||
def action_create_rappel_invoices(self):
|
||||
self.ensure_one()
|
||||
|
||||
if not self.journal_id:
|
||||
raise UserError(
|
||||
_(
|
||||
"Please select a journal for the rappel commission invoices, or "
|
||||
"configure a default one in Purchase Settings."
|
||||
)
|
||||
)
|
||||
if not self.product_id:
|
||||
raise UserError(
|
||||
_(
|
||||
"Please select a product for the rappel commission invoices, or "
|
||||
"configure a default one in Purchase Settings."
|
||||
)
|
||||
)
|
||||
|
||||
# Group eligible bills by partner (only partners with rappel enabled)
|
||||
bills_by_partner = defaultdict(lambda: self.env["account.move"])
|
||||
for bill in self.move_ids:
|
||||
if (
|
||||
bill.partner_id.rappel_commission
|
||||
and bill.partner_id.rappel_commission_rate
|
||||
):
|
||||
bills_by_partner[bill.partner_id] |= bill
|
||||
|
||||
if not bills_by_partner:
|
||||
raise UserError(
|
||||
_(
|
||||
"None of the selected vendor bills belong to vendors with a rappel "
|
||||
"commission rate configured."
|
||||
)
|
||||
)
|
||||
|
||||
created_invoices = self.env["account.move"]
|
||||
|
||||
for partner, bills in bills_by_partner.items():
|
||||
rate = partner.rappel_commission_rate
|
||||
invoice_lines = []
|
||||
|
||||
for bill in bills:
|
||||
taxable_base = bill.amount_untaxed
|
||||
commission_amount = taxable_base * rate / 100.0
|
||||
vendor_ref = bill.ref or bill.name
|
||||
if bill.move_type == "in_refund":
|
||||
# Vendor refunds reduce the commission: negate the amount so
|
||||
# the resulting line subtracts from the rappel invoice total.
|
||||
# amount_untaxed is always positive in Odoo, so we flip the
|
||||
# sign here and display a negative base in the description.
|
||||
commission_amount = -commission_amount
|
||||
display_base = -taxable_base
|
||||
name = _(
|
||||
"Rappel commission %(rate)s%% — Refund %(bill)s "
|
||||
"(taxable base: %(base)s %(currency)s)",
|
||||
rate=rate,
|
||||
bill=vendor_ref,
|
||||
base=f"{display_base:,.2f}",
|
||||
currency=bill.currency_id.name,
|
||||
)
|
||||
else:
|
||||
name = _(
|
||||
"Rappel commission %(rate)s%% — Bill %(bill)s "
|
||||
"(taxable base: %(base)s %(currency)s)",
|
||||
rate=rate,
|
||||
bill=vendor_ref,
|
||||
base=f"{taxable_base:,.2f}",
|
||||
currency=bill.currency_id.name,
|
||||
)
|
||||
invoice_lines.append(
|
||||
(
|
||||
0,
|
||||
0,
|
||||
{
|
||||
"product_id": self.product_id.id,
|
||||
"name": name,
|
||||
"quantity": 1,
|
||||
"price_unit": commission_amount,
|
||||
"tax_ids": [
|
||||
(
|
||||
6,
|
||||
0,
|
||||
self.product_id.taxes_id.filtered(
|
||||
lambda t: t.company_id == self.company_id
|
||||
).ids,
|
||||
)
|
||||
],
|
||||
},
|
||||
)
|
||||
)
|
||||
|
||||
invoice_vals = {
|
||||
"move_type": "out_invoice",
|
||||
"partner_id": partner.id,
|
||||
"invoice_date": self.invoice_date,
|
||||
"journal_id": self.journal_id.id,
|
||||
"company_id": self.company_id.id,
|
||||
"invoice_line_ids": invoice_lines,
|
||||
"narration": _(
|
||||
"Rappel commission invoice generated from %d vendor bill(s).",
|
||||
len(bills),
|
||||
),
|
||||
}
|
||||
created_invoice = self.env["account.move"].create(invoice_vals)
|
||||
created_invoices |= created_invoice
|
||||
|
||||
# Mark source bills as commissioned
|
||||
bills.write({"rappel_pending": False})
|
||||
|
||||
# Open the created invoices
|
||||
if len(created_invoices) == 1:
|
||||
return {
|
||||
"type": "ir.actions.act_window",
|
||||
"res_model": "account.move",
|
||||
"res_id": created_invoices.id,
|
||||
"view_mode": "form",
|
||||
"views": [(False, "form")],
|
||||
}
|
||||
return {
|
||||
"type": "ir.actions.act_window",
|
||||
"res_model": "account.move",
|
||||
"domain": [("id", "in", created_invoices.ids)],
|
||||
"view_mode": "list,form",
|
||||
"name": _("Rappel Commission Invoices"),
|
||||
}
|
||||
62
purchase_rappel/wizard/account_move_rappel_wizard_views.xml
Normal file
62
purchase_rappel/wizard/account_move_rappel_wizard_views.xml
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<!-- Wizard form view -->
|
||||
<record id="view_account_move_rappel_wizard_form" model="ir.ui.view">
|
||||
<field name="name">account.move.rappel.wizard.form</field>
|
||||
<field name="model">account.move.rappel.wizard</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Create Rappel Commission Invoice">
|
||||
<sheet>
|
||||
<field name="company_id" invisible="1"/>
|
||||
<group>
|
||||
<group>
|
||||
<field name="invoice_date"/>
|
||||
<field name="journal_id"/>
|
||||
<field name="product_id"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
</group>
|
||||
</group>
|
||||
<notebook>
|
||||
<page string="Vendor Bills" name="vendor_bills">
|
||||
<field name="move_ids">
|
||||
<list string="Vendor Bills">
|
||||
<field name="name"/>
|
||||
<field name="move_type"
|
||||
widget="badge"
|
||||
decoration-info="move_type == 'in_invoice'"
|
||||
decoration-danger="move_type == 'in_refund'"/>
|
||||
<field name="partner_id"/>
|
||||
<field name="invoice_date"/>
|
||||
<field name="amount_untaxed"
|
||||
string="Taxable Base"/>
|
||||
<field name="rappel_pending"/>
|
||||
</list>
|
||||
</field>
|
||||
</page>
|
||||
</notebook>
|
||||
</sheet>
|
||||
<footer>
|
||||
<button name="action_create_rappel_invoices"
|
||||
type="object"
|
||||
string="Create Rappel Invoice(s)"
|
||||
class="btn-primary"/>
|
||||
<button string="Cancel" class="btn-secondary" special="cancel"/>
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Action bound to the vendor bills list view (Action menu) -->
|
||||
<record id="action_open_rappel_wizard" model="ir.actions.act_window">
|
||||
<field name="name">Create Rappel Commission Invoice</field>
|
||||
<field name="res_model">account.move.rappel.wizard</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="target">new</field>
|
||||
<field name="binding_model_id" ref="account.model_account_move"/>
|
||||
<field name="binding_view_types">list</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
Loading…
Add table
Add a link
Reference in a new issue