Compare commits

...

52 Commits

Author SHA1 Message Date
Clément Mombereau
c88e7b0bb4 [ADD] new module project_task_report 2024-12-09 12:32:12 -03:00
Alexis de Lattre
5af6c895d0 Add modules commission_simple, commission_simple_agent, commission_simple_agent_purchase
Add demo data in sale_agent
2024-11-30 01:19:31 +01:00
Alexis de Lattre
7bdd579b1c [IMP] product_usability: add main supplier in tree view as optional 2024-11-25 09:33:03 +01:00
Alexis de Lattre
c9f0569516 [IMP] account_usability_akretion: improve action from account.account form view that jumps to account.move.line tree view 2024-11-25 08:23:45 +00:00
Alexis de Lattre
c37b607f97 [IMP] sale_agent: add tracking and fr translation 2024-11-21 09:59:39 +01:00
Alexis de Lattre
5f4929f819 [IMP] base_usability: add possibility to have fax in header if partner_fax is installed 2024-11-19 16:14:35 +00:00
Alexis de Lattre
59c7084159 base_company_extension: handle case where company legal type is already in company name 2024-11-19 15:28:59 +00:00
Alexis de Lattre
a2952ca6b2 [IMP] base_usability: add fields in partner tree view with optional=hide 2024-11-08 16:19:39 +00:00
Alexis de Lattre
f5b8f1674a [FIX] sale_agent: double string 2024-11-07 17:24:57 +01:00
Alexis de Lattre
e22badc605 Add module sale_agent 2024-11-07 17:18:57 +01:00
Alexis de Lattre
f93f17b27b [IMP] stock_usability: add tracking on lot fields (model already inherit from mail.thread) 2024-11-05 00:21:36 +01:00
Florian
74586cff13 Merge pull request #220 from akretion/16-account-usability-warning-existing-reverse-move
[16] account_usability_akretion : Replace error by warning in case a user try to reverse an already reversed account move
2024-10-23 11:27:11 +02:00
Alexis de Lattre
48c0e02e94 [IMP] stock_valuation_xlsx french translation 2024-10-22 10:06:19 +02:00
Alexis de Lattre
a035748c2d [IMP] stock_valuation_xlsx: FR translation 2024-10-21 18:39:45 +02:00
Alexis de Lattre
594c3fb0ed [IMP] stock_valuation_xlsx: add barcode in stock variation report
Fix empty col in variation XLSX report
2024-10-21 17:31:02 +02:00
Alexis de Lattre
02c082f966 [MIG] stock_valuation_xlsx from v14 to v16 2024-10-21 14:46:24 +02:00
Alexis de Lattre
97cf376e90 purchase_usability: take into account ir.config_parameter usability.line_name_no_product_code when using _prepare_purchase_order_line() 2024-10-17 10:57:35 +02:00
Alexis de Lattre
c3f007e716 [IMP] product_usability: optional=show on min_qty 2024-10-15 12:33:36 +00:00
Alexis de Lattre
a333bc4e84 [IMP] stock_usability: always show picking_type_id in the last tab of the picking form view 2024-10-10 17:27:08 +00:00
Alexis de Lattre
9e5670934e Improve mrp_subcontracting_usability: add fields in views, domain on subcontractor_ids M2M field on mrp.bom. 2024-10-08 13:54:36 +00:00
Alexis de Lattre
c74a647945 [IMP] account_usability_akretion: simplify code for invoice attach del upon invoice back to draft 2024-09-30 10:54:14 +02:00
Alexis de Lattre
fca7209056 [FIX] account_usability_akretion: fix deletion of PDF invoice attachment when invoice is back to draft 2024-09-30 09:08:58 +02:00
Alexis de Lattre
6d9b4c92eb sale_stock_usability: add method to display delivery order on out invoice report 2024-09-30 08:18:37 +02:00
Alexis de Lattre
68327c28b6 base_usability: Add rcs_siren in company header 2024-09-30 08:15:07 +02:00
Alexis de Lattre
592e40637a mrp_usability: add tracking on some fields 2024-09-30 08:12:56 +02:00
Alexis de Lattre
b6624f2491 [IMP] account_usability_akretion: add search on account in account.move search view 2024-09-30 08:07:00 +02:00
Alexis de Lattre
3a11c99ccb stock_usability: Add product_barcode on orderpoint tree view (optional hide) 2024-09-30 07:47:36 +02:00
Alexis de Lattre
36f277940c [MIG] partner_products_shortcut to v16 2024-09-30 07:40:24 +02:00
Florian da Costa
c09e3a1108 [IMP] account_usability_akretion : Replace error by warning in case a user try to reverse an already reversed account move
The goal is to allow multiple refund for a single invoice. It may happen to refund invoice partially and they refund again partially later.
2024-08-28 15:49:26 +02:00
Alexis de Lattre
3b5b64349b stock_usability: trigger now 'manual' by default 2024-07-18 13:11:32 +00:00
Alexis de Lattre
efddeb3a3c product_usability: add support for GTIN-14 in barcode type 2024-07-18 13:05:50 +00:00
Alexis de Lattre
c126a286c4 forward port patch web-buttons_14_max_instead_of_7.diff from v14 to v16 2024-07-15 08:29:31 +00:00
Alexis de Lattre
670ba212d9 Remove patch web-export-add_technical_field_name.diff because the feature is now native 2024-07-11 18:53:03 +02:00
Alexis de Lattre
c26ed6cdfb base_partner_ref: Remove commented code 2024-07-09 14:45:39 +02:00
Alexis de Lattre
dd0841385f account_usability_akretion: update FR translation
Fix res.company form view
sale_usability: enable static terms on res.company form view
2024-07-09 12:50:52 +02:00
Alexis de Lattre
b91abe54a5 Add fr translation several usability modules
Add fr translation for crm_usability, delivery_usability, link_tracker_usability, mail_usability, mass_mailing_usability, mrp_subcontracting_usability and pos_usability
2024-07-08 00:12:44 +02:00
Raphaël Valyi
210af49098 Merge pull request #219 from akretion/16.0-mig-sale_no_optional_product
[MIG] sale_no_optional_product
2024-07-06 16:06:46 -03:00
Raphaël Valyi
19158d9309 [MIG] sale_no_optional_product 2024-07-05 21:02:46 +00:00
Alexis de Lattre
4577524f0e stock_usability: add FR translation 2024-07-05 00:32:26 +02:00
Alexis de Lattre
8fd0cb5601 mrp_usability: update FR translation 2024-07-04 18:23:23 +02:00
Alexis de Lattre
8d584871d6 sale_usability+sale_stock_usability: update FR translation
sale_usability: remove wizard discount on all lines, which is mostly native
2024-07-04 18:13:41 +02:00
Alexis de Lattre
a7fd6a1361 purchase_usability+purchase_stock_usability: Add FR translation 2024-07-04 17:32:51 +02:00
Alexis de Lattre
2b2293593c product_usability: add FR translation 2024-07-04 17:15:53 +02:00
Alexis de Lattre
f1614afda2 base_usability: update fr translation 2024-07-04 16:49:54 +02:00
Alexis de Lattre
227a7ec18d Add patch for OCA localization 2024-06-21 17:32:16 +02:00
Arnaud LAYEC
827557689f Add a 'send & save' button next to 'save & close' 2024-06-15 12:30:21 +02:00
Arnaud LAYEC
67ff087f6e Add 'Opportunity' field on a new 'CRM' notebook page on Calendar 2024-06-15 12:30:21 +02:00
Arnaud LAYEC
9507be2943 [base_mail_sender_bcc] manifest version change from 14 to 16.0.1.0.0 2024-06-15 12:30:21 +02:00
Alexis de Lattre
740d167331 purchase_stock_generic_product and sale_stock_generic_product: allows the use of generic products 2024-06-15 12:24:12 +02:00
Alexis de Lattre
d07e38e1f3 base_usability: add group by on industry_id on partner search view 2024-06-13 10:04:08 +02:00
Alexis de Lattre
55b84a170e account_usability_ak: pivot view by default on account.invoice.report 2024-06-13 10:03:03 +02:00
Mourad
252da11a30 [16.0] IMP display currency for partner bank account 2024-05-06 14:07:28 +02:00
159 changed files with 7016 additions and 1595 deletions

View File

@@ -23,14 +23,14 @@ This modules adds the following functions:
* Add an *Overdue* filter on invoice search view (this feature was previously
located in te module *account_invoice_overdue_filter*)
* Increase the default limit of 80 lines in account move and account move line view.
* Increase the default limit of 80 lines in journal entries and journal items views.
* disable reconciliation "guessing"
* fast search on *Reconcile Ref* for account move line.
* fast search on *Reconcile Ref* for journal items.
* add sale dates to invoice report to be compliant with
https://www.service-public.fr/professionnels-entreprises/vosdroits/F31808
* Sale date on qweb invoices
* A wizard to mark several invoices as sent at once (forward from v8)
* Default date for Account Move Reversal is now D+1 instead of today
* Default date for reversal journal entry is now D+1 instead of today
* Track more fields on invoice (see details in account.py)
* Add boolean fields `has_discount` and `has_attachment` on invoice
* Add button "Delete line qty = 0" on supplier invoice
@@ -41,8 +41,8 @@ This modules adds the following functions:
* add direct search of journal using code
* add copy=False on some fields
* Add unicity constraint on analytic codes per company
* Better default values on account move
* Add link from account move line to invoice
* Better default values on journal entry
* Add link from journal items to to invoice
* Add start_date and end_date on bank statements
* Add transfer_account_id to invoicing config page
* Improve domain reconciliation widget

View File

@@ -30,9 +30,11 @@
'wizard/account_invoice_mark_sent_view.xml',
'wizard/account_group_generate_view.xml',
'wizard/account_payment_register_views.xml',
'wizard/account_move_reversal.xml',
'security/ir.model.access.csv',
# 'report/invoice_report.xml', # TODO
],
"views/res_partner.xml",
],
# 'qweb': ['static/src/xml/account_payment.xml'],
'installable': True,
# "post_init_hook": "post_init_hook",

View File

@@ -0,0 +1,15 @@
diff --git a/addons/account/__init__.py b/addons/account/__init__.py
index 138004b0849..07e6475f760 100644
--- a/addons/account/__init__.py
+++ b/addons/account/__init__.py
@@ -45,7 +45,9 @@ def _auto_install_l10n(env):
module_list.append('l10n_de_skr03')
module_list.append('l10n_de_skr04')
else:
- if env['ir.module.module'].search([('name', '=', 'l10n_' + country_code.lower())]):
+ if env['ir.module.module'].search([('name', '=', 'l10n_%s_oca' % country_code.lower())]):
+ module_list.append('l10n_%s_oca' % country_code.lower())
+ elif env['ir.module.module'].search([('name', '=', 'l10n_' + country_code.lower())]):
module_list.append('l10n_' + country_code.lower())
else:
module_list.append('l10n_generic_coa')

View File

@@ -1,691 +0,0 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * account_usability
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 14.0\n"
"Report-Msgid-Bugs-To: \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: account_usability
#: code:addons/account_usability/wizard/account_group_generate.py:0
#, python-format
msgid ""
"%d account groups already exists in company '%s'. This wizard is designed to"
" generate account groups from scratch."
msgstr ""
#. module: account_usability
#: model:ir.model,name:account_usability.model_account_account
msgid "Account"
msgstr ""
#. module: account_usability
#: code:addons/account_usability/wizard/account_group_generate.py:0
#, python-format
msgid "Account Groups"
msgstr ""
#. module: account_usability
#: model:ir.model,name:account_usability.model_account_move_reversal
msgid "Account Move Reversal"
msgstr ""
#. module: account_usability
#: model:ir.model,name:account_usability.model_account_reconciliation_widget
msgid "Account Reconciliation widget"
msgstr ""
#. module: account_usability
#: model:ir.model.fields,field_description:account_usability.field_account_journal__account_type_current_assets_id
msgid "Account Type Current Assets"
msgstr ""
#. module: account_usability
#: model:ir.model.fields,field_description:account_usability.field_account_journal__account_type_current_liabilities_id
msgid "Account Type Current Liabilities"
msgstr ""
#. module: account_usability
#: model:ir.model.fields,field_description:account_usability.field_account_move_line__account_reconcile
msgid "Allow Reconciliation"
msgstr ""
#. module: account_usability
#: model:ir.model.constraint,message:account_usability.constraint_account_analytic_account_code_company_unique
msgid ""
"An analytic account with the same code already exists in the same company!"
msgstr ""
#. module: account_usability
#: model:ir.model,name:account_usability.model_account_analytic_account
msgid "Analytic Account"
msgstr ""
#. module: account_usability
#: model_terms:ir.ui.view,arch_db:account_usability.view_bank_statement_form
msgid "Are you sure to unreconcile all the entrie of the bank statement?"
msgstr ""
#. module: account_usability
#: model:ir.model.fields,help:account_usability.field_account_bank_statement_line__partner_bank_id
#: model:ir.model.fields,help:account_usability.field_account_move__partner_bank_id
msgid ""
"Bank Account Number to which the invoice will be paid. A Company bank "
"account if this is a Customer Invoice or Vendor Credit Note, otherwise a "
"Partner bank account number."
msgstr ""
#. module: account_usability
#: model:ir.ui.menu,name:account_usability.res_partner_bank_account_config_menu
msgid "Bank Accounts"
msgstr ""
#. module: account_usability
#: model:ir.model,name:account_usability.model_account_bank_statement
msgid "Bank Statement"
msgstr ""
#. module: account_usability
#: model:ir.model,name:account_usability.model_account_bank_statement_line
msgid "Bank Statement Line"
msgstr ""
#. module: account_usability
#: model:ir.ui.menu,name:account_usability.res_bank_account_config_menu
msgid "Banks"
msgstr ""
#. module: account_usability
#: model_terms:ir.ui.view,arch_db:account_usability.account_group_generate_form
#: model_terms:ir.ui.view,arch_db:account_usability.account_invoice_mark_sent_form
msgid "Cancel"
msgstr ""
#. module: account_usability
#: model:ir.model.fields,help:account_usability.field_account_move_line__account_reconcile
msgid ""
"Check this box if this account allows invoices & payments matching of "
"journal items."
msgstr ""
#. module: account_usability
#: model_terms:ir.ui.view,arch_db:account_usability.view_account_search
msgid "Code"
msgstr ""
#. module: account_usability
#: model:ir.model,name:account_usability.model_res_company
msgid "Companies"
msgstr ""
#. module: account_usability
#: model:ir.model,name:account_usability.model_res_config_settings
msgid "Config Settings"
msgstr ""
#. module: account_usability
#: model:ir.model,name:account_usability.model_res_partner
msgid "Contact"
msgstr ""
#. module: account_usability
#: model:ir.model.fields,field_description:account_usability.field_account_group_generate__create_uid
#: model:ir.model.fields,field_description:account_usability.field_account_invoice_mark_sent__create_uid
msgid "Created by"
msgstr ""
#. module: account_usability
#: model:ir.model.fields,field_description:account_usability.field_account_group_generate__create_date
#: model:ir.model.fields,field_description:account_usability.field_account_invoice_mark_sent__create_date
msgid "Created on"
msgstr ""
#. module: account_usability
#: model:ir.model.fields,help:account_usability.field_account_move_line__matched_credit_ids
msgid "Credit journal items that are matched with this journal item."
msgstr ""
#. module: account_usability
#: model_terms:ir.ui.view,arch_db:account_usability.view_account_move_line_filter
msgid "Current Year"
msgstr ""
#. module: account_usability
#: model:ir.model.fields,field_description:account_usability.field_account_bank_statement_line__date
#: model:ir.model.fields,field_description:account_usability.field_account_move__date
#: model:ir.model.fields,field_description:account_usability.field_account_payment__date
msgid "Date"
msgstr ""
#. module: account_usability
#: model:ir.model.fields,help:account_usability.field_account_move_line__matched_debit_ids
msgid "Debit journal items that are matched with this journal item."
msgstr ""
#. module: account_usability
#: model_terms:ir.ui.view,arch_db:account_usability.view_account_move_line_filter
msgid "Debit or Credit"
msgstr ""
#. module: account_usability
#: model:ir.model.fields,field_description:account_usability.field_account_account__display_name
#: model:ir.model.fields,field_description:account_usability.field_account_analytic_account__display_name
#: model:ir.model.fields,field_description:account_usability.field_account_bank_statement__display_name
#: model:ir.model.fields,field_description:account_usability.field_account_bank_statement_line__display_name
#: model:ir.model.fields,field_description:account_usability.field_account_group_generate__display_name
#: model:ir.model.fields,field_description:account_usability.field_account_incoterms__display_name
#: model:ir.model.fields,field_description:account_usability.field_account_invoice_mark_sent__display_name
#: model:ir.model.fields,field_description:account_usability.field_account_invoice_report__display_name
#: model:ir.model.fields,field_description:account_usability.field_account_journal__display_name
#: model:ir.model.fields,field_description:account_usability.field_account_move__display_name
#: model:ir.model.fields,field_description:account_usability.field_account_move_line__display_name
#: model:ir.model.fields,field_description:account_usability.field_account_move_reversal__display_name
#: model:ir.model.fields,field_description:account_usability.field_account_partial_reconcile__display_name
#: model:ir.model.fields,field_description:account_usability.field_product_supplierinfo__display_name
#: model:ir.model.fields,field_description:account_usability.field_product_template__display_name
#: model:ir.model.fields,field_description:account_usability.field_res_company__display_name
#: model:ir.model.fields,field_description:account_usability.field_res_config_settings__display_name
#: model:ir.model.fields,field_description:account_usability.field_res_partner__display_name
msgid "Display Name"
msgstr ""
#. module: account_usability
#: model:ir.model.fields,field_description:account_usability.field_account_bank_statement_line__invoice_date_due
#: model:ir.model.fields,field_description:account_usability.field_account_move__invoice_date_due
#: model:ir.model.fields,field_description:account_usability.field_account_payment__invoice_date_due
msgid "Due Date"
msgstr ""
#. module: account_usability
#: model:ir.model.fields,field_description:account_usability.field_account_bank_statement__end_date
#: model_terms:ir.ui.view,arch_db:account_usability.view_bank_statement_search
msgid "End Date"
msgstr ""
#. module: account_usability
#: model:ir.model,name:account_usability.model_account_fiscal_position
#: model:ir.model.fields,field_description:account_usability.field_account_bank_statement_line__fiscal_position_id
#: model:ir.model.fields,field_description:account_usability.field_account_move__fiscal_position_id
#: model:ir.model.fields,field_description:account_usability.field_account_payment__fiscal_position_id
#: model:ir.model.fields,field_description:account_usability.field_res_partner__property_account_position_id
#: model:ir.model.fields,field_description:account_usability.field_res_users__property_account_position_id
msgid "Fiscal Position"
msgstr ""
#. module: account_usability
#: model:ir.model,name:account_usability.model_account_fiscalyear
msgid "Fiscal Year"
msgstr ""
#. module: account_usability
#: model:ir.model.fields,help:account_usability.field_account_bank_statement_line__fiscal_position_id
#: model:ir.model.fields,help:account_usability.field_account_move__fiscal_position_id
#: model:ir.model.fields,help:account_usability.field_account_payment__fiscal_position_id
msgid ""
"Fiscal positions are used to adapt taxes and accounts for particular "
"customers or sales orders/invoices. The default value comes from the "
"customer."
msgstr ""
#. module: account_usability
#: model:ir.model.fields,field_description:account_usability.field_account_move_line__full_reconcile_id
msgid "Full Reconcile"
msgstr ""
#. module: account_usability
#: model_terms:ir.ui.view,arch_db:account_usability.view_account_move_line_filter
msgid "Fully Reconciled"
msgstr ""
#. module: account_usability
#: model_terms:ir.ui.view,arch_db:account_usability.account_group_generate_form
msgid "Generate"
msgstr ""
#. module: account_usability
#: model:ir.actions.act_window,name:account_usability.account_group_generate_action
#: model:ir.model,name:account_usability.model_account_group_generate
#: model:ir.ui.menu,name:account_usability.account_group_generate_menu
msgid "Generate Account Groups"
msgstr ""
#. module: account_usability
#: model_terms:ir.ui.view,arch_db:account_usability.account_group_generate_form
msgid "Generate account groups"
msgstr ""
#. module: account_usability
#: model_terms:ir.ui.view,arch_db:account_usability.view_account_analytic_account_search
#: model_terms:ir.ui.view,arch_db:account_usability.view_account_search
msgid "Group"
msgstr ""
#. module: account_usability
#: model_terms:ir.ui.view,arch_db:account_usability.view_account_journal_search
msgid "Group By"
msgstr ""
#. module: account_usability
#: model:ir.model.fields,field_description:account_usability.field_account_bank_statement_line__has_attachment
#: model:ir.model.fields,field_description:account_usability.field_account_move__has_attachment
#: model:ir.model.fields,field_description:account_usability.field_account_payment__has_attachment
msgid "Has Attachment"
msgstr ""
#. module: account_usability
#: model:ir.model.fields,field_description:account_usability.field_account_bank_statement_line__has_discount
#: model:ir.model.fields,field_description:account_usability.field_account_move__has_discount
#: model:ir.model.fields,field_description:account_usability.field_account_payment__has_discount
msgid "Has Discount"
msgstr ""
#. module: account_usability
#: model:ir.model.fields,field_description:account_usability.field_account_bank_statement__hide_bank_statement_balance
#: model:ir.model.fields,field_description:account_usability.field_account_journal__hide_bank_statement_balance
msgid "Hide Bank Statement Balance"
msgstr ""
#. module: account_usability
#: model:ir.model.fields,field_description:account_usability.field_account_account__id
#: model:ir.model.fields,field_description:account_usability.field_account_analytic_account__id
#: model:ir.model.fields,field_description:account_usability.field_account_bank_statement__id
#: model:ir.model.fields,field_description:account_usability.field_account_bank_statement_line__id
#: model:ir.model.fields,field_description:account_usability.field_account_group_generate__id
#: model:ir.model.fields,field_description:account_usability.field_account_incoterms__id
#: model:ir.model.fields,field_description:account_usability.field_account_invoice_mark_sent__id
#: model:ir.model.fields,field_description:account_usability.field_account_invoice_report__id
#: model:ir.model.fields,field_description:account_usability.field_account_journal__id
#: model:ir.model.fields,field_description:account_usability.field_account_move__id
#: model:ir.model.fields,field_description:account_usability.field_account_move_line__id
#: model:ir.model.fields,field_description:account_usability.field_account_move_reversal__id
#: model:ir.model.fields,field_description:account_usability.field_account_partial_reconcile__id
#: model:ir.model.fields,field_description:account_usability.field_product_supplierinfo__id
#: model:ir.model.fields,field_description:account_usability.field_product_template__id
#: model:ir.model.fields,field_description:account_usability.field_res_company__id
#: model:ir.model.fields,field_description:account_usability.field_res_config_settings__id
#: model:ir.model.fields,field_description:account_usability.field_res_partner__id
msgid "ID"
msgstr ""
#. module: account_usability
#: model:ir.model,name:account_usability.model_account_incoterms
msgid "Incoterms"
msgstr ""
#. module: account_usability
#: model:ir.model.fields,field_description:account_usability.field_res_config_settings__transfer_account_id
msgid "Inter-Banks Transfer Account"
msgstr ""
#. module: account_usability
#: model:ir.model.fields,help:account_usability.field_res_config_settings__transfer_account_id
msgid ""
"Intermediary account used when moving money from a liquidity account to "
"another"
msgstr ""
#. module: account_usability
#: model:ir.model.fields,help:account_usability.field_account_move_line__product_barcode
msgid "International Article Number used for product identification."
msgstr ""
#. module: account_usability
#: model:ir.model,name:account_usability.model_account_invoice
#: model:ir.model.fields,field_description:account_usability.field_res_partner__invoice_warn
#: model:ir.model.fields,field_description:account_usability.field_res_users__invoice_warn
msgid "Invoice"
msgstr ""
#. module: account_usability
#: model_terms:ir.ui.view,arch_db:account_usability.view_company_form
msgid "Invoice Legal Terms"
msgstr ""
#. module: account_usability
#: model:ir.model,name:account_usability.model_account_invoice_line
msgid "Invoice Line"
msgstr ""
#. module: account_usability
#: model_terms:ir.ui.view,arch_db:account_usability.account_invoice_report_tree
msgid "Invoices Analysis"
msgstr ""
#. module: account_usability
#: model:ir.model,name:account_usability.model_account_invoice_report
msgid "Invoices Statistics"
msgstr ""
#. module: account_usability
#: model:ir.model,name:account_usability.model_account_journal
#: model:ir.model.fields,field_description:account_usability.field_account_bank_statement_line__journal_id
#: model:ir.model.fields,field_description:account_usability.field_account_move__journal_id
#: model:ir.model.fields,field_description:account_usability.field_account_payment__journal_id
msgid "Journal"
msgstr ""
#. module: account_usability
#: model:ir.model,name:account_usability.model_account_move
msgid "Journal Entry"
msgstr ""
#. module: account_usability
#: model:ir.model,name:account_usability.model_account_move_line
msgid "Journal Item"
msgstr ""
#. module: account_usability
#: model:ir.model.fields,field_description:account_usability.field_account_account____last_update
#: model:ir.model.fields,field_description:account_usability.field_account_analytic_account____last_update
#: model:ir.model.fields,field_description:account_usability.field_account_bank_statement____last_update
#: model:ir.model.fields,field_description:account_usability.field_account_bank_statement_line____last_update
#: model:ir.model.fields,field_description:account_usability.field_account_group_generate____last_update
#: model:ir.model.fields,field_description:account_usability.field_account_incoterms____last_update
#: model:ir.model.fields,field_description:account_usability.field_account_invoice_mark_sent____last_update
#: model:ir.model.fields,field_description:account_usability.field_account_invoice_report____last_update
#: model:ir.model.fields,field_description:account_usability.field_account_journal____last_update
#: model:ir.model.fields,field_description:account_usability.field_account_move____last_update
#: model:ir.model.fields,field_description:account_usability.field_account_move_line____last_update
#: model:ir.model.fields,field_description:account_usability.field_account_move_reversal____last_update
#: model:ir.model.fields,field_description:account_usability.field_account_partial_reconcile____last_update
#: model:ir.model.fields,field_description:account_usability.field_product_supplierinfo____last_update
#: model:ir.model.fields,field_description:account_usability.field_product_template____last_update
#: model:ir.model.fields,field_description:account_usability.field_res_company____last_update
#: model:ir.model.fields,field_description:account_usability.field_res_config_settings____last_update
#: model:ir.model.fields,field_description:account_usability.field_res_partner____last_update
msgid "Last Modified on"
msgstr ""
#. module: account_usability
#: model:ir.model.fields,field_description:account_usability.field_account_group_generate__write_uid
#: model:ir.model.fields,field_description:account_usability.field_account_invoice_mark_sent__write_uid
msgid "Last Updated by"
msgstr ""
#. module: account_usability
#: model:ir.model.fields,field_description:account_usability.field_account_group_generate__write_date
#: model:ir.model.fields,field_description:account_usability.field_account_invoice_mark_sent__write_date
msgid "Last Updated on"
msgstr ""
#. module: account_usability
#: model_terms:ir.ui.view,arch_db:account_usability.view_company_form
msgid "Legal Terms"
msgstr ""
#. module: account_usability
#: model:ir.model.fields,field_description:account_usability.field_res_company__static_invoice_terms
msgid "Legal Terms on Invoice"
msgstr ""
#. module: account_usability
#: model:ir.model.fields,field_description:account_usability.field_account_group_generate__level
msgid "Level"
msgstr ""
#. module: account_usability
#: model:ir.actions.act_window,name:account_usability.account_invoice_mark_sent_action
#: model_terms:ir.ui.view,arch_db:account_usability.account_invoice_mark_sent_form
msgid "Mark as Sent"
msgstr ""
#. module: account_usability
#: model:ir.model,name:account_usability.model_account_invoice_mark_sent
#: model_terms:ir.ui.view,arch_db:account_usability.account_invoice_mark_sent_form
msgid "Mark invoices as sent"
msgstr ""
#. module: account_usability
#: model_terms:ir.ui.view,arch_db:account_usability.view_account_invoice_filter
msgid "Missing Attachment"
msgstr ""
#. module: account_usability
#: model:ir.model,name:account_usability.model_account_partial_reconcile
msgid "Partial Reconcile"
msgstr ""
#. module: account_usability
#: model:ir.model.fields,field_description:account_usability.field_account_move_line__matched_credit_ids
msgid "Partial Reconcile Credit"
msgstr ""
#. module: account_usability
#: model:ir.model.fields,field_description:account_usability.field_account_move_line__matched_debit_ids
msgid "Partial Reconcile Debit"
msgstr ""
#. module: account_usability
#: model:ir.model.fields,field_description:account_usability.field_account_invoice_report__industry_id
msgid "Partner Industry"
msgstr ""
#. module: account_usability
#: model:ir.model.fields,field_description:account_usability.field_account_bank_statement_line__invoice_payment_term_id
#: model:ir.model.fields,field_description:account_usability.field_account_move__invoice_payment_term_id
#: model:ir.model.fields,field_description:account_usability.field_account_payment__invoice_payment_term_id
msgid "Payment Terms"
msgstr ""
#. module: account_usability
#: code:addons/account_usability/models/account_move.py:0
#, python-format
msgid "Please post the following entries before reconciliation :"
msgstr ""
#. module: account_usability
#: model:ir.model.fields,field_description:account_usability.field_account_group_generate__name_prefix
msgid "Prefix"
msgstr ""
#. module: account_usability
#: model:ir.model,name:account_usability.model_account_reconcile_model
msgid ""
"Preset to create journal entries during a invoices and payments matching"
msgstr ""
#. module: account_usability
#: model_terms:ir.ui.view,arch_db:account_usability.view_account_move_line_filter
msgid "Previous Year"
msgstr ""
#. module: account_usability
#: model_terms:ir.ui.view,arch_db:account_usability.view_move_form
msgid "Print"
msgstr ""
#. module: account_usability
#: model:ir.model.fields,field_description:account_usability.field_account_move_line__product_barcode
msgid "Product Barcode"
msgstr ""
#. module: account_usability
#: model:ir.model,name:account_usability.model_product_template
msgid "Product Template"
msgstr ""
#. module: account_usability
#: model:ir.model.fields,field_description:account_usability.field_product_product__purchase_price_type
#: model:ir.model.fields,field_description:account_usability.field_product_supplierinfo__purchase_price_type
#: model:ir.model.fields,field_description:account_usability.field_product_template__purchase_price_type
msgid "Purchase Price Type"
msgstr ""
#. module: account_usability
#: model:ir.model.fields,field_description:account_usability.field_account_bank_statement_line__partner_bank_id
#: model:ir.model.fields,field_description:account_usability.field_account_move__partner_bank_id
msgid "Recipient Bank"
msgstr ""
#. module: account_usability
#: model:ir.model.fields,field_description:account_usability.field_account_bank_statement_line__ref
#: model:ir.model.fields,field_description:account_usability.field_account_move__ref
#: model:ir.model.fields,field_description:account_usability.field_account_payment__ref
msgid "Reference"
msgstr ""
#. module: account_usability
#: model:ir.model.fields,field_description:account_usability.field_account_move_reversal__date
msgid "Reversal date"
msgstr ""
#. module: account_usability
#: model:ir.model.fields,field_description:account_usability.field_account_bank_statement_line__sale_dates
#: model:ir.model.fields,field_description:account_usability.field_account_move__sale_dates
#: model:ir.model.fields,field_description:account_usability.field_account_payment__sale_dates
msgid "Sale Dates"
msgstr ""
#. module: account_usability
#: model:ir.model.fields,field_description:account_usability.field_product_product__sale_price_type
#: model:ir.model.fields,field_description:account_usability.field_product_template__sale_price_type
msgid "Sale Price Type"
msgstr ""
#. module: account_usability
#: model:ir.model.fields,help:account_usability.field_res_partner__invoice_warn
#: model:ir.model.fields,help:account_usability.field_res_users__invoice_warn
msgid ""
"Selecting the \"Warning\" option will notify user with the message, "
"Selecting \"Blocking Message\" will throw an exception with the message and "
"block the flow. The Message has to be written in the next field."
msgstr ""
#. module: account_usability
#: model_terms:ir.ui.view,arch_db:account_usability.view_account_invoice_filter
msgid "Sent"
msgstr ""
#. module: account_usability
#: model:ir.model.fields,field_description:account_usability.field_account_bank_statement__start_date
#: model_terms:ir.ui.view,arch_db:account_usability.view_bank_statement_search
msgid "Start Date"
msgstr ""
#. module: account_usability
#: model:ir.model,name:account_usability.model_product_supplierinfo
msgid "Supplier Pricelist"
msgstr ""
#. module: account_usability
#: model_terms:ir.ui.view,arch_db:account_usability.product_supplierinfo_tree_view
msgid "Tax"
msgstr ""
#. module: account_usability
#: code:addons/account_usability/models/product.py:0
#, python-format
msgid "Tax excl."
msgstr ""
#. module: account_usability
#: code:addons/account_usability/models/product.py:0
#, python-format
msgid "Tax incl."
msgstr ""
#. module: account_usability
#: code:addons/account_usability/wizard/account_group_generate.py:0
#, python-format
msgid ""
"The code of account '%s' is %d caracters. It cannot be inferior to level "
"(%d)."
msgstr ""
#. module: account_usability
#: model:ir.model.fields,help:account_usability.field_res_partner__property_account_position_id
#: model:ir.model.fields,help:account_usability.field_res_users__property_account_position_id
msgid ""
"The fiscal position determines the taxes/accounts used for this contact."
msgstr ""
#. module: account_usability
#: code:addons/account_usability/wizard/account_group_generate.py:0
#, python-format
msgid "The level must be >= 1."
msgstr ""
#. module: account_usability
#: model:ir.model.fields,help:account_usability.field_account_bank_statement_line__sale_dates
#: model:ir.model.fields,help:account_usability.field_account_move__sale_dates
#: model:ir.model.fields,help:account_usability.field_account_payment__sale_dates
msgid ""
"This information appears on invoice qweb report (you may use it for your own"
" report)"
msgstr ""
#. module: account_usability
#: model_terms:ir.ui.view,arch_db:account_usability.account_group_generate_form
msgid ""
"This wizard is designed to auto-generate account groups from the chart of "
"account."
msgstr ""
#. module: account_usability
#: model_terms:ir.ui.view,arch_db:account_usability.account_invoice_mark_sent_form
msgid ""
"This wizard will mark as <i>sent</i> all the selected invoices in open or "
"paid state."
msgstr ""
#. module: account_usability
#: model_terms:ir.ui.view,arch_db:account_usability.view_account_invoice_filter
msgid "To Send"
msgstr ""
#. module: account_usability
#: model:ir.model.fields,field_description:account_usability.field_account_bank_statement_line__amount_total
#: model:ir.model.fields,field_description:account_usability.field_account_move__amount_total
#: model:ir.model.fields,field_description:account_usability.field_account_payment__amount_total
msgid "Total"
msgstr ""
#. module: account_usability
#: model_terms:ir.ui.view,arch_db:account_usability.res_config_settings_view_form
msgid ""
"Transit account when you transfer money from a bank account of your company "
"to another bank account of your company."
msgstr ""
#. module: account_usability
#: model_terms:ir.ui.view,arch_db:account_usability.view_account_journal_search
msgid "Type"
msgstr ""
#. module: account_usability
#: model_terms:ir.ui.view,arch_db:account_usability.view_bank_statement_form
msgid "Unreconcile All"
msgstr ""
#. module: account_usability
#: model_terms:ir.ui.view,arch_db:account_usability.view_account_move_line_filter
msgid "Unreconciled or Partially Reconciled"
msgstr ""
#. module: account_usability
#: model_terms:ir.ui.view,arch_db:account_usability.view_bank_statement_form
msgid "View Journal Entry"
msgstr ""
#. module: account_usability
#: model_terms:ir.ui.view,arch_db:account_usability.view_move_line_tree
msgid "View Journal Entry Form"
msgstr ""
#. module: account_usability
#: model:ir.model.fields,help:account_usability.field_account_bank_statement__hide_bank_statement_balance
#: model:ir.model.fields,help:account_usability.field_account_journal__hide_bank_statement_balance
msgid ""
"You may want to enable this option when your bank journal is generated from "
"a bank statement file that doesn't handle start/end balance (QIF for "
"instance) and you don't want to enter the start/end balance manually: it "
"will prevent the display of wrong information in the accounting dashboard "
"and on bank statements."
msgstr ""

View File

@@ -6,8 +6,8 @@ msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-06-08 14:47+0000\n"
"PO-Revision-Date: 2023-06-08 14:47+0000\n"
"POT-Creation-Date: 2024-07-07 14:47+0000\n"
"PO-Revision-Date: 2024-07-07 14:47+0000\n"
"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
@@ -23,7 +23,7 @@ msgid ""
"%d account groups already exists in company '%s'. This wizard is designed to"
" generate account groups from scratch."
msgstr ""
"%d des groupes de comptes existent déjà dans la société '%s'. Cet assistant "
"%d groupes de comptes existent déjà dans la société '%s'. Cet assistant "
"est conçu pour créer des groupes de comptes à partir de zéro."
#. module: account_usability_akretion
@@ -34,6 +34,23 @@ msgid ""
"A reverse journal entry <a href=# data-oe-model=account.move data-oe-"
"id=%d>%s</a> has been generated."
msgstr ""
"Une extourne <a href=# data-oe-model=account.move data-oe-"
"id=%d>%s</a> a été générée."
#. module: account_usability_akretion
#. odoo-python
#: code:addons/account_usability_akretion/wizard/account_move_reversal.py:0
#, python-format
msgid "%s reversed by %s"
msgstr "%s extourné par %s"
#. module: account_usability_akretion
#: model_terms:ir.ui.view,arch_db:account_usability_akretion.view_account_move_reversal
msgid ""
"You are about to reverse entries that have already been reversed or partially reversed (refund). Make sure it is intented.\n"
" Already reversed entries are the following :"
msgstr "Vous êtes sur le point d'extourner une pièce comptable déjà extournée, ou partiellement extournée (avoir). Vérifiez que c'est bien ce que vous souhaitez faire.\n"
" Les pièces comptables déjà extournées sont les suivantes :"
#. module: account_usability_akretion
#: model:ir.model,name:account_usability_akretion.model_account_account
@@ -50,7 +67,7 @@ msgstr "Groupes de comptes"
#. module: account_usability_akretion
#: model:ir.model,name:account_usability_akretion.model_account_move_reversal
msgid "Account Move Reversal"
msgstr "Extourne d'écritures"
msgstr "Extourne de l'écriture comptable"
#. module: account_usability_akretion
#: model:ir.model.fields,field_description:account_usability_akretion.field_account_move_line__account_reconcile
@@ -77,9 +94,10 @@ msgstr "Êtes-vous sûr de vouloir annuler cette facture ?"
#. module: account_usability_akretion
#: model_terms:ir.ui.view,arch_db:account_usability_akretion.view_move_form
msgid "Are you sure you want to cancel this journal entry?"
msgstr "Êtes-vous sûr de vouloir annuler cette écriture ?"
msgstr "Êtes-vous sûr de vouloir annuler cette pièce comptable ?"
#. module: account_usability_akretion
#: model:ir.model,name:account_usability_akretion.model_res_partner_bank
#: model:ir.ui.menu,name:account_usability_akretion.res_partner_bank_account_config_menu
msgid "Bank Accounts"
msgstr "Comptes bancaires"
@@ -101,18 +119,18 @@ msgid ""
"Check this box if this account allows invoices & payments matching of "
"journal items."
msgstr ""
"Cochez cette case si ce compte permet de faire du rapprochement entre "
"Cochez cette case si ce compte permet de faire du lettrage entre "
"factures et paiements."
#. module: account_usability_akretion
#: model_terms:ir.ui.view,arch_db:account_usability_akretion.view_account_search
msgid "Code"
msgstr "Code"
msgstr ""
#. module: account_usability_akretion
#: model_terms:ir.ui.view,arch_db:account_usability_akretion.view_account_invoice_filter
msgid "Commercial Partner"
msgstr "Parternaire commercial"
msgstr "Partenaire commercial"
#. module: account_usability_akretion
#: model:ir.model,name:account_usability_akretion.model_res_company
@@ -127,7 +145,7 @@ msgstr "Société"
#. module: account_usability_akretion
#: model:ir.model,name:account_usability_akretion.model_res_partner
msgid "Contact"
msgstr "Contact"
msgstr ""
#. module: account_usability_akretion
#: model:ir.model.fields,field_description:account_usability_akretion.field_account_group_generate__create_uid
@@ -144,12 +162,14 @@ msgstr "Créé le"
#. module: account_usability_akretion
#: model:ir.model.fields,help:account_usability_akretion.field_account_move_line__matched_credit_ids
msgid "Credit journal items that are matched with this journal item."
msgstr "Écritures comptables au crédit qui correspondent à cette écriture comptable."
msgstr ""
"Écritures comptables au crédit qui sont lettrées avec cette écriture comptable."
#. module: account_usability_akretion
#: model:ir.model.fields,help:account_usability_akretion.field_account_move_line__matched_debit_ids
msgid "Debit journal items that are matched with this journal item."
msgstr "Écritures comptables au débit qui correspondent avec cette écriture comptable."
msgstr ""
"Écritures comptables au débit qui sont lettrées avec cette écriture comptable."
#. module: account_usability_akretion
#: model_terms:ir.ui.view,arch_db:account_usability_akretion.view_account_move_line_filter
@@ -162,6 +182,14 @@ msgstr "Débit ou crédit"
msgid "Display Name"
msgstr "Nom affiché"
#. module: account_usability_akretion
#: model:ir.model.fields,field_description:account_usability_akretion.field_account_bank_statement_line__blocked
#: model:ir.model.fields,field_description:account_usability_akretion.field_account_move__blocked
#: model:ir.model.fields,field_description:account_usability_akretion.field_account_payment__blocked
#: model_terms:ir.ui.view,arch_db:account_usability_akretion.view_account_invoice_filter
msgid "Dispute"
msgstr "Litige"
#. module: account_usability_akretion
#: model:ir.model.fields,field_description:account_usability_akretion.field_account_bank_statement_line__invoice_date_due
#: model:ir.model.fields,field_description:account_usability_akretion.field_account_move__invoice_date_due
@@ -188,13 +216,13 @@ msgid ""
"customer."
msgstr ""
"Les positions fiscales sont utilisées pour adapter les taxes et les comptes "
"à des clients particuliers ou à des bons de commande/factures. La valeur "
"par défaut provient du client."
"à des clients spécifiques ou à des bons de commande/factures. La valeur par"
" défaut provient de la fiche client."
#. module: account_usability_akretion
#: model:ir.model.fields,field_description:account_usability_akretion.field_account_move_line__full_reconcile_id
msgid "Full Reconcile"
msgstr "Marque de lettrage"
msgstr "Lettrage total"
#. module: account_usability_akretion
#: model_terms:ir.ui.view,arch_db:account_usability_akretion.view_account_move_line_filter
@@ -235,29 +263,29 @@ msgstr "Possède une pièce jointe"
#: model:ir.model.fields,field_description:account_usability_akretion.field_account_move__has_discount
#: model:ir.model.fields,field_description:account_usability_akretion.field_account_payment__has_discount
msgid "Has Discount"
msgstr "A une réduction"
msgstr "A une remise"
#. module: account_usability_akretion
#: model:ir.model.fields,field_description:account_usability_akretion.field_account_journal__hide_bank_statement_balance
msgid "Hide and Disable Bank Statement Balance"
msgstr "Masquer et désactiver le solde du relevé bancaire"
msgstr "Masquer et désactiver le solde du relevé de compte"
#. module: account_usability_akretion
#: model:ir.model.fields,field_description:account_usability_akretion.field_account_group_generate__id
#: model:ir.model.fields,field_description:account_usability_akretion.field_account_invoice_mark_sent__id
msgid "ID"
msgstr "ID"
msgstr ""
#. module: account_usability_akretion
#: model:ir.model,name:account_usability_akretion.model_account_incoterms
msgid "Incoterms"
msgstr "Incoterms"
msgstr ""
#. module: account_usability_akretion
#: model:ir.model.fields,help:account_usability_akretion.field_account_move_line__product_barcode
msgid "International Article Number used for product identification."
msgstr ""
"Numéro d'article international (IAN) utilisé pour identifier cet article."
"Numéro d'article international utilisé pour identifier cet article."
#. module: account_usability_akretion
#: model:ir.model.fields,field_description:account_usability_akretion.field_res_partner__invoice_warn
@@ -273,7 +301,7 @@ msgstr "Mentions légales sur les factures"
#. module: account_usability_akretion
#: model:ir.model,name:account_usability_akretion.model_account_invoice_report
msgid "Invoices Statistics"
msgstr "Statistiques des factures"
msgstr "Statistiques de facturation"
#. module: account_usability_akretion
#: model:ir.model,name:account_usability_akretion.model_account_journal
@@ -281,7 +309,7 @@ msgstr "Statistiques des factures"
#: model:ir.model.fields,field_description:account_usability_akretion.field_account_move__journal_id
#: model:ir.model.fields,field_description:account_usability_akretion.field_account_payment__journal_id
msgid "Journal"
msgstr "Journal"
msgstr ""
#. module: account_usability_akretion
#: model:ir.model,name:account_usability_akretion.model_account_move
@@ -353,13 +381,6 @@ msgstr "Divers"
msgid "Missing Attachment"
msgstr "Pièce jointe manquante"
#. module: account_usability_akretion
#. odoo-python
#: code:addons/account_usability_akretion/wizard/account_move_reversal.py:0
#, python-format
msgid "Move '%s' has already been reversed by move '%s'."
msgstr "L'écritures '%s' a déjà été annulée par l'écritures '%s'."
#. module: account_usability_akretion
#: model:ir.model,name:account_usability_akretion.model_account_partial_reconcile
msgid "Partial Reconcile"
@@ -383,7 +404,7 @@ msgstr "Secteur dactivité du partenaire"
#. module: account_usability_akretion
#: model_terms:ir.ui.view,arch_db:account_usability_akretion.view_account_invoice_filter
msgid "Payment Status"
msgstr "Etat de paiement"
msgstr "État de paiement"
#. module: account_usability_akretion
#: model:ir.model.fields,field_description:account_usability_akretion.field_account_bank_statement_line__invoice_payment_term_id
@@ -409,6 +430,11 @@ msgstr "Préfixe"
msgid "Print"
msgstr "Imprimer"
#. module: account_usability_akretion
#: model_terms:ir.ui.view,arch_db:account_usability_akretion.view_account_invoice_report_search
msgid "Product"
msgstr "Produit"
#. module: account_usability_akretion
#: model:ir.model.fields,field_description:account_usability_akretion.field_account_move_line__product_barcode
msgid "Product Barcode"
@@ -437,7 +463,7 @@ msgid ""
"block the flow. The Message has to be written in the next field."
msgstr ""
"Sélectionner l'option 'Avertissement' notifiera l'utilisateur avec le "
"Message. Sélectionner 'Message Bloquant' lancera une exception avec le "
"message. Sélectionner 'Message Bloquant' lancera une exception avec le "
"message et bloquera le flux. Le Message doit être encodé dans le champ "
"suivant."
@@ -468,8 +494,8 @@ msgid ""
"The code of account '%s' is %d caracters. It cannot be inferior to level "
"(%d)."
msgstr ""
"Le code du compte '%s' fait %d caractères. Il ne peut pas être de niveau "
"inférieur à (%d)."
"Le code du compte '%s' fait %d caractères. Il ne peut pas être "
"inférieur au niveau (%d)."
#. module: account_usability_akretion
#: model:ir.model.fields,help:account_usability_akretion.field_res_partner__property_account_position_id
@@ -486,6 +512,11 @@ msgstr ""
msgid "The level must be >= 1."
msgstr "Le niveau doit être >= 1."
#. module: account_usability_akretion
#: model_terms:ir.ui.view,arch_db:account_usability_akretion.view_move_form
msgid "This"
msgstr "Ce"
#. module: account_usability_akretion
#: model:ir.model.constraint,message:account_usability_akretion.constraint_account_incoterms_code_unique
msgid "This incoterm code already exists."
@@ -499,9 +530,8 @@ msgid ""
"This information appear on invoice qweb report (you may use it for your own "
"report)"
msgstr ""
"Cette information apparait sur le rapport qweb de la facture (vous "
"pouvez les utiliser pour votre propre rapport)"
"Cette information apparait sur le rapport qweb de la facture (vous pouvez "
"les utiliser pour votre propre rapport)"
#. module: account_usability_akretion
#. odoo-python
@@ -511,7 +541,7 @@ msgid ""
"This journal entry has been generated as the reverse of <a href=# data-oe-"
"model=account.move data-oe-id=%d>%s</a>."
msgstr ""
"Cette écriture de journal a été générée comme extourne de <a href=# data-oe-"
"Cette pièce comptable a été générée comme extourne de <a href=# data-oe-"
"model=account.move data-oe-id=%d>%s</a>."
#. module: account_usability_akretion
@@ -540,12 +570,12 @@ msgstr "À envoyer"
#: model:ir.model.fields,field_description:account_usability_akretion.field_account_move__amount_total
#: model:ir.model.fields,field_description:account_usability_akretion.field_account_payment__amount_total
msgid "Total"
msgstr "Total"
msgstr ""
#. module: account_usability_akretion
#: model_terms:ir.ui.view,arch_db:account_usability_akretion.view_account_journal_search
msgid "Type"
msgstr "Type"
msgstr ""
#. module: account_usability_akretion
#: model_terms:ir.ui.view,arch_db:account_usability_akretion.view_account_move_line_filter
@@ -565,11 +595,16 @@ msgid ""
"end balance is disabled. When you enable this option, you process the "
"statement lines without considering the start/end balance and you regularly "
"check the accounting balance of the bank account vs the amount of your bank "
"account (the 2 processes are managed separately)."
"account."
msgstr ""
"Lorsque cette option est activée, le solde de début et de fin ne s'affiche pas sur "
"la vue du formulaire de relevé bancaire, et la vérification du solde final vs "
"le solde final réel est désactivé. Lorsque vous activez cette option, vous traitez les "
"lignes de relevé sans tenir compte du solde de début/fin et vous vérifiez régulièrement "
"le solde du compte comptable bancaire vs le montant sur votre compte en banque"
"(les 2 processus sont gérés séparément)."
"Lorsque cette option est activée, le solde de début et de fin ne s'affiche "
"pas sur la vue du formulaire du relevé de compte, et la vérification du solde"
" final vs le solde final réel est désactivée. Lorsque vous activez cette "
"option, vous traitez les lignes de relevé de compte sans tenir compte du solde de "
"début/fin et vous vérifiez régulièrement le solde du compte "
"bancaire vs le montant sur votre compte en banque."
#. module: account_usability_akretion
#: model_terms:ir.ui.view,arch_db:account_usability_akretion.view_move_form
msgid "is marked as <b>disputed</b>."
msgstr "est marquée <b>en litige</b>."

View File

@@ -9,3 +9,4 @@ from . import res_partner
from . import res_company
#from . import product
from . import account_invoice_report
from . import res_partner_bank

View File

@@ -15,8 +15,7 @@ class AccountJournal(models.Model):
"the end balance vs the real end balance is disabled. When you enable "
"this option, you process the statement lines without considering "
"the start/end balance and you regularly check the accounting balance "
"of the bank account vs the amount of your bank account "
"(the 2 processes are managed separately)."
"of the bank account vs the amount of your bank account."
)
# Used to set default user_type_id on account fields via context
# account_type_current_assets_id = fields.Many2one(

View File

@@ -3,6 +3,7 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from datetime import timedelta
from collections import defaultdict
import logging
from odoo import api, fields, models, _
@@ -10,6 +11,7 @@ from odoo.exceptions import UserError
from odoo.osv import expression
from odoo.tools import float_is_zero
from odoo.tools.misc import format_date
from odoo.tools.safe_eval import safe_eval, time
_logger = logging.getLogger(__name__)
@@ -36,7 +38,7 @@ class AccountMove(models.Model):
compute="_compute_sales_dates",
help="This information appear on invoice qweb report "
"(you may use it for your own report)")
# There is a native "blocked" field (bool) on account.move.line
# There is a native "blocked" field (bool) on account.move.line
# We want to have that field on invoices to improve usability
# while keeping compatibility with the standard Odoo datamodel
blocked = fields.Boolean(
@@ -46,6 +48,8 @@ class AccountMove(models.Model):
string="Dispute",
tracking=True,
)
# Field search_account_id is just for search view
search_account_id = fields.Many2one(related='line_ids.account_id')
@api.depends("line_ids", "line_ids.blocked")
def _compute_blocked(self):
@@ -201,33 +205,14 @@ class AccountMove(models.Model):
move.suitable_journal_ids = self.env['account.journal'].search(domain)
def button_draft(self):
super().button_draft()
# Delete attached pdf invoice
try:
report_invoice = self.env['ir.actions.report']._get_report_from_name('account.report_invoice')
except IndexError:
report_invoice = False
if report_invoice and report_invoice.attachment:
for move in self.filtered(lambda x: x.move_type in ('out_invoice', 'out_refund')):
# The pb is that the filename is dynamic and related to move.state
# in v12, the feature was native and they used that kind of code:
# with invoice.env.do_in_draft():
# invoice.number, invoice.state = invoice.move_name, 'open'
# attachment = self.env.ref('account.account_invoices').retrieve_attachment(invoice)
# But do_in_draft() doesn't exists in v14
# If you know how we could do that, please update the code below
attachment = self.env['ir.attachment'].search([
('name', '=', self._get_invoice_attachment_name()),
('res_id', '=', move.id),
('res_model', '=', self._name),
('type', '=', 'binary'),
], limit=1)
if attachment:
attachment.unlink()
def _get_invoice_attachment_name(self):
self.ensure_one()
return '%s.pdf' % (self.name and self.name.replace('/', '_') or 'INV')
for move in self.filtered(lambda x: x.move_type in ('out_invoice', 'out_refund')):
for report_xmlid in ('account.account_invoices', 'account.account_invoices_without_payment'):
report = self.env.ref(report_xmlid)
attach = report.retrieve_attachment(move)
if attach:
attach.unlink()
super().button_draft()
def _get_accounting_date(self, invoice_date, has_tax):
# On vendor bills/refunds, we want date = invoice_date unless

View File

@@ -0,0 +1,21 @@
# Copyright 2015-2022 Akretion France (http://www.akretion.com/)
# @author: Mourad EL HADJ MIMOUNE <mourad.elhadj.mimoune@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import models
class ResPartnerBank(models.Model):
_inherit = 'res.partner.bank'
def name_get(self):
res = []
for acc in self:
name = acc.acc_number
if acc.currency_id:
name = "%s (%s)" % (name, acc.currency_id.name)
if acc.bank_id.name:
name = "%s - %s" % (name, acc.bank_id.name)
res += [(acc.id, name)]
return res

View File

@@ -35,4 +35,12 @@
</field>
</record>
<record id="account.action_account_invoice_report_all_supp" model="ir.actions.act_window">
<field name="view_mode">pivot,graph</field>
</record>
<record id="account.action_account_invoice_report_all" model="ir.actions.act_window">
<field name="view_mode">pivot,graph</field>
</record>
</odoo>

View File

@@ -99,6 +99,16 @@
</field>
</record>
<record id="view_account_move_filter" model="ir.ui.view">
<field name="model">account.move</field>
<field name="inherit_id" ref="account.view_account_move_filter"/>
<field name="arch" type="xml">
<field name="journal_id" position="after">
<field name="search_account_id"/>
</field>
</field>
</record>
<record id="view_move_line_form" model="ir.ui.view">
<field name="model">account.move.line</field>
<field name="inherit_id" ref="account.view_move_line_form"/>
@@ -157,5 +167,12 @@
</field>
</record>
<!-- Inherit action called from button of account.account form view
Make it similar to standard "Journal Items" menu account.action_account_moves_all_a -->
<record id="account.action_move_line_select" model="ir.actions.act_window">
<field name="domain">[('display_type', 'not in', ('line_section', 'line_note'))]</field>
<field name="view_id" ref="account.view_move_line_tree"/>
<field name="view_mode">tree,pivot,graph,kanban</field>
</record>
</odoo>

View File

@@ -16,7 +16,7 @@
<notebook position="inside">
<page string="Legal Terms" name="legal_terms">
<group string="Invoice Legal Terms" name="static_invoice_terms">
<field name="static_invoice_terms" nolabel="1"/>
<field name="static_invoice_terms" nolabel="1" colspan="2"/>
</group>
</page>
</notebook>

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2014-2024 Akretion (http://www.akretion.com/)
@author: Mourad EL HADJ MIMOUNE <mourad.elhadj.mimoune@akretion.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
-->
<odoo>
<record id="view_partner_simple_form" model="ir.ui.view">
<field name="name">base_usability.title.on.partner.simplified.form</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="account.view_partner_property_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='bank_ids']//field[@name='acc_number']" position="after">
<field name="currency_id" optional="hide"/>
</xpath>
</field>
</record>
</odoo>

View File

@@ -2,7 +2,7 @@
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import api, models, _
from odoo import api, fields, models, _
from dateutil.relativedelta import relativedelta
from odoo.exceptions import UserError
@@ -10,6 +10,23 @@ from odoo.exceptions import UserError
class AccountMoveReversal(models.TransientModel):
_inherit = 'account.move.reversal'
already_reversed_warning = fields.Text(compute="_compute_already_reversed_warning")
@api.depends("move_ids")
def _compute_already_reversed_warning(self):
for wizard in self:
moves = wizard.move_ids or self.env["account.move"].browse(self._context['active_ids'])
reversed_moves = self.env["account.move"].search([('reversed_entry_id', 'in', moves.ids)])
warning = ""
for already_reversed_move in reversed_moves.reversed_entry_id:
if warning:
warning += "\n"
reversed_by = " ; ".join(already_reversed_move.reversal_move_id.mapped("display_name"))
move_detail = _("%s reversed by %s") % (already_reversed_move.display_name, reversed_by)
warning += move_detail
wizard.already_reversed_warning = warning or False
# Set default reversal date to original move + 1 day
# and raise error if original move has already been reversed
@api.model
@@ -20,10 +37,4 @@ class AccountMoveReversal(models.TransientModel):
moves = amo.browse(self._context['active_ids'])
if len(moves) == 1:
res['date'] = moves.date + relativedelta(days=1)
reversed_move = amo.search([('reversed_entry_id', 'in', moves.ids)], limit=1)
if reversed_move:
raise UserError(_(
"Move '%s' has already been reversed by move '%s'.") % (
reversed_move.reversed_entry_id.display_name,
reversed_move.display_name))
return res

View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="view_account_move_reversal" model="ir.ui.view">
<field name="model">account.move.reversal</field>
<field name="inherit_id" ref="account.view_account_move_reversal"/>
<field name="arch" type="xml">
<field name="residual" position="before">
<div
class="alert alert-warning"
role="alert"
attrs="{'invisible': [('already_reversed_warning', '=', False)]}"
>
You are about to reverse entries that have already been reversed or partially reversed (refund). Make sure it is intented.
Already reversed entries are the following :
<field
name="already_reversed_warning"
/>
</div>
</field>
</field>
</record>
</odoo>

View File

@@ -15,7 +15,7 @@ class ResCompany(models.Model):
def _report_company_legal_name(self):
self.ensure_one()
if self.legal_type:
if self.legal_type and not self.name.endswith(self.legal_type):
name = '%s %s' % (self.name, self.legal_type)
else:
name = self.name

View File

@@ -4,7 +4,7 @@
{
'name': 'Mail Sender Bcc',
'version': '14.0.1.0.0',
'version': '16.0.1.0.0',
'category': 'Mail',
'license': 'AGPL-3',
'summary': "Always send a copy of the mail to the sender",
@@ -17,5 +17,5 @@ With this module, when Odoo sends an outgoing email, it adds the sender as Bcc (
'author': 'Akretion',
'website': 'https://github.com/akretion/odoo-usability',
'depends': ['base'],
'installable': False,
'installable': True,
}

View File

@@ -22,40 +22,9 @@
</field>
</record>
<!-- show name and ref in separate columns -->
<!-- ref is added in tree view by base_usability with optional="hide"
<record id="view_partner_tree" model="ir.ui.view">
<field name="name">Add ref in partner tree view</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_partner_tree"/>
<field name="arch" type="xml">
<field name="display_name" position="after">
<field name="name"/>
<field name="ref" optional="hide"/>
</field>
<field name="display_name" position="attributes">
<attribute name="invisible">1</attribute>
</field>
</field>
</record>
-->
<!--
The kanban view displays the field 'display_name', which has the [ref]
prefix, so no need to add to the view
<record id="res_partner_kanban_view" model="ir.ui.view">
<field name="name">Add ref in partner kanban view</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.res_partner_kanban_view"/>
<field name="arch" type="xml">
<field name="display_name" position="after">
<field name="ref"/>
</field>
<li t-if="record.email.raw_value" position="after">
<li t-if="record.ref.raw_value">Ref: <field name="ref"/></li>
</li>
</field>
</record>
Tree view: ref is added by base_usability with optional="hide"
Kanban view: it displays the field 'display_name', which has the [ref] prefix
-->
</odoo>

View File

@@ -6,8 +6,8 @@ msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-03-27 10:15+0000\n"
"PO-Revision-Date: 2024-03-27 10:15+0000\n"
"POT-Creation-Date: 2024-07-04 13:46+0000\n"
"PO-Revision-Date: 2024-07-04 13:46+0000\n"
"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
@@ -94,11 +94,21 @@ msgstr ""
msgid "Field"
msgstr ""
#. module: base_usability
#: model:ir.model,name:base_usability.model_ir_model_fields
msgid "Fields"
msgstr ""
#. module: base_usability
#: model_terms:ir.ui.view,arch_db:base_usability.res_country_search
msgid "Group By"
msgstr ""
#. module: base_usability
#: model_terms:ir.ui.view,arch_db:base_usability.view_res_partner_filter
msgid "Industry"
msgstr ""
#. module: base_usability
#: model_terms:ir.ui.view,arch_db:base_usability.view_module_filter
msgid "Installable"

View File

@@ -6,8 +6,8 @@ msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-03-27 10:15+0000\n"
"PO-Revision-Date: 2024-03-27 10:15+0000\n"
"POT-Creation-Date: 2024-07-04 13:47+0000\n"
"PO-Revision-Date: 2024-07-04 13:47+0000\n"
"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
@@ -94,15 +94,25 @@ msgstr "EORI :"
msgid "Field"
msgstr "Champ"
#. module: base_usability
#: model:ir.model,name:base_usability.model_ir_model_fields
msgid "Fields"
msgstr "Champs"
#. module: base_usability
#: model_terms:ir.ui.view,arch_db:base_usability.res_country_search
msgid "Group By"
msgstr "Grouper par"
#. module: base_usability
#: model_terms:ir.ui.view,arch_db:base_usability.view_res_partner_filter
msgid "Industry"
msgstr "Industrie"
#. module: base_usability
#: model_terms:ir.ui.view,arch_db:base_usability.view_module_filter
msgid "Installable"
msgstr ""
msgstr "Installable"
#. module: base_usability
#: model:ir.model,name:base_usability.model_ir_mail_server
@@ -119,7 +129,7 @@ msgstr "Portable :"
#. module: base_usability
#: model:ir.model,name:base_usability.model_ir_model
msgid "Models"
msgstr ""
msgstr "Modèles"
#. module: base_usability
#: model_terms:ir.ui.view,arch_db:base_usability.res_country_search
@@ -181,7 +191,7 @@ msgstr "Tél :"
#. module: base_usability
#: model:ir.model,name:base_usability.model_res_users
msgid "User"
msgstr ""
msgstr "Utilisateur"
#. module: base_usability
#. odoo-python

View File

@@ -69,6 +69,10 @@ class ResCompany(models.Model):
'value': hasattr(self, 'siren') and self.siren or False,
'label': _('SIREN:'),
},
'rcs_siren': {
'value': hasattr(self, 'siren') and self.siren and self.company_registry and f"{self.company_registry} {self.siren}",
'label': 'RCS',
},
'eori': {
'value': self._get_eori(),
'label': _('EORI:'),
@@ -82,6 +86,13 @@ class ResCompany(models.Model):
# 'legal_type' added by base_company_extension
if hasattr(self, 'legal_type') and self.legal_type:
options['capital']['label'] = _('%s with a capital of') % self.legal_type
# 'fax' added by OCA/partner-contact module 'partner_fax'
if hasattr(self.partner_id, 'fax'):
options['fax'] = {
'value': self.partner_id.fax or False,
'icon': '\U0001F5B7',
'label': _('Fax:'),
}
return options
def _get_eori(self):
@@ -102,7 +113,7 @@ class ResCompany(models.Model):
"""This method is designed to be inherited"""
# I decided not to put email in the default header because only a few very small
# companies have a generic company email address
line_details = [['phone', 'website', 'capital'], ['vat', 'siret', 'eori', 'ape']]
line_details = [['phone', 'website', 'rcs_siren', 'capital'], ['vat', 'siret', 'eori', 'ape']]
return line_details
# for reports

View File

@@ -45,6 +45,11 @@
<field name="phone" position="after">
<field name="mobile" optional="show" widget="phone" class="o_force_ltr"/>
</field>
<field name="city" position="before">
<field name="street" optional="hide"/>
<field name="street2" optional="hide"/>
<field name="zip" optional="hide"/>
</field>
</field>
</record>
@@ -58,6 +63,9 @@
<!-- for 'ref', change '=' to 'start with' -->
<attribute name="filter_domain">['|', '|', '|', '|', ('display_name', 'ilike', self), ('ref', '=ilike', self + '%'), ('email', 'ilike', self), ('vat', 'ilike', self), ('company_registry', 'ilike', self)]</attribute>
</field>
<group name="group_by" position="inside">
<filter name="group_industry" string="Industry" context="{'group_by': 'industry_id'}"/>
</group>
</field>
</record>

View File

@@ -0,0 +1,14 @@
diff --git a/addons/web/static/src/views/form/button_box/button_box.js b/addons/web/static/src/views/form/button_box/button_box.js
index 0dd1184ca2b..43139ab6e58 100644
--- a/addons/web/static/src/views/form/button_box/button_box.js
+++ b/addons/web/static/src/views/form/button_box/button_box.js
@@ -8,7 +8,8 @@ import { Component } from "@odoo/owl";
export class ButtonBox extends Component {
setup() {
const ui = useService("ui");
- this.getMaxButtons = () => [2, 2, 2, 4][ui.size] || 7;
+ /* HACK button box on 2 lines: || 7 => || 14 */
+ this.getMaxButtons = () => [2, 2, 2, 4][ui.size] || 14;
}
getButtons() {

View File

@@ -1,21 +0,0 @@
diff --git a/addons/web/controllers/export.py b/addons/web/controllers/export.py
index 5a1bbcb6b02..04c70131660 100644
--- a/addons/web/controllers/export.py
+++ b/addons/web/controllers/export.py
@@ -308,7 +308,6 @@ class Export(http.Controller):
def get_fields(self, model, prefix='', parent_name='',
import_compat=True, parent_field_type=None,
parent_field=None, exclude=None):
-
fields = self.fields_get(model)
if import_compat:
if parent_field_type in ['many2one', 'many2many']:
@@ -347,7 +346,7 @@ class Export(http.Controller):
# Add name field when expand m2o and m2m fields in import-compatible mode
val = prefix
name = parent_name + (parent_name and '/' or '') + field['string']
- record = {'id': ident, 'string': name,
+ record = {'id': ident, 'string': name + f' ({field_name})',
'value': val, 'children': False,
'field_type': field.get('type'),
'required': field.get('required'),

View File

@@ -0,0 +1,2 @@
from . import models
from . import wizards

View File

@@ -0,0 +1,48 @@
# Copyright 2019-2024 Akretion France (http://www.akretion.com)
# @author Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{
'name': 'Commission Simple',
'version': '16.0.1.0.0',
'category': 'Sales',
'license': 'AGPL-3',
'summary': 'Compute commissions for salesman',
'description': """
Commission Simple
=================
This module is a **simple** module to compute commission for salesman. From my experience, companies often use very specific methods to compute commissions and it's impossible to develop a module that can support all of them. So the goal of this module is just to have a simple base to build the company-specific commissionning system by inheriting this simple module.
Here is a short description of this module:
* create commission profiles using rules (per product category, per product, per product and customer, etc.),
* the commission rules can have a start and end date (optional),
* commissionning can happen on invoicing or on payment,
* each invoice line can only be commissionned to one salesman,
* commission reports are stored in Odoo.
This module has been written by Alexis de Lattre from Akretion
<alexis.delattre@akretion.com>.
""",
'author': 'Akretion',
'website': 'https://github.com/akretion/odoo-usability',
'depends': [
'account',
'date_range',
# this uses some related fields on account.move.line
# 'account_usability_akretion',
],
'data': [
'security/ir.model.access.csv',
'security/rule.xml',
'data/decimal_precision.xml',
'views/commission_profile.xml',
'views/commission_rule.xml',
'views/commission_result.xml',
# 'views/res_users.xml',
'views/res_config_settings.xml',
'wizards/commission_compute_view.xml',
],
'installable': True,
}

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo noupdate="1">
<record forcecreate="True" id="commission_rate" model="decimal.precision">
<field name="name">Commission Rate</field>
<field name="digits">2</field>
</record>
</odoo>

View File

@@ -0,0 +1,640 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * commission_simple
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-11-29 23:38+0000\n"
"PO-Revision-Date: 2024-11-29 23:38+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: commission_simple
#: model:ir.model.constraint,message:commission_simple.constraint_commission_result_salesman_period_company_unique
msgid ""
"A commission result already exists for this salesman/agent for the same "
"period."
msgstr ""
"Un état des commissions existe déjà pour ce vendeur/agent pour la même "
"période."
#. module: commission_simple
#. odoo-python
#: code:addons/commission_simple/models/commission_profile.py:0
#, python-format
msgid "A salesman must be selected when the assignment type is 'Salesman'."
msgstr ""
"Un vendeur doit être sélectionné lorsque le type d'affectation est "
"\"Vendeur\"."
#. module: commission_simple
#: model:ir.model.fields,field_description:commission_simple.field_commission_result__message_needaction
msgid "Action Needed"
msgstr "Action requise"
#. module: commission_simple
#: model:ir.model.fields,field_description:commission_simple.field_commission_profile__active
#: model:ir.model.fields,field_description:commission_simple.field_commission_rule__active
msgid "Active"
msgstr "Actif"
#. module: commission_simple
#: model:ir.model.fields,field_description:commission_simple.field_commission_result__activity_ids
msgid "Activities"
msgstr "Activités"
#. module: commission_simple
#: model:ir.model.fields,field_description:commission_simple.field_commission_result__activity_exception_decoration
msgid "Activity Exception Decoration"
msgstr "Style d'affichage de l'activité-alerte"
#. module: commission_simple
#: model:ir.model.fields,field_description:commission_simple.field_commission_result__activity_state
msgid "Activity State"
msgstr "État de l'activité"
#. module: commission_simple
#: model:ir.model.fields,field_description:commission_simple.field_commission_result__activity_type_icon
msgid "Activity Type Icon"
msgstr "Îcone du type d'activité"
#. module: commission_simple
#: model:ir.model.fields,field_description:commission_simple.field_commission_rule__applied_on
msgid "Apply On"
msgstr "Conditions"
#. module: commission_simple
#: model_terms:ir.ui.view,arch_db:commission_simple.commission_profile_form
#: model_terms:ir.ui.view,arch_db:commission_simple.commission_rule_search
msgid "Archived"
msgstr "Archivé"
#. module: commission_simple
#: model_terms:ir.ui.view,arch_db:commission_simple.commission_result_form
msgid "Are you sure you want to go back to draft?"
msgstr "Êtes-vous sûr de vouloir revenir à l'état brouillon ?"
#. module: commission_simple
#: model:ir.model.fields,field_description:commission_simple.field_commission_result__assign_type
#: model_terms:ir.ui.view,arch_db:commission_simple.commission_result_search
msgid "Assign Type"
msgstr "Type d'affectation"
#. module: commission_simple
#: model:ir.model.fields,field_description:commission_simple.field_commission_profile__assign_ids
#: model_terms:ir.ui.view,arch_db:commission_simple.commission_profile_form
msgid "Assignments"
msgstr "Assignations"
#. module: commission_simple
#: model:ir.model.fields,field_description:commission_simple.field_commission_result__message_attachment_count
msgid "Attachment Count"
msgstr "Nombre de pièces jointes"
#. module: commission_simple
#: model_terms:ir.ui.view,arch_db:commission_simple.commission_result_form
msgid "Back to Draft"
msgstr "Remettre en brouillon"
#. module: commission_simple
#: model_terms:ir.ui.view,arch_db:commission_simple.commission_compute_form
msgid "Cancel"
msgstr "Annuler"
#. module: commission_simple
#: model:ir.model.fields,field_description:commission_simple.field_account_move_line__commission_amount
msgid "Commission Amount"
msgstr "Montant de la commission"
#. module: commission_simple
#: model:ir.model.fields,field_description:commission_simple.field_account_move_line__commission_base
#: model:ir.model.fields,field_description:commission_simple.field_commission_rule__base
msgid "Commission Base"
msgstr "Base de la commission"
#. module: commission_simple
#: model:ir.model.fields,field_description:commission_simple.field_commission_result__line_ids
#: model_terms:ir.ui.view,arch_db:commission_simple.commission_result_form
msgid "Commission Lines"
msgstr "Lignes commission"
#. module: commission_simple
#: model:ir.model.fields,field_description:commission_simple.field_commission_compute__date_range_type_id
#: model:ir.model.fields,field_description:commission_simple.field_res_company__commission_date_range_type_id
#: model:ir.model.fields,field_description:commission_simple.field_res_config_settings__commission_date_range_type_id
msgid "Commission Periodicity"
msgstr "Périodicité de commission"
#. module: commission_simple
#: model:ir.model,name:commission_simple.model_commission_profile
#: model:ir.model.fields,field_description:commission_simple.field_commission_result__profile_id
msgid "Commission Profile"
msgstr "Profil de commission"
#. module: commission_simple
#: model:ir.model,name:commission_simple.model_commission_profile_assignment
msgid "Commission Profile Assignment"
msgstr "Affectation du profil de commission"
#. module: commission_simple
#: model:ir.actions.act_window,name:commission_simple.commission_profile_action
#: model:ir.ui.menu,name:commission_simple.commission_profile_menu
msgid "Commission Profiles"
msgstr "Profils de commission"
#. module: commission_simple
#: model:ir.model.fields,field_description:commission_simple.field_account_move_line__commission_rate
#: model:ir.model.fields,field_description:commission_simple.field_commission_rule__rate
msgid "Commission Rate"
msgstr "Taux de commission"
#. module: commission_simple
#: model:ir.model,name:commission_simple.model_commission_result
#: model:ir.model.fields,field_description:commission_simple.field_account_move_line__commission_result_id
msgid "Commission Result"
msgstr "État des commissions"
#. module: commission_simple
#: model:ir.model,name:commission_simple.model_commission_rule
msgid "Commission Rule"
msgstr "Règle de commission"
#. module: commission_simple
#: model:ir.actions.act_window,name:commission_simple.commission_rule_action
#: model:ir.model.fields,field_description:commission_simple.field_commission_profile__rule_ids
#: model:ir.ui.menu,name:commission_simple.commission_rule_menu
msgid "Commission Rules"
msgstr "Règles de commission"
#. module: commission_simple
#: model:ir.model.fields,field_description:commission_simple.field_commission_result__amount_total
msgid "Commission Total"
msgstr "Total des commissions"
#. module: commission_simple
#: model:ir.actions.act_window,name:commission_simple.commission_result_action
#: model:ir.ui.menu,name:commission_simple.commission_config_root
#: model:ir.ui.menu,name:commission_simple.commission_result_menu
#: model:ir.ui.menu,name:commission_simple.commission_root
#: model_terms:ir.ui.view,arch_db:commission_simple.res_config_settings_view_form
msgid "Commissions"
msgstr ""
#. module: commission_simple
#. odoo-python
#: code:addons/commission_simple/wizards/commission_compute.py:0
#, python-format
msgid "Commissions already exist for %(period)s in company %(company)s."
msgstr ""
"Des commissions existent déjà pour %(period)s dans la société %(company)s."
#. module: commission_simple
#: model:ir.model,name:commission_simple.model_res_company
msgid "Companies"
msgstr "Sociétés"
#. module: commission_simple
#: model:ir.model.fields,field_description:commission_simple.field_commission_compute__company_id
#: model:ir.model.fields,field_description:commission_simple.field_commission_profile__company_id
#: model:ir.model.fields,field_description:commission_simple.field_commission_profile_assignment__company_id
#: model:ir.model.fields,field_description:commission_simple.field_commission_result__company_id
#: model:ir.model.fields,field_description:commission_simple.field_commission_rule__company_id
msgid "Company"
msgstr "Société"
#. module: commission_simple
#: model:ir.model.fields,field_description:commission_simple.field_commission_result__company_currency_id
msgid "Company Currency"
msgstr "Devise de la société"
#. module: commission_simple
#: model_terms:ir.ui.view,arch_db:commission_simple.commission_compute_form
#: model_terms:ir.ui.view,arch_db:commission_simple.commission_rule_form
msgid "Compute"
msgstr "Calculer"
#. module: commission_simple
#: model:ir.actions.act_window,name:commission_simple.commission_compute_action
#: model:ir.model,name:commission_simple.model_commission_compute
#: model:ir.ui.menu,name:commission_simple.commission_compute_menu
msgid "Compute Commissions"
msgstr "Calculer les commissions"
#. module: commission_simple
#: model:ir.model,name:commission_simple.model_res_config_settings
msgid "Config Settings"
msgstr "Configuration"
#. module: commission_simple
#: model_terms:ir.ui.view,arch_db:commission_simple.commission_result_form
msgid "Confirm"
msgstr "Confirmer"
#. module: commission_simple
#: model:ir.model.fields,field_description:commission_simple.field_commission_compute__create_uid
#: model:ir.model.fields,field_description:commission_simple.field_commission_profile__create_uid
#: model:ir.model.fields,field_description:commission_simple.field_commission_profile_assignment__create_uid
#: model:ir.model.fields,field_description:commission_simple.field_commission_result__create_uid
#: model:ir.model.fields,field_description:commission_simple.field_commission_rule__create_uid
msgid "Created by"
msgstr "Créé par"
#. module: commission_simple
#: model:ir.model.fields,field_description:commission_simple.field_commission_compute__create_date
#: model:ir.model.fields,field_description:commission_simple.field_commission_profile__create_date
#: model:ir.model.fields,field_description:commission_simple.field_commission_profile_assignment__create_date
#: model:ir.model.fields,field_description:commission_simple.field_commission_result__create_date
#: model:ir.model.fields,field_description:commission_simple.field_commission_rule__create_date
msgid "Created on"
msgstr "Créé le"
#. module: commission_simple
#: model:ir.model.fields,field_description:commission_simple.field_commission_rule__partner_ids
msgid "Customers"
msgstr "Clients"
#. module: commission_simple
#: model:ir.model.fields,field_description:commission_simple.field_commission_compute__display_name
#: model:ir.model.fields,field_description:commission_simple.field_commission_profile__display_name
#: model:ir.model.fields,field_description:commission_simple.field_commission_profile_assignment__display_name
#: model:ir.model.fields,field_description:commission_simple.field_commission_result__display_name
#: model:ir.model.fields,field_description:commission_simple.field_commission_rule__display_name
msgid "Display Name"
msgstr "Nom affiché"
#. module: commission_simple
#: model:ir.model.fields.selection,name:commission_simple.selection__commission_result__state__done
#: model_terms:ir.ui.view,arch_db:commission_simple.commission_result_search
msgid "Done"
msgstr "Validé"
#. module: commission_simple
#: model:ir.model.fields.selection,name:commission_simple.selection__commission_result__state__draft
#: model_terms:ir.ui.view,arch_db:commission_simple.commission_result_search
msgid "Draft"
msgstr "Brouillon"
#. module: commission_simple
#: model:ir.model.fields,field_description:commission_simple.field_commission_rule__date_end
msgid "End Date"
msgstr "Date de fin"
#. module: commission_simple
#: model:ir.model.fields,field_description:commission_simple.field_commission_compute__date_end
#: model:ir.model.fields,field_description:commission_simple.field_commission_result__date_end
msgid "End date"
msgstr "Date de fin"
#. module: commission_simple
#: model:ir.model.fields,field_description:commission_simple.field_commission_result__message_follower_ids
msgid "Followers"
msgstr "Abonnés"
#. module: commission_simple
#: model:ir.model.fields,field_description:commission_simple.field_commission_result__message_partner_ids
msgid "Followers (Partners)"
msgstr "Abonnés (partenaires)"
#. module: commission_simple
#: model:ir.model.fields,help:commission_simple.field_commission_result__activity_type_icon
msgid "Font awesome icon e.g. fa-tasks"
msgstr "Îcone font-awesome, par exemple fa-task"
#. module: commission_simple
#: model:ir.model.fields.selection,name:commission_simple.selection__commission_rule__applied_on__4_global
msgid "Global"
msgstr ""
#. module: commission_simple
#: model:ir.model.fields,field_description:commission_simple.field_commission_result__has_message
msgid "Has Message"
msgstr "A un message"
#. module: commission_simple
#: model:ir.model.fields,field_description:commission_simple.field_commission_compute__id
#: model:ir.model.fields,field_description:commission_simple.field_commission_profile__id
#: model:ir.model.fields,field_description:commission_simple.field_commission_profile_assignment__id
#: model:ir.model.fields,field_description:commission_simple.field_commission_result__id
#: model:ir.model.fields,field_description:commission_simple.field_commission_rule__id
msgid "ID"
msgstr ""
#. module: commission_simple
#: model:ir.model.fields,field_description:commission_simple.field_commission_result__activity_exception_icon
msgid "Icon"
msgstr "Îcone"
#. module: commission_simple
#: model:ir.model.fields,help:commission_simple.field_commission_result__activity_exception_icon
msgid "Icon to indicate an exception activity."
msgstr "Îcone pour indiquer une activité-alerte"
#. module: commission_simple
#: model:ir.model.fields,help:commission_simple.field_commission_result__message_needaction
msgid "If checked, new messages require your attention."
msgstr "Si activé, de nouveaux messages nécessitent votre attention."
#. module: commission_simple
#: model:ir.model.fields,help:commission_simple.field_commission_result__message_has_error
msgid "If checked, some messages have a delivery error."
msgstr "Si activé, des messages ont une erreur d'envoi."
#. module: commission_simple
#: model:ir.model.fields.selection,name:commission_simple.selection__commission_profile__trigger_type__in_payment
msgid "In Payment and Paid"
msgstr "En paiement et payé"
#. module: commission_simple
#: model:ir.model.fields.selection,name:commission_simple.selection__commission_profile__trigger_type__invoice
msgid "Invoiced"
msgstr "Facturé"
#. module: commission_simple
#: model:ir.model.fields.selection,name:commission_simple.selection__commission_rule__base__invoiced
#: model_terms:ir.ui.view,arch_db:commission_simple.commission_result_form
msgid "Invoiced Amount"
msgstr "Montant facturé"
#. module: commission_simple
#: model:ir.model.fields,field_description:commission_simple.field_commission_result__message_is_follower
msgid "Is Follower"
msgstr "Est abonné"
#. module: commission_simple
#: model:ir.model,name:commission_simple.model_account_move_line
msgid "Journal Item"
msgstr "Écriture comptable"
#. module: commission_simple
#: model:ir.model.fields,field_description:commission_simple.field_commission_compute____last_update
#: model:ir.model.fields,field_description:commission_simple.field_commission_profile____last_update
#: model:ir.model.fields,field_description:commission_simple.field_commission_profile_assignment____last_update
#: model:ir.model.fields,field_description:commission_simple.field_commission_result____last_update
#: model:ir.model.fields,field_description:commission_simple.field_commission_rule____last_update
msgid "Last Modified on"
msgstr "Dernière modification le"
#. module: commission_simple
#: model:ir.model.fields,field_description:commission_simple.field_commission_compute__write_uid
#: model:ir.model.fields,field_description:commission_simple.field_commission_profile__write_uid
#: model:ir.model.fields,field_description:commission_simple.field_commission_profile_assignment__write_uid
#: model:ir.model.fields,field_description:commission_simple.field_commission_result__write_uid
#: model:ir.model.fields,field_description:commission_simple.field_commission_rule__write_uid
msgid "Last Updated by"
msgstr "Dernière mise à jour par"
#. module: commission_simple
#: model:ir.model.fields,field_description:commission_simple.field_commission_compute__write_date
#: model:ir.model.fields,field_description:commission_simple.field_commission_profile__write_date
#: model:ir.model.fields,field_description:commission_simple.field_commission_profile_assignment__write_date
#: model:ir.model.fields,field_description:commission_simple.field_commission_result__write_date
#: model:ir.model.fields,field_description:commission_simple.field_commission_rule__write_date
msgid "Last Updated on"
msgstr "Dernière mise à jour le"
#. module: commission_simple
#: model:ir.model.fields,field_description:commission_simple.field_commission_result__message_main_attachment_id
msgid "Main Attachment"
msgstr "Pièce jointe principale"
#. module: commission_simple
#: model:ir.model.fields.selection,name:commission_simple.selection__commission_rule__base__margin
msgid "Margin"
msgstr "Marge"
#. module: commission_simple
#: model_terms:ir.ui.view,arch_db:commission_simple.commission_rule_form
msgid "Match"
msgstr ""
#. module: commission_simple
#: model:ir.model.fields,field_description:commission_simple.field_account_move_line__commission_rule_id
msgid "Matched Commission Rule"
msgstr "Règle de commission associée"
#. module: commission_simple
#: model:ir.model.fields,field_description:commission_simple.field_commission_result__message_has_error
msgid "Message Delivery error"
msgstr "Erreur d'envoi du message"
#. module: commission_simple
#: model:ir.model.fields,field_description:commission_simple.field_commission_result__message_ids
msgid "Messages"
msgstr ""
#. module: commission_simple
#: model:ir.model.fields,field_description:commission_simple.field_commission_result__my_activity_date_deadline
msgid "My Activity Deadline"
msgstr "Date butoir de l'activité"
#. module: commission_simple
#: model:ir.model.fields,field_description:commission_simple.field_commission_profile__name
msgid "Name of the Profile"
msgstr "Nom du profil"
#. module: commission_simple
#: model:ir.model.fields,field_description:commission_simple.field_commission_result__activity_calendar_event_id
msgid "Next Activity Calendar Event"
msgstr "Prochaine activité du calendrier"
#. module: commission_simple
#: model:ir.model.fields,field_description:commission_simple.field_commission_result__activity_date_deadline
msgid "Next Activity Deadline"
msgstr "Date butoir de l'activité suivante"
#. module: commission_simple
#: model:ir.model.fields,field_description:commission_simple.field_commission_result__activity_summary
msgid "Next Activity Summary"
msgstr "Résumé de l'activité suivante"
#. module: commission_simple
#: model:ir.model.fields,field_description:commission_simple.field_commission_result__activity_type_id
msgid "Next Activity Type"
msgstr "Type de l'activité suivante"
#. module: commission_simple
#. odoo-python
#: code:addons/commission_simple/wizards/commission_compute.py:0
#, python-format
msgid "No commissions generated."
msgstr "Aucune commission n'a été générée."
#. module: commission_simple
#: model:ir.model.fields,field_description:commission_simple.field_commission_result__message_needaction_counter
msgid "Number of Actions"
msgstr "Nombre d'actions"
#. module: commission_simple
#: model:ir.model.fields,field_description:commission_simple.field_commission_result__message_has_error_counter
msgid "Number of errors"
msgstr "Nombre d'erreurs"
#. module: commission_simple
#: model:ir.model.fields,help:commission_simple.field_commission_result__message_needaction_counter
msgid "Number of messages requiring action"
msgstr "Nombre de messages nécessitant une action"
#. module: commission_simple
#: model:ir.model.fields,help:commission_simple.field_commission_result__message_has_error_counter
msgid "Number of messages with delivery error"
msgstr "Nombre de messages en échec d'envoi"
#. module: commission_simple
#: model:ir.model.fields.selection,name:commission_simple.selection__commission_profile__trigger_type__paid
msgid "Paid"
msgstr "Payé"
#. module: commission_simple
#: model:ir.model.fields,field_description:commission_simple.field_commission_compute__date_range_id
#: model:ir.model.fields,field_description:commission_simple.field_commission_result__date_range_id
#: model_terms:ir.ui.view,arch_db:commission_simple.commission_result_search
msgid "Period"
msgstr "Période"
#. module: commission_simple
#: model:ir.model.fields,field_description:commission_simple.field_commission_rule__product_categ_ids
#: model:ir.model.fields.selection,name:commission_simple.selection__commission_rule__applied_on__3_product_category
msgid "Product Categories"
msgstr "Catégories de produits"
#. module: commission_simple
#: model:ir.model.fields.selection,name:commission_simple.selection__commission_rule__applied_on__1_customer_product_category
msgid "Product Categories and Customers"
msgstr "Catégories de produits et clients"
#. module: commission_simple
#: model:ir.model.fields,field_description:commission_simple.field_account_move_line__product_categ_id
msgid "Product Category"
msgstr "Catégorie de produit"
#. module: commission_simple
#: model:ir.model.fields,field_description:commission_simple.field_commission_rule__product_ids
#: model:ir.model.fields.selection,name:commission_simple.selection__commission_rule__applied_on__2_product
msgid "Products"
msgstr "Produits"
#. module: commission_simple
#: model:ir.model.fields.selection,name:commission_simple.selection__commission_rule__applied_on__0_customer_product
msgid "Products and Customers"
msgstr "Produits et clients"
#. module: commission_simple
#: model:ir.model.fields,field_description:commission_simple.field_commission_profile_assignment__profile_id
#: model:ir.model.fields,field_description:commission_simple.field_commission_rule__profile_id
#: model_terms:ir.ui.view,arch_db:commission_simple.commission_rule_search
msgid "Profile"
msgstr "Profil"
#. module: commission_simple
#: model_terms:ir.ui.view,arch_db:commission_simple.commission_result_form
#: model_terms:ir.ui.view,arch_db:commission_simple.commission_rule_tree
msgid "Rate (%)"
msgstr "Taux (%)"
#. module: commission_simple
#: model:ir.model.constraint,message:commission_simple.constraint_commission_rule_rate_positive
msgid "Rate must be positive !"
msgstr "Le taux doit être positif !"
#. module: commission_simple
#: model:ir.model.fields,field_description:commission_simple.field_commission_result__activity_user_id
msgid "Responsible User"
msgstr "Utilisateur responsable"
#. module: commission_simple
#: model_terms:ir.ui.view,arch_db:commission_simple.commission_profile_form
msgid "Rules"
msgstr "Règles"
#. module: commission_simple
#. odoo-python
#: code:addons/commission_simple/models/commission_profile.py:0
#: model:ir.model.fields,field_description:commission_simple.field_commission_profile_assignment__user_id
#: model_terms:ir.ui.view,arch_db:commission_simple.commission_result_search
#, python-format
msgid "Salesman"
msgstr "Vendeur"
#. module: commission_simple
#: model:ir.model.fields,field_description:commission_simple.field_commission_result__partner_id
msgid "Salesman/Agent"
msgstr "Vendeur/Agent"
#. module: commission_simple
#: model:ir.model.fields,field_description:commission_simple.field_commission_profile__sequence
msgid "Sequence"
msgstr "Séquence"
#. module: commission_simple
#: model:ir.model.fields,field_description:commission_simple.field_commission_rule__date_start
msgid "Start Date"
msgstr "Date de début"
#. module: commission_simple
#: model:ir.model.fields,field_description:commission_simple.field_commission_compute__date_start
#: model:ir.model.fields,field_description:commission_simple.field_commission_result__date_start
msgid "Start date"
msgstr "Date de début"
#. module: commission_simple
#: model:ir.model.fields,field_description:commission_simple.field_commission_result__state
msgid "State"
msgstr "État"
#. module: commission_simple
#: model:ir.model.fields,help:commission_simple.field_commission_result__activity_state
msgid ""
"Status based on activities\n"
"Overdue: Due date is already passed\n"
"Today: Activity date is today\n"
"Planned: Future activities."
msgstr ""
"Statut basé sur les activités\n"
"En retard : La date d'échéance est déjà dépassée\n"
"Aujourd'hui : La date de l'activité est aujourd'hui\n"
"Planifié : Activités futures."
#. module: commission_simple
#: model:ir.model.constraint,message:commission_simple.constraint_commission_profile_assignment_company_user_uniq
msgid "This salesman already has an assignment in this company."
msgstr "Ce vendeur a déjà une assignation dans cette société."
#. module: commission_simple
#: model:ir.model.fields,field_description:commission_simple.field_commission_profile__trigger_type
msgid "Trigger"
msgstr "Déclencheur"
#. module: commission_simple
#: model:ir.model.fields,field_description:commission_simple.field_commission_profile_assignment__assign_type
msgid "Type"
msgstr ""
#. module: commission_simple
#: model:ir.model.fields,help:commission_simple.field_commission_result__activity_exception_decoration
msgid "Type of the exception activity on record."
msgstr "Type de l'activité-alerte sur l'enregistrement."
#. module: commission_simple
#: model:ir.model.fields,field_description:commission_simple.field_commission_result__website_message_ids
msgid "Website Messages"
msgstr "Messages du site Web"
#. module: commission_simple
#: model:ir.model.fields,help:commission_simple.field_commission_result__website_message_ids
msgid "Website communication history"
msgstr "Historique des échanges sur le site Web"
#. module: commission_simple
#. odoo-python
#: code:addons/commission_simple/models/commission_result.py:0
#, python-format
msgid "You cannot delete commission result %s because it is in done state."
msgstr ""
"Vous ne pouvez pas supprimer l'état de commission %s parce qu'il est à "
"l'état \"validé\"."

View File

@@ -0,0 +1,5 @@
from . import commission_profile
from . import commission_rule
from . import commission_result
from . import res_company
from . import account_move_line

View File

@@ -0,0 +1,90 @@
# Copyright 2019-2024 Akretion France (http://www.akretion.com/)
# @author Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import api, fields, models
from odoo.tools import float_is_zero
class AccountMoveLine(models.Model):
_inherit = 'account.move.line'
commission_result_id = fields.Many2one(
'commission.result', string='Commission Result', check_company=True)
commission_rule_id = fields.Many2one(
'commission.rule', 'Matched Commission Rule', ondelete='restrict', check_company=True)
commission_base = fields.Monetary('Commission Base', currency_field='company_currency_id')
commission_rate = fields.Float('Commission Rate', digits='Commission Rate')
commission_amount = fields.Monetary(
string='Commission Amount', currency_field='company_currency_id',
readonly=True, compute='_compute_commission_amount', store=True)
# to display on commission line
product_categ_id = fields.Many2one(
related='product_id.product_tmpl_id.categ_id')
@api.depends('commission_rate', 'commission_base')
def _compute_commission_amount(self):
for line in self:
commission_amount = False
if line.display_type == 'product':
commission_amount = line.company_currency_id.round(
line.commission_rate * line.commission_base / 100.0)
line.commission_amount = commission_amount
def _match_commission_rule(self, rules):
# commission rules are already in the right order
self.ensure_one()
for rule in rules:
if rule['date_start'] and rule['date_start'] > self.date:
continue
if rule['date_end'] and rule['date_end'] < self.date:
continue
if rule['applied_on'] == '0_customer_product':
if (
self.partner_id.id in
rule['partner_ids'] and
self.product_id.id in rule['product_ids']):
return rule
elif rule['applied_on'] == '1_customer_product_category':
if (
self.partner_id.id in
rule['partner_ids'] and
self.product_categ_id.id in rule['product_categ_ids']):
return rule
elif rule['applied_on'] == '2_product':
if self.product_id.id in rule['product_ids']:
return rule
elif rule['applied_on'] == '3_product_category':
if self.product_categ_id.id in rule['product_categ_ids']:
return rule
elif rule['applied_on'] == '4_global':
return rule
return False
def _prepare_commission_data(self, rule):
self.ensure_one()
rate_prec = self.env['decimal.precision'].precision_get('Commission Rate')
lvals = {
'commission_rule_id': rule['id'],
# company currency
# inherit this method to change the value below if you want to base on margin
# or something else
'commission_rate': rule['rate'],
}
if rule['base'] == 'margin':
# What do we do if it's negative ? For the moment, it adds a negative commission line
cost = 0
if self.product_id and self.product_uom_id:
# if the module account_invoice_margin from akretion/odoo-usability is installed
if hasattr(self, 'margin_company_currency'):
cost = self.margin_company_currency
else:
sign = self.move_id.move_type == 'out_refund' and -1 or 1
cost = self.product_id.standard_price * self.product_uom_id._compute_quantity(self.quantity, self.product_id.uom_id) * sign
lvals['commission_base'] = self.balance * -1 - cost
else:
lvals['commission_base'] = self.balance * -1
if float_is_zero(lvals['commission_rate'], precision_digits=rate_prec) or self.company_currency_id.is_zero(lvals['commission_base']):
return False
return lvals

View File

@@ -0,0 +1,125 @@
# Copyright Akretion France (http://www.akretion.com/)
# @author Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import fields, models, api, _
from odoo.exceptions import ValidationError
class CommissionProfile(models.Model):
_name = 'commission.profile'
_description = 'Commission Profile'
_order = 'sequence, id'
name = fields.Char(string='Name of the Profile', required=True)
active = fields.Boolean(string='Active', default=True)
sequence = fields.Integer()
company_id = fields.Many2one(
'res.company', string='Company', ondelete='cascade',
required=False, default=lambda self: self.env.company)
assign_ids = fields.One2many(
'commission.profile.assignment', 'profile_id', string="Assignments")
rule_ids = fields.One2many(
'commission.rule', 'profile_id', string='Commission Rules')
trigger_type = fields.Selection([
('invoice', 'Invoiced'),
('paid', 'Paid'),
('in_payment', 'In Payment and Paid'),
], default='paid', string='Trigger', required=True)
class CommissionProfileAssignment(models.Model):
_name = "commission.profile.assignment"
_description = "Commission Profile Assignment"
profile_id = fields.Many2one('commission.profile', ondelete='cascade')
company_id = fields.Many2one(
'res.company', string='Company', ondelete='cascade',
required=True, default=lambda self: self.env.company)
assign_type = fields.Selection(
'_assign_type_selection', default='user', required=True, string="Type")
user_id = fields.Many2one(
'res.users', compute="_compute_user_id", store=True, precompute=True, readonly=False,
ondelete="restrict", string="Salesman",
)
_sql_constraints = [
(
'company_user_uniq',
'unique(user_id, company_id)',
'This salesman already has an assignment in this company.')]
@api.model
def _assign_type_selection(self):
return [('user', _('Salesman'))]
@api.constrains('assign_type', 'user_id')
def _check_user(self):
for assignment in self:
if assignment.assign_type == 'user' and not assignment.user_id:
raise ValidationError(_("A salesman must be selected when the assignment type is 'Salesman'."))
@api.depends('assign_type')
def _compute_user_id(self):
for assign in self:
if assign.assign_type != 'user':
assign.user_id = False
def _get_partner(self):
self.ensure_one()
if self.assign_type == 'user':
return self.user_id.partner_id
return False
def _prepare_move_line_domain(self, date_range):
self.ensure_one()
domain = [
('display_type', '=', 'product'),
('move_id.move_type', 'in', ('out_invoice', 'out_refund')),
('date', '<=', date_range.date_end),
('company_id', '=', self.company_id.id),
('commission_result_id', '=', False),
('parent_state', '=', 'posted'),
]
if self.assign_type == 'user':
domain.append(('move_id.invoice_user_id', '=', self.user_id.id))
# TODO : for trigger 'paid' and 'in_payment', we would need to filter
# out the invoices paid after the end date of the commission period
if self.profile_id.trigger_type == 'paid':
domain.append(('move_id.payment_state', 'in', ('paid', 'reversed')))
elif self.profile_id.trigger_type == 'in_payment':
domain.append(('move_id.payment_state', 'in', ('in_payment', 'paid', 'reversed')))
elif self.profile_id.trigger_type == 'invoice':
domain.append(('date', '>=', date_range.date_start))
return domain
def _prepare_commission_result(self, date_range):
vals = {
'partner_id': self._get_partner().id,
'profile_id': self.profile_id.id,
'date_range_id': date_range.id,
'assign_type': self.assign_type,
'company_id': self.company_id.id,
}
return vals
def _generate_commission_result(self, date_range, rules):
self.ensure_one()
ilines = self.env['account.move.line'].search(
self._prepare_move_line_domain(date_range), order='date, move_id, sequence, id')
profile = self.profile_id
ilines2write = {}
for iline in ilines:
rule = iline._match_commission_rule(rules[profile.id])
if rule:
lvals = iline._prepare_commission_data(rule)
if lvals:
ilines2write[iline] = lvals
if ilines2write:
com_result = self.env['commission.result'].create(self._prepare_commission_result(date_range))
for iline, vals in ilines2write.items():
iline.write(dict(vals, commission_result_id=com_result.id))
return com_result
else:
return False

View File

@@ -0,0 +1,77 @@
# Copyright Akretion France (http://www.akretion.com/)
# @author Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import fields, models, api, _
from odoo.exceptions import UserError
class CommissionResult(models.Model):
_name = 'commission.result'
_description = "Commission Result"
_order = 'date_start desc'
_inherit = ['mail.thread', 'mail.activity.mixin']
partner_id = fields.Many2one(
'res.partner', string='Salesman/Agent', required=True, ondelete='restrict',
readonly=True, tracking=True)
profile_id = fields.Many2one(
'commission.profile', string='Commission Profile', readonly=True, tracking=True)
assign_type = fields.Selection('_assign_type_selection', readonly=True, tracking=True)
company_id = fields.Many2one(
'res.company', string='Company', ondelete='cascade',
required=True, readonly=True, default=lambda self: self.env.company, tracking=True)
company_currency_id = fields.Many2one(
related='company_id.currency_id', string='Company Currency', store=True)
date_range_id = fields.Many2one(
'date.range', required=True, string='Period', readonly=True, tracking=True)
date_start = fields.Date(related='date_range_id.date_start', store=True)
date_end = fields.Date(related='date_range_id.date_end', store=True)
line_ids = fields.One2many(
'account.move.line', 'commission_result_id', string='Commission Lines',
states={'done': [('readonly', True)]})
amount_total = fields.Monetary(
string='Commission Total', currency_field='company_currency_id',
compute='_compute_amount_total', store=True, tracking=True)
state = fields.Selection([
('draft', 'Draft'),
('done', 'Done'),
], default='draft', tracking=True)
# TODO copy amount to another field
# help='This is the total amount at the date of the computation of the commission')
@api.model
def _assign_type_selection(self):
return self.env['commission.profile.assignment']._assign_type_selection()
@api.depends('line_ids.commission_amount')
def _compute_amount_total(self):
rg_res = self.env['account.move.line'].read_group([('commission_result_id', 'in', self.ids)], ['commission_result_id', 'commission_amount:sum'], ['commission_result_id'])
mapped_data = dict([(x['commission_result_id'][0], x['commission_amount']) for x in rg_res])
for rec in self:
rec.amount_total = mapped_data.get(rec.id, 0)
def unlink(self):
for result in self:
if result.state == 'done':
raise UserError(_(
"You cannot delete commission result %s because it is in done state.") % result.display_name)
return super().unlink()
def draft2done(self):
self.write({'state': 'done'})
def backtodraft(self):
self.write({'state': 'draft'})
def name_get(self):
res = []
for result in self:
name = '%s (%s)' % (result.partner_id.name, result.date_range_id.name)
res.append((result.id, name))
return res
_sql_constraints = [(
'salesman_period_company_unique',
'unique(company_id, partner_id, date_range_id)',
'A commission result already exists for this salesman/agent for the same period.')]

View File

@@ -0,0 +1,52 @@
# Copyright Akretion France (http://www.akretion.com/)
# @author Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import fields, models, api
class CommissionRule(models.Model):
_name = 'commission.rule'
_description = 'Commission Rule'
_order = 'profile_id, applied_on'
partner_ids = fields.Many2many(
'res.partner', string='Customers', domain=[('parent_id', '=', False)])
product_categ_ids = fields.Many2many(
'product.category', string="Product Categories")
product_ids = fields.Many2many('product.product', string='Products')
date_start = fields.Date('Start Date')
date_end = fields.Date('End Date')
profile_id = fields.Many2one(
'commission.profile', string='Profile', ondelete='cascade')
company_id = fields.Many2one(related='profile_id.company_id', store=True)
rate = fields.Float('Commission Rate', digits="Commission Rate", copy=False)
base = fields.Selection([
('invoiced', 'Invoiced Amount'),
('margin', 'Margin'),
], default='invoiced', required=True, string="Commission Base")
applied_on = fields.Selection([
('0_customer_product', 'Products and Customers'),
('1_customer_product_category', "Product Categories and Customers"),
('2_product', "Products"),
('3_product_category', "Product Categories"),
('4_global', 'Global')],
string='Apply On', default='4_global', required=True)
active = fields.Boolean(string='Active', default=True)
@api.model
def load_all_rules(self):
rules = self.search_read([('profile_id', '!=', False)])
res = {} # key = profile, value = [rule1 recordset, rule2]
for rule in rules:
if rule['profile_id'][0] not in res:
res[rule['profile_id'][0]] = [rule]
else:
res[rule['profile_id'][0]].append(rule)
return res
_sql_constraints = [(
'rate_positive',
'CHECK(rate >= 0)',
'Rate must be positive !')]

View File

@@ -0,0 +1,13 @@
# Copyright 2019-2024 Akretion France (https://www.akretion.com/)
# @author Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import fields, models
class ResCompany(models.Model):
_inherit = 'res.company'
commission_date_range_type_id = fields.Many2one(
'date.range.type', string='Commission Periodicity', ondelete='restrict')

View File

@@ -0,0 +1,20 @@
# Copyright 2019-2024 Akretion France (https://www.akretion.com/)
# @author Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import fields, models
class ResUsers(models.Model):
_inherit = 'res.users'
# TODO mon idée : déplacer ça dans une table dédiée
# company_id oblig
# partner_id (filtré... sur lien vers user ou agent petit difficulté)
# profile_id
# type agent ou user => ça donne le champ de recherche
commission_profile_id = fields.Many2one(
'commission.profile', string='Commission Profile',
company_dependent=True)

View File

@@ -0,0 +1,11 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_commission_profile_read,Read access on commission.profile for employees,model_commission_profile,base.group_user,1,0,0,0
access_commission_profile_full,Full access on commission.profile for financial manager,model_commission_profile,account.group_account_manager,1,1,1,1
access_commission_profile_assignment_full,Full access on commission.profile.assignment for financial manager,model_commission_profile_assignment,account.group_account_manager,1,1,1,1
access_commission_rule_full,Full access on commission.rule for financial manager,model_commission_rule,account.group_account_manager,1,1,1,1
access_commission_rule_read,Read access on commission.rule for invoicing group,model_commission_rule,account.group_account_invoice,1,0,0,0
access_commission_rule_audit,Read access on commission.rule for viewer group,model_commission_rule,account.group_account_readonly,1,0,0,0
access_commission_result_full,Full access on commission.result to accountant,model_commission_result,account.group_account_user,1,1,1,1
access_commission_result_read,Read access on commission.result to invoicing grp,model_commission_result,account.group_account_invoice,1,0,0,0
access_commission_result_audit,Read access on commission.result to viewer grp,model_commission_result,account.group_account_readonly,1,0,0,0
access_commission_compute_full,Full access to wizard commission.compute,model_commission_compute,account.group_account_manager,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_commission_profile_read Read access on commission.profile for employees model_commission_profile base.group_user 1 0 0 0
3 access_commission_profile_full Full access on commission.profile for financial manager model_commission_profile account.group_account_manager 1 1 1 1
4 access_commission_profile_assignment_full Full access on commission.profile.assignment for financial manager model_commission_profile_assignment account.group_account_manager 1 1 1 1
5 access_commission_rule_full Full access on commission.rule for financial manager model_commission_rule account.group_account_manager 1 1 1 1
6 access_commission_rule_read Read access on commission.rule for invoicing group model_commission_rule account.group_account_invoice 1 0 0 0
7 access_commission_rule_audit Read access on commission.rule for viewer group model_commission_rule account.group_account_readonly 1 0 0 0
8 access_commission_result_full Full access on commission.result to accountant model_commission_result account.group_account_user 1 1 1 1
9 access_commission_result_read Read access on commission.result to invoicing grp model_commission_result account.group_account_invoice 1 0 0 0
10 access_commission_result_audit Read access on commission.result to viewer grp model_commission_result account.group_account_readonly 1 0 0 0
11 access_commission_compute_full Full access to wizard commission.compute model_commission_compute account.group_account_manager 1 1 1 1

View File

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2019-2024 Akretion France (https://www.akretion.com)
@author Alexis de Lattre <alexis.delattre@akretion.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
-->
<odoo noupdate="1">
<record id="commission_profile_rule" model="ir.rule">
<field name="name">Commission Profile multi-company</field>
<field name="model_id" ref="model_commission_profile"/>
<field name="domain_force">[('company_id', 'in', company_ids + [False])]</field>
</record>
<record id="commission_rule_rule" model="ir.rule">
<field name="name">Commission Rule multi-company</field>
<field name="model_id" ref="model_commission_rule"/>
<field name="domain_force">[('company_id', 'in', company_ids + [False])]</field>
</record>
<record id="commission_result_rule" model="ir.rule">
<field name="name">Commission Result multi-company</field>
<field name="model_id" ref="model_commission_result"/>
<field name="domain_force">[('company_id', 'in', company_ids)]</field>
</record>
</odoo>

View File

@@ -0,0 +1,206 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2019 Akretion France (http://www.akretion.com)
@author Alexis de Lattre <alexis.delattre@akretion.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
-->
<odoo>
<menuitem id="commission_root" name="Commissions" parent="account.menu_finance" sequence="11"/>
<menuitem id="commission_config_root" name="Commissions" parent="account.menu_finance_configuration" sequence="110"/>
<!-- PROFILE -->
<record id="commission_profile_form" model="ir.ui.view">
<field name="name">commission.profile.form</field>
<field name="model">commission.profile</field>
<field name="arch" type="xml">
<form>
<sheet>
<widget name="web_ribbon" title="Archived" bg_color="bg-danger" attrs="{'invisible': [('active', '=', True)]}"/>
<group name="main">
<field name="name"/>
<field name="active" invisible="1"/>
<field name="company_id" invisible="1"/>
<field name="company_id" groups="base.group_multi_company"/>
<field name="trigger_type"/>
</group>
<group name="lines" string="Rules">
<field name="line_ids" nolabel="1" colspan="2"/>
</group>
</sheet>
</form>
</field>
</record>
<record id="commission_profile_tree" model="ir.ui.view">
<field name="name">commission.profile.tree</field>
<field name="model">commission.profile</field>
<field name="arch" type="xml">
<tree>
<field name="sequence" widget="handle"/>
<field name="name" decoration-bf="1"/>
<field name="trigger_type" optional="show"/>
<field name="company_id" groups="base.group_multi_company"/>
</tree>
</field>
</record>
<record id="commission_profile_action" model="ir.actions.act_window">
<field name="name">Commission Profiles</field>
<field name="res_model">commission.profile</field>
<field name="view_mode">tree,form</field>
</record>
<menuitem id="commission_profile_menu" action="commission_profile_action" parent="commission_config_root" sequence="18"/>
<!-- RULE -->
<record id="commission_rule_form" model="ir.ui.view">
<field name="name">commission.rule.form</field>
<field name="model">commission.rule</field>
<field name="arch" type="xml">
<form>
<sheet>
<group name="main">
<field name="profile_id" invisible="not context.get('commission_rule_main_view')"/>
<field name="company_id" groups="base.group_multi_company"/>
<field name="company_id" invisible="1"/>
<field name="applied_on" widget="radio"/>
</group>
<group name="match" string="Match">
<field name="partner_ids" attrs="{'invisible': [('applied_on', 'not in', ('0_customer_product', '1_customer_product_category'))], 'required': [('applied_on', 'in', ('0_customer_product', '1_customer_product_category'))]}"/>
<field name="product_categ_ids" attrs="{'invisible': [('applied_on', 'not in', ('1_customer_product_category', '3_product_category'))], 'required': [('applied_on', 'in', ('1_customer_product_category', '3_product_category'))]}"/>
<field name="product_ids" attrs="{'invisible': [('applied_on', 'not in', ('0_customer_product', '2_product'))], 'required': [('applied_on', 'in', ('0_customer_product', '2_product'))]}"/>
<field name="date_start"/>
<field name="date_end"/>
</group>
<group name="compute" string="Compute">
<label for="rate"/>
<div name="rate">
<field name="rate" class="oe_inline"/> %
</div>
</group>
</sheet>
</form>
</field>
</record>
<record id="commission_rule_tree" model="ir.ui.view">
<field name="name">commission.rule.tree</field>
<field name="model">commission.rule</field>
<field name="arch" type="xml">
<tree>
<field name="profile_id" invisible="not context.get('commission_rule_main_view')"/>
<field name="applied_on"/>
<field name="date_start"/>
<field name="date_end"/>
<field name="rate" string="Rate (%)"/>
</tree>
</field>
</record>
<record id="commission_rule_search" model="ir.ui.view">
<field name="name">commission.rule.search</field>
<field name="model">commission.rule</field>
<field name="arch" type="xml">
<search>
<filter string="Archived" name="inactive" domain="[('active', '=', False)]"/>
<group name="groupby">
<filter name="profile_groupby" string="Profile" context="{'group_by': 'profile_id'}"/>
</group>
</search>
</field>
</record>
<record id="commission_rule_action" model="ir.actions.act_window">
<field name="name">Commission Rules</field>
<field name="res_model">commission.rule</field>
<field name="view_mode">tree,form</field>
<field name="context">{'commission_rule_main_view': True}</field>
</record>
<menuitem id="commission_rule_menu" action="commission_rule_action" parent="commission_config_root" sequence="20"/>
<!-- RESULT -->
<record id="commission_result_form" model="ir.ui.view">
<field name="name">commission.result.form</field>
<field name="model">commission.result</field>
<field name="arch" type="xml">
<form>
<group name="main">
<group name="main-left">
<field name="partner_id"/>
<field name="profile_id" groups="account.group_account_manager"/>
<field name="company_currency_id" invisible="1"/>
<field name="company_id" invisible="1"/>
<field name="company_id" groups="base.group_multi_company"/>
<field name="amount_total"/>
</group>
<group name="main-right">
<field name="date_range_id"/>
<field name="date_start"/>
<field name="date_end"/>
</group>
</group>
<group name="lines" string="Commission Lines">
<field nolabel="1" name="line_ids" colspan="2">
<tree>
<field name="move_id"/>
<field name="move_line_id"/>
<field name="base"/>
<field name="rate" string="Rate (%)"/>
<field name="amount" sum="1"/>
<field name="rule_id"/>
<field name="company_currency_id" invisible="1"/>
</tree>
</field>
</group>
</form>
</field>
</record>
<record id="commission_result_tree" model="ir.ui.view">
<field name="name">commission.result.tree</field>
<field name="model">commission.result</field>
<field name="arch" type="xml">
<tree>
<field name="date_range_id" optional="show"/>
<field name="date_start" optional="hide"/>
<field name="date_end" optional="hide"/>
<field name="partner_id"/>
<field name="profile_id" groups="account.group_account_manager"/>
<field name="company_currency_id" invisible="1"/>
<field name="company_id" groups="base.group_multi_company"/>
<field name="amount_total" sum="1" optional="show"/>
</tree>
</field>
</record>
<record id="commission_result_search" model="ir.ui.view">
<field name="name">commission.result.search</field>
<field name="model">commission.result</field>
<field name="arch" type="xml">
<search>
<field name="partner_id"/>
<field name="date_range_id"/>
<group name="groupby">
<filter name="partner_groupby" string="Salesman" context="{'group_by': 'partner_id'}"/>
<filter name="date_range_groupby" string="Period" context="{'group_by': 'date_range_id'}"/>
</group>
</search>
</field>
</record>
<record id="commission_result_action" model="ir.actions.act_window">
<field name="name">Commissions</field>
<field name="res_model">commission.result</field>
<field name="view_mode">tree,form</field>
</record>
<menuitem id="commission_result_menu" action="commission_result_action" parent="commission_root" sequence="10"/>
</odoo>

View File

@@ -0,0 +1,73 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2019-2024 Akretion France (http://www.akretion.com)
@author Alexis de Lattre <alexis.delattre@akretion.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
-->
<odoo>
<menuitem id="commission_root" name="Commissions" parent="account.menu_finance" sequence="11"/>
<menuitem id="commission_config_root" name="Commissions" parent="account.menu_finance_configuration" sequence="110"/>
<record id="commission_profile_form" model="ir.ui.view">
<field name="name">commission.profile.form</field>
<field name="model">commission.profile</field>
<field name="arch" type="xml">
<form>
<sheet>
<widget name="web_ribbon" title="Archived" bg_color="bg-danger" attrs="{'invisible': [('active', '=', True)]}"/>
<group name="main">
<group name="main-left">
<field name="name"/>
<field name="active" invisible="1"/>
<field name="trigger_type" widget="radio"/>
</group>
<group name="main-right">
<field name="company_id" invisible="1"/>
<field name="company_id" groups="base.group_multi_company"/>
</group>
</group>
<notebook>
<page name="assignments" string="Assignments">
<field name="assign_ids">
<tree editable="bottom">
<field name="assign_type"/>
<field name="user_id" attrs="{'required': [('assign_type', '=', 'user')], 'readonly': [('assign_type', '!=', 'user')]}"/>
<field name="company_id" groups="base.group_multi_company"/>
<field name="company_id" invisible="1"/>
</tree>
</field>
</page>
<page name="rules" string="Rules">
<field name="rule_ids"/>
</page>
</notebook>
</sheet>
</form>
</field>
</record>
<record id="commission_profile_tree" model="ir.ui.view">
<field name="name">commission.profile.tree</field>
<field name="model">commission.profile</field>
<field name="arch" type="xml">
<tree>
<field name="sequence" widget="handle"/>
<field name="name" decoration-bf="1"/>
<field name="trigger_type" optional="show"/>
<field name="company_id" groups="base.group_multi_company"/>
</tree>
</field>
</record>
<record id="commission_profile_action" model="ir.actions.act_window">
<field name="name">Commission Profiles</field>
<field name="res_model">commission.profile</field>
<field name="view_mode">tree,form</field>
</record>
<menuitem id="commission_profile_menu" action="commission_profile_action" parent="commission_config_root" sequence="18"/>
</odoo>

View File

@@ -0,0 +1,113 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2024 Akretion France (http://www.akretion.com)
@author Alexis de Lattre <alexis.delattre@akretion.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
-->
<odoo>
<record id="commission_result_form" model="ir.ui.view">
<field name="name">commission.result.form</field>
<field name="model">commission.result</field>
<field name="arch" type="xml">
<form>
<header>
<button name="draft2done" type="object" states="draft" string="Confirm" class="btn-primary"/>
<button name="backtodraft" type="object" states="done" string="Back to Draft" confirm="Are you sure you want to go back to draft?"/>
<field name="state" widget="statusbar"/>
</header>
<group name="main">
<group name="main-left">
<field name="partner_id"/>
<field name="date_range_id"/>
<field name="date_start"/>
<field name="date_end"/>
<field name="amount_total"/>
<field name="company_currency_id" invisible="1"/>
<field name="company_id" invisible="1"/>
</group>
<group name="main-right">
<field name="profile_id" groups="account.group_account_manager"/>
<field name="assign_type"/>
<field name="company_id" groups="base.group_multi_company"/>
</group>
</group>
<group name="lines" string="Commission Lines">
<field nolabel="1" name="line_ids" colspan="2">
<tree>
<field name="move_id"/>
<field name="date" optional="hide"/>
<field name="partner_id"/>
<field name="product_id"/>
<field name="product_categ_id" optional="hide"/>
<field name="name" optional="hide"/>
<field name="price_subtotal" optional="hide" string="Invoiced Amount"/>
<field name="commission_base"/>
<field name="commission_rate" string="Rate (%)"/>
<field name="commission_amount" sum="1"/>
<field name="commission_rule_id" optional="hide"/>
<field name="company_currency_id" invisible="1"/>
<field name="currency_id" invisible="1"/>
</tree>
</field>
</group>
<div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers"/>
<field name="activity_ids" widget="mail_activity"/>
<field name="message_ids" widget="mail_thread"/>
</div>
</form>
</field>
</record>
<record id="commission_result_tree" model="ir.ui.view">
<field name="name">commission.result.tree</field>
<field name="model">commission.result</field>
<field name="arch" type="xml">
<tree>
<field name="date_range_id" optional="show"/>
<field name="date_start" optional="hide"/>
<field name="date_end" optional="hide"/>
<field name="partner_id"/>
<field name="profile_id" groups="account.group_account_manager"/>
<field name="assign_type" optional="hide" widget="badge" decoration-warning="assign_type == 'user'"/>
<field name="company_currency_id" invisible="1"/>
<field name="company_id" groups="base.group_multi_company"/>
<field name="amount_total" sum="1" optional="show"/>
<field name="state" decoration-info="state == 'draft'" decoration-success="state == 'done'" widget="badge"/>
</tree>
</field>
</record>
<record id="commission_result_search" model="ir.ui.view">
<field name="name">commission.result.search</field>
<field name="model">commission.result</field>
<field name="arch" type="xml">
<search>
<field name="partner_id"/>
<field name="date_range_id"/>
<separator/>
<filter name="draft" domain="[('state', '=', 'draft')]" string="Draft"/>
<filter name="done" domain="[('state', '=', 'done')]" string="Done"/>
<separator/>
<filter name="user" domain="[('assign_type', '=', 'user')]" string="Salesman"/>
<group name="groupby">
<filter name="partner_groupby" string="Salesman" context="{'group_by': 'partner_id'}"/>
<filter name="date_range_groupby" string="Period" context="{'group_by': 'date_range_id'}"/>
<filter name="assign_type_groupby" string="Assign Type" context="{'group_by': 'assign_type'}"/>
</group>
</search>
</field>
</record>
<record id="commission_result_action" model="ir.actions.act_window">
<field name="name">Commissions</field>
<field name="res_model">commission.result</field>
<field name="view_mode">tree,form</field>
</record>
<menuitem id="commission_result_menu" action="commission_result_action" parent="commission_root" sequence="10"/>
</odoo>

View File

@@ -0,0 +1,80 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2019 Akretion France (http://www.akretion.com)
@author Alexis de Lattre <alexis.delattre@akretion.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
-->
<odoo>
<record id="commission_rule_form" model="ir.ui.view">
<field name="name">commission.rule.form</field>
<field name="model">commission.rule</field>
<field name="arch" type="xml">
<form>
<sheet>
<group name="main">
<field name="profile_id" invisible="not context.get('commission_rule_main_view')"/>
<field name="applied_on" widget="radio"/>
<field name="company_id" invisible="1"/>
</group>
<group name="match" string="Match">
<field name="partner_ids" attrs="{'invisible': [('applied_on', 'not in', ('0_customer_product', '1_customer_product_category'))], 'required': [('applied_on', 'in', ('0_customer_product', '1_customer_product_category'))]}"/>
<field name="product_categ_ids" attrs="{'invisible': [('applied_on', 'not in', ('1_customer_product_category', '3_product_category'))], 'required': [('applied_on', 'in', ('1_customer_product_category', '3_product_category'))]}"/>
<field name="product_ids" attrs="{'invisible': [('applied_on', 'not in', ('0_customer_product', '2_product'))], 'required': [('applied_on', 'in', ('0_customer_product', '2_product'))]}"/>
<field name="date_start"/>
<field name="date_end"/>
</group>
<group name="compute" string="Compute">
<label for="rate"/>
<div name="rate">
<field name="rate" class="oe_inline"/> %
</div>
<field name="base" widget="radio"/>
</group>
</sheet>
</form>
</field>
</record>
<record id="commission_rule_tree" model="ir.ui.view">
<field name="name">commission.rule.tree</field>
<field name="model">commission.rule</field>
<field name="arch" type="xml">
<tree>
<field name="profile_id" invisible="not context.get('commission_rule_main_view')"/>
<field name="applied_on"/>
<field name="date_start"/>
<field name="date_end"/>
<field name="rate" string="Rate (%)"/>
<field name="base"/>
</tree>
</field>
</record>
<record id="commission_rule_search" model="ir.ui.view">
<field name="name">commission.rule.search</field>
<field name="model">commission.rule</field>
<field name="arch" type="xml">
<search>
<filter string="Archived" name="inactive" domain="[('active', '=', False)]"/>
<group name="groupby">
<filter name="profile_groupby" string="Profile" context="{'group_by': 'profile_id'}"/>
</group>
</search>
</field>
</record>
<record id="commission_rule_action" model="ir.actions.act_window">
<field name="name">Commission Rules</field>
<field name="res_model">commission.rule</field>
<field name="view_mode">tree,form</field>
<field name="context">{'commission_rule_main_view': True}</field>
</record>
<menuitem id="commission_rule_menu" action="commission_rule_action" parent="commission_config_root" sequence="20"/>
</odoo>

View File

@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2019-2024 Akretion France (https://www.akretion.com)
@author: Alexis de Lattre <alexis.delattre@akretion.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
-->
<odoo>
<record id="res_config_settings_view_form" model="ir.ui.view">
<field name="name">commission.res.config.settings.form</field>
<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='storno']" position="after">
<h2>Commissions</h2>
<div class="row mt16 o_settings_container" id="commission_simple">
<div class="col-12 col-lg-12 o_setting_box" id="commission_simple-settings">
<div class="o_setting_left_pane" />
<div class="o_setting_right_pane">
<div class="row" id="commission_date_range_type_id">
<label
for="commission_date_range_type_id"
class="col-md-5"
/>
<field name="commission_date_range_type_id" />
</div>
</div>
</div>
</div>
</xpath>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2019-2024 Akretion France (https://www.akretion.com)
@author Alexis de Lattre <alexis.delattre@akretion.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
-->
<odoo>
<record id="view_users_form" model="ir.ui.view">
<field name="name">commission.res.users.form</field>
<field name="model">res.users</field>
<field name="inherit_id" ref="base.view_users_form"/>
<field name="arch" type="xml">
<group name="preferences" position="after">
<group name="commission" string="Commission" groups="account.group_account_manager">
<field name="commission_profile_id"/>
</group>
</group>
</field>
</record>
<record id="view_users_tree" model="ir.ui.view">
<field name="name">commission.res.users.tree</field>
<field name="model">res.users</field>
<field name="inherit_id" ref="base.view_users_tree"/>
<field name="arch" type="xml">
<field name="login_date" position="after">
<field name="commission_profile_id" optional="hide" groups="account.group_account_manager"/>
</field>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,2 @@
from . import commission_compute
from . import res_config_settings

View File

@@ -0,0 +1,77 @@
# Copyright 2019-2024 Akretion France (http://www.akretion.com)
# @author Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import api, fields, models, _
from dateutil.relativedelta import relativedelta
from odoo.exceptions import UserError
import logging
logger = logging.getLogger(__name__)
class CommissionCompute(models.TransientModel):
_name = 'commission.compute'
_description = 'Compute Commissions'
company_id = fields.Many2one('res.company', required=True, default=lambda self: self.env.company)
date_range_type_id = fields.Many2one(related='company_id.commission_date_range_type_id')
date_range_id = fields.Many2one(
'date.range', required=True, string='Period',
compute='_compute_date_range_id', store=True, precompute=True, readonly=False,
domain="[('type_id', '=', date_range_type_id)]")
date_start = fields.Date(related='date_range_id.date_start')
date_end = fields.Date(related='date_range_id.date_end')
@api.depends('company_id')
def _compute_date_range_id(self):
for wiz in self:
date_range_id = False
company = wiz.company_id
if company and company.commission_date_range_type_id:
type_id = company.commission_date_range_type_id.id
last_commission_result = self.env['commission.result'].search([
('company_id', '=', company.id),
], order='date_end desc', limit=1)
limit_date = last_commission_result and last_commission_result.date_end or (fields.Date.context_today(self) + relativedelta(months=-2, day=31))
date_range = self.env['date.range'].search([
('company_id', 'in', (company.id, False)),
('type_id', '=', type_id),
('date_start', '>', limit_date)
], order='date_start', limit=1)
date_range_id = date_range and date_range.id or False
wiz.date_range_id = date_range_id
def run(self):
self.ensure_one()
creso = self.env['commission.result']
date_range = self.date_range_id
existing_commissions = creso.search([
('date_range_id', '=', date_range.id),
('company_id', '=', self.company_id.id),
])
if existing_commissions:
raise UserError(_(
'Commissions already exist for %(period)s in company %(company)s.',
period=date_range.display_name, company=self.company_id.display_name))
com_result_ids = self._core_compute()
if not com_result_ids:
raise UserError(_('No commissions generated.'))
action = self.env['ir.actions.actions']._for_xml_id(
'commission_simple.commission_result_action')
action.update({
'views': False,
'domain': f"[('id', 'in', {com_result_ids})]",
})
return action
def _core_compute(self):
rules = self.env['commission.rule'].load_all_rules()
com_result_ids = []
assignments = self.env['commission.profile.assignment'].search([('company_id', '=', self.company_id.id)])
for assignment in assignments:
com_result = assignment._generate_commission_result(self.date_range_id, rules)
if com_result:
com_result_ids.append(com_result.id)
else:
logger.info("No commission for %s", assignment._get_partner().display_name)
return com_result_ids

View File

@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2019-2024 Akretion France (https://www.akretion.com)
@author Alexis de Lattre <alexis.delattre@akretion.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
-->
<odoo>
<record id="commission_compute_form" model="ir.ui.view">
<field name="name">commission.compute.form</field>
<field name="model">commission.compute</field>
<field name="arch" type="xml">
<form>
<group name="main">
<field name="company_id" groups="base.group_multi_company"/>
<field name="company_id" invisible="1"/>
<field name="date_range_type_id" invisible="1"/>
<field name="date_range_id"/>
<field name="date_start"/>
<field name="date_end"/>
</group>
<footer>
<button name="run" type="object" string="Compute"
class="btn-primary"/>
<button special="cancel" string="Cancel"/>
</footer>
</form>
</field>
</record>
<record id="commission_compute_action" model="ir.actions.act_window">
<field name="name">Compute Commissions</field>
<field name="res_model">commission.compute</field>
<field name="view_mode">form</field>
<field name="target">new</field>
</record>
<menuitem id="commission_compute_menu" action="commission_compute_action" parent="commission_root" sequence="15" groups="account.group_account_user"/>
</odoo>

View File

@@ -0,0 +1,12 @@
# Copyright 2019-2024 Akretion France (https://www.akretion.com/)
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import fields, models
class ResConfigSettings(models.TransientModel):
_inherit = 'res.config.settings'
commission_date_range_type_id = fields.Many2one(
related='company_id.commission_date_range_type_id', readonly=False)

View File

@@ -0,0 +1 @@
from . import models

View File

@@ -0,0 +1,22 @@
# Copyright 2019-2024 Akretion France (http://www.akretion.com)
# @author Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{
'name': 'Commission Simple Agent',
'version': '16.0.1.0.0',
'category': 'Sales',
'license': 'AGPL-3',
'summary': 'Glue module between commission_simple and sale_agent',
'author': 'Akretion',
'website': 'https://github.com/akretion/odoo-usability',
'depends': [
'commission_simple',
'sale_agent',
],
'data': [
'views/commission_profile.xml',
'views/commission_result.xml',
],
'installable': True,
}

View File

@@ -0,0 +1,44 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * commission_simple_agent
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-11-29 23:32+0000\n"
"PO-Revision-Date: 2024-11-29 23:32+0000\n"
"Last-Translator: Alexis de Lattre <alexis.delattre@akretion.com>\n"
"Language-Team: \n"
"Language: fr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: commission_simple_agent
#. odoo-python
#: code:addons/commission_simple_agent/models/commission_profile_assignment.py:0
#: model:ir.model.fields,field_description:commission_simple_agent.field_commission_profile_assignment__agent_id
#: model_terms:ir.ui.view,arch_db:commission_simple_agent.commission_result_search
#, python-format
msgid "Agent"
msgstr "Agent"
#. module: commission_simple_agent
#. odoo-python
#: code:addons/commission_simple_agent/models/commission_profile_assignment.py:0
#, python-format
msgid "An agent must be selected when the assignment type is 'Agent'."
msgstr ""
"Un agent doit être sélectionné lorsque le type d'affectation est \"Agent\"."
#. module: commission_simple_agent
#: model:ir.model,name:commission_simple_agent.model_commission_profile_assignment
msgid "Commission Profile Assignment"
msgstr "Affectation du profil de commission"
#. module: commission_simple_agent
#: model:ir.model.constraint,message:commission_simple_agent.constraint_commission_profile_assignment_company_agent_uniq
msgid "This agent already has an assignment in this company."
msgstr "Cet agent a déjà une affectation dans cette société."

View File

@@ -0,0 +1 @@
from . import commission_profile_assignment

View File

@@ -0,0 +1,51 @@
# Copyright Akretion France (http://www.akretion.com/)
# @author Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import api, fields, models, _
from odoo.exceptions import ValidationError
class CommissionProfileAssignment(models.Model):
_inherit = "commission.profile.assignment"
agent_id = fields.Many2one(
'res.partner', ondelete='restrict',
compute="_compute_agent_id", store=True, precompute=True, readonly=False,
domain=[('agent', '=', True)])
_sql_constraints = [
(
'company_agent_uniq',
'unique(agent_id, company_id)',
'This agent already has an assignment in this company.')]
@api.model
def _assign_type_selection(self):
sel = super()._assign_type_selection()
sel.append(('agent', _('Agent')))
return sel
@api.constrains('assign_type', 'agent_id')
def _check_agent(self):
for assignment in self:
if assignment.assign_type == 'agent' and not assignment.agent_id:
raise ValidationError(_("An agent must be selected when the assignment type is 'Agent'."))
@api.depends('assign_type')
def _compute_agent_id(self):
for assign in self:
if assign.assign_type != 'agent':
assign.agent_id = False
def _prepare_move_line_domain(self, date_range):
domain = super()._prepare_move_line_domain(date_range)
if self.assign_type == 'agent':
domain.append(('move_id.invoice_agent_id', '=', self.agent_id.id))
return domain
def _get_partner(self):
self.ensure_one()
if self.assign_type == 'agent':
return self.agent_id
return super()._get_partner()

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2024 Akretion France (https://www.akretion.com)
@author Alexis de Lattre <alexis.delattre@akretion.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
-->
<odoo>
<record id="commission_profile_form" model="ir.ui.view">
<field name="model">commission.profile</field>
<field name="inherit_id" ref="commission_simple.commission_profile_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='assign_ids']/tree/field[@name='user_id']" position="after">
<field name="agent_id" attrs="{'required': [('assign_type', '=', 'agent')], 'readonly': [('assign_type', '!=', 'agent')]}"/>
</xpath>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2024 Akretion France (http://www.akretion.com)
@author Alexis de Lattre <alexis.delattre@akretion.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
-->
<odoo>
<record id="commission_result_tree" model="ir.ui.view">
<field name="model">commission.result</field>
<field name="inherit_id" ref="commission_simple.commission_result_tree"/>
<field name="arch" type="xml">
<field name="assign_type" position="attributes">
<attribute name="decoration-danger">assign_type == 'agent'</attribute>
</field>
</field>
</record>
<record id="commission_result_search" model="ir.ui.view">
<field name="model">commission.result</field>
<field name="inherit_id" ref="commission_simple.commission_result_search"/>
<field name="arch" type="xml">
<filter name="user" position="after">
<filter name="agent" domain="[('assign_type', '=', 'agent')]" string="Agent"/>
</filter>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,2 @@
from . import models
from . import wizards

View File

@@ -0,0 +1,22 @@
# Copyright 2019-2024 Akretion France (http://www.akretion.com)
# @author Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{
'name': 'Commission Simple Agent Purchase',
'version': '16.0.1.0.0',
'category': 'Sales',
'license': 'AGPL-3',
'summary': 'Glue module between commission_simple_agent and purchase',
'author': 'Akretion',
'website': 'https://github.com/akretion/odoo-usability',
'depends': [
'commission_simple_agent',
'purchase',
],
'data': [
'views/commission_result.xml',
'wizards/res_config_settings.xml',
],
'installable': True,
}

View File

@@ -0,0 +1,79 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * commission_simple_agent_purchase
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-11-29 23:33+0000\n"
"PO-Revision-Date: 2024-11-29 23:34+0000\n"
"Last-Translator: Alexis de Lattre <alexis.delattre@akretion.com>\n"
"Language-Team: \n"
"Language: fr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: commission_simple_agent_purchase
#. odoo-python
#: code:addons/commission_simple_agent_purchase/models/commission_result.py:0
#, python-format
msgid ""
"Cannot delete commission %(commission)s because it is linked to purchase "
"order %(po)s. You must delete the purchase order first."
msgstr ""
"Impossible de supprimer la commission %(commission)s car elle est liée à la "
"commande fournisseur %(po)s. Vous devez d'abord supprimer la commande "
"fournisseur."
#. module: commission_simple_agent_purchase
#. odoo-python
#: code:addons/commission_simple_agent_purchase/models/commission_result.py:0
#, python-format
msgid "Commission %s"
msgstr "Commission %s"
#. module: commission_simple_agent_purchase
#: model:ir.model.fields,field_description:commission_simple_agent_purchase.field_res_company__commission_product_id
#: model:ir.model.fields,field_description:commission_simple_agent_purchase.field_res_config_settings__commission_product_id
msgid "Commission Product"
msgstr "Produit de commission"
#. module: commission_simple_agent_purchase
#: model:ir.model,name:commission_simple_agent_purchase.model_commission_result
msgid "Commission Result"
msgstr "État des commissions"
#. module: commission_simple_agent_purchase
#. odoo-python
#: code:addons/commission_simple_agent_purchase/models/commission_result.py:0
#, python-format
msgid "Commission product is not set on company %s."
msgstr "Le produit de commission n'est pas défini sur la société %s."
#. module: commission_simple_agent_purchase
#: model:ir.model,name:commission_simple_agent_purchase.model_res_company
msgid "Companies"
msgstr "Sociétés"
#. module: commission_simple_agent_purchase
#: model:ir.model,name:commission_simple_agent_purchase.model_res_config_settings
msgid "Config Settings"
msgstr "Configuration"
#. module: commission_simple_agent_purchase
#: model:ir.model.fields,field_description:commission_simple_agent_purchase.field_commission_result__purchase_id
msgid "Purchase Order"
msgstr "Commande fournisseur"
#. module: commission_simple_agent_purchase
#. odoo-python
#: code:addons/commission_simple_agent_purchase/models/commission_result.py:0
#, python-format
msgid ""
"Purchase Order %s has already been confirmed. You should cancel it first."
msgstr ""
"La commande fournisseur %s a déjà été confirmée. Vous devez d'abord "
"l'annuler."

View File

@@ -0,0 +1,2 @@
from . import commission_result
from . import res_company

View File

@@ -0,0 +1,78 @@
# Copyright Akretion France (https://www.akretion.com/)
# @author Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import fields, models, _
from odoo.exceptions import UserError
from odoo.tools.misc import format_amount, formatLang
class CommissionResult(models.Model):
_inherit = 'commission.result'
purchase_id = fields.Many2one('purchase.order', string="Purchase Order", tracking=True, readonly=True)
def draft2done(self):
for result in self:
if result.assign_type == 'agent':
if not result.purchase_id:
vals = result._prepare_purchase_order()
po = self.env['purchase.order'].create(vals)
result.write({'purchase_id': po.id})
else:
po = self.purchase_id
if po.state in ('draft', 'sent', 'cancel'):
po.order_line.unlink()
else:
raise UserError(_("Purchase Order %s has already been confirmed. You should cancel it first.") % po.display_name)
if po.state == 'cancel':
po.button_draft()
assert not po.order_line
# create lines
if not result.company_id.commission_product_id:
raise UserError(_("Commission product is not set on company %s.") % result.company_id.display_name)
line_vals = []
for move_line in result.line_ids:
line_vals.append(result._prepare_purchase_order_line(move_line, po))
po_lines = self.env['purchase.order.line'].create(line_vals)
po_lines._compute_tax_id()
return super().draft2done()
def _prepare_purchase_order(self):
self.ensure_one()
fp = self.env['account.fiscal.position']._get_fiscal_position(self.partner_id)
vals = {
'partner_id': self.partner_id.id,
'origin': _('Commission %s') % self.date_range_id.display_name,
'company_id': self.company_id.id,
'currency_id': self.company_id.currency_id.id,
'fiscal_position_id': fp and fp.id or False,
'payment_term_id': self.partner_id.property_supplier_payment_term_id.id,
}
return vals
def _prepare_purchase_order_line(self, move_line, order):
self.ensure_one()
move = move_line.move_id
company_currency = move_line.company_id.currency_id
lang = self.partner_id.lang or self.env.lang
env = self.with_context(lang=lang).env
product = self.company_id.commission_product_id
vals = {
'order_id': order.id,
'product_id': product.id,
'name': f"""{move.name} {move.commercial_partner_id.name}: {move_line.product_id.display_name} x {formatLang(env, move_line.quantity, dp='Product Unit of Measure')} {move_line.product_uom_id.display_name}\n{_('Base:')} {format_amount(env, move_line.commission_base, company_currency)} - {_('Rate:')} {formatLang(env, move_line.commission_rate, dp='Commission Rate')} %""",
'product_qty': 1,
'product_uom': product.uom_id.id,
'price_unit': move_line.commission_amount,
}
return vals
def unlink(self):
for result in self:
if result.purchase_id:
raise UserError(_(
"Cannot delete commission %(commission)s because it is linked to "
"purchase order %(po)s. You must delete the purchase order first.",
commission=result.display_name, po=result.purchase_id.display_name))
return super().unlink()

View File

@@ -0,0 +1,14 @@
# Copyright 2024 Akretion France (https://www.akretion.com/)
# @author Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import fields, models
class ResCompany(models.Model):
_inherit = 'res.company'
commission_product_id = fields.Many2one(
'product.product', string='Commission Product', ondelete='restrict', check_company=True,
domain=[('type', '=', 'service')])

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2019 Akretion France (http://www.akretion.com)
@author Alexis de Lattre <alexis.delattre@akretion.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl)
-->
<odoo>
<record id="commission_result_form" model="ir.ui.view">
<field name="model">commission.result</field>
<field name="inherit_id" ref="commission_simple.commission_result_form"/>
<field name="arch" type="xml">
<group name="main-right" position="inside">
<field name="purchase_id" attrs="{'invisible': [('assign_type', '!=', 'agent')]}"/>
</group>
</field>
</record>
</odoo>

View File

@@ -0,0 +1 @@
from . import res_config_settings

View File

@@ -0,0 +1,12 @@
# Copyright 2019-2024 Akretion France (https://www.akretion.com/)
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import fields, models
class ResConfigSettings(models.TransientModel):
_inherit = 'res.config.settings'
commission_product_id = fields.Many2one(
related='company_id.commission_product_id', readonly=False)

View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2019-2024 Akretion France (https://www.akretion.com)
@author: Alexis de Lattre <alexis.delattre@akretion.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
-->
<odoo>
<record id="res_config_settings_view_form" model="ir.ui.view">
<field name="name">commission.res.config.settings.form</field>
<field name="model">res.config.settings</field>
<field name="inherit_id" ref="commission_simple.res_config_settings_view_form" />
<field name="arch" type="xml">
<xpath expr="//div[@id='commission_simple-settings']/div[hasclass('o_setting_right_pane')]" position="inside">
<div class="row" id="commission_product_id">
<label for="commission_product_id" class="col-md-5" />
<field name="commission_product_id" context="{'default_detailed_type': 'service', 'default_purchase_ok': True, 'default_sale_ok': False, 'default_available_in_pos': False, 'default_purchase_method': 'purchase'}"/>
</div>
</xpath>
</field>
</record>
</odoo>

66
crm_usability/i18n/fr.po Normal file
View File

@@ -0,0 +1,66 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * crm_usability
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-07-07 14:23+0000\n"
"PO-Revision-Date: 2024-07-07 14:23+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: crm_usability
#: model_terms:ir.ui.view,arch_db:crm_usability.view_calendar_event_form
msgid "CRM"
msgstr "CRM"
#. module: crm_usability
#: model_terms:ir.ui.view,arch_db:crm_usability.view_crm_case_opportunities_filter
msgid "Customer"
msgstr "Client"
#. module: crm_usability
#: model_terms:ir.ui.view,arch_db:crm_usability.view_calendar_event_form
msgid "Discard"
msgstr "Ne pas sauvegarder"
#. module: crm_usability
#: model:ir.model.fields,help:crm_usability.field_crm_lead__date_deadline
msgid "Estimate of the date on which the opportunity will be won."
msgstr "Estimation de la date à laquelle l'opportunité sera gagnée."
#. module: crm_usability
#: model:ir.model.fields,field_description:crm_usability.field_crm_lead__date_deadline
msgid "Expected Closing"
msgstr "Date estimée"
#. module: crm_usability
#: model:ir.model,name:crm_usability.model_crm_lead
msgid "Lead/Opportunity"
msgstr "Piste/Opportunité"
#. module: crm_usability
#: model:ir.model.fields,field_description:crm_usability.field_crm_lead__name
msgid "Opportunity"
msgstr "Opportunité"
#. module: crm_usability
#: model:ir.model.fields,field_description:crm_usability.field_crm_lead__probability
msgid "Probability"
msgstr "Probabilité"
#. module: crm_usability
#: model_terms:ir.ui.view,arch_db:crm_usability.view_calendar_event_form
msgid "Save & Close"
msgstr "Sauvegarder et fermer"
#. module: crm_usability
#: model_terms:ir.ui.view,arch_db:crm_usability.view_calendar_event_form
msgid "Save & Send"
msgstr "Sauvegarder et envoyer"

View File

@@ -19,4 +19,29 @@
</field>
</record>
<record id="view_calendar_event_form" model="ir.ui.view">
<field name="name">calendar.event.form.usability</field>
<field name="model">calendar.event</field>
<field name="inherit_id" ref="calendar.view_calendar_event_form"/>
<field name="arch" type="xml">
<!-- Add "Opportunity" field on calendar event -->
<notebook position="inside">
<page name="crm" string="CRM">
<group>
<field name="opportunity_id" />
</group>
</page>
</notebook>
<!-- Add "send & save" button next to "save & close" -->
<form position="inside">
<footer>
<button name="action_open_composer" type="object" string="Save &amp; Send" class="btn btn-primary" />
<button string="Save &amp; Close" special="save" />
<button string="Discard" special="cancel"/>
</footer>
</form>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,31 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * delivery_usability
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-07-07 14:40+0000\n"
"PO-Revision-Date: 2024-07-07 14:40+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: delivery_usability
#: model:ir.model.fields,field_description:delivery_usability.field_stock_picking__carrier_id
msgid "Carrier"
msgstr "Transporteur"
#. module: delivery_usability
#: model:ir.model.fields,field_description:delivery_usability.field_stock_picking__carrier_tracking_ref
msgid "Tracking Reference"
msgstr "Numéro de suivi"
#. module: delivery_usability
#: model:ir.model,name:delivery_usability.model_stock_picking
msgid "Transfer"
msgstr "Transfert"

View File

@@ -0,0 +1,23 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * link_tracker_usability
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-07-07 14:42+0000\n"
"PO-Revision-Date: 2024-07-07 14:42+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: link_tracker_usability
#: model_terms:ir.ui.view,arch_db:link_tracker_usability.link_tracker_click_view_form
#: model_terms:ir.ui.view,arch_db:link_tracker_usability.link_tracker_click_view_search
#: model_terms:ir.ui.view,arch_db:link_tracker_usability.link_tracker_click_view_tree
msgid "Click Date"
msgstr "Date du clic"

129
mail_usability/i18n/fr.po Normal file
View File

@@ -0,0 +1,129 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * mail_usability
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-07-07 14:35+0000\n"
"PO-Revision-Date: 2024-07-07 14:35+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: mail_usability
#: model:ir.model.fields,field_description:mail_usability.field_res_partner__active
msgid "Active"
msgstr "Actif"
#. module: mail_usability
#: model:ir.model.fields,help:mail_usability.field_res_partner__lang
#: model:ir.model.fields,help:mail_usability.field_res_users__lang
msgid ""
"All the emails and documents sent to this contact will be translated in this"
" language."
msgstr ""
"Tous les emails et documents envoyés à ce contact seront traduits dans cette"
" langue."
#. module: mail_usability
#: model:ir.model.fields,field_description:mail_usability.field_mail_template__auto_delete
msgid "Auto Delete"
msgstr "Suppression automatique"
#. module: mail_usability
#: model:ir.model.fields,help:mail_usability.field_res_partner__is_company
#: model:ir.model.fields,help:mail_usability.field_res_users__is_company
msgid "Check if the contact is a company, otherwise it is a person"
msgstr ""
"Cochez si ce contact est une société, sinon il s'agit d'un particulier"
#. module: mail_usability
#: model:ir.model.fields,field_description:mail_usability.field_res_partner__city
#: model:ir.model.fields,field_description:mail_usability.field_res_users__city
msgid "City"
msgstr "Ville"
#. module: mail_usability
#: model:ir.model.fields,field_description:mail_usability.field_res_partner__company_id
msgid "Company"
msgstr "Société"
#. module: mail_usability
#: model:ir.model,name:mail_usability.model_res_partner
msgid "Contact"
msgstr "Contact"
#. module: mail_usability
#: model:ir.model.fields,field_description:mail_usability.field_res_partner__country_id
#: model:ir.model.fields,field_description:mail_usability.field_res_users__country_id
msgid "Country"
msgstr "Pays"
#. module: mail_usability
#: model:ir.model,name:mail_usability.model_mail_template
msgid "Email Templates"
msgstr "Modèles d'email"
#. module: mail_usability
#: model:ir.model.fields,field_description:mail_usability.field_res_partner__is_company
#: model:ir.model.fields,field_description:mail_usability.field_res_users__is_company
msgid "Is a Company"
msgstr "Est une entreprise"
#. module: mail_usability
#: model:ir.model.fields,field_description:mail_usability.field_res_partner__lang
#: model:ir.model.fields,field_description:mail_usability.field_res_users__lang
msgid "Language"
msgstr "Langue"
#. module: mail_usability
#: model:ir.model.fields,field_description:mail_usability.field_res_partner__name
#: model:ir.model.fields,field_description:mail_usability.field_res_users__name
msgid "Name"
msgstr "Nom"
#. module: mail_usability
#: model:ir.model.fields,field_description:mail_usability.field_res_partner__ref
#: model:ir.model.fields,field_description:mail_usability.field_res_users__ref
msgid "Reference"
msgstr "Référence"
#. module: mail_usability
#: model:ir.model.fields,field_description:mail_usability.field_res_partner__state_id
#: model:ir.model.fields,field_description:mail_usability.field_res_users__state_id
msgid "State"
msgstr "État"
#. module: mail_usability
#: model:ir.model.fields,field_description:mail_usability.field_res_partner__street
#: model:ir.model.fields,field_description:mail_usability.field_res_users__street
msgid "Street"
msgstr "Rue"
#. module: mail_usability
#: model:ir.model.fields,field_description:mail_usability.field_res_partner__street2
#: model:ir.model.fields,field_description:mail_usability.field_res_users__street2
msgid "Street2"
msgstr "Rue 2"
#. module: mail_usability
#: model:ir.model.fields,help:mail_usability.field_mail_template__auto_delete
msgid ""
"This option permanently removes any track of email after it's been sent, "
"including from the Technical menu in the Settings, in order to preserve "
"storage space of your Odoo database."
msgstr ""
"Cette option supprime définitivement toute trace de l'email après son "
"envoi, y compris du menu Technique dans les Paramètres, afin de préserver de"
" l'espace de stockage dans votre base de données Odoo."
#. module: mail_usability
#: model:ir.model.fields,field_description:mail_usability.field_res_partner__zip
#: model:ir.model.fields,field_description:mail_usability.field_res_users__zip
msgid "Zip"
msgstr "Code postal"

View File

@@ -0,0 +1,15 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-07-07 14:44+0000\n"
"PO-Revision-Date: 2024-07-07 14:44+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"

View File

@@ -0,0 +1 @@
from . import models

View File

@@ -10,9 +10,10 @@
'summary': 'Usability improvements on mrp_subcontracting',
'author': 'Akretion',
'website': 'https://github.com/akretion/odoo-usability',
'depends': ['mrp_subcontracting'],
'depends': ['mrp_subcontracting', 'stock_usability'],
'data': [
'views/mrp_bom.xml',
'views/stock_warehouse.xml',
],
'installable': True,
}

View File

@@ -0,0 +1,21 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * mrp_subcontracting_usability
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-07-07 14:38+0000\n"
"PO-Revision-Date: 2024-07-07 14:38+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: mrp_subcontracting_usability
#: model_terms:ir.ui.view,arch_db:mrp_subcontracting_usability.view_mrp_bom_filter
msgid "Subcontracting"
msgstr "Sous-traitance"

View File

@@ -0,0 +1 @@
from . import mrp_bom

View File

@@ -0,0 +1,11 @@
# Copyright 2024 Akretion France (https://www.akretion.com/)
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import fields, models
class MrpBom(models.Model):
_inherit = 'mrp.bom'
subcontractor_ids = fields.Many2many(domain=[('parent_id', '=', False)])

View File

@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2024 Akretion France (https://www.akretion.com/)
@author: Alexis de Lattre <alexis.delattre@akretion.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
-->
<odoo>
<record id="view_warehouse" model="ir.ui.view">
<field name="model">stock.warehouse</field>
<field name="inherit_id" ref="stock_usability.view_warehouse" />
<field name="arch" type="xml">
<group name="routes" position="inside">
<field name="subcontracting_route_id"/>
</group>
<field name="out_type_id" position="after">
<field name="subcontracting_type_id" readonly="1"/>
<field name="subcontracting_resupply_type_id" readonly="1"/>
</field>
</field>
</record>
</odoo>

View File

@@ -4,65 +4,140 @@
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 12.0\n"
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-10-06 13:37+0000\n"
"PO-Revision-Date: 2020-10-06 15:38+0200\n"
"Last-Translator: <>\n"
"POT-Creation-Date: 2024-07-04 16:16+0000\n"
"PO-Revision-Date: 2024-07-04 16:16+0000\n"
"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
"Language: fr\n"
"X-Generator: Poedit 2.3\n"
#. module: mrp_usability
#: model_terms:ir.ui.view,arch_db:mrp_usability.mrp_production_form_view
msgid "Are you sure you want to cancel this manufacturing order?"
msgstr "Etes vous sur de vouloir annuler cet ordre de production"
msgstr "Êtes-vous sur de vouloir annuler cet ordre de fabrication ?"
#. module: mrp_usability
#: model_terms:ir.ui.view,arch_db:mrp_usability.product_template_form_view_bom_button
msgid "Bill of Materials"
#: model:ir.model,name:mrp_usability.model_mrp_bom
msgid "Bill of Material"
msgstr "Nomenclature"
#. module: mrp_usability
#: model_terms:ir.ui.view,arch_db:mrp_usability.report_mrporder
msgid "Lot"
msgstr ""
#: model:ir.model.fields,field_description:mrp_usability.field_mrp_bom__type
msgid "BoM Type"
msgstr "Type de nomenclature"
#. module: mrp_usability
#: model:ir.model,name:mrp_usability.model_product_product
#: model_terms:ir.ui.view,arch_db:mrp_usability.report_mrporder
msgid "Product"
msgstr "Article"
#: model:ir.model.fields,help:mrp_usability.field_mrp_bom__consumption
msgid ""
"Defines if you can consume more or less components than the quantity defined on the BoM:\n"
" * Allowed: allowed for all manufacturing users.\n"
" * Allowed with warning: allowed for all manufacturing users with summary of consumption differences when closing the manufacturing order.\n"
" Note that in the case of component Manual Consumption, where consumption is registered manually exclusively, consumption warnings will still be issued when appropriate also.\n"
" * Blocked: only a manager can close a manufacturing order when the BoM consumption is not respected."
msgstr ""
"Définit si vous pouvez consommer plus ou moins de composants que la quantité définie sur la nomenclature :\n"
"* Autorisé : autorisé pour tous les utilisateurs de Fabrication.\n"
"* Autorisé avec avertissement : autorisé pour tous les utilisateurs de fabrication avec récapitulatif des écarts de consommation lors de la clôture de l'ordre de fabrication.\n"
"Notez que dans le cas du composant Consommation manuelle, où la consommation est enregistrée manuellement exclusivement, des avertissements de consommation seront également émis le cas échéant.\n"
"* Bloqué : seul un responsable peut clôturer un ordre de fabrication lorsque la consommation de la nomenclature n'est pas respectée."
#. module: mrp_usability
#: model:ir.model.fields,field_description:mrp_usability.field_mrp_production__location_dest_id
msgid "Finished Products Location"
msgstr "Emplacement du produit fini"
#. module: mrp_usability
#: model:ir.model.fields,field_description:mrp_usability.field_mrp_bom__consumption
msgid "Flexible Consumption"
msgstr "Consommation flexible"
#. module: mrp_usability
#: model:ir.model.fields,help:mrp_usability.field_mrp_bom__product_id
msgid ""
"If a product variant is defined the BOM is available only for this product."
msgstr ""
"Si une variante de produit est définie, la nomenclature n'est disponible que"
" pour ce produit."
#. module: mrp_usability
#: model:ir.model.fields,help:mrp_usability.field_mrp_production__location_dest_id
msgid "Location where the system will stock the finished products."
msgstr "Emplacement où le système stockera les produits finis."
#. module: mrp_usability
#: model:ir.model.fields,field_description:mrp_usability.field_mrp_bom__ready_to_produce
msgid "Manufacturing Readiness"
msgstr "Statut de préparation de la fabrication"
#. module: mrp_usability
#: model:ir.model.fields,field_description:mrp_usability.field_mrp_bom__picking_type_id
msgid "Operation Type"
msgstr "Type d'opération"
#. module: mrp_usability
#: model:ir.model,name:mrp_usability.model_product_template
msgid "Product Template"
msgstr "Modèle d'article"
#: model:ir.model.fields,field_description:mrp_usability.field_mrp_bom__product_tmpl_id
msgid "Product"
msgstr "Produit"
#. module: mrp_usability
#: model:ir.model,name:mrp_usability.model_product_product
#: model:ir.model.fields,field_description:mrp_usability.field_mrp_bom__product_id
msgid "Product Variant"
msgstr "Variante de produit"
#. module: mrp_usability
#: model:ir.model,name:mrp_usability.model_mrp_production
msgid "Production Order"
msgstr ""
msgstr "Ordre de fabrication"
#. module: mrp_usability
#: model_terms:ir.ui.view,arch_db:mrp_usability.report_mrporder
msgid "Sold Out Quantity"
msgstr "Quantité en Rupture"
#: model:ir.model.fields,field_description:mrp_usability.field_mrp_bom__product_qty
msgid "Quantity"
msgstr "Quantité"
#. module: mrp_usability
#: model_terms:ir.ui.view,arch_db:mrp_usability.report_mrporder
#: model:ir.model.fields,field_description:mrp_usability.field_mrp_bom__code
msgid "Reference"
msgstr "Référence"
#. module: mrp_usability
#: model:ir.model.fields,help:mrp_usability.field_mrp_bom__product_qty
msgid ""
"These products were unavailable (or partially) while edition of this Manufacturing Order.\n"
" Here is missing quantities."
"This should be the smallest quantity that this product can be produced in. "
"If the BOM contains operations, make sure the work center capacity is "
"accurate."
msgstr ""
"Les produits ci-dessous étaient indisponibles (complètement ou partiellement) lors de l'édition de l'OF.<br/>\n"
"Voici les quantités manquantes."
"Il doit s'agir de la plus petite quantité dans laquelle ce produit peut être"
" produit. Si la nomenclature contient des opérations, assurez-vous que la "
"capacité du poste de travail est exacte."
#. module: mrp_usability
#: model_terms:ir.ui.view,arch_db:mrp_usability.view_mrp_bom_filter
msgid "Type"
#: model:ir.model.fields,field_description:mrp_usability.field_mrp_bom__product_uom_id
msgid "Unit of Measure"
msgstr "Unité de mesure"
#. module: mrp_usability
#: model:ir.model.fields,help:mrp_usability.field_mrp_bom__product_uom_id
msgid ""
"Unit of Measure (Unit of Measure) is the unit of measurement for the "
"inventory control"
msgstr "L'unité de mesure est l'unité utilisée dans la gestion du stock"
#. module: mrp_usability
#: model:ir.model.fields,help:mrp_usability.field_mrp_bom__picking_type_id
msgid ""
"When a procurement has a produce route with a operation type set, it will "
"try to create a Manufacturing Order for that product using a BoM of the same"
" operation type. That allows to define stock rules which trigger different "
"manufacturing orders with different BoMs."
msgstr ""
"Quand un approvisionnement a une route 'fabriquer' avec un type d'opération "
"défini, le système essayera de créer un ordre de fabrication pour ce produit"
" en utilisant une nomenclature qui a le même type d'opération. Cela permet "
"de définir des règles de stock qui génèrent des ordres de fabrication avec "
"différentes nomenclatures."

View File

@@ -9,7 +9,10 @@ from odoo import fields, models, Command
class MrpProduction(models.Model):
_inherit = 'mrp.production'
lot_producing_id = fields.Many2one(tracking=True)
location_src_id = fields.Many2one(tracking=True)
location_dest_id = fields.Many2one(tracking=True)
bom_id = fields.Many2one(tracking=True)
# Target: allow to modify location_dest_id until the button 'Mark as done' is pushed
# I didn't find a better implementation... feel free to improve if you find one

View File

@@ -0,0 +1 @@
from . import res_partner

View File

@@ -0,0 +1,27 @@
# Copyright 2014-2024 Akretion (http://www.akretion.com)
# @author Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{
'name': 'Partner Product Shortcut',
'version': '16.0.1.0.0',
'category': 'Contact Management',
'license': 'AGPL-3',
'summary': 'Adds a shortcut on partner form to the products supplied by this partner',
'description': """
Partner Product Shortcut
========================
Adds a smartbutton on partner form to the products supplied by this partner.
This is an alternative to the OCA module `partner_supplierinfo_smartbutton <https://github.com/OCA/purchase-workflow/tree/14.0/partner_supplierinfo_smartbutton>`_ which adds a smartbutton on partner form to links to the related product.supplierinfo (and not to product.template like in this module).
This module has been written by Alexis de Lattre from Akretion
<alexis.delattre@akretion.com>.
""",
'author': 'Akretion',
'website': 'https://github.com/akretion/odoo-usability',
'depends': ['product'],
'data': ['res_partner_view.xml'],
'installable': True,
}

View File

@@ -0,0 +1,38 @@
# Copyright 2014-2024 Akretion (http://www.akretion.com)
# @author Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import models, fields, _
class ResPartner(models.Model):
_inherit = 'res.partner'
def _product_supplied_count(self):
for partner in self:
count = 0
sellers = self.env['product.supplierinfo'].search(
[('partner_id', '=', partner.id)])
if sellers:
count = self.env['product.template'].search_count(
[('seller_ids', 'in', sellers.ids)])
partner.product_supplied_count = count
product_supplied_count = fields.Integer(
compute='_product_supplied_count', string="# of Products Supplied",
)
def show_supplied_products(self):
self.ensure_one()
sellers = self.env['product.supplierinfo'].search(
[('partner_id', '=', self.id)])
ptemplates = self.env['product.template'].search(
[('seller_ids', 'in', sellers.ids)])
action = {
'name': _('Products'),
'type': "ir.actions.act_window",
"res_model": "product.template",
"view_mode": 'tree,kanban,form',
'domain': f"[('id', 'in', {ptemplates.ids})]",
}
return action

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2014-2024 Akretion (http://www.akretion.com/)
@author Alexis de Lattre <alexis.delattre@akretion.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
-->
<odoo>
<record id="view_partner_form" model="ir.ui.view">
<field name="name">add.shortcut.to.product.variants.partner.form</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_partner_form"/>
<field name="arch" type="xml">
<div name="button_box" position="inside">
<button class="oe_inline oe_stat_button" type="object"
name="show_supplied_products"
icon="fa-shopping-basket"
attrs="{'invisible': [('product_supplied_count', '=', 0)]}">
<field string="Products Supplied" name="product_supplied_count"
widget="statinfo"/>
</button>
</div>
</field>
</record>
</odoo>

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

@@ -4,28 +4,26 @@
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 14.0\n"
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-05-09 16:56+0000\n"
"PO-Revision-Date: 2022-05-09 18:57+0200\n"
"POT-Creation-Date: 2024-07-07 14:27+0000\n"
"PO-Revision-Date: 2024-07-07 14:27+0000\n"
"Last-Translator: \n"
"Language-Team: \n"
"Language: fr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
"X-Generator: Poedit 3.0.1\n"
#. module: pos_usability
#: model:ir.model.fields,field_description:pos_usability.field_pos_category__product_count
msgid "# Products"
msgstr ""
msgstr "Nb de produits"
#. module: pos_usability
#: model_terms:ir.ui.view,arch_db:pos_usability.product_pos_category_form_view
msgid "<span class=\"o_stat_text\"> Products</span>"
msgstr ""
msgstr "<span class=\"o_stat_text\"> Produits</span>"
#. module: pos_usability
#: model_terms:ir.ui.view,arch_db:pos_usability.report_saledetails
@@ -38,85 +36,129 @@ msgstr "Montant"
msgid "Available in POS"
msgstr "Disponible dans le PdV"
#. module: pos_usability
#: model:ir.model.fields,field_description:pos_usability.field_pos_payment_method__cash_journal_id
msgid "Cash Journal"
msgstr "Journal de caisse"
#. module: pos_usability
#: model:ir.model.fields,help:pos_usability.field_product_product__pos_categ_id
#: model:ir.model.fields,help:pos_usability.field_product_template__pos_categ_id
msgid "Category used in the Point of Sale."
msgstr "Catégorie utilisé dans le point de vente"
msgstr "Catégorie utilisée sur le Point de Vente."
#. module: pos_usability
#: model:ir.model.fields,help:pos_usability.field_product_product__to_weight
#: model:ir.model.fields,help:pos_usability.field_product_template__to_weight
msgid ""
"Check if the product should be weighted using the hardware scale "
"integration."
msgstr ""
"Cochez cette case si le produit doit être pesé sur la balance électronique."
#. module: pos_usability
#: model:ir.model.fields,help:pos_usability.field_product_product__available_in_pos
#: model:ir.model.fields,help:pos_usability.field_product_template__available_in_pos
msgid "Check if you want this product to appear in the Point of Sale."
msgstr ""
"Cochez si vous souhaitez faire apparaître ce produit dans le Point de Vente"
"Cochez cette case si vous souhaitez faire apparaître ce produit dans le "
"Point de Vente."
#. module: pos_usability
#: model:ir.model.fields,field_description:pos_usability.field_pos_category__display_name
#: model:ir.model.fields,field_description:pos_usability.field_pos_payment_method__display_name
#: model:ir.model.fields,field_description:pos_usability.field_product_template__display_name
msgid "Display Name"
msgstr "Nom affiché"
#: model:ir.model.fields,field_description:pos_usability.field_pos_payment_method__receivable_account_id
msgid "Intermediary Account"
msgstr "Compte intermédiaire"
#. module: pos_usability
#: model:ir.model.fields,field_description:pos_usability.field_pos_category__id
#: model:ir.model.fields,field_description:pos_usability.field_pos_payment_method__id
#: model:ir.model.fields,field_description:pos_usability.field_product_template__id
msgid "ID"
#: model:ir.model.fields,field_description:pos_usability.field_pos_payment_method__journal_id
msgid "Journal"
msgstr "Journal"
#. module: pos_usability
#: model:ir.model.fields,help:pos_usability.field_pos_payment_method__outstanding_account_id
msgid ""
"Leave empty to use the default account from the company setting.\n"
"Account used as outstanding account when creating accounting payment records for bank payments."
msgstr ""
"Laisser vide pour utiliser le compte par défaut défini dans les paramètres de la société.\n"
"Compte utilisé comme compte en suspens lors de la création des lignes comptables pour les paiements."
#. module: pos_usability
#: model:ir.model.fields,field_description:pos_usability.field_pos_category____last_update
#: model:ir.model.fields,field_description:pos_usability.field_pos_payment_method____last_update
#: model:ir.model.fields,field_description:pos_usability.field_product_template____last_update
msgid "Last Modified on"
msgstr "Dernière modification le"
#: model:ir.model.fields,help:pos_usability.field_pos_payment_method__receivable_account_id
msgid ""
"Leave empty to use the default account from the company setting.\n"
"Overrides the company's receivable account (for Point of Sale) used in the journal entries."
msgstr ""
"Laisser vide pour utiliser le compte par défaut défini dans les paramètres de la société.\n"
"Remplace le compte débiteur de la société (pour le point de vente) utilisé dans les pièces comptables."
#. module: pos_usability
#: model:ir.model.fields,help:pos_usability.field_pos_payment_method__journal_id
msgid ""
"Leave empty to use the receivable account of customer.\n"
"Defines the journal where to book the accumulated payments (or individual payment if Identify Customer is true) after closing the session.\n"
"For cash journal, we directly write to the default account in the journal via statement lines.\n"
"For bank journal, we write to the outstanding account specified in this payment method.\n"
"Only cash and bank journals are allowed."
msgstr ""
"Laisser vide pour utiliser le compte débiteur du client.\n"
"Définit le journal où seront comptabilisés les paiements cumulés (ou les paiements individuels si l'identifiant du client est coché) après avoir fermé la session. \n"
"Pour le journal de caisse, nous écrivons directement dans le compte par défaut du journal par des lignes de relevé.\n"
"Pour le journal de banque, nous écrivons dans le compte en suspens défini pour ce mode de paiement.\n"
"Seuls les journaux de caisse et de banque sont autorisés. "
#. module: pos_usability
#: model:ir.model.fields,field_description:pos_usability.field_pos_payment_method__outstanding_account_id
msgid "Outstanding Account"
msgstr "Compte en suspens"
#. module: pos_usability
#: model:ir.model.fields,field_description:pos_usability.field_pos_order__payments_char
msgid "Payment Methods"
msgstr "Modes de paiement"
#. module: pos_usability
#: model:ir.model,name:pos_usability.model_pos_category
#: model:ir.model.fields,field_description:pos_usability.field_product_product__pos_categ_id
#: model:ir.model.fields,field_description:pos_usability.field_product_template__pos_categ_id
#: model_terms:ir.ui.view,arch_db:pos_usability.product_template_search_view
msgid "Point of Sale Category"
msgstr "Catégorie du point de vente"
#. module: pos_usability
#: model:ir.model,name:pos_usability.model_pos_order
msgid "Point of Sale Orders"
msgstr "Commandes du point de vente"
#. module: pos_usability
#: model:ir.model,name:pos_usability.model_pos_payment_method
msgid "Point of Sale Payment Methods"
msgstr "Modes de paiement au point de vente"
msgstr "Modes de paiement du point de vente"
#. module: pos_usability
#: model:ir.model,name:pos_usability.model_pos_session
msgid "Point of Sale Session"
msgstr "Session du point de vente"
#. module: pos_usability
#: model:ir.model,name:pos_usability.model_product_template
msgid "Product Template"
msgstr "Modèle d'article"
msgid "Product"
msgstr "Produit"
#. module: pos_usability
#: model_terms:ir.ui.view,arch_db:pos_usability.view_pos_session_form
msgid "Starting Balance"
msgstr "Montant à l'ouverture"
#: model:ir.model.fields,field_description:pos_usability.field_pos_payment_method__sequence
msgid "Sequence"
msgstr "Séquence"
#. module: pos_usability
#: model_terms:ir.ui.view,arch_db:pos_usability.view_pos_session_form
msgid "Stats"
msgstr ""
msgstr "Stats"
#. module: pos_usability
#: model:ir.model.fields,help:pos_usability.field_pos_category__product_count
msgid ""
"The number of products under this point of sale category (does not consider "
"the children categories)"
"The number of products under this point of sale category (children "
"categories included)"
msgstr ""
"Le nombre de produits de cette catégorie du point de vente (catégories enfant incluses)"
#. module: pos_usability
#: model:ir.model.fields,help:pos_usability.field_pos_payment_method__cash_journal_id
msgid ""
"The payment method is of type cash. A cash statement will be automatically "
"generated."
msgstr ""
"Cette méthode de paiement est de type cash. Un relevé sera automatiquement "
"généré. "
#: model:ir.model.fields,field_description:pos_usability.field_product_product__to_weight
#: model:ir.model.fields,field_description:pos_usability.field_product_template__to_weight
msgid "To Weigh With Scale"
msgstr "À peser sur une balance"

View File

@@ -0,0 +1,430 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * product_usability
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-07-04 15:00+0000\n"
"PO-Revision-Date: 2024-07-04 15:01+0000\n"
"Last-Translator: Alexis de Lattre <alexis.delattre@akretion.com>\n"
"Language-Team: \n"
"Language: fr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: product_usability
#: model_terms:ir.ui.view,arch_db:product_usability.product_pricelist_view
msgid "<span class=\"o_stat_text\">Lines Fullscreen</span>"
msgstr "<span class=\"o_stat_text\">Lignes plein écran</span>"
#. module: product_usability
#: model:ir.model.fields,help:product_usability.field_product_product__detailed_type
#: model:ir.model.fields,help:product_usability.field_product_template__detailed_type
msgid ""
"A storable product is a product for which you manage stock. The Inventory "
"app has to be installed.\n"
"A consumable product is a product for which stock is not managed.\n"
"A service is a non-material product you provide."
msgstr ""
"Un produit stockable est un produit pour lequel on gère le stock. "
"L'application \"Inventaire\" doit être installée.\n"
"Un produit consommable est un produit pour lequel le stock n'est pas géré.\n"
"Un service est un produit immatériel que vous fournissez."
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_category__message_needaction
msgid "Action Needed"
msgstr "Action requise"
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_product__active
#: model:ir.model.fields,field_description:product_usability.field_product_template__active
msgid "Active"
msgstr "Actif"
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_category__activity_ids
msgid "Activities"
msgstr "Activités"
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_category__activity_exception_decoration
msgid "Activity Exception Decoration"
msgstr "Style d'affichage de l'activité-alerte"
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_category__activity_state
msgid "Activity State"
msgstr "État de l'activité"
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_category__activity_type_icon
msgid "Activity Type Icon"
msgstr "Îcone du type d'activité"
#. module: product_usability
#: model_terms:ir.ui.view,arch_db:product_usability.product_pricelist_item_view_search
msgid "Apply On"
msgstr "Postuler sur"
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_category__message_attachment_count
msgid "Attachment Count"
msgstr "Nombre de pièces jointes"
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_product__barcode
#: model:ir.model.fields,field_description:product_usability.field_product_template__barcode
msgid "Barcode"
msgstr "Code-barres"
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_product__barcode_type
#: model:ir.model.fields,field_description:product_usability.field_product_template__barcode_type
msgid "Barcode Type"
msgstr "Type de code-barres"
#. module: product_usability
#: model_terms:ir.ui.view,arch_db:product_usability.product_pricelist_item_view_search
msgid "Based On"
msgstr "Basé sur"
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_product__purchase_ok
#: model:ir.model.fields,field_description:product_usability.field_product_template__purchase_ok
msgid "Can be Purchased"
msgstr "Peut être acheté"
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_product__sale_ok
#: model:ir.model.fields,field_description:product_usability.field_product_template__sale_ok
msgid "Can be Sold"
msgstr "Peut être vendu"
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_pricelist__company_id
#: model:ir.model.fields,field_description:product_usability.field_product_product__company_id
#: model:ir.model.fields,field_description:product_usability.field_product_template__company_id
msgid "Company"
msgstr "Société"
#. module: product_usability
#: model_terms:ir.ui.view,arch_db:product_usability.product_pricelist_item_view_search
msgid "Compute Price"
msgstr "Calcul du prix"
#. module: product_usability
#: model_terms:ir.ui.view,arch_db:product_usability.product_pricelist_item_view_search
msgid "Currency"
msgstr "Devise"
#. module: product_usability
#: model:ir.model.fields,help:product_usability.field_product_product__uom_id
#: model:ir.model.fields,help:product_usability.field_product_template__uom_id
msgid "Default unit of measure used for all stock operations."
msgstr ""
"Unité de mesure par défaut utilisée pour toutes les opérations de stock."
#. module: product_usability
#: model:ir.model.fields,help:product_usability.field_product_product__uom_po_id
#: model:ir.model.fields,help:product_usability.field_product_template__uom_po_id
msgid ""
"Default unit of measure used for purchase orders. It must be in the same "
"category as the default unit of measure."
msgstr ""
"Unité de mesure par défaut utilisée pour les commandes fournisseurs. Elle "
"doit appartenir à la même catégorie que l'unité de mesure par défaut."
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_category__message_follower_ids
msgid "Followers"
msgstr "Abonnés"
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_category__message_partner_ids
msgid "Followers (Partners)"
msgstr "Abonnés (partenaires)"
#. module: product_usability
#: model:ir.model.fields,help:product_usability.field_product_category__activity_type_icon
msgid "Font awesome icon e.g. fa-tasks"
msgstr "Îcone font-awesome, par exemple fa-task"
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_category__has_message
msgid "Has Message"
msgstr "A un message"
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_category__activity_exception_icon
msgid "Icon"
msgstr "Îcone"
#. module: product_usability
#: model:ir.model.fields,help:product_usability.field_product_category__activity_exception_icon
msgid "Icon to indicate an exception activity."
msgstr "Îcone pour indiquer une activité-alerte"
#. module: product_usability
#: model:ir.model.fields,help:product_usability.field_product_category__message_needaction
msgid "If checked, new messages require your attention."
msgstr "Si activé, de nouveaux messages nécessitent votre attention."
#. module: product_usability
#: model:ir.model.fields,help:product_usability.field_product_category__message_has_error
msgid "If checked, some messages have a delivery error."
msgstr "Si activé, des messages ont une erreur d'envoi."
#. module: product_usability
#: model:ir.model.fields,help:product_usability.field_product_product__active
#: model:ir.model.fields,help:product_usability.field_product_template__active
msgid ""
"If unchecked, it will allow you to hide the product without removing it."
msgstr ""
"Décocher cette case vous permet de masquer le produit sans le supprimer."
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_product__default_code
#: model:ir.model.fields,field_description:product_usability.field_product_template__default_code
msgid "Internal Reference"
msgstr "Référence interne"
#. module: product_usability
#: model:ir.model.fields,help:product_usability.field_product_product__barcode
msgid "International Article Number used for product identification."
msgstr ""
"Numéro d'article international utilisé pour l'identification du produit."
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_category__message_is_follower
msgid "Is Follower"
msgstr "Est abonné"
#. module: product_usability
#: model_terms:ir.ui.view,arch_db:product_usability.product_pricelist_view
msgid "List view of price rules"
msgstr "Liste de règles de prix"
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_category__message_main_attachment_id
msgid "Main Attachment"
msgstr "Pièce jointe principale"
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_product__seller_id
#: model:ir.model.fields,field_description:product_usability.field_product_template__seller_id
msgid "Main Supplier"
msgstr "Fournisseur principal"
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_category__message_has_error
msgid "Message Delivery error"
msgstr "Erreur d'envoi du message"
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_category__message_ids
msgid "Messages"
msgstr "Messages"
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_category__my_activity_date_deadline
msgid "My Activity Deadline"
msgstr "Date butoir de l'activité"
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_category__name
#: model:ir.model.fields,field_description:product_usability.field_product_product__name
#: model:ir.model.fields,field_description:product_usability.field_product_template__name
msgid "Name"
msgstr "Nom"
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_category__activity_calendar_event_id
msgid "Next Activity Calendar Event"
msgstr "Prochaine activité du calendrier"
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_category__activity_date_deadline
msgid "Next Activity Deadline"
msgstr "Date butoir de l'activité suivante"
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_category__activity_summary
msgid "Next Activity Summary"
msgstr "Résumé de l'activité suivante"
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_category__activity_type_id
msgid "Next Activity Type"
msgstr "Type de l'activité suivante"
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_category__message_needaction_counter
msgid "Number of Actions"
msgstr "Nombre d'actions"
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_category__message_has_error_counter
msgid "Number of errors"
msgstr "Nombre d'erreurs"
#. module: product_usability
#: model:ir.model.fields,help:product_usability.field_product_category__message_needaction_counter
msgid "Number of messages requiring action"
msgstr "Nombre de messages nécessitant une action"
#. module: product_usability
#: model:ir.model.fields,help:product_usability.field_product_category__message_has_error_counter
msgid "Number of messages with delivery error"
msgstr "Nombre de messages en échec d'envoi"
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_category__parent_id
msgid "Parent Category"
msgstr "Catégorie mère"
#. module: product_usability
#: model:ir.actions.act_window,name:product_usability.pricelist_item_fullscreen_action
msgid "Price Rules"
msgstr "Règles de liste de prix"
#. module: product_usability
#: model:ir.model.fields,help:product_usability.field_product_product__list_price
#: model:ir.model.fields,help:product_usability.field_product_template__list_price
msgid "Price at which the product is sold to customers."
msgstr "Prix auquel le produit est vendu aux clients."
#. module: product_usability
#: model:ir.model,name:product_usability.model_product_pricelist
msgid "Pricelist"
msgstr "Liste de prix"
#. module: product_usability
#: model:ir.model,name:product_usability.model_product_template
msgid "Product"
msgstr "Produit"
#. module: product_usability
#: model:ir.ui.menu,name:product_usability.product_categ_config_menu
msgid "Product Categories"
msgstr "Catégories de produit"
#. module: product_usability
#: model:ir.model,name:product_usability.model_product_category
#: model:ir.model.fields,field_description:product_usability.field_product_product__categ_id
#: model:ir.model.fields,field_description:product_usability.field_product_template__categ_id
msgid "Product Category"
msgstr "Catégorie de produit"
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_product__detailed_type
#: model:ir.model.fields,field_description:product_usability.field_product_template__detailed_type
msgid "Product Type"
msgstr "Type de produit"
#. module: product_usability
#: model:ir.model,name:product_usability.model_product_product
msgid "Product Variant"
msgstr "Variante de produit"
#. module: product_usability
#: model:ir.ui.menu,name:product_usability.product_product_config_menu
msgid "Product Variants"
msgstr "Variantes de produit"
#. module: product_usability
#: model:ir.ui.menu,name:product_usability.product_config_menu
#: model:ir.ui.menu,name:product_usability.product_template_config_menu
msgid "Products"
msgstr "Produits"
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_product__uom_po_id
#: model:ir.model.fields,field_description:product_usability.field_product_template__uom_po_id
msgid "Purchase UoM"
msgstr "Unité de mesure à l'achat"
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_category__activity_user_id
msgid "Responsible User"
msgstr "Utilisateur responsable"
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_product__list_price
#: model:ir.model.fields,field_description:product_usability.field_product_template__list_price
msgid "Sales Price"
msgstr "Prix de vente"
#. module: product_usability
#: model:ir.model.fields,help:product_usability.field_product_category__activity_state
msgid ""
"Status based on activities\n"
"Overdue: Due date is already passed\n"
"Today: Activity date is today\n"
"Planned: Future activities."
msgstr ""
"Statut basé sur les activités\n"
"En retard : La date d'échéance est déjà dépassée\n"
"Aujourd'hui : La date de l'activité est aujourd'hui\n"
"Planifié : Activités futures."
#. module: product_usability
#: model_terms:ir.ui.view,arch_db:product_usability.product_template_search_view
msgid "Supplier"
msgstr "Fournisseur"
#. module: product_usability
#: model:ir.model,name:product_usability.model_product_supplierinfo
msgid "Supplier Pricelist"
msgstr "Liste de prix fournisseur"
#. module: product_usability
#: model:ir.model.constraint,message:product_usability.constraint_product_product_default_code_uniq
msgid "This internal reference already exists!"
msgstr "Cette référence interne existe déjà !"
#. module: product_usability
#: model:ir.model.fields,help:product_usability.field_product_category__activity_exception_decoration
msgid "Type of the exception activity on record."
msgstr "Type de l'activité-alerte sur l'enregistrement."
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_product__uom_id
#: model:ir.model.fields,field_description:product_usability.field_product_template__uom_id
msgid "Unit of Measure"
msgstr "Unité de mesure"
#. module: product_usability
#: model:ir.ui.menu,name:product_usability.uom_uom_config_menu
msgid "Units of Measure"
msgstr "Unités de mesure"
#. module: product_usability
#: model:ir.ui.menu,name:product_usability.uom_categ_config_menu
msgid "Units of Measure Categories"
msgstr "Catégories d'unités de mesure"
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_supplierinfo__partner_id
msgid "Vendor"
msgstr "Vendeur"
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_category__website_message_ids
msgid "Website Messages"
msgstr "Messages du site Web"
#. module: product_usability
#: model:ir.model.fields,help:product_usability.field_product_category__website_message_ids
msgid "Website communication history"
msgstr "Historique des échanges sur le site Web"
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_product__weight
#: model:ir.model.fields,field_description:product_usability.field_product_template__weight
msgid "Weight"
msgstr "Poids"

View File

@@ -0,0 +1,415 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * product_usability
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-07-04 15:00+0000\n"
"PO-Revision-Date: 2024-07-04 15: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: product_usability
#: model_terms:ir.ui.view,arch_db:product_usability.product_pricelist_view
msgid "<span class=\"o_stat_text\">Lines Fullscreen</span>"
msgstr ""
#. module: product_usability
#: model:ir.model.fields,help:product_usability.field_product_product__detailed_type
#: model:ir.model.fields,help:product_usability.field_product_template__detailed_type
msgid ""
"A storable product is a product for which you manage stock. The Inventory app has to be installed.\n"
"A consumable product is a product for which stock is not managed.\n"
"A service is a non-material product you provide."
msgstr ""
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_category__message_needaction
msgid "Action Needed"
msgstr ""
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_product__active
#: model:ir.model.fields,field_description:product_usability.field_product_template__active
msgid "Active"
msgstr ""
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_category__activity_ids
msgid "Activities"
msgstr ""
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_category__activity_exception_decoration
msgid "Activity Exception Decoration"
msgstr ""
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_category__activity_state
msgid "Activity State"
msgstr ""
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_category__activity_type_icon
msgid "Activity Type Icon"
msgstr ""
#. module: product_usability
#: model_terms:ir.ui.view,arch_db:product_usability.product_pricelist_item_view_search
msgid "Apply On"
msgstr ""
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_category__message_attachment_count
msgid "Attachment Count"
msgstr ""
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_product__barcode
#: model:ir.model.fields,field_description:product_usability.field_product_template__barcode
msgid "Barcode"
msgstr ""
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_product__barcode_type
#: model:ir.model.fields,field_description:product_usability.field_product_template__barcode_type
msgid "Barcode Type"
msgstr ""
#. module: product_usability
#: model_terms:ir.ui.view,arch_db:product_usability.product_pricelist_item_view_search
msgid "Based On"
msgstr ""
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_product__purchase_ok
#: model:ir.model.fields,field_description:product_usability.field_product_template__purchase_ok
msgid "Can be Purchased"
msgstr ""
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_product__sale_ok
#: model:ir.model.fields,field_description:product_usability.field_product_template__sale_ok
msgid "Can be Sold"
msgstr ""
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_pricelist__company_id
#: model:ir.model.fields,field_description:product_usability.field_product_product__company_id
#: model:ir.model.fields,field_description:product_usability.field_product_template__company_id
msgid "Company"
msgstr ""
#. module: product_usability
#: model_terms:ir.ui.view,arch_db:product_usability.product_pricelist_item_view_search
msgid "Compute Price"
msgstr ""
#. module: product_usability
#: model_terms:ir.ui.view,arch_db:product_usability.product_pricelist_item_view_search
msgid "Currency"
msgstr ""
#. module: product_usability
#: model:ir.model.fields,help:product_usability.field_product_product__uom_id
#: model:ir.model.fields,help:product_usability.field_product_template__uom_id
msgid "Default unit of measure used for all stock operations."
msgstr ""
#. module: product_usability
#: model:ir.model.fields,help:product_usability.field_product_product__uom_po_id
#: model:ir.model.fields,help:product_usability.field_product_template__uom_po_id
msgid ""
"Default unit of measure used for purchase orders. It must be in the same "
"category as the default unit of measure."
msgstr ""
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_category__message_follower_ids
msgid "Followers"
msgstr ""
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_category__message_partner_ids
msgid "Followers (Partners)"
msgstr ""
#. module: product_usability
#: model:ir.model.fields,help:product_usability.field_product_category__activity_type_icon
msgid "Font awesome icon e.g. fa-tasks"
msgstr ""
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_category__has_message
msgid "Has Message"
msgstr ""
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_category__activity_exception_icon
msgid "Icon"
msgstr ""
#. module: product_usability
#: model:ir.model.fields,help:product_usability.field_product_category__activity_exception_icon
msgid "Icon to indicate an exception activity."
msgstr ""
#. module: product_usability
#: model:ir.model.fields,help:product_usability.field_product_category__message_needaction
msgid "If checked, new messages require your attention."
msgstr ""
#. module: product_usability
#: model:ir.model.fields,help:product_usability.field_product_category__message_has_error
msgid "If checked, some messages have a delivery error."
msgstr ""
#. module: product_usability
#: model:ir.model.fields,help:product_usability.field_product_product__active
#: model:ir.model.fields,help:product_usability.field_product_template__active
msgid ""
"If unchecked, it will allow you to hide the product without removing it."
msgstr ""
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_product__default_code
#: model:ir.model.fields,field_description:product_usability.field_product_template__default_code
msgid "Internal Reference"
msgstr ""
#. module: product_usability
#: model:ir.model.fields,help:product_usability.field_product_product__barcode
msgid "International Article Number used for product identification."
msgstr ""
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_category__message_is_follower
msgid "Is Follower"
msgstr ""
#. module: product_usability
#: model_terms:ir.ui.view,arch_db:product_usability.product_pricelist_view
msgid "List view of price rules"
msgstr ""
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_category__message_main_attachment_id
msgid "Main Attachment"
msgstr ""
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_product__seller_id
#: model:ir.model.fields,field_description:product_usability.field_product_template__seller_id
msgid "Main Supplier"
msgstr ""
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_category__message_has_error
msgid "Message Delivery error"
msgstr ""
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_category__message_ids
msgid "Messages"
msgstr ""
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_category__my_activity_date_deadline
msgid "My Activity Deadline"
msgstr ""
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_category__name
#: model:ir.model.fields,field_description:product_usability.field_product_product__name
#: model:ir.model.fields,field_description:product_usability.field_product_template__name
msgid "Name"
msgstr ""
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_category__activity_calendar_event_id
msgid "Next Activity Calendar Event"
msgstr ""
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_category__activity_date_deadline
msgid "Next Activity Deadline"
msgstr ""
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_category__activity_summary
msgid "Next Activity Summary"
msgstr ""
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_category__activity_type_id
msgid "Next Activity Type"
msgstr ""
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_category__message_needaction_counter
msgid "Number of Actions"
msgstr ""
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_category__message_has_error_counter
msgid "Number of errors"
msgstr ""
#. module: product_usability
#: model:ir.model.fields,help:product_usability.field_product_category__message_needaction_counter
msgid "Number of messages requiring action"
msgstr ""
#. module: product_usability
#: model:ir.model.fields,help:product_usability.field_product_category__message_has_error_counter
msgid "Number of messages with delivery error"
msgstr ""
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_category__parent_id
msgid "Parent Category"
msgstr ""
#. module: product_usability
#: model:ir.actions.act_window,name:product_usability.pricelist_item_fullscreen_action
msgid "Price Rules"
msgstr ""
#. module: product_usability
#: model:ir.model.fields,help:product_usability.field_product_product__list_price
#: model:ir.model.fields,help:product_usability.field_product_template__list_price
msgid "Price at which the product is sold to customers."
msgstr ""
#. module: product_usability
#: model:ir.model,name:product_usability.model_product_pricelist
msgid "Pricelist"
msgstr ""
#. module: product_usability
#: model:ir.model,name:product_usability.model_product_template
msgid "Product"
msgstr ""
#. module: product_usability
#: model:ir.ui.menu,name:product_usability.product_categ_config_menu
msgid "Product Categories"
msgstr ""
#. module: product_usability
#: model:ir.model,name:product_usability.model_product_category
#: model:ir.model.fields,field_description:product_usability.field_product_product__categ_id
#: model:ir.model.fields,field_description:product_usability.field_product_template__categ_id
msgid "Product Category"
msgstr ""
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_product__detailed_type
#: model:ir.model.fields,field_description:product_usability.field_product_template__detailed_type
msgid "Product Type"
msgstr ""
#. module: product_usability
#: model:ir.model,name:product_usability.model_product_product
msgid "Product Variant"
msgstr ""
#. module: product_usability
#: model:ir.ui.menu,name:product_usability.product_product_config_menu
msgid "Product Variants"
msgstr ""
#. module: product_usability
#: model:ir.ui.menu,name:product_usability.product_config_menu
#: model:ir.ui.menu,name:product_usability.product_template_config_menu
msgid "Products"
msgstr ""
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_product__uom_po_id
#: model:ir.model.fields,field_description:product_usability.field_product_template__uom_po_id
msgid "Purchase UoM"
msgstr ""
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_category__activity_user_id
msgid "Responsible User"
msgstr ""
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_product__list_price
#: model:ir.model.fields,field_description:product_usability.field_product_template__list_price
msgid "Sales Price"
msgstr ""
#. module: product_usability
#: model:ir.model.fields,help:product_usability.field_product_category__activity_state
msgid ""
"Status based on activities\n"
"Overdue: Due date is already passed\n"
"Today: Activity date is today\n"
"Planned: Future activities."
msgstr ""
#. module: product_usability
#: model_terms:ir.ui.view,arch_db:product_usability.product_template_search_view
msgid "Supplier"
msgstr ""
#. module: product_usability
#: model:ir.model,name:product_usability.model_product_supplierinfo
msgid "Supplier Pricelist"
msgstr ""
#. module: product_usability
#: model:ir.model.constraint,message:product_usability.constraint_product_product_default_code_uniq
msgid "This internal reference already exists!"
msgstr ""
#. module: product_usability
#: model:ir.model.fields,help:product_usability.field_product_category__activity_exception_decoration
msgid "Type of the exception activity on record."
msgstr ""
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_product__uom_id
#: model:ir.model.fields,field_description:product_usability.field_product_template__uom_id
msgid "Unit of Measure"
msgstr ""
#. module: product_usability
#: model:ir.ui.menu,name:product_usability.uom_uom_config_menu
msgid "Units of Measure"
msgstr ""
#. module: product_usability
#: model:ir.ui.menu,name:product_usability.uom_categ_config_menu
msgid "Units of Measure Categories"
msgstr ""
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_supplierinfo__partner_id
msgid "Vendor"
msgstr ""
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_category__website_message_ids
msgid "Website Messages"
msgstr ""
#. module: product_usability
#: model:ir.model.fields,help:product_usability.field_product_category__website_message_ids
msgid "Website communication history"
msgstr ""
#. module: product_usability
#: model:ir.model.fields,field_description:product_usability.field_product_product__weight
#: model:ir.model.fields,field_description:product_usability.field_product_template__weight
msgid "Weight"
msgstr ""

View File

@@ -29,12 +29,15 @@ class ProductProduct(models.Model):
@api.model
def _get_barcode_type(self, barcode):
barcode_type = False
size2label = {
8: 'EAN-8',
13: 'EAN-13',
14: 'GTIN-14',
}
if barcode:
size = len(barcode)
if size == 13 and is_valid(barcode):
barcode_type = 'EAN13'
elif size == 8 and is_valid(barcode):
barcode_type = 'EAN8'
if size in size2label and is_valid(barcode):
barcode_type = size2label[size]
return barcode_type
@api.depends('barcode')

View File

@@ -9,7 +9,7 @@
<record id="pricelist_item_fullscreen_action" model="ir.actions.act_window">
<field name="name">Pricelists Items</field>
<field name="name">Price Rules</field>
<field name="res_model">product.pricelist.item</field>
<field name="view_mode">tree,form</field>
<field name="domain">[('pricelist_id', '=', active_id)]</field>
@@ -27,7 +27,7 @@
class="oe_stat_button"
icon="fa-building-o"
type="action"
help="List view of pricelist items">
help="List view of price rules">
<div class="o_form_field o_stat_info">
<span class="o_stat_text">Lines Fullscreen</span>
</div>

View File

@@ -24,6 +24,9 @@
<field name="product_code" position="attributes">
<attribute name="optional">show</attribute>
</field>
<field name="min_qty" position="attributes">
<attribute name="optional">show</attribute>
</field>
</field>
</record>

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2015-2020 Akretion (http://www.akretion.com/)
Copyright 2015-2024 Akretion France (https://www.akretion.com/)
@author Alexis de Lattre <alexis.delattre@akretion.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
-->
@@ -35,4 +35,15 @@
</field>
</record>
<record id="product_template_tree_view" model="ir.ui.view">
<field name="model">product.template</field>
<field name="inherit_id" ref="product.product_template_tree_view"/>
<field name="arch" type="xml">
<field name="barcode" position="after">
<field name="seller_id" optional="hide"/>
</field>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,17 @@
===================
Project Task Report
===================
Task wizard to sum up the progress of some projects tasks between two dates
Usage
=====
To use this module, you need to:
#. Go to Project > Reporting > Tasks Report
#. Select the related Projects and the Start and End dates of the report
#. The resulting report is a list of the Tasks with new timesheets and/or with stage change between the two selected dates

View File

@@ -0,0 +1 @@
from . import wizards

View File

@@ -0,0 +1,17 @@
# Copyright 2024 Akretion
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
{
"name": "Project Task Report",
"summary": """Task wizard to sum up the progress between two dates""",
"version": "16.0.1.0.0",
"license": "AGPL-3",
"author": "Akretion",
"website": "http://akretion.com",
"depends": ["project", "hr_timesheet"],
"data": [
"security/ir.model.access.csv",
"wizards/project_task_report.xml",
],
"demo": ["data/project_task_report_demo.xml"],
}

View File

@@ -0,0 +1,104 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<!-- Tasks -->
<record id="task_1" model="project.task">
<field name="project_id" ref="project.project_project_1"/>
<field name="name">Task 1</field>
</record>
<record id="task_2" model="project.task">
<field name="project_id" ref="project.project_project_1"/>
<field name="name">Task 2</field>
<field name="create_date" eval="datetime(2023, 12, 1)"/>
</record>
<!-- Timesheets -->
<record id="timesheet_11" model="account.analytic.line">
<field name="name">Timesheet 1.1</field>
<field name="employee_id" ref="hr.employee_qdp"/>
<field name="date" eval="datetime(2024, 3, 2)"/>
<field name="task_id" ref="task_1"/>
<field name="unit_amount">1.00</field>
</record>
<record id="timesheet_21" model="account.analytic.line">
<field name="name">Timesheet 2.1</field>
<field name="employee_id" ref="hr.employee_qdp"/>
<field name="date" eval="datetime(2024, 2, 1)"/>
<field name="task_id" ref="task_2"/>
</record>
<record id="timesheet_22" model="account.analytic.line">
<field name="name">Timesheet 2.2</field>
<field name="employee_id" ref="hr.employee_qdp"/>
<field name="date" eval="datetime(2024, 3, 1)"/>
<field name="task_id" ref="task_2"/>
<field name="unit_amount">10.00</field>
</record>
<record id="timesheet_23" model="account.analytic.line">
<field name="name">Timesheet 2.3</field>
<field name="employee_id" ref="hr.employee_qdp"/>
<field name="date" eval="datetime(2024, 3, 2)"/>
<field name="task_id" ref="task_2"/>
<field name="unit_amount">2.00</field>
</record>
<!-- Historic stage changes on Task 2 -->
<record id="task_2_mail_message_1" model="mail.message">
<field name="model">project.task</field>
<field name="res_id" ref="task_2"/>
<field name="message_type">notification</field>
<field name="date" eval="datetime(2024, 1, 1)"/>
<field name="subtype_id" ref="project.mt_task_stage"/>
<field name="author_id" ref="base.partner_admin"/>
</record>
<record id="task_2_mail_message_1_track" model="mail.tracking.value">
<field name="field" model="ir.model.fields" eval="obj().search([('model', '=', 'project.task'), ('name', '=', 'stage_id')])"/>
<field name="field_desc">Stage</field>
<field name="old_value_char">New</field>
<field name="new_value_char">In Progress</field>
<field name="field_type">many2one</field>
<field name="old_value_integer">1</field>
<field name="new_value_integer">2</field>
<field name="mail_message_id" ref="task_2_mail_message_1"/>
</record>
<record id="task_2_mail_message_2" model="mail.message">
<field name="model">project.task</field>
<field name="res_id" ref="task_2"/>
<field name="message_type">notification</field>
<field name="date" eval="datetime(2024, 4, 1)"/>
<field name="subtype_id" ref="project.mt_task_stage"/>
<field name="author_id" ref="base.partner_admin"/>
</record>
<record id="task_2_mail_message_2_track" model="mail.tracking.value">
<field name="field" model="ir.model.fields" eval="obj().search([('model', '=', 'project.task'), ('name', '=', 'stage_id')])"/>
<field name="field_desc">Stage</field>
<field name="old_value_char">In Progress</field>
<field name="new_value_char">Done</field>
<field name="field_type">many2one</field>
<field name="old_value_integer">2</field>
<field name="new_value_integer">3</field>
<field name="mail_message_id" ref="task_2_mail_message_2"/>
</record>
<record id="task_2_mail_message_3" model="mail.message">
<field name="model">project.task</field>
<field name="res_id" ref="task_2"/>
<field name="message_type">notification</field>
<field name="date" eval="datetime(2024, 5, 1)"/>
<field name="subtype_id" ref="project.mt_task_stage"/>
<field name="author_id" ref="base.partner_admin"/>
</record>
<record id="task_2_mail_message_3_track" model="mail.tracking.value">
<field name="field" model="ir.model.fields" eval="obj().search([('model', '=', 'project.task'), ('name', '=', 'stage_id')])"/>
<field name="field_desc">Stage</field>
<field name="old_value_char">Done</field>
<field name="new_value_char">Canceled</field>
<field name="field_type">many2one</field>
<field name="old_value_integer">3</field>
<field name="new_value_integer">4</field>
<field name="mail_message_id" ref="task_2_mail_message_3"/>
</record>
</data>
</odoo>

View File

@@ -0,0 +1,3 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
project_task_report.access_project_task_report,access_project_task_report,project_task_report.model_project_task_report,base.group_user,1,1,1,1
project_task_report.access_project_task_report_line,access_project_task_report_line,project_task_report.model_project_task_report_line,base.group_user,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 project_task_report.access_project_task_report access_project_task_report project_task_report.model_project_task_report base.group_user 1 1 1 1
3 project_task_report.access_project_task_report_line access_project_task_report_line project_task_report.model_project_task_report_line base.group_user 1 1 1 1

View File

@@ -0,0 +1 @@
from . import test_project_task_report

View File

@@ -0,0 +1,38 @@
# Copyright 2024 Akretion
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from datetime import datetime
from odoo.tests.common import TransactionCase
class TestProjectTaskReport(TransactionCase):
def setUp(self):
super().setUp()
self.task_report_id = self.env["project.task.report"].create(
{
"start_date": datetime(2024, 2, 2),
"end_date": datetime(2024, 6, 1),
"project_ids": self.env.ref("project.project_project_1").ids,
}
)
line_ids = self.task_report_id._create_line_ids()
self.line_ids = line_ids.sorted(lambda l: l.task_id.name)
self.stage_new = self.env.ref("project.project_stage_0")
self.stage_in_progress = self.env.ref("project.project_stage_1")
self.stage_canceled = self.env.ref("project.project_stage_3")
def test_task_report_no_stage_change(self):
task_line_id = self.line_ids[0]
self.assertEqual(task_line_id.task_id.name, "Task 1")
self.assertEqual(task_line_id.hours_spent, 1)
self.assertEqual(task_line_id.start_stage_id, self.stage_new)
self.assertEqual(task_line_id.end_stage_id, self.stage_new)
def test_task_report_with_stage_change(self):
task_line_id = self.line_ids[1]
self.assertEqual(task_line_id.task_id.name, "Task 2")
self.assertEqual(task_line_id.hours_spent, 12)
self.assertEqual(task_line_id.start_stage_id, self.stage_in_progress)
self.assertEqual(task_line_id.end_stage_id, self.stage_canceled)

View File

@@ -0,0 +1 @@
from . import project_task_report

View File

@@ -0,0 +1,84 @@
# Copyright 2024 Akretion
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import _, api, fields, models
class ProjectTaskReport(models.TransientModel):
_name = "project.task.report"
_description = "Task Report"
start_date = fields.Date()
end_date = fields.Date()
project_ids = fields.Many2many("project.project", string="Projects")
def _create_line_ids(self):
line_vals = []
task_ids = self.env["project.task"].search(
[("project_id", "in", self.project_ids.ids)]
)
field_stage_id = self.env["ir.model.fields"].search(
[("model", "=", "project.task"), ("name", "=", "stage_id")]
)
for task_id in task_ids:
line_val = {"task_id": task_id.id, "timesheet_ids": []}
# Catch the timesheets between the start and end dates
for timesheet_id in task_id.timesheet_ids:
if self.start_date < timesheet_id.date < self.end_date:
line_val["timesheet_ids"].append(timesheet_id.id)
# Catch the historic stage changes between the start and end dates
track_ids = task_id.message_ids.tracking_value_ids.filtered(
lambda t: t.field == field_stage_id
and self.start_date < t.mail_message_id.date.date() < self.end_date
).sorted(lambda t: t.mail_message_id.date)
if track_ids:
line_val.update(
{
"start_stage_id": track_ids[0].old_value_integer,
"end_stage_id": track_ids[-1].new_value_integer,
}
)
if line_val["timesheet_ids"] or line_val.get("start_stage_id"):
# Fill stage fields in case there have been timesheets without stage change
if not line_val.get("start_stage_id"):
line_val.update(
{
"start_stage_id": task_id.stage_id.id,
"end_stage_id": task_id.stage_id.id,
}
)
line_vals.append(line_val)
return self.env["project.task.report.line"].create(line_vals)
def action_view_task_report(self):
self.ensure_one()
line_ids = self._create_line_ids()
action_xml_id = "project_task_report.project_task_report_line_act_window"
action = self.env["ir.actions.act_window"]._for_xml_id(action_xml_id)
action.update({"domain": [("id", "in", line_ids.ids)]})
return action
class ProjectTaskReportLine(models.TransientModel):
_name = "project.task.report.line"
_description = "Task Report Line"
task_id = fields.Many2one("project.task", readonly=True)
start_stage_id = fields.Many2one("project.task.type", readonly=True)
end_stage_id = fields.Many2one("project.task.type", readonly=True)
timesheet_ids = fields.Many2many("account.analytic.line", readonly=True)
hours_spent = fields.Float(compute="_compute_hours_spent", store=True)
@api.depends("timesheet_ids.unit_amount")
def _compute_hours_spent(self):
for rec in self:
rec.hours_spent = sum(rec.timesheet_ids.mapped("unit_amount"))

View File

@@ -0,0 +1,82 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2024 Akretion
License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). -->
<odoo>
<record id="project_task_report_form_view" model="ir.ui.view">
<field name="model">project.task.report</field>
<field name="arch" type="xml">
<form string="Project Task Report">
<group>
<field name="start_date"/>
<field name="end_date"/>
<field name="project_ids" widget="many2many_tags"/>
</group>
<footer>
<button name="action_view_task_report"
string="Create Task Report"
class="btn-primary"
type="object"/>
<button string="Cancel"
class="btn-default"
special="cancel"/>
</footer>
</form>
</field>
</record>
<record model="ir.actions.act_window" id="project_task_report_act_window">
<field name="name">Tasks Report</field>
<field name="res_model">project.task.report</field>
<field name="view_mode">form</field>
<field name="target">new</field>
</record>
<record id="project_task_report_line_tree_view" model="ir.ui.view">
<field name="name">project.task.report.line.tree</field>
<field name="model">project.task.report.line</field>
<field name="arch" type="xml">
<tree string="Task Report" create="false" delete="false" edit="false">
<field name="task_id"/>
<field name="start_stage_id"/>
<field name="end_stage_id"/>
<field name="hours_spent" widget="timesheet_uom"/>
</tree>
</field>
</record>
<record id="project_task_report_line_form_view" model="ir.ui.view">
<field name="model">project.task.report.line</field>
<field name="arch" type="xml">
<form string="Project Task Report Line">
<sheet>
<div class="oe_title">
<label for="task_id"/>
<h1><field name="task_id"/></h1>
</div>
<group class="col-12 col-lg-6">
<field name="start_stage_id"/>
<field name="end_stage_id"/>
</group>
<group class="col-12 col-lg-6">
<field name="timesheet_ids"/>
</group>
</sheet>
</form>
</field>
</record>
<record model="ir.actions.act_window" id="project_task_report_line_act_window">
<field name="name">Tasks Report</field>
<field name="res_model">project.task.report.line</field>
<field name="view_mode">tree,form</field>
</record>
<record model="ir.ui.menu" id="project_task_report_menu">
<field name="name">Tasks Report</field>
<field name="parent_id" ref="project.menu_project_report"/>
<field name="action" ref="project_task_report_act_window"/>
<field name="sequence" eval="10"/>
</record>
</odoo>

Some files were not shown because too many files have changed in this diff Show More