Compare commits

..

51 Commits

Author SHA1 Message Date
Florian da Costa
3f133ab663 [IMP] Add default agent boolean when creating an agent from the commission profile view 2025-09-10 10:46:26 +02:00
Florian da Costa
47197eb5f6 [FIX] chatter in commission result view + add action name for all commission related new actions 2025-09-09 12:21:32 +02:00
Florian da Costa
5ca18e6374 [MIG] commission_simple_agent_purchase to 18 2025-09-09 12:04:37 +02:00
Benoît
4d52d54460 fix missing import 2025-09-02 17:50:27 +02:00
Benoît
0a260e0b54 mig report 2025-09-02 17:30:48 +02:00
Florian da Costa
46e11948fd [MIG] commission_simple_agent : technical migration to 18 2025-09-02 16:02:40 +02:00
Florian da Costa
a19ec0db45 [MIG] commission_simple to 18 2025-09-02 15:59:08 +02:00
Florian da Costa
6af8aac67e [MIG] sale_agent to v18 2025-09-02 15:32:29 +02:00
Alexis de Lattre
36b35f1b87 [IMP] l10n_fr_account_profile_akretion: Add dep on account_dashboard_banner 2025-07-17 15:28:24 +02:00
Alexis de Lattre
f1f808d977 [UDP] l10n_fr_account_profile_akretion: new module names and newly ported modules 2025-06-25 16:02:24 +02:00
Alexis de Lattre
11f3d393b5 mail_debrand has been moved from OCA/social to OCA/mail in v18 2025-06-25 12:31:18 +02:00
Alexis de Lattre
ca5730c701 [IMP] base_profile_akretion: add mail_debrand 2025-06-25 12:23:13 +02:00
Alexis de Lattre
76a1bbd9f4 [IMP] stock_usability_akretion: add button to show reservations from quand tree view 2025-06-23 12:32:03 +02:00
Alexis de Lattre
48d5a3b327 [IMP] stock_quant_package_move_wizard: more accurate source location on picking when all quants have the same location 2025-06-23 12:24:43 +02:00
Akretion Git Bot
836a88dfeb [BOT] add or update setup/_metapackage 2025-05-26 10:16:44 +00:00
Akretion Git Bot
8182b839d4 [BOT] add pyproject.toml 2025-05-26 10:16:43 +00:00
Akretion Git Bot
6cd86f8820 [ADD] icon.png 2025-05-26 10:16:43 +00:00
Alexis de Lattre
76e93f0379 [MIG] l10n_fr_account_profile_akretion from v16 to v18 2025-05-26 12:16:18 +02:00
Alexis de Lattre
d9f65b96fc Remove patch web-advanced_search_startswith.diff (native in v18) 2025-05-26 11:47:26 +02:00
Akretion Git Bot
a729762b4a [BOT] add or update setup/_metapackage 2025-05-26 09:19:03 +00:00
Akretion Git Bot
18551f9b0d [BOT] add pyproject.toml 2025-05-26 09:19:03 +00:00
Akretion Git Bot
05b2d14cd2 [ADD] icon.png 2025-05-26 09:19:02 +00:00
Akretion Git Bot
1d57615b97 [UPD] README.rst 2025-05-26 09:19:02 +00:00
Alexis de Lattre
545cd797e3 [MIG] base_company_extension, eradicate_quick_create, mail_usability_akretion, base_profile_akretion to v18 2025-05-26 11:18:22 +02:00
Alexis de Lattre
70b66681d6 [IMP] stock_usability_akretion: add seller_id on orderpoints 2025-05-20 10:30:29 +02:00
Akretion Git Bot
2e93aaa55b [UPD] README.rst 2025-04-01 16:35:45 +00:00
Alexis de Lattre
5b6a166ed6 [IMP] account_usability_akretion: add move_id on account.payment form view 2025-04-01 18:35:07 +02:00
Alexis de Lattre
a6f1d4a230 [IMP] stock_valuation_xlsx: move field in wizard 2025-02-26 12:12:17 +01:00
Akretion Bot
4abcac94d5 [BOT] add or update setup/_metapackage 2025-01-30 02:36:14 +00:00
Akretion Bot
30d16837ed [BOT] add pyproject.toml 2025-01-30 02:36:14 +00:00
Akretion Bot
9068bf1d97 [ADD] icon.png 2025-01-30 02:36:14 +00:00
Akretion Bot
d0f9ce3d62 [UPD] README.rst 2025-01-30 02:36:13 +00:00
Alexis de Lattre
b0961e4f8d [FIX] base_partner_ref: don't display [REF] when there is show_address in contex 2025-01-15 21:29:29 +01:00
Alexis de Lattre
ea4b698590 [IMP] base_usability: add siren/siret on display method for partners 2025-01-14 15:43:00 +01:00
Benoît Guillot
a0aec274a5 Merge pull request #229 from akretion/18.0-base_usability_akretion_Send-mail
[FIX] base_usability_akretion ir.mail_server send mail
2025-01-09 14:06:14 +01:00
David Beal
65458407b7 REMove developer_menu: see OCA/server-ux 2025-01-09 12:45:52 +01:00
Bonnerue
62ca33ed4b [FIX] base_usability_akretion ir.mail_server send mail 2025-01-09 12:02:40 +01:00
Alexis de Lattre
dbc2b3ddcc [MIG] pos-always_open_cashbox.diff to v18 2024-12-31 18:14:31 +01:00
Alexis de Lattre
8d5a23b478 [MIG] mrp_usability_akretion: migrate to v18 2024-12-31 11:28:06 +01:00
Alexis de Lattre
fae6bf361a [MIG] sale_stock_usability_akretion: migrate to 18 2024-12-31 11:01:01 +01:00
Alexis de Lattre
b51c1ff7d9 [MIG] sale_usability_akretion: migrate to v18 2024-12-31 10:38:09 +01:00
Alexis de Lattre
bdf4a527de [MIG] account_usability_akretion to v18
Move code from account_usability_akretion to base_usability_akretion
2024-12-31 01:02:50 +01:00
Alexis de Lattre
8e5d3b8a74 [MIG] purchase_stock_usability_akretion to v18
incoterm_id is a field of purchase module, not purchase_stock ; so move
the inherit of this field from purchase_stock_usability_akretion to
purchase_usability_akretion
2024-12-30 12:47:30 +01:00
Alexis de Lattre
b9d313fa8c [MIG] stock_usability_akretion to v18 2024-12-30 12:18:32 +01:00
Alexis de Lattre
37fb616524 [MIG] purchase_usability_akretion to v18 2024-12-30 00:06:13 +01:00
Alexis de Lattre
88f6521964 [MIG] pos_usability_akretion: migrate to v18 2024-12-29 00:41:22 +01:00
Alexis de Lattre
ab7ec7829d [MIG] product_usability_akretion to v18 2024-12-28 23:52:48 +01:00
Alexis de Lattre
f9f06d83e2 [MIG] base_usability_akretion, base_partner_ref, partner_tree_default_account, partner_tree_default_base, partner_tree_default_contacts to v18 2024-12-25 01:50:21 +01:00
Alexis de Lattre
47cf7389cc [FIX] pos_check_deposit: fix field visibility 2024-12-24 12:50:47 +01:00
Alexis de Lattre
29a2739c18 [MIG] pos_check_deposit to v18 2024-12-24 12:29:14 +01:00
Alexis de Lattre
13744fc404 Initialize v18 branch
Rename *_usability modules to *_usability_akretion
2024-12-24 10:11:21 +01:00
449 changed files with 2209 additions and 3969 deletions

View File

@@ -1 +1,2 @@
from . import models
from . import account_invoice
from . import account_invoice_report

View File

@@ -1,26 +1,24 @@
# Copyright 2015-2025 Akretion France (https://www.akretion.com)
# Copyright 2015-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).
{
'name': 'Account Invoice Margin',
'version': '16.0.1.0.0',
'version': '12.0.1.0.0',
'category': 'Invoicing Management',
'license': 'AGPL-3',
'summary': 'Copy standard price on invoice line and compute margins',
'description': """
This module copies the field *standard_price* of the product on the invoice line when the invoice line is created. The allows the computation of the margin of the invoice.
A new measure *Margin* is available in the Invoice Analysis.
This module has been written by Alexis de Lattre from Akretion
<alexis.delattre@akretion.com>.
""",
'author': 'Akretion',
'website': 'https://github.com/akretion/odoo-usability',
'website': 'http://www.akretion.com',
'depends': ['account'],
'data': [
'views/account_move.xml',
'account_invoice_view.xml',
],
'installable': True,
'installable': False,
}

View File

@@ -0,0 +1,152 @@
# Copyright 2015-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).
from odoo import api, fields, models
import odoo.addons.decimal_precision as dp
class AccountInvoiceLine(models.Model):
_inherit = 'account.invoice.line'
standard_price_company_currency = fields.Float(
string='Cost Price in Company Currency', readonly=True,
digits=dp.get_precision('Product Price'),
help="Cost price in company currency in the unit of measure "
"of the invoice line (which may be different from the unit "
"of measure of the product).")
standard_price_invoice_currency = fields.Float(
string='Cost Price in Invoice Currency', readonly=True,
compute='_compute_margin', store=True,
digits=dp.get_precision('Product Price'),
help="Cost price in invoice currency in the unit of measure "
"of the invoice line")
margin_invoice_currency = fields.Monetary(
string='Margin in Invoice Currency', readonly=True, store=True,
compute='_compute_margin', currency_field='currency_id')
margin_company_currency = fields.Monetary(
string='Margin in Company Currency', readonly=True, store=True,
compute='_compute_margin', currency_field='company_currency_id')
margin_rate = fields.Float(
string="Margin Rate", readonly=True, store=True,
compute='_compute_margin',
digits=(16, 2), help="Margin rate in percentage of the sale price")
@api.depends(
'standard_price_company_currency', 'invoice_id.currency_id',
'invoice_id.type', 'invoice_id.company_id',
'invoice_id.date_invoice', 'quantity', 'price_subtotal')
def _compute_margin(self):
for il in self:
standard_price_inv_cur = 0.0
margin_inv_cur = 0.0
margin_comp_cur = 0.0
margin_rate = 0.0
inv = il.invoice_id
if inv and inv.type in ('out_invoice', 'out_refund'):
# it works in _get_current_rate
# even if we set date = False in context
# standard_price_inv_cur is in the UoM of the invoice line
date = inv._get_currency_rate_date() or\
fields.Date.context_today(self)
company = inv.company_id
company_currency = company.currency_id
standard_price_inv_cur =\
company_currency._convert(
il.standard_price_company_currency,
inv.currency_id, company, date)
margin_inv_cur =\
il.price_subtotal - il.quantity * standard_price_inv_cur
margin_comp_cur = inv.currency_id._convert(
margin_inv_cur, company_currency, company, date)
if il.price_subtotal:
margin_rate = 100 * margin_inv_cur / il.price_subtotal
# for a refund, margin should be negative
# but margin rate should stay positive
if inv.type == 'out_refund':
margin_inv_cur *= -1
margin_comp_cur *= -1
il.standard_price_invoice_currency = standard_price_inv_cur
il.margin_invoice_currency = margin_inv_cur
il.margin_company_currency = margin_comp_cur
il.margin_rate = margin_rate
# We want to copy standard_price on invoice line for customer
# invoice/refunds. We can't do that via on_change of product_id,
# because it is not always played when invoice is created from code
# => we inherit write/create
# We write standard_price_company_currency even on supplier invoice/refunds
# because we don't have access to the 'type' of the invoice
@api.model
def create(self, vals):
if vals.get('product_id'):
pp = self.env['product.product'].browse(vals['product_id'])
std_price = pp.standard_price
inv_uom_id = vals.get('uom_id')
if inv_uom_id and inv_uom_id != pp.uom_id.id:
inv_uom = self.env['uom.uom'].browse(inv_uom_id)
std_price = pp.uom_id._compute_price(
std_price, inv_uom)
vals['standard_price_company_currency'] = std_price
return super(AccountInvoiceLine, self).create(vals)
def write(self, vals):
if not vals:
vals = {}
if 'product_id' in vals or 'uom_id' in vals:
for il in self:
if 'product_id' in vals:
if vals.get('product_id'):
pp = self.env['product.product'].browse(
vals['product_id'])
else:
pp = False
else:
pp = il.product_id or False
# uom_id is NOT a required field
if 'uom_id' in vals:
if vals.get('uom_id'):
inv_uom = self.env['uom.uom'].browse(
vals['uom_id'])
else:
inv_uom = False
else:
inv_uom = il.uom_id or False
std_price = 0.0
if pp:
std_price = pp.standard_price
if inv_uom and inv_uom != pp.uom_id:
std_price = pp.uom_id._compute_price(
std_price, inv_uom)
il.write({'standard_price_company_currency': std_price})
return super(AccountInvoiceLine, self).write(vals)
class AccountInvoice(models.Model):
_inherit = 'account.invoice'
margin_invoice_currency = fields.Monetary(
string='Margin in Invoice Currency',
compute='_compute_margin', store=True, readonly=True,
currency_field='currency_id')
margin_company_currency = fields.Monetary(
string='Margin in Company Currency',
compute='_compute_margin', store=True, readonly=True,
currency_field='company_currency_id')
@api.depends(
'type',
'invoice_line_ids.margin_invoice_currency',
'invoice_line_ids.margin_company_currency')
def _compute_margin(self):
res = self.env['account.invoice.line'].read_group(
[('invoice_id', 'in', self.ids)],
['invoice_id', 'margin_invoice_currency',
'margin_company_currency'],
['invoice_id'])
for re in res:
if re['invoice_id']:
inv = self.browse(re['invoice_id'][0])
if inv.type in ('out_invoice', 'out_refund'):
inv.margin_invoice_currency = re['margin_invoice_currency']
inv.margin_company_currency = re['margin_company_currency']

View File

@@ -0,0 +1,60 @@
# Copyright 2018-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).
from odoo import api, fields, models
class AccountInvoiceReport(models.Model):
_inherit = 'account.invoice.report'
margin = fields.Float(string='Margin', readonly=True)
# why digits=0 ??? Why is it like that in the native "account" module
user_currency_margin = fields.Float(
string="Margin", compute='_compute_user_currency_margin', digits=0)
_depends = {
'account.invoice': [
'account_id', 'amount_total_company_signed',
'commercial_partner_id', 'company_id',
'currency_id', 'date_due', 'date_invoice', 'fiscal_position_id',
'journal_id', 'number', 'partner_bank_id', 'partner_id',
'payment_term_id', 'residual', 'state', 'type', 'user_id',
],
'account.invoice.line': [
'account_id', 'invoice_id', 'price_subtotal', 'product_id',
'quantity', 'uom_id', 'account_analytic_id',
'margin_company_currency',
],
'product.product': ['product_tmpl_id'],
'product.template': ['categ_id'],
'uom.uom': ['category_id', 'factor', 'name', 'uom_type'],
'res.currency.rate': ['currency_id', 'name'],
'res.partner': ['country_id'],
}
@api.depends('currency_id', 'date', 'margin')
def _compute_user_currency_margin(self):
user_currency = self.env.user.company_id.currency_id
currency_rate = self.env['res.currency.rate'].search([
('rate', '=', 1),
'|',
('company_id', '=', self.env.user.company_id.id),
('company_id', '=', False)], limit=1)
base_currency = currency_rate.currency_id
for record in self:
date = record.date or fields.Date.today()
company = record.company_id
record.user_currency_margin = base_currency._convert(
record.margin, user_currency, company, date)
# TODO check for refunds
def _sub_select(self):
select_str = super(AccountInvoiceReport, self)._sub_select()
select_str += ", SUM(ail.margin_company_currency) AS margin"
return select_str
def _select(self):
select_str = super(AccountInvoiceReport, self)._select()
select_str += ", sub.margin AS margin"
return select_str

View File

@@ -0,0 +1,51 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
© 2015-2017 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_invoice_line_form" model="ir.ui.view">
<field name="name">margin.account.invoice.line.form</field>
<field name="model">account.invoice.line</field>
<field name="inherit_id" ref="account.view_invoice_line_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='analytic_tag_ids']/.." position="inside">
<field name="standard_price_company_currency"
string="Cost Price in Comp. Cur."
groups="base.group_no_one"/>
<field name="standard_price_invoice_currency"
string="Cost Price in Inv. Cur."
groups="base.group_no_one"/>
<field name="margin_invoice_currency"
string="Margin in Inv. Cur."
groups="base.group_no_one"/>
<field name="margin_company_currency"
string="Margin in Comp. Cur."
groups="base.group_no_one"/>
<label for="margin_rate" groups="base.group_no_one"/>
<div name="margin_rate" groups="base.group_no_one">
<field name="margin_rate" class="oe_inline"/> %
</div>
</xpath>
</field>
</record>
<record id="invoice_form" model="ir.ui.view">
<field name="name">margin.account.invoice.form</field>
<field name="model">account.invoice</field>
<field name="inherit_id" ref="account.invoice_form"/>
<field name="arch" type="xml">
<field name="move_id" position="after">
<field name="margin_invoice_currency"
string="Margin in Inv. Cur." groups="base.group_no_one"/>
<field name="margin_company_currency"
string="Margin in Comp. Cur." groups="base.group_no_one"/>
</field>
</field>
</record>
</odoo>

View File

@@ -1,98 +0,0 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * account_invoice_margin
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-01-16 16:24+0000\n"
"PO-Revision-Date: 2025-01-16 16:24+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: account_invoice_margin
#: model:ir.model,name:account_invoice_margin.model_account_invoice_report
msgid "Invoices Statistics"
msgstr "Statistiques des factures"
#. module: account_invoice_margin
#: model:ir.model,name:account_invoice_margin.model_account_move
msgid "Journal Entry"
msgstr "Pièce comptable"
#. module: account_invoice_margin
#: model:ir.model,name:account_invoice_margin.model_account_move_line
msgid "Journal Item"
msgstr "Écriture comptable"
#. module: account_invoice_margin
#: model:ir.model.fields,field_description:account_invoice_margin.field_account_invoice_report__margin
#: model_terms:ir.ui.view,arch_db:account_invoice_margin.view_invoice_tree
#: model_terms:ir.ui.view,arch_db:account_invoice_margin.view_move_form
msgid "Margin"
msgstr "Marge"
#. module: account_invoice_margin
#: model_terms:ir.ui.view,arch_db:account_invoice_margin.view_move_form
msgid "Margin %"
msgstr "Marge %"
#. module: account_invoice_margin
#: model:ir.model.fields,field_description:account_invoice_margin.field_account_move_line__margin_rate
msgid "Margin Rate"
msgstr "Taux de marge"
#. module: account_invoice_margin
#: model:ir.model.fields,field_description:account_invoice_margin.field_account_bank_statement_line__margin_company_currency
#: model:ir.model.fields,field_description:account_invoice_margin.field_account_move__margin_company_currency
#: model:ir.model.fields,field_description:account_invoice_margin.field_account_move_line__margin_company_currency
#: model:ir.model.fields,field_description:account_invoice_margin.field_account_payment__margin_company_currency
msgid "Margin in Company Currency"
msgstr "Marge dans la devise de la société"
#. module: account_invoice_margin
#: model:ir.model.fields,field_description:account_invoice_margin.field_account_bank_statement_line__margin_invoice_currency
#: model:ir.model.fields,field_description:account_invoice_margin.field_account_move__margin_invoice_currency
#: model:ir.model.fields,field_description:account_invoice_margin.field_account_move_line__margin_invoice_currency
#: model:ir.model.fields,field_description:account_invoice_margin.field_account_payment__margin_invoice_currency
msgid "Margin in Invoice Currency"
msgstr "Marge dans la devise de la facture"
#. module: account_invoice_margin
#: model:ir.model.fields,help:account_invoice_margin.field_account_move_line__margin_rate
msgid "Margin rate in percentage of the sale price"
msgstr "Taux de marge en pourcentage du prix de vente"
#. module: account_invoice_margin
#: model:ir.model.fields,field_description:account_invoice_margin.field_account_move_line__standard_price_company_currency
msgid "Unit Cost in Company Currency"
msgstr "Coût unitaire dans la devise de la société"
#. module: account_invoice_margin
#: model:ir.model.fields,field_description:account_invoice_margin.field_account_move_line__standard_price_invoice_currency
msgid "Unit Cost in Invoice Currency"
msgstr "Coût unitaire dans la devise de la facture"
#. module: account_invoice_margin
#: model:ir.model.fields,help:account_invoice_margin.field_account_move_line__standard_price_company_currency
msgid ""
"Unit Cost in company currency in the unit of measure of the invoice line "
"(which may be different from the unit of measure of the product)."
msgstr ""
"Coût unitaire dans la devise de la société dans l'unité de mesure de la "
"ligne de facture (qui peut être différente de l'unité de mesure du produit)."
#. module: account_invoice_margin
#: model:ir.model.fields,help:account_invoice_margin.field_account_move_line__standard_price_invoice_currency
msgid ""
"Unit Cost in invoice currency in the unit of measure of the invoice line "
"(which may be different from the unit of measure of the product)."
msgstr ""
"Coût unitaire dans la devise de la facture dans l'unité de mesure "
"de la ligne de la facture (qui peut être différente de l'unité de mesure du produit)."

View File

@@ -1,2 +0,0 @@
from . import account_move
from . import account_invoice_report

View File

@@ -1,17 +0,0 @@
# Copyright 2018-2025 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 api, fields, models
class AccountInvoiceReport(models.Model):
_inherit = 'account.invoice.report'
margin = fields.Float(string='Margin', readonly=True)
@api.model
def _select(self):
select_str = super()._select()
select_str += ", line.margin_company_currency * currency_table.rate AS margin"
return select_str

View File

@@ -1,109 +0,0 @@
# Copyright 2015-2025 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 api, fields, models
class AccountMoveLine(models.Model):
_inherit = 'account.move.line'
standard_price_company_currency = fields.Float(
compute='_compute_margin', store=True, digits='Product Price',
string='Unit Cost in Company Currency',
help="Unit Cost in company currency in the unit of measure "
"of the invoice line (which may be different from the unit "
"of measure of the product).")
standard_price_invoice_currency = fields.Float(
compute='_compute_margin', store=True, digits='Product Price',
string='Unit Cost in Invoice Currency',
help="Unit Cost in invoice currency in the unit of measure "
"of the invoice line (which may be different from the unit "
"of measure of the product).")
margin_invoice_currency = fields.Monetary(
compute='_compute_margin', store=True,
string='Margin in Invoice Currency', currency_field='currency_id')
margin_company_currency = fields.Monetary(
compute='_compute_margin', store=True,
string='Margin in Company Currency',
currency_field='company_currency_id')
margin_rate = fields.Float(
string="Margin Rate", readonly=True, store=True,
compute='_compute_margin',
digits=(16, 2), help="Margin rate in percentage of the sale price")
@api.depends(
'product_id', 'product_uom_id', 'display_type', 'quantity', 'price_subtotal',
'move_id.currency_id', 'move_id.move_type', 'move_id.company_id', 'move_id.date')
def _compute_margin(self):
for ml in self:
standard_price_comp_cur = 0.0
standard_price_inv_cur = 0.0
margin_inv_cur = 0.0
margin_comp_cur = 0.0
margin_rate = 0.0
if (
ml.display_type == 'product' and
ml.product_id and
ml.move_type in ('out_invoice', 'out_refund')):
move = ml.move_id
date = move.date
company = move.company_id
company_currency = company.currency_id
move_currency = move.currency_id
standard_price_comp_cur = ml.product_id.with_company(company.id).standard_price
if ml.product_uom_id and ml.product_uom_id != ml.product_id.uom_id:
standard_price_comp_cur = ml.product_id.uom_id._compute_price(
standard_price_comp_cur, ml.product_uom_id)
standard_price_inv_cur = company_currency._convert(
standard_price_comp_cur, move_currency, company, date)
margin_inv_cur =\
ml.price_subtotal - (ml.quantity * standard_price_inv_cur)
margin_comp_cur = move_currency._convert(
margin_inv_cur, company_currency, company, date)
if ml.price_subtotal:
margin_rate = 100 * margin_inv_cur / ml.price_subtotal
# for a refund, margin should be negative
# but margin rate should stay positive
if ml.move_type == 'out_refund':
margin_inv_cur *= -1
margin_comp_cur *= -1
ml.standard_price_company_currency = standard_price_comp_cur
ml.standard_price_invoice_currency = standard_price_inv_cur
ml.margin_invoice_currency = margin_inv_cur
ml.margin_company_currency = margin_comp_cur
ml.margin_rate = margin_rate
class AccountMove(models.Model):
_inherit = 'account.move'
margin_invoice_currency = fields.Monetary(
string='Margin in Invoice Currency',
compute='_compute_margin', store=True,
currency_field='currency_id')
margin_company_currency = fields.Monetary(
string='Margin in Company Currency',
compute='_compute_margin', store=True,
currency_field='company_currency_id')
@api.depends(
'move_type',
'invoice_line_ids.margin_invoice_currency',
'invoice_line_ids.margin_company_currency')
def _compute_margin(self):
rg_res = self.env['account.move.line'].read_group(
[
('move_id', 'in', self.ids),
('display_type', '=', 'product'),
('move_id.move_type', 'in', ('out_invoice', 'out_refund')),
],
['move_id', 'margin_invoice_currency:sum', 'margin_company_currency:sum'],
['move_id'])
mapped_data = dict([(x['move_id'][0], {
'margin_invoice_currency': x['margin_invoice_currency'],
'margin_company_currency': x['margin_company_currency'],
}) for x in rg_res])
for move in self:
move.margin_invoice_currency = mapped_data.get(move.id, {}).get('margin_invoice_currency')
move.margin_company_currency = mapped_data.get(move.id, {}).get('margin_company_currency')

View File

@@ -1,55 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2015-2025 Akretion (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_move_form" model="ir.ui.view">
<field name="name">margin.account.move.form</field>
<field name="model">account.move</field>
<field name="inherit_id" ref="account.view_move_form"/>
<field name="arch" type="xml">
<group name="sale_info_group" position="inside">
<field name="margin_invoice_currency"
groups="base.group_no_one"
attrs="{'invisible': [('move_type', 'not in', ('out_invoice', 'out_refund'))]}"/>
<field name="margin_company_currency"
groups="base.group_no_one"
attrs="{'invisible': [('move_type', 'not in', ('out_invoice', 'out_refund'))]}"/>
</group>
<xpath expr="//field[@name='invoice_line_ids']/tree/field[@name='price_total']" position="after">
<field name="standard_price_invoice_currency" optional="hide" attrs="{'column_invisible': [('parent.move_type', 'not in', ('out_invoice', 'out_refund'))]}"/>
<field name="margin_invoice_currency" optional="hide" attrs="{'column_invisible': [('parent.move_type', 'not in', ('out_invoice', 'out_refund'))]}" string="Margin"/>
<field name="margin_rate" optional="hide" string="Margin %" attrs="{'column_invisible': [('parent.move_type', 'not in', ('out_invoice', 'out_refund'))]}"/>
</xpath>
<xpath expr="//field[@name='invoice_line_ids']/form//field[@name='price_total']/.." position="inside">
<field name="standard_price_company_currency"
groups="base.group_no_one" attrs="{'invisible': [('parent.move_type', 'not in', ('out_invoice', 'out_refund'))]}"/>
<field name="standard_price_invoice_currency"
groups="base.group_no_one" attrs="{'invisible': [('parent.move_type', 'not in', ('out_invoice', 'out_refund'))]}"/>
<field name="margin_invoice_currency"
groups="base.group_no_one" attrs="{'invisible': [('parent.move_type', 'not in', ('out_invoice', 'out_refund'))]}"/>
<field name="margin_company_currency"
groups="base.group_no_one" attrs="{'invisible': [('parent.move_type', 'not in', ('out_invoice', 'out_refund'))]}"/>
<label for="margin_rate" groups="base.group_no_one" attrs="{'invisible': [('parent.move_type', 'not in', ('out_invoice', 'out_refund'))]}"/>
<div name="margin_rate" groups="base.group_no_one" attrs="{'invisible': [('parent.move_type', 'not in', ('out_invoice', 'out_refund'))]}">
<field name="margin_rate" class="oe_inline"/> %
</div>
</xpath>
</field>
</record>
<record id="view_invoice_tree" model="ir.ui.view">
<field name="model">account.move</field>
<field name="inherit_id" ref="account.view_invoice_tree"/>
<field name="arch" type="xml">
<field name="amount_residual_signed" position="after">
<field name="margin_company_currency" optional="hide" sum="1" invisible="context.get('default_move_type') not in ('out_invoice', 'out_refund')" string="Margin"/>
</field>
</field>
</record>
</odoo>

View File

@@ -1,18 +0,0 @@
# Copyright 2022 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': 'Account Menu Usability',
'version': '14.0.1.0.0',
'category': 'Accounting & Finance',
'license': 'AGPL-3',
'summary': 'Small usability enhancements in account_menu module',
'author': 'Akretion',
'website': 'https://github.com/akretion/odoo-usability',
'depends': ['account_menu'],
'data': [
'views/account_menu.xml',
],
'installable': False,
}

View File

@@ -1,20 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2022 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>
<!-- Accounting Templates are useful only when creating a new company/loading
a chart of accounts, so we put it under 'Settings > Technical' and not
under 'Invoicing > Configuration' which already has a lot of menu entries -->
<record id="account_menu.menu_account_coa_settings" model="ir.ui.menu">
<field name="name">Accounting Templates</field>
<field name="parent_id" ref="base.menu_custom"/>
</record>
</odoo>

View File

@@ -29,4 +29,5 @@ This module has been written by Alexis de Lattre from Akretion
'depends': ['pos_sale', 'account_product_fiscal_classification'],
"data": ['report/sale_report_view.xml'],
'auto_install': True,
'installable': False,
}

View File

@@ -2,10 +2,13 @@
Account Usability
=================
.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:dbf367e7cf8330c803622d0c171cd10e128344d318466d6e37ad7b0fc812e152
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
:target: https://odoo-community.org/page/development-status
@@ -14,23 +17,23 @@ Account Usability
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-akretion%2Fodoo--usability-lightgray.png?logo=github
:target: https://github.com/akretion/odoo-usability/tree/12.0/account_usability
:target: https://github.com/akretion/odoo-usability/tree/18.0/account_usability_akretion
:alt: akretion/odoo-usability
|badge1| |badge2| |badge3|
|badge1| |badge2| |badge3|
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 journal entries and journal items views.
* Increase the default limit of 80 lines in account move and account move line view.
* disable reconciliation "guessing"
* fast search on *Reconcile Ref* for journal items.
* fast search on *Reconcile Ref* for account move line.
* 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 reversal journal entry is now D+1 instead of today
* Default date for Account Move Reversal 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 +44,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 journal entry
* Add link from journal items to to invoice
* Better default values on account move
* Add link from account move line to invoice
* Add start_date and end_date on bank statements
* Add transfer_account_id to invoicing config page
* Improve domain reconciliation widget
@@ -52,7 +55,6 @@ This modules adds the following functions:
* don't attach PDF upon invoice report generation on supplier invoices/refunds
* Add filter on debit and credit amount for Move Lines
* Add supplier invoice number in invoice tree view
* Add date in outstanding payment widget on invoice form view (requires `odoo PR 84180 <https://github.com/odoo/odoo/pull/84180>`_)
Together with this module, I recommend the use of the following modules:
@@ -70,8 +72,8 @@ Bug Tracker
Bugs are tracked on `GitHub Issues <https://github.com/akretion/odoo-usability/issues>`_.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us smashing it by providing a detailed and welcomed
`feedback <https://github.com/akretion/odoo-usability/issues/new?body=module:%20account_usability%0Aversion:%2012.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
If you spotted it first, help us to smash it by providing a detailed and welcomed
`feedback <https://github.com/akretion/odoo-usability/issues/new?body=module:%20account_usability_akretion%0Aversion:%2018.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
Do not contact contributors directly about support or help with technical issues.
@@ -92,6 +94,6 @@ Contributors
Maintainers
~~~~~~~~~~~
This module is part of the `akretion/odoo-usability <https://github.com/akretion/odoo-usability/tree/12.0/account_usability>`_ project on GitHub.
This module is part of the `akretion/odoo-usability <https://github.com/akretion/odoo-usability/tree/18.0/account_usability_akretion>`_ project on GitHub.
You are welcome to contribute.

View File

@@ -1,3 +1,3 @@
from . import models
from . import wizard
from .hooks import post_init_hook
from . import wizards
# from .hooks import post_init_hook

View File

@@ -1,10 +1,10 @@
# Copyright 2015-2022 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).
{
'name': 'Account Usability',
'version': '16.0.1.0.0',
'version': '18.0.1.0.0',
'category': 'Accounting & Finance',
'license': 'AGPL-3',
'summary': 'Small usability enhancements in account module',
@@ -12,7 +12,7 @@
'website': 'https://github.com/akretion/odoo-usability',
'depends': [
'account',
'base_usability', # needed only to access base_usability.group_nobody
'base_usability_akretion', # needed only to access base_usability.group_nobody
],
'data': [
'views/account_account.xml',
@@ -21,16 +21,17 @@
'views/account_invoice_report.xml',
'views/account_journal.xml',
'views/account_move.xml',
'views/account_move_line.xml',
'views/account_payment.xml',
'views/account_analytic_line.xml',
'views/account_menu.xml',
'views/account_tax.xml',
# 'views/product.xml', # TODO
'views/res_company.xml',
'views/account_report.xml',
'wizard/account_invoice_mark_sent_view.xml',
'wizard/account_group_generate_view.xml',
'wizard/account_payment_register_views.xml',
'wizard/account_move_reversal.xml',
# 'views/account_report.xml',
'wizards/account_invoice_mark_sent_view.xml',
# 'wizards/account_group_generate_view.xml',
'wizards/account_move_reversal.xml',
'security/ir.model.access.csv',
# 'report/invoice_report.xml', # TODO
"views/res_partner.xml",

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

@@ -2,8 +2,8 @@
# @author Sébastien BEAU <sebastien.beau@akretion.com>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import SUPERUSER_ID, api
# from odoo import SUPERUSER_ID, api
def post_init_hook(cr, registry):
env = api.Environment(cr, SUPERUSER_ID, {})
env["account.move.line"].update_matching_number()
# def post_init_hook(cr, registry):
# env = api.Environment(cr, SUPERUSER_ID, {})
# env["account.move.line"].update_matching_number()

View File

@@ -0,0 +1,55 @@
diff --git a/addons/account/models/account_payment.py b/addons/account/models/account_payment.py
index 2dd1f9cef83..62275fca65e 100644
--- a/addons/account/models/account_payment.py
+++ b/addons/account/models/account_payment.py
@@ -262,6 +262,7 @@ class AccountPayment(models.Model):
'credit': write_off_balance > 0.0 and write_off_balance or 0.0,
'partner_id': self.partner_id.id,
'account_id': write_off_line_vals.get('account_id'),
+ 'analytic_account_id': write_off_line_vals.get('analytic_account_id'),
})
return line_vals_list
@@ -699,6 +700,7 @@ class AccountPayment(models.Model):
'name': writeoff_lines[0].name,
'amount': writeoff_amount * sign,
'account_id': writeoff_lines[0].account_id.id,
+ 'analytic_account_id': writeoff_lines[0].analytic_account_id.id,
}
else:
write_off_line_vals = {}
diff --git a/addons/account/wizard/account_payment_register.py b/addons/account/wizard/account_payment_register.py
index 3fc91f716ad..35636774c7e 100644
--- a/addons/account/wizard/account_payment_register.py
+++ b/addons/account/wizard/account_payment_register.py
@@ -93,6 +93,7 @@ class AccountPaymentRegister(models.TransientModel):
], default='open', string="Payment Difference Handling")
writeoff_account_id = fields.Many2one('account.account', string="Difference Account", copy=False,
domain="[('deprecated', '=', False), ('company_id', '=', company_id)]")
+ writeoff_analytic_account_id = fields.Many2one('account.analytic.account', string="Difference Analytic Account", copy=False, domain="[('company_id', '=', company_id)]")
writeoff_label = fields.Char(string='Journal Item Label', default='Write-Off',
help='Change label of the counterpart that will hold the payment difference')
@@ -422,6 +423,7 @@ class AccountPaymentRegister(models.TransientModel):
'name': self.writeoff_label,
'amount': self.payment_difference,
'account_id': self.writeoff_account_id.id,
+ 'analytic_account_id': self.writeoff_analytic_account_id.id or False,
}
return payment_vals
diff --git a/addons/account/wizard/account_payment_register_views.xml b/addons/account/wizard/account_payment_register_views.xml
index 16eec30e265..b9386567baa 100644
--- a/addons/account/wizard/account_payment_register_views.xml
+++ b/addons/account/wizard/account_payment_register_views.xml
@@ -65,6 +65,10 @@
string="Post Difference In"
options="{'no_create': True}"
attrs="{'required': [('payment_difference_handling', '=', 'reconcile')]}"/>
+ <label for="writeoff_analytic_account_id" class="oe_edit_only" string="Analytic Account" groups="analytic.group_analytic_accounting"/>
+ <field name="writeoff_analytic_account_id"
+ groups="analytic.group_analytic_accounting"
+ options="{'no_create': True}" />
<label for="writeoff_label" class="oe_edit_only" string="Label"/>
<field name="writeoff_label" attrs="{'required': [('payment_difference_handling', '=', 'reconcile')]}"/>
</div>

View File

@@ -1,9 +0,0 @@
# Copyright 2020 ACSONE SA/NV
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import SUPERUSER_ID, api
def migrate(cr, version):
env = api.Environment(cr, SUPERUSER_ID, {})
env["account.move.line"].update_matching_number()

View File

@@ -1,12 +1,10 @@
from . import account_account
from . import account_analytic_account
#from . import account_bank_statement
from . import account_incoterms
from . import account_journal
from . import account_move
from . import account_move_line
from . import account_partial_reconcile
from . import res_partner
from . import res_company
#from . import product
from . import account_invoice_report
from . import res_partner_bank

View File

@@ -1,19 +0,0 @@
# Copyright 2015-2022 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 api, models
class AccountAccount(models.Model):
_inherit = 'account.account'
@api.depends('name', 'code')
def name_get(self):
if self._context.get('account_account_show_code_only'):
res = []
for record in self:
res.append((record.id, record.code))
return res
else:
return super().name_get()

View File

@@ -1,23 +1,20 @@
# Copyright 2015-2022 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).
from odoo import models
from odoo import api, models
class AccountAnalyticAccount(models.Model):
_inherit = 'account.analytic.account'
# native: _order = 'plan_id, name asc'
_order = 'plan_id, code, name'
def name_get(self):
@api.depends_context('analytic_account_show_code_only')
def _compute_display_name(self):
if self._context.get('analytic_account_show_code_only'):
res = []
for record in self:
res.append((record.id, record.code or record.name))
return res
for rec in self:
rec.display_name = rec.code or rec.name
else:
return super().name_get()
return super()._compute_display_name()
_sql_constraints = [(
'code_company_unique',

View File

@@ -1,104 +0,0 @@
# Copyright 2015-2020 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 api, fields, models
from odoo.tools.misc import format_date
class AccountBankStatement(models.Model):
_inherit = 'account.bank.statement'
start_date = fields.Date(
compute='_compute_dates', string='Start Date', store=True)
end_date = fields.Date(
compute='_compute_dates', string='End Date', store=True)
line_count = fields.Integer(
compute='_compute_dates', string='# of Lines', store=True)
hide_bank_statement_balance = fields.Boolean(
related='journal_id.hide_bank_statement_balance', readonly=True)
@api.depends('line_ids.date')
def _compute_dates(self):
for st in self:
dates = [line.date for line in st.line_ids]
st.start_date = dates and min(dates) or False
st.end_date = dates and max(dates) or False
st.line_count = len(dates)
def _check_balance_end_real_same_as_computed(self):
for stmt in self:
if not stmt.hide_bank_statement_balance:
super(AccountBankStatement, stmt)._check_balance_end_real_same_as_computed()
return True
@api.depends('name', 'start_date', 'end_date')
def name_get(self):
res = []
for statement in self:
name = "%s (%s => %s)" % (
statement.name,
statement.start_date and format_date(self.env, statement.start_date) or '',
statement.end_date and format_date(self.env, statement.end_date) or '')
res.append((statement.id, name))
return res
def button_reopen(self):
self = self.with_context(skip_undo_reconciliation=True)
return super().button_reopen()
def button_undo_reconciliation(self):
self.line_ids.button_undo_reconciliation()
class AccountBankStatementLine(models.Model):
_inherit = 'account.bank.statement.line'
# Native order is:
# _order = 'statement_id desc, sequence, id desc'
_order = 'statement_id desc, date desc, sequence, id desc'
# Disable guessing for reconciliation
# because my experience with several customers shows that it is a problem
# in the following scenario : move line 'x' has been "guessed" by OpenERP
# to be reconciled with a statement line 'Y' at the end of the bank
# statement, but it is a mistake because it should be reconciled with
# statement line 'B' at the beginning of the bank statement
# When the user is on statement line 'B', he tries to select
# move line 'x', but it can't find it... because it is already "reserved"
# by the guess of OpenERP for statement line 'Y' ! To solve this problem,
# the user must go to statement line 'Y' and unselect move line 'x'
# and then come back on statement line 'B' and select move line 'A'...
# but non super-expert users can't do that because it is impossible to
# figure out that the fact that the user can't find move line 'x'
# is caused by this.
# Set search_reconciliation_proposition to False by default
# TODO: re-write in v10
# def get_data_for_reconciliations(
# self, cr, uid, ids, excluded_ids=None,
# search_reconciliation_proposition=False, context=None):
# # Make variable name shorted for PEP8 !
# search_rec_prop = search_reconciliation_proposition
# return super().\
# get_data_for_reconciliations(
# cr, uid, ids, excluded_ids=excluded_ids,
# search_reconciliation_proposition=search_rec_prop,
# context=context)
def show_account_move(self):
self.ensure_one()
action = self.env["ir.actions.actions"]._for_xml_id(
'account.action_move_line_form')
# Note: this action is on account.move, not account.move.line !
action.update({
'views': False,
'view_id': False,
'view_mode': 'form,tree',
'res_id': self.move_id.id,
})
return action
def button_undo_reconciliation(self):
if self._context.get("skip_undo_reconciliation"):
return
else:
return super().button_undo_reconciliation()

View File

@@ -1,31 +1,15 @@
# Copyright 2015-2022 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).
from odoo import api, models
from odoo import models
class AccountIncoterms(models.Model):
_inherit = 'account.incoterms'
_rec_names_search = ["name", "code"]
_sql_constraints = [(
'code_unique',
'unique(code)',
'This incoterm code already exists.')]
@api.depends('code', 'name')
def name_get(self):
res = []
for rec in self:
res.append((rec.id, '[%s] %s' % (rec.code, rec.name)))
return res
@api.model
def name_search(self, name='', args=None, operator='ilike', limit=100):
if args is None:
args = []
if name and operator == 'ilike':
recs = self.search([('code', '=ilike', name + '%')] + args, limit=limit)
if recs:
return recs.name_get()
return super().name_search(name=name, args=args, operator=operator, limit=limit)

View File

@@ -1,8 +1,9 @@
# Copyright 2022 Akretion (http://www.akretion.com)
# Copyright 2022-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 api, fields, models
from odoo.tools import SQL
class AccountInvoiceReport(models.Model):
@@ -12,6 +13,6 @@ class AccountInvoiceReport(models.Model):
@api.model
def _select(self):
res = super()._select()
res += ", COALESCE(partner.industry_id, commercial_partner.industry_id) AS industry_id"
return res
return SQL(
"%s, COALESCE(partner.industry_id, commercial_partner.industry_id) AS industry_id",
super()._select())

View File

@@ -1,4 +1,4 @@
# Copyright 2015-2022 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).
@@ -9,7 +9,7 @@ class AccountJournal(models.Model):
_inherit = 'account.journal'
hide_bank_statement_balance = fields.Boolean(
string='Hide and Disable Bank Statement Balance', default=True,
string='Hide and Disable Bank Statement Balance',
help="When this option is enabled, the start and end balance is "
"not displayed on the bank statement form view, and the check of "
"the end balance vs the real end balance is disabled. When you enable "
@@ -17,50 +17,34 @@ class AccountJournal(models.Model):
"the start/end balance and you regularly check the accounting balance "
"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(
# 'account.account.type',
# default=lambda self: self.env.ref('account.data_account_type_current_assets').id)
@api.depends(
'name', 'currency_id', 'company_id', 'company_id.currency_id', 'code')
def name_get(self):
res = []
@api.depends('name', 'currency_id', 'company_id', 'code')
@api.depends_context('journal_show_code_only')
def _compute_display_name(self):
if self._context.get('journal_show_code_only'):
for journal in self:
res.append((journal.id, journal.code))
return res
journal.display_name = journal.code
else:
for journal in self:
name = "[%s] %s" % (journal.code, journal.name)
name = f"[{journal.code}] {journal.name}"
if (
journal.currency_id and
journal.currency_id != journal.company_id.currency_id):
name = "%s (%s)" % (name, journal.currency_id.name)
res.append((journal.id, name))
return res
name = f"{name} ({journal.currency_id.name})"
journal.display_name = name
def open_outstanding_payments(self):
self.ensure_one()
action = self.env["ir.actions.actions"]._for_xml_id(
"account.action_account_moves_all")
action['domain'] = [
('account_id', 'in', (self.payment_debit_account_id.id, self.payment_credit_account_id.id)),
('journal_id', '=', self.id),
('display_type', 'not in', ('line_section', 'line_note')),
('parent_state', '!=', 'cancel'),
]
action['context'] = {
'search_default_unreconciled': True,
'search_default_posted': True,
}
return action
# field used in journal dashboard for bank journals
# compute account_balance like in v14, using accounting and
# NOT bank statement balance_start/balance_end
def _compute_current_statement_balance(self):
query_result = self._get_journal_dashboard_bank_running_balance()
for journal in self:
journal.has_statement_lines = query_result.get(journal.id)[0]
journal.current_statement_balance = journal._get_journal_bank_account_balance()[0]
# def open_outstanding_payments(self):
# self.ensure_one()
# action = self.env["ir.actions.actions"]._for_xml_id(
# "account.action_account_moves_all")
# action['domain'] = [
# ('account_id', 'in', (self.payment_debit_account_id.id, self.payment_credit_account_id.id)),
# ('journal_id', '=', self.id),
# ('display_type', 'not in', ('line_section', 'line_note')),
# ('parent_state', '!=', 'cancel'),
# ]
# action['context'] = {
# 'search_default_unreconciled': True,
# 'search_default_posted': True,
# }
# return action

View File

@@ -1,17 +1,14 @@
# Copyright 2015-2022 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).
from datetime import timedelta
from collections import defaultdict
import logging
from odoo import api, fields, models, _
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__)
@@ -19,9 +16,6 @@ _logger = logging.getLogger(__name__)
class AccountMove(models.Model):
_inherit = 'account.move'
# By default, we can still modify "ref" when account move is posted
# which seems a bit lazy for me...
ref = fields.Char(states={'posted': [('readonly', True)]})
invoice_date_due = fields.Date(tracking=True)
invoice_payment_term_id = fields.Many2one(tracking=True)
journal_id = fields.Many2one(tracking=True)
@@ -38,36 +32,34 @@ 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
# We want to have that field on invoices to improve usability
# while keeping compatibility with the standard Odoo datamodel
blocked = fields.Boolean(
compute="_compute_blocked",
inverse="_inverse_blocked",
store=True,
string="Dispute",
tracking=True,
)
# The native "blocked" field (bool) on account.move.line has been removed in v18
# blocked = fields.Boolean(
# compute="_compute_blocked",
# inverse="_inverse_blocked",
# store=True,
# 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):
for move in self:
move.blocked = any(
[
l.blocked
for l in move.line_ids
if l.account_id.account_type in ("liability_payable", "asset_receivable")
]
)
# @api.depends("line_ids", "line_ids.blocked")
# def _compute_blocked(self):
# for move in self:
# move.blocked = any(
# [
# l.blocked
# for l in move.line_ids
# if l.account_id.account_type in ("liability_payable", "asset_receivable")
# ]
# )
def _inverse_blocked(self):
for move in self:
for line in move.line_ids.filtered(
lambda l: l.account_id.account_type in ("liability_payable", "asset_receivable")
):
line.blocked = move.blocked
# def _inverse_blocked(self):
# for move in self:
# for line in move.line_ids.filtered(
# lambda l: l.account_id.account_type in ("liability_payable", "asset_receivable")
# ):
# line.blocked = move.blocked
def _compute_has_discount(self):
prec = self.env['decimal.precision'].precision_get('Discount')
@@ -103,35 +95,6 @@ class AccountMove(models.Model):
res = [('id', value and 'in' or 'not in', list(att_inv_ids))]
return res
# when you have an invoice created from a lot of sale orders, the 'name'
# field is very large, which makes the name_get() of that invoice very big
# which screws-up the form view of that invoice because of the link at the
# top of the screen
# That's why we have to cut the name_get() when it's too long
def name_get(self):
old_res = super().name_get()
res = []
for old_re in old_res:
name = old_re[1]
if name and len(name) > 100:
# nice cut
name = '%s ...' % ', '.join(name.split(', ')[:3])
# if not enough, hard cut
if len(name) > 120:
name = '%s ...' % old_re[1][:120]
res.append((old_re[0], name))
return res
def _reverse_moves(self, default_values_list=None, cancel=False):
reverse_moves = super()._reverse_moves(
default_values_list=default_values_list, cancel=cancel)
# In the simple scenario 1 invoice -> 1 refund, we add a message in the chatter
# of the invoice and in the chatter of the refund
if len(self) == 1 and len(reverse_moves) == 1:
self.message_post(body=_("A reverse journal entry <a href=# data-oe-model=account.move data-oe-id=%d>%s</a> has been generated.") % (reverse_moves.id, reverse_moves.display_name))
reverse_moves.message_post(body=_("This journal entry has been generated as the reverse of <a href=# data-oe-model=account.move data-oe-id=%d>%s</a>.") % (self.id, self.display_name))
return reverse_moves
def delete_lines_qty_zero(self):
lines = self.env['account.move.line'].search([
('display_type', '=', 'product'),
@@ -204,94 +167,27 @@ class AccountMove(models.Model):
])
move.suitable_journal_ids = self.env['account.journal'].search(domain)
def button_draft(self):
# There is no more attachment by default on invoice reports...
# TODO check what's the editor strategy on this
# def button_draft(self):
# Delete attached pdf invoice
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()
# 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):
def _get_accounting_date(self, invoice_date, has_tax, lock_dates=None):
# On vendor bills/refunds, we want date = invoice_date unless
# we have a company tax_lock_date and the invoice has taxes
# and invoice_date <= tax_lock_date
date = super()._get_accounting_date(invoice_date, has_tax)
if self.is_purchase_document(include_receipts=True):
tax_lock_date = self.company_id.tax_lock_date
if invoice_date and tax_lock_date and has_tax and invoice_date <= tax_lock_date:
invoice_date = tax_lock_date + timedelta(days=1)
date = invoice_date
date = super()._get_accounting_date(invoice_date, has_tax, lock_dates=lock_dates)
lock_dates = lock_dates or self._get_violated_lock_dates(invoice_date, has_tax)
if self.is_purchase_document(include_receipts=True) and invoice_date:
if lock_dates:
date = max([entry[0] for entry in lock_dates]) + timedelta(1)
else:
date = invoice_date
return date
class AccountMoveLine(models.Model):
_inherit = 'account.move.line'
# Native order:
# _order = "date desc, move_name desc, id"
# Problem: when you manually create a journal entry, the
# order of the lines is inverted when you save ! It is quite annoying for
# the user...
_order = "date desc, id asc"
# In the 'account' module, we have related stored field for:
# name (move_name), date, ref, state (parent_state),
# journal_id, company_id, payment_id, statement_line_id,
account_reconcile = fields.Boolean(related='account_id.reconcile')
full_reconcile_id = fields.Many2one(string='Full Reconcile')
matched_debit_ids = fields.One2many(string='Partial Reconcile Debit')
matched_credit_ids = fields.One2many(string='Partial Reconcile Credit')
# for optional display in tree view
product_barcode = fields.Char(related='product_id.barcode', string="Product Barcode")
def show_account_move_form(self):
self.ensure_one()
action = self.env["ir.actions.actions"]._for_xml_id(
'account.action_move_line_form')
action.update({
'res_id': self.move_id.id,
'view_id': False,
'views': False,
'view_mode': 'form,tree',
})
return action
def update_matching_number(self):
records = self.search([("matching_number", "=", "P")])
_logger.info(f"Update partial reconcile number for {len(records)} lines")
records._compute_matching_number()
# def _compute_matching_number(self):
# TODO maybe it will be better to have the same maching_number for
# all partial so it will be easier to group by
# super()._compute_matching_number()
# for record in self:
# if record.matching_number == "P":
# record.matching_number = ", ".join([
# "a%d" % pr.id
# for pr in record.matched_debit_ids + record.matched_credit_ids
# ])
def _compute_name(self):
# This is useful when you want to have the product code in a dedicated
# column in your customer invoice report
# The same ir.config_parameter is used in sale_usability,
# purchase_usability and account_usability
no_product_code_param = self.env['ir.config_parameter'].sudo().get_param(
'usability.line_name_no_product_code')
if no_product_code_param and no_product_code_param == 'True':
self = self.with_context(display_default_code=False)
return super()._compute_name()
def reconcile(self):
"""Explicit error message if unposted lines"""
unposted_ids = self.filtered(lambda l: l.move_id.state != "posted")
if unposted_ids:
m = _("Please post the following entries before reconciliation :")
sep = "\n - "
unpost = sep.join([am.display_name for am in unposted_ids.move_id])
raise UserError(m + sep + unpost)
return super().reconcile()

View File

@@ -0,0 +1,70 @@
# 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).
from odoo import fields, models
import logging
_logger = logging.getLogger(__name__)
class AccountMoveLine(models.Model):
_inherit = 'account.move.line'
# Native order:
# _order = "date desc, move_name desc, id"
# Problem: when you manually create a journal entry, the
# order of the lines is inverted when you save ! It is quite annoying for
# the user...
_order = "date desc, id asc"
# for optional display in list view
product_barcode = fields.Char(related='product_id.barcode', string="Product Barcode")
def show_account_move_form(self):
self.ensure_one()
action = self.env["ir.actions.actions"]._for_xml_id(
'account.action_move_line_form')
action.update({
'res_id': self.move_id.id,
'view_id': False,
'views': False,
'view_mode': 'form,list',
})
return action
# def update_matching_number(self):
# records = self.search([("matching_number", "=", "P")])
# _logger.info(f"Update partial reconcile number for {len(records)} lines")
# records._compute_matching_number()
# def _compute_matching_number(self):
# TODO maybe it will be better to have the same maching_number for
# all partial so it will be easier to group by
# super()._compute_matching_number()
# for record in self:
# if record.matching_number == "P":
# record.matching_number = ", ".join([
# "a%d" % pr.id
# for pr in record.matched_debit_ids + record.matched_credit_ids
# ])
def _compute_name(self):
# This is useful when you want to have the product code in a dedicated
# column in your customer invoice report
# The same ir.config_parameter is used in sale_usability,
# purchase_usability and account_usability
no_product_code_param = self.env['ir.config_parameter'].sudo().get_param(
'usability.line_name_no_product_code')
if no_product_code_param and no_product_code_param == 'True':
self = self.with_context(display_default_code=False)
return super()._compute_name()
# def reconcile(self):
# """Explicit error message if unposted lines"""
# unposted_ids = self.filtered(lambda l: l.move_id.state != "posted")
# if unposted_ids:
# m = _("Please post the following entries before reconciliation :")
# sep = "\n - "
# unpost = sep.join([am.display_name for am in unposted_ids.move_id])
# raise UserError(m + sep + unpost)
# return super().reconcile()

View File

@@ -3,21 +3,21 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import models
from odoo.tools.misc import formatLang
# from odoo.tools.misc import formatLang
class AccountPartialReconcile(models.Model):
_inherit = "account.partial.reconcile"
_rec_name = "id"
# _rec_name = "id"
def name_get(self):
res = []
for rec in self:
# def name_get(self):
# res = []
# for rec in self:
# There is no seq for partial rec, so I simulate one with the ID
# Prefix for full rec: 'A' (upper case)
# Prefix for partial rec: 'a' (lower case)
amount_fmt = formatLang(
self.env, rec.amount, currency_obj=rec.company_currency_id)
name = 'a%d (%s)' % (rec.id, amount_fmt)
res.append((rec.id, name))
return res
# amount_fmt = formatLang(
# self.env, rec.amount, currency_obj=rec.company_currency_id)
# name = 'a%d (%s)' % (rec.id, amount_fmt)
# res.append((rec.id, name))
# return res

View File

@@ -4,6 +4,9 @@
from odoo import api, fields, models, _
# CODE DISABLED FOR THE MOMENT. I need to decide if I want to drop it
# because native code is enough and if I want to re-enable it
class ProductTemplate(models.Model):
_inherit = 'product.template'

View File

@@ -13,7 +13,7 @@ class ResCompany(models.Model):
# But there are several problems with this native field:
# - it is copied on the 'narration' field of account.move => we don't want that
# - the text block is very small on the form view of res.config.settings
# So I decided to have our own field "fixed_invoice_terms"
# So I decided to have our own field "static_invoice_terms"
# The native field can still be used when you need to customise some
# terms and conditions on each invoice (not very common, but...)
# To underline this different with the native field, I prefix it with 'static_'

View File

@@ -1,4 +1,4 @@
# Copyright 2017-2022 Akretion France (https://akretion.com/)
# Copyright 2017-2024 Akretion France (https://akretion.com/)
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

View File

@@ -1,21 +0,0 @@
# 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

@@ -0,0 +1,3 @@
[build-system]
requires = ["whool"]
build-backend = "whool.buildapi"

View File

@@ -1,3 +1,2 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_account_group_generate_full,Full access on account.group.generate,model_account_group_generate,account.group_account_manager,1,1,1,1
access_account_invoice_mark_sent_full,Full access on account.invoice.mark.sent,model_account_invoice_mark_sent,account.group_account_invoice,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
access_account_group_generate_full Full access on account.group.generate model_account_group_generate account.group_account_manager 1 1 1 1
2 access_account_invoice_mark_sent_full Full access on account.invoice.mark.sent model_account_invoice_mark_sent account.group_account_invoice 1 1 1 1

View File

@@ -1,20 +1,20 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.15.1: http://docutils.sourceforge.net/" />
<meta name="generator" content="Docutils: https://docutils.sourceforge.io/" />
<title>Account Usability</title>
<style type="text/css">
/*
:Author: David Goodger (goodger@python.org)
:Id: $Id: html4css1.css 7952 2016-07-26 18:15:59Z milde $
:Id: $Id: html4css1.css 9511 2024-01-13 09:50:07Z milde $
:Copyright: This stylesheet has been placed in the public domain.
Default cascading style sheet for the HTML output of Docutils.
Despite the name, some widely supported CSS2 features are used.
See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to
customize this style sheet.
*/
@@ -275,7 +275,7 @@ pre.literal-block, pre.doctest-block, pre.math, pre.code {
margin-left: 2em ;
margin-right: 2em }
pre.code .ln { color: grey; } /* line numbers */
pre.code .ln { color: gray; } /* line numbers */
pre.code, code { background-color: #eeeeee }
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
@@ -301,7 +301,7 @@ span.option {
span.pre {
white-space: pre }
span.problematic {
span.problematic, pre.problematic {
color: red }
span.section-subtitle {
@@ -366,8 +366,10 @@ ul.auto-toc {
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:dbf367e7cf8330c803622d0c171cd10e128344d318466d6e37ad7b0fc812e152
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external" href="https://github.com/akretion/odoo-usability/tree/12.0/account_usability"><img alt="akretion/odoo-usability" src="https://img.shields.io/badge/github-akretion%2Fodoo--usability-lightgray.png?logo=github" /></a></p>
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/akretion/odoo-usability/tree/18.0/account_usability_akretion"><img alt="akretion/odoo-usability" src="https://img.shields.io/badge/github-akretion%2Fodoo--usability-lightgray.png?logo=github" /></a></p>
<p>This modules adds the following functions:</p>
<ul class="simple">
<li>Add an <em>Overdue</em> filter on invoice search view (this feature was previously
@@ -411,41 +413,41 @@ located in te module <em>account_invoice_overdue_filter</em>)</li>
<p><strong>Table of contents</strong></p>
<div class="contents local topic" id="contents">
<ul class="simple">
<li><a class="reference internal" href="#bug-tracker" id="id1">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="id2">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="id3">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="id4">Contributors</a></li>
<li><a class="reference internal" href="#maintainers" id="id5">Maintainers</a></li>
<li><a class="reference internal" href="#bug-tracker" id="toc-entry-1">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="toc-entry-2">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="toc-entry-3">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="toc-entry-4">Contributors</a></li>
<li><a class="reference internal" href="#maintainers" id="toc-entry-5">Maintainers</a></li>
</ul>
</li>
</ul>
</div>
<div class="section" id="bug-tracker">
<h1><a class="toc-backref" href="#id1">Bug Tracker</a></h1>
<h1><a class="toc-backref" href="#toc-entry-1">Bug Tracker</a></h1>
<p>Bugs are tracked on <a class="reference external" href="https://github.com/akretion/odoo-usability/issues">GitHub Issues</a>.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us smashing it by providing a detailed and welcomed
<a class="reference external" href="https://github.com/akretion/odoo-usability/issues/new?body=module:%20account_usability%0Aversion:%2012.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
If you spotted it first, help us to smash it by providing a detailed and welcomed
<a class="reference external" href="https://github.com/akretion/odoo-usability/issues/new?body=module:%20account_usability_akretion%0Aversion:%2018.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
<p>Do not contact contributors directly about support or help with technical issues.</p>
</div>
<div class="section" id="credits">
<h1><a class="toc-backref" href="#id2">Credits</a></h1>
<h1><a class="toc-backref" href="#toc-entry-2">Credits</a></h1>
<div class="section" id="authors">
<h2><a class="toc-backref" href="#id3">Authors</a></h2>
<h2><a class="toc-backref" href="#toc-entry-3">Authors</a></h2>
<ul class="simple">
<li>Akretion</li>
</ul>
</div>
<div class="section" id="contributors">
<h2><a class="toc-backref" href="#id4">Contributors</a></h2>
<h2><a class="toc-backref" href="#toc-entry-4">Contributors</a></h2>
<ul class="simple">
<li>Alexis de Lattre &lt;<a class="reference external" href="mailto:alexis.delattre&#64;akretion.com">alexis.delattre&#64;akretion.com</a>&gt;</li>
<li>David Beal &lt;<a class="reference external" href="mailto:david.beal&#64;akretion.com">david.beal&#64;akretion.com</a>&gt;</li>
</ul>
</div>
<div class="section" id="maintainers">
<h2><a class="toc-backref" href="#id5">Maintainers</a></h2>
<p>This module is part of the <a class="reference external" href="https://github.com/akretion/odoo-usability/tree/12.0/account_usability">akretion/odoo-usability</a> project on GitHub.</p>
<h2><a class="toc-backref" href="#toc-entry-5">Maintainers</a></h2>
<p>This module is part of the <a class="reference external" href="https://github.com/akretion/odoo-usability/tree/18.0/account_usability_akretion">akretion/odoo-usability</a> project on GitHub.</p>
<p>You are welcome to contribute.</p>
</div>
</div>

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2015-2022 Akretion France (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).
-->
@@ -14,7 +14,7 @@
<field name="inherit_id" ref="account.view_account_form"/>
<field name="arch" type="xml">
<field name="deprecated" position="before">
<field name="reconcile" attrs="{'invisible': ['|', ('account_type', 'in', ('asset_cash', 'liability_credit_card')), ('internal_group', '=', 'off_balance')]}" widget="boolean_toggle"/>
<field name="reconcile" invisible="account_type in ('asset_cash', 'liability_credit_card', 'off_balance')" widget="boolean_toggle"/>
</field>
</field>
</record>
@@ -28,9 +28,6 @@
<field name="name" position="after">
<field name="code" filter_domain="[('code', '=like', self + '%')]" string="Code"/>
</field>
<filter name="accounttype" position="after">
<filter name="group_groupby" string="Group" context="{'group_by': 'group_id'}"/>
</filter>
</field>
</record>

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2024 Akretion France (http://www.akretion.com/)
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).
-->
@@ -12,8 +12,8 @@
<field name="model">account.analytic.line</field>
<field name="inherit_id" ref="account.view_account_analytic_line_tree_inherit_account"/>
<field name="arch" type="xml">
<field name="general_account_id" position="attributes">
<attribute name="optional">show</attribute>
<field name="general_account_id" position="attributes">
<attribute name="optional">show</attribute>
</field>
</field>
</record>

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2021-2022 Akretion France (http://www.akretion.com/)
Copyright 2021-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).
-->

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2018-2024 Akretion (http://www.akretion.com/)
Copyright 2018-2024 Akretion (https://www.akretion.com/)
@author: Alexis de Lattre <alexis.delattre@akretion.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
-->
@@ -15,7 +15,6 @@
<field name="arch" type="xml">
<field name="partner_id" position="after">
<field name="commercial_partner_id" optional="hide"/>
<field name="country_id" optional="hide"/>
<field name="industry_id" optional="hide"/>
<field name="fiscal_position_id" optional="hide"/>
</field>
@@ -34,20 +33,14 @@
</field>
<filter name="category_product" position="after">
<filter string="Product" name="product_groupby" context="{'group_by': 'product_id', 'residual_invisible':True}"/>
<filter name="invoice_refund_groupby" string="Invoice/Refund" context="{'group_by': 'move_type'}"/>
</filter>
<!-- group by on commercial_partner_id by default -->
<filter name="partner_id" position="attributes">
<attribute name="invisible">1</attribute>
</filter>
<filter name="partner_id" position="after">
<filter name="commercial_partner_groupby" string="Commercial Partner" context="{'group_by': 'commercial_partner_id'}"/>
<filter name="industry_groupby" string="Partner Industry" context="{'group_by': 'industry_id'}"/>
</filter>
</field>
</record>
<!-- Switch order: pivot in 1st position -->
<!-- pivot in first position instead of graph -->
<record id="account.action_account_invoice_report_all_supp" model="ir.actions.act_window">
<field name="view_mode">pivot,graph</field>
</record>

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2015-2022 Akretion France (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).
-->
@@ -13,26 +13,10 @@
<field name="inherit_id" ref="account.view_account_journal_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='account_control_ids']/.." position="after">
<group name="usability" string="Misc" attrs="{'invisible': [('type', '!=', 'bank')]}">
<group name="usability" string="Misc" invisible="type != 'bank'">
<field name="hide_bank_statement_balance" groups="account.group_account_readonly"/>
</group>
</xpath>
<xpath expr="//field[@name='inbound_payment_method_line_ids']/tree/field[@name='payment_account_id']" position="attributes">
<attribute name="optional">show</attribute>
</xpath>
<xpath expr="//field[@name='outbound_payment_method_line_ids']/tree/field[@name='payment_account_id']" position="attributes">
<attribute name="optional">show</attribute>
</xpath>
<!--
<field name="suspense_account_id" position="attributes">
<attribute name="context">{'default_user_type_id': account_type_current_assets_id, 'default_reconcile': False}</attribute>
</field>
<field name="payment_debit_account_id" position="attributes">
<attribute name="context">{'default_user_type_id': account_type_current_assets_id, 'default_reconcile': True}</attribute>
</field>
<field name="payment_credit_account_id" position="attributes">
<attribute name="context">{'default_user_type_id': account_type_current_assets_id, 'default_reconcile': True}</attribute>
</field> -->
</field>
</record>
@@ -53,6 +37,7 @@
</t> -->
</field>
</record>
-->
<record id="view_account_journal_search" model="ir.ui.view">
<field name="name">usability.account.journal.search</field>

View File

@@ -1,13 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2015-2022 Akretion France (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).
-->
<odoo>
<!-- Duplicate the menu "Sales > Configuration > Contacts > Bank Accounts"
<!-- Duplicate the menu "Bank Accounts"
under "Accounting > Configuration", because most users will try to find it there -->
<menuitem id="res_bank_account_config_menu" action="base.action_res_bank_form" parent="account.account_banks_menu" sequence="10"/>

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2015-2022 Akretion France (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).
-->
@@ -12,37 +12,30 @@
<field name="model">account.move</field>
<field name="inherit_id" ref="account.view_move_form"/>
<field name="arch" type="xml">
<!--
<field name="fiscal_position_id" position="attributes">
<attribute name="widget">selection</attribute>
</field>
<field name="invoice_incoterm_id" position="attributes">
<attribute name="widget">selection</attribute>
</field> -->
<button id="account_invoice_payment_btn" position="attributes">
<attribute name="class">btn-default</attribute>
</button>
<button name="action_register_payment" position="before">
<button name="%(account.account_invoices)d" type="action" string="Print" attrs="{'invisible': [('move_type', 'not in', ('out_invoice', 'out_refund'))]}"/>
<button name="%(account.account_invoices)d" type="action" string="Print" invisible="move_type not in ('out_invoice', 'out_refund')"/>
</button>
<button name="preview_invoice" position="attributes">
<attribute name="attrs">{}</attribute>
<attribute name="invisible">1</attribute>
</button>
<!-- move sent field and make it visible -->
<!-- move field is_move_sent and make it visible -->
<field name="is_move_sent" position="replace"/>
<field name="invoice_origin" position="attributes">
<attribute name="invisible">0</attribute>
</field>
<field name="invoice_origin" position="after">
<field name="is_move_sent" attrs="{'invisible': [('move_type', 'not in', ('out_invoice', 'out_refund'))]}"/>
<field name="is_move_sent" invisible="move_type not in ('out_invoice', 'out_refund')"/>
</field>
<xpath expr="//field[@name='line_ids']/tree/field[@name='tax_tag_ids']" position="after">
<xpath expr="//field[@name='line_ids']/list/field[@name='tax_tag_ids']" position="after">
<field name="matching_number" optional="show"/>
</xpath>
<xpath expr="//field[@name='invoice_line_ids']/tree/field[@name='product_id']" position="after">
<xpath expr="//field[@name='invoice_line_ids']/list/field[@name='product_id']" position="after">
<field name="product_barcode" optional="hide"/>
</xpath>
<!--
<field name="invoice_source_email" position="after">
<field name="blocked"/>
</field>
@@ -52,15 +45,15 @@
attrs="{'invisible': ['|', ('move_type', 'not in', ('in_invoice', 'in_refund', 'out_invoice', 'out_refund')), ('blocked', '=', False)]}">
This <field name="move_type"/> is marked as <b>disputed</b>.
</div>
</div>
<xpath expr="//button[@name='open_duplicated_ref_bill_view']/.." position="attributes">
</div> -->
<xpath expr="//field[@name='duplicated_ref_ids']/.." position="attributes">
<!-- show duplicate warning not only in draft state, but also in posted state -->
<attribute name="attrs">{'invisible': ['|', ('state', '=', 'cancel'), ('duplicated_ref_ids', '=', [])]}</attribute>
<attribute name="invisible">not duplicated_ref_ids</attribute>
</xpath>
<button name="button_cancel" attrs="{'invisible' : ['|', '|', ('id', '=', False), ('state', '!=', 'draft'),('move_type', '!=', 'entry')]}" position="attributes">
<button name="button_cancel" invisible="not id or state != 'draft' or move_type != 'entry'" position="attributes">
<attribute name="confirm">Are you sure you want to cancel this journal entry?</attribute>
</button>
<button name="button_cancel" attrs="{'invisible' : ['|', '|', ('id', '=', False), ('state', '!=', 'draft'),('move_type', '==', 'entry')]}" position="attributes">
<button name="button_cancel" invisible="not id or state != 'draft' or move_type == 'entry'" position="attributes">
<attribute name="confirm">Are you sure you want to cancel this invoice?</attribute>
</button>
</field>
@@ -71,6 +64,7 @@
<field name="inherit_id" ref="account.view_invoice_tree"/>
<field name="arch" type="xml">
<field name="amount_residual_signed" position="attributes">
<!-- switch from hide to show -->
<attribute name="optional">show</attribute>
</field>
</field>
@@ -81,21 +75,12 @@
<field name="model">account.move</field>
<field name="inherit_id" ref="account.view_account_invoice_filter"/>
<field name="arch" type="xml">
<filter name="invoice_date" position="before">
<filter name="invoice" string="Invoices" domain="[('move_type', 'in', ('out_invoice', 'in_invoice'))]"/>
<filter name="refund" string="Refunds" domain="[('move_type', 'in', ('out_refund', 'in_refund'))]"/>
<separator/>
</filter>
<filter name="due_date" position="after">
<separator/>
<filter name="to_send" string="To Send" domain="[('is_move_sent', '=', False), ('state', '=', 'posted'), ('move_type', 'in', ('out_invoice', 'out_refund'))]"/>
<filter name="sent" string="Sent" domain="[('is_move_sent', '=', True), ('move_type', 'in', ('out_invoice', 'out_refund'))]"/>
<separator/>
<filter name="no_attachment" string="Missing Attachment" domain="[('has_attachment', '=', False)]"/>
<separator/>
<filter name="dispute" string="Dispute" domain="[('blocked', '=', True)]"/>
<!-- <filter name="dispute" string="Dispute" domain="[('blocked', '=', True)]"/> -->
</filter>
<filter name="salesperson" position="before">
<filter name="partner" position="before">
<filter name="commercial_partner_groupby" string="Commercial Partner" context="{'group_by': 'commercial_partner_id'}"/>
</filter>
<filter name="status" position="after">
@@ -114,70 +99,5 @@
</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"/>
<field name="arch" type="xml">
<!-- The field 'blocked' is alone in it's block
We don't want to display an empty block, so we put the attrs on the group
The drawback of this is that, if someone added a field in that group,
he won't see the field when internal_type is not payable/receivable -->
<xpath expr="//field[@name='blocked']/.." position="attributes">
<attribute name="attrs">{'invisible': [('account_type', 'not in', ('liability_payable', 'asset_receivable'))]}</attribute>
</xpath>
<field name="account_id" position="after">
<field name="account_type" invisible="1"/>
</field>
</field>
</record>
<record id="view_move_line_tree" model="ir.ui.view">
<field name="model">account.move.line</field>
<field name="inherit_id" ref="account.view_move_line_tree"/>
<field name="arch" type="xml">
<field name="analytic_distribution" position="after">
<button title="View Journal Entry Form" type="object" name="show_account_move_form" icon="fa-arrow-right"/>
</field>
<!-- balance is already present
<field name="credit" position="after">
<field name="balance" sum="Balance" optional="show"/>
</field> -->
</field>
</record>
<record id="view_account_move_line_filter" model="ir.ui.view">
<field name="name">account_usability.account_move_line_search</field>
<field name="model">account.move.line</field>
<field name="inherit_id" ref="account.view_account_move_line_filter"/>
<field name="arch" type="xml">
<field name="partner_id" position="after">
<field name="matching_number" />
<field name="debit" filter_domain="['|', ('debit', '=', self), ('credit', '=', self)]" string="Debit or Credit"/>
</field>
<filter name="unreconciled" position="before">
<filter name="reconciled" string="Fully Reconciled" domain="[('account_id.reconcile', '=', True), ('full_reconcile_id', '!=', False)]"/>
</filter>
<filter name="unreconciled" position="attributes">
<attribute name="string">Unreconciled or Partially Reconciled</attribute>
</filter>
<field name="name" position="attributes">
<attribute name="string">Label, Reference, Account or Partner</attribute>
</field>
<field name="name" position="before">
<field name="move_id" position="move"/>
</field>
<field name="partner_id" position="attributes">
<attribute name="domain">['|', ('parent_id', '=', False), ('is_company', '=', True)]</attribute>
</field>
</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

@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
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).
-->
<odoo>
<record id="view_move_line_tree" model="ir.ui.view">
<field name="model">account.move.line</field>
<field name="inherit_id" ref="account.view_move_line_tree"/>
<field name="arch" type="xml">
<list position="inside">
<button title="View Journal Entry Form" type="object" name="show_account_move_form" icon="fa-arrow-right"/>
</list>
</field>
</record>
<record id="view_account_move_line_filter" model="ir.ui.view">
<field name="name">account_usability.account_move_line_search</field>
<field name="model">account.move.line</field>
<field name="inherit_id" ref="account.view_account_move_line_filter"/>
<field name="arch" type="xml">
<field name="partner_id" position="after">
<field name="matching_number" />
<field name="debit" filter_domain="['|', ('debit', '=', self), ('credit', '=', self)]" string="Debit or Credit"/>
</field>
<filter name="reconcilable_account" position="before">
<filter name="reconciled" string="Fully Reconciled" domain="[('account_id.reconcile', '=', True), ('full_reconcile_id', '!=', False)]"/>
</filter>
<filter name="reconcilable_account" position="attributes">
<attribute name="string">Unreconciled or Partially Reconciled</attribute>
</filter>
<field name="name" position="attributes">
<attribute name="string">Label, Reference, Account or Partner</attribute>
</field>
<field name="partner_id" position="attributes">
<attribute name="domain">['|', ('parent_id', '=', False), ('is_company', '=', True)]</attribute>
</field>
</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">list,pivot,graph,kanban</field>
</record>
</odoo>

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2025 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_account_payment_form" model="ir.ui.view">
<field name="model">account.payment</field>
<field name="inherit_id" ref="account.view_account_payment_form"/>
<field name="arch" type="xml">
<group name="group2" position="inside">
<field name="move_id" readonly="1"/>
</group>
</field>
</record>
</odoo>

View File

@@ -7,6 +7,10 @@
<odoo>
<!-- in v18, attachments are disabled by default
TODO see what's the editor idea about it
in the meantime, this field is disabled in manifest -->
<record id="account.account_invoices" model="ir.actions.report">
<!-- Attach only on customer invoices/refunds -->
<field name="attachment">(object.move_type in ('out_invoice', 'out_refund')) and (object.state == 'posted') and ((object.name or 'INV').replace('/','_')+'.pdf')</field>

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2015-2022 Akretion France (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).
-->

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2021-2022 Akretion (http://www.akretion.com/)
Copyright 2021-2024 Akretion (https://www.akretion.com/)
@author: Alexis de Lattre <alexis.delattre@akretion.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
-->

View File

@@ -1,18 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2014-2024 Akretion (http://www.akretion.com/)
Copyright 2014-2024 Akretion (https://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>
<record id="view_partner_property_form" model="ir.ui.view">
<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">
<xpath expr="//field[@name='bank_ids']/list/field[@name='acc_number']" position="after">
<field name="currency_id" optional="hide"/>
</xpath>
</field>

View File

@@ -1,22 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2021-2022 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>
<!-- When you change the date, it resets the amount via the onchange
So, in the view, the date should be BEFORE the amount -->
<record id="view_account_payment_register_form" model="ir.ui.view">
<field name="model">account.payment.register</field>
<field name="inherit_id" ref="account.view_account_payment_register_form"/>
<field name="arch" type="xml">
<label for="amount" position="before">
<field name="payment_date" position="move"/>
</label>
</field>
</record>
</odoo>

View File

@@ -1,3 +1,3 @@
from . import account_invoice_mark_sent
from . import account_move_reversal
from . import account_group_generate
#from . import account_group_generate

View File

@@ -1,4 +1,4 @@
# Copyright 2015-2022 Akretion (http://www.akretion.com)
# Copyright 2015-2024 Akretion (https://www.akretion.com)
# @author Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
@@ -56,7 +56,7 @@ class AccountGroupGenerate(models.TransientModel):
action = {
'type': 'ir.actions.act_window',
'name': _('Account Groups'),
'view_mode': 'tree,form',
'view_mode': 'list,form',
'res_model': 'account.group',
}
return action

View File

@@ -1,4 +1,4 @@
# Copyright 2017-2022 Akretion France (https://akretion.com/en)
# Copyright 2017-2024 Akretion France (https://akretion.com/en)
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
@@ -12,7 +12,7 @@ class AccountInvoiceMarkSent(models.TransientModel):
_description = 'Mark invoices as sent'
def run(self):
assert self.env.context.get('active_model') == 'account.move',\
assert self.env.context.get('active_model') == 'account.move', \
'Source model must be invoices'
assert self.env.context.get('active_ids'), 'No invoices selected'
invoices = self.env['account.move'].search([

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2017-2022 Akretion France
Copyright 2017-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).
-->
@@ -11,7 +11,7 @@
<field name="name">account.invoice.mark.sent.form</field>
<field name="model">account.invoice.mark.sent</field>
<field name="arch" type="xml">
<form string="Mark invoices as sent">
<form>
<p>
This wizard will mark as <i>sent</i> all the selected posted invoices.
</p>

View File

@@ -1,10 +1,9 @@
# Copyright 2018-2022 Akretion France (https://akretion.com/)
# Copyright 2018-2024 Akretion France (https://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
from datetime import timedelta
class AccountMoveReversal(models.TransientModel):
@@ -17,15 +16,9 @@ class AccountMoveReversal(models.TransientModel):
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
# in v18, display_name contains "MISC/2024/0008 (Reversal of: MISC/2024/0007)"
warning = "\n".join([m.display_name for m in reversed_moves])
wizard.already_reversed_warning = warning
# Set default reversal date to original move + 1 day
# and raise error if original move has already been reversed
@@ -36,5 +29,5 @@ class AccountMoveReversal(models.TransientModel):
amo = self.env['account.move']
moves = amo.browse(self._context['active_ids'])
if len(moves) == 1:
res['date'] = moves.date + relativedelta(days=1)
res['date'] = moves.date + timedelta(1)
return res

View File

@@ -9,10 +9,9 @@
<div
class="alert alert-warning"
role="alert"
attrs="{'invisible': [('already_reversed_warning', '=', False)]}"
invisible="not already_reversed_warning"
>
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 :
You are about to reverse entries that have already been reversed:
<field
name="already_reversed_warning"
/>

View File

@@ -2,10 +2,13 @@
Base Company Extension
======================
.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:075f72950033a5c6f57ecfa5c2d101bd874dd2ae29adcecdc4905b378e89a3a2
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
:target: https://odoo-community.org/page/development-status
@@ -14,25 +17,29 @@ Base Company Extension
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-akretion%2Fodoo--usability-lightgray.png?logo=github
:target: https://github.com/akretion/odoo-usability/tree/12.0/base_company_extension
:target: https://github.com/akretion/odoo-usability/tree/18.0/base_company_extension
:alt: akretion/odoo-usability
|badge1| |badge2| |badge3|
This module adds the following fields on the company:
|badge1| |badge2| |badge3|
This module adds the following fields to the ResCompany model:
* Capital Amount
* Legal Type
This is useful to display the legal name of the company in reports.
This is useful to display the legal name of the company in reports
**Table of contents**
.. contents::
:local:
Bug Tracker
===========
Bugs are tracked on `GitHub Issues <https://github.com/akretion/odoo-usability/issues>`_.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us smashing it by providing a detailed and welcomed
`feedback <https://github.com/akretion/odoo-usability/issues/new?body=module:%20base_company_extension%0Aversion:%2014.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
If you spotted it first, help us to smash it by providing a detailed and welcomed
`feedback <https://github.com/akretion/odoo-usability/issues/new?body=module:%20base_company_extension%0Aversion:%2018.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
Do not contact contributors directly about support or help with technical issues.
@@ -52,6 +59,6 @@ Contributors
Maintainers
~~~~~~~~~~~
This module is part of the `akretion/odoo-usability <https://github.com/akretion/odoo-usability/tree/12.0/base_company_extension>`_ project on GitHub.
This module is part of the `akretion/odoo-usability <https://github.com/akretion/odoo-usability/tree/18.0/base_company_extension>`_ project on GitHub.
You are welcome to contribute.

View File

@@ -4,14 +4,14 @@
{
'name': 'Base Company Extension',
'version': '16.0.1.0.0',
'version': '18.0.1.0.0',
'category': 'Partner',
'license': 'AGPL-3',
'summary': 'Adds capital and title on company',
'author': 'Akretion',
'website': 'https://github.com/akretion/odoo-usability',
# I depend on base_usability only for _report_company_legal_name()
'depends': ['base_usability'],
'depends': ['base_usability_akretion'],
'data': ['views/res_company.xml'],
'installable': True,
}

View File

@@ -0,0 +1,3 @@
[build-system]
requires = ["whool"]
build-backend = "whool.buildapi"

View File

Before

Width:  |  Height:  |  Size: 9.2 KiB

After

Width:  |  Height:  |  Size: 9.2 KiB

View File

@@ -1,20 +1,20 @@
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.15.1: http://docutils.sourceforge.net/" />
<meta name="generator" content="Docutils: https://docutils.sourceforge.io/" />
<title>Base Company Extension</title>
<style type="text/css">
/*
:Author: David Goodger (goodger@python.org)
:Id: $Id: html4css1.css 7952 2016-07-26 18:15:59Z milde $
:Id: $Id: html4css1.css 9511 2024-01-13 09:50:07Z milde $
:Copyright: This stylesheet has been placed in the public domain.
Default cascading style sheet for the HTML output of Docutils.
Despite the name, some widely supported CSS2 features are used.
See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
See https://docutils.sourceforge.io/docs/howto/html-stylesheets.html for how to
customize this style sheet.
*/
@@ -275,7 +275,7 @@ pre.literal-block, pre.doctest-block, pre.math, pre.code {
margin-left: 2em ;
margin-right: 2em }
pre.code .ln { color: grey; } /* line numbers */
pre.code .ln { color: gray; } /* line numbers */
pre.code, code { background-color: #eeeeee }
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
@@ -301,7 +301,7 @@ span.option {
span.pre {
white-space: pre }
span.problematic {
span.problematic, pre.problematic {
color: red }
span.section-subtitle {
@@ -366,8 +366,10 @@ ul.auto-toc {
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:075f72950033a5c6f57ecfa5c2d101bd874dd2ae29adcecdc4905b378e89a3a2
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external" href="https://github.com/akretion/odoo-usability/tree/12.0/base_company_extension"><img alt="akretion/odoo-usability" src="https://img.shields.io/badge/github-akretion%2Fodoo--usability-lightgray.png?logo=github" /></a></p>
<p><a class="reference external image-reference" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external image-reference" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external image-reference" href="https://github.com/akretion/odoo-usability/tree/18.0/base_company_extension"><img alt="akretion/odoo-usability" src="https://img.shields.io/badge/github-akretion%2Fodoo--usability-lightgray.png?logo=github" /></a></p>
<p>This module adds the following fields to the ResCompany model:
* Capital Amount
* Legal Type</p>
@@ -375,40 +377,40 @@ ul.auto-toc {
<p><strong>Table of contents</strong></p>
<div class="contents local topic" id="contents">
<ul class="simple">
<li><a class="reference internal" href="#bug-tracker" id="id1">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="id2">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="id3">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="id4">Contributors</a></li>
<li><a class="reference internal" href="#maintainers" id="id5">Maintainers</a></li>
<li><a class="reference internal" href="#bug-tracker" id="toc-entry-1">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="toc-entry-2">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="toc-entry-3">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="toc-entry-4">Contributors</a></li>
<li><a class="reference internal" href="#maintainers" id="toc-entry-5">Maintainers</a></li>
</ul>
</li>
</ul>
</div>
<div class="section" id="bug-tracker">
<h1><a class="toc-backref" href="#id1">Bug Tracker</a></h1>
<h1><a class="toc-backref" href="#toc-entry-1">Bug Tracker</a></h1>
<p>Bugs are tracked on <a class="reference external" href="https://github.com/akretion/odoo-usability/issues">GitHub Issues</a>.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us smashing it by providing a detailed and welcomed
<a class="reference external" href="https://github.com/akretion/odoo-usability/issues/new?body=module:%20base_company_extension%0Aversion:%2012.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
If you spotted it first, help us to smash it by providing a detailed and welcomed
<a class="reference external" href="https://github.com/akretion/odoo-usability/issues/new?body=module:%20base_company_extension%0Aversion:%2018.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
<p>Do not contact contributors directly about support or help with technical issues.</p>
</div>
<div class="section" id="credits">
<h1><a class="toc-backref" href="#id2">Credits</a></h1>
<h1><a class="toc-backref" href="#toc-entry-2">Credits</a></h1>
<div class="section" id="authors">
<h2><a class="toc-backref" href="#id3">Authors</a></h2>
<h2><a class="toc-backref" href="#toc-entry-3">Authors</a></h2>
<ul class="simple">
<li>Akretion</li>
</ul>
</div>
<div class="section" id="contributors">
<h2><a class="toc-backref" href="#id4">Contributors</a></h2>
<h2><a class="toc-backref" href="#toc-entry-4">Contributors</a></h2>
<ul class="simple">
<li>Alexis de Lattre &lt;<a class="reference external" href="mailto:alexis.delattre&#64;akretion.com">alexis.delattre&#64;akretion.com</a>&gt;</li>
</ul>
</div>
<div class="section" id="maintainers">
<h2><a class="toc-backref" href="#id5">Maintainers</a></h2>
<p>This module is part of the <a class="reference external" href="https://github.com/akretion/odoo-usability/tree/12.0/base_company_extension">akretion/odoo-usability</a> project on GitHub.</p>
<h2><a class="toc-backref" href="#toc-entry-5">Maintainers</a></h2>
<p>This module is part of the <a class="reference external" href="https://github.com/akretion/odoo-usability/tree/18.0/base_company_extension">akretion/odoo-usability</a> project on GitHub.</p>
<p>You are welcome to contribute.</p>
</div>
</div>

View File

@@ -58,5 +58,5 @@ Limitation: when you want to have different access rights on these lists dependi
'security/ir.model.access.csv',
'views/dynamic_list.xml',
],
'installable': True,
'installable': False,
}

View File

@@ -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': True,
'installable': False,
}

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 models, tools
from odoo import models
class IrMailServer(models.Model):
@@ -25,13 +25,3 @@ class IrMailServer(models.Model):
message_id=message_id, references=references, object_id=object_id,
subtype=subtype, headers=headers,
body_alternative=body_alternative, subtype_alternative=subtype_alternative)
def _prepare_email_message(self, message, smtp_session):
validated_to = self.env.context.get('send_validated_to') or []
if message['Bcc']:
email_bcc_normalized = tools.email_normalize_all(message['Bcc'])
for email in email_bcc_normalized:
if email not in validated_to:
validated_to.append(email)
return super(IrMailServer, self.with_context(send_validated_to=validated_to))._prepare_email_message(
message, smtp_session)

View File

@@ -27,6 +27,6 @@ It has been developped by brother Bernard from Barroux Abbey and Alexis de Lattr
'views/res_partner.xml',
'security/ir.model.access.csv',
],
'installable': True,
'installable': False,
'post_init_hook': 'migrate_to_partner_phone',
}

View File

@@ -1,10 +1,10 @@
# Copyright 2017-2023 Akretion France (https://www.akretion.com)
# Copyright 2017-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).
{
'name': 'Base Partner Reference',
'version': '16.0.1.0.0',
'version': '18.0.1.0.0',
'category': 'Partner',
'license': 'AGPL-3',
'summary': "Improve usage of partner's Internal Reference",

View File

@@ -4,14 +4,13 @@
from odoo import api, fields, models
import re
import logging
logger = logging.getLogger(__name__)
class ResPartner(models.Model):
_inherit = 'res.partner'
ref = fields.Char(copy=False) # To avoid blocking duplicate
invalidate_display_name = fields.Boolean()
_sql_constraints = [(
'ref_unique',
@@ -20,64 +19,28 @@ class ResPartner(models.Model):
)]
# add 'ref' in depends
@api.depends('ref')
@api.depends('ref', 'invalidate_display_name')
def _compute_display_name(self):
super()._compute_display_name()
def _get_name(self):
partner = self
name = partner.name or ''
def _get_complete_name(self):
self.ensure_one()
displayed_types = self._complete_name_displayed_types
type_description = dict(self._fields['type']._description_selection(self.env))
name = self.name or ''
# START modif of native method
if not self._context.get('show_address') and partner.ref:
name = "[%s] %s" % (partner.ref, name)
if not self._context.get('show_address') and self.ref:
name = "[%s] %s" % (self.ref, name)
# END modif of native method
if partner.company_name or partner.parent_id:
if not name and partner.type in ['invoice', 'delivery', 'other']:
name = dict(self.fields_get(
['type'])['type']['selection'])[partner.type]
if not partner.is_company:
# START modif of native name_get() method
company_name = partner.commercial_company_name or\
partner.sudo().parent_id.name
if not self._context.get('show_address') and partner.parent_id.ref:
company_name = "[%s] %s" % (partner.parent_id.ref, company_name)
name = "%s, %s" % (company_name, name)
# END modif of native name_get() method
if self._context.get('show_address_only'):
name = partner._display_address(without_company=True)
if self._context.get('show_address'):
name = name + "\n" + partner._display_address(without_company=True)
name = re.sub(r'\s+\n', '\n', name)
if self._context.get('partner_show_db_id'):
name = "%s (%s)" % (name, partner.id)
if self._context.get('address_inline'):
splitted_names = name.split("\n")
name = ", ".join([n for n in splitted_names if n.strip()])
if self._context.get('show_email') and partner.email:
name = "%s <%s>" % (name, partner.email)
if self._context.get('html_format'):
name = name.replace('\n', '<br/>')
if self._context.get('show_vat') and partner.vat:
name = "%s %s" % (name, partner.vat)
if self.company_name or self.parent_id:
if not name and self.type in displayed_types:
name = type_description[self.type]
if not self.is_company:
name = f"{self.commercial_company_name or self.sudo().parent_id.name}, {name}"
# START modif of native method
if not self._context.get('show_address') and self.parent_id.ref:
name = f"[{self.parent_id.ref}] {name}"
# END modif of native method
return name.strip()
@api.model
def name_search(self, name='', args=None, operator='ilike', limit=100):
if args is None:
args = []
if name and operator == 'ilike':
recs = self.search([('ref', '=', name)] + args, limit=limit)
if recs:
rec_childs = self.search([('id', 'child_of', recs.ids)])
return rec_childs.name_get()
return super().name_search(name=name, args=args, operator=operator, limit=limit)
@api.model
def _script_invalidate_display_name(self):
"""Script designed to regenerate the display_name"""
logger.info('Start script to invalidate display_name')
partners = self.with_context(active_test=False).search([])
logger.info('Calling _compute_display_name on %d partners', len(partners))
partners._compute_display_name()
logger.info('End of the script to invalidate display_name')
# native _rec_names_search contains "ref", so no need to inherit name_search()

View File

@@ -2,11 +2,8 @@
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import api, SUPERUSER_ID
def update_partner_display_name(cr, registry):
env = api.Environment(cr, SUPERUSER_ID, {})
def update_partner_display_name(env):
partners = env['res.partner'].with_context(active_test=False).search(
[('ref', '!=', False)])
partners._compute_display_name()
partners.write({'invalidate_display_name': True})

View File

@@ -0,0 +1,3 @@
[build-system]
requires = ["whool"]
build-backend = "whool.buildapi"

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2017-2023 Akretion France (http://www.akretion.com/)
Copyright 2017-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).
-->
@@ -13,9 +13,9 @@
<field name="inherit_id" ref="base.view_partner_form"/>
<field name="priority">1000</field> <!-- inherit after l10n_fr -->
<field name="arch" type="xml">
<field name="vat" position="before">
<div class="o_address_format" position="after">
<field name="ref"/>
</field>
</div>
<xpath expr="//page[@name='sales_purchases']//field[@name='ref']" position="attributes">
<attribute name="invisible">1</attribute>
</xpath>

View File

@@ -4,7 +4,7 @@
{
'name': 'Base Profile by Akretion',
'version': '16.0.1.0.0',
'version': '18.0.1.0.0',
'category': 'Tools',
'license': 'AGPL-3',
'summary': 'Base module set selected by Alexis de Lattre',
@@ -21,7 +21,7 @@
# REMOVE or FIX BAD NATIVE STUFF
'disable_odoo_online', # OCA/server-brand
'remove_odoo_enterprise', # OCA/server-brand
'mail_debrand', # OCA/social
'mail_debrand', # OCA/mail
'partner_disable_gravatar', # OCA/partner-contact
'base_technical_features', # OCA/server-ux
### WEB
@@ -31,8 +31,8 @@
'web_dialog_size', # OCA/web
'web_chatter_position', # OCA/web
### MISC
'base_usability', # akretion/odoo-usability
'mail_usability', # akretion/odoo-usability
'base_usability_akretion', # akretion/odoo-usability
'mail_usability_akretion', # akretion/odoo-usability
'eradicate_quick_create', # akretion/odoo-usability
'base_company_extension', # akretion/odoo-usability
# password_security will be enabled when the move to ir.config_parameter

View File

@@ -0,0 +1,3 @@
[build-system]
requires = ["whool"]
build-backend = "whool.buildapi"

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

View File

@@ -1,16 +0,0 @@
# 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).
from odoo import api, models
class IrModelFields(models.Model):
_inherit = 'ir.model.fields'
@api.depends('name', 'field_description')
def name_get(self):
res = []
for rec in self:
res.append((rec.id, '%s (%s)' % (rec.field_description, rec.name)))
return res

View File

@@ -1,36 +0,0 @@
# Copyright 2016-2025 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 models
from odoo.tools import misc, float_compare
class BaseUsabilityInstalled(models.AbstractModel):
_name = "base.usability.installed"
_description = "Base Usability Installed"
formatLang_original = misc.formatLang
def formatLang(
env, value, digits=None, grouping=True,
monetary=False, dp=False, currency_obj=False, int_no_digits=True):
if (
'base.usability.installed' in env and
int_no_digits and
not monetary and
isinstance(value, float) and
dp):
prec = env['decimal.precision'].precision_get(dp)
if not float_compare(value, int(value), precision_digits=prec):
digits = 0
dp = False
res = formatLang_original(
env, value, digits=digits, grouping=grouping,
monetary=monetary, dp=dp, currency_obj=currency_obj)
return res
misc.formatLang = formatLang

View File

@@ -1,14 +0,0 @@
# Copyright 2015-2022 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
class ResPartnerBank(models.Model):
_inherit = 'res.partner.bank'
# In the 'base' module, they didn't put any string, so the bank name is
# displayed as 'Name', which the string of the related field it
# points to
bank_name = fields.Char(string='Bank Name')

View File

@@ -1,40 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2022 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="ir_property_view_tree" model="ir.ui.view">
<field name="model">ir.property</field>
<field name="inherit_id" ref="base.ir_property_view_tree"/>
<field name="arch" type="xml">
<field name="type" position="after">
<field name="value_reference" optional="show"/>
<field name="value_integer" optional="hide"/>
<field name="value_float" optional="hide"/>
<field name="value_datetime" optional="hide"/>
<field name="value_text" optional="hide"/>
</field>
<field name="type" position="attributes">
<attribute name="optional">hide</attribute>
</field>
</field>
</record>
<record id="ir_property_view_search" model="ir.ui.view">
<field name="model">ir.property</field>
<field name="inherit_id" ref="base.ir_property_view_search"/>
<field name="arch" type="xml">
<search position="inside">
<group name="groupby">
<filter name="field_groupby" string="Field" context="{'group_by': 'fields_id'}"/>
<filter name="company_groupby" string="Company" context="{'group_by': 'company_id'}"/>
</group>
</search>
</field>
</record>
</odoo>

View File

@@ -1,24 +0,0 @@
diff --git a/addons/web/static/src/search/filter_menu/custom_filter_item.js b/addons/web/static/src/search/filter_menu/custom_filter_item.js
index f67f5fb40af..22525b7cbfd 100644
--- a/addons/web/static/src/search/filter_menu/custom_filter_item.js
+++ b/addons/web/static/src/search/filter_menu/custom_filter_item.js
@@ -46,6 +46,8 @@ const FIELD_OPERATORS = {
char: [
{ symbol: "ilike", description: _lt("contains") },
{ symbol: "not ilike", description: _lt("doesn't contain") },
+ { symbol: "startswith", description: _lt("starts with") },
+ { symbol: "endswith", description: _lt("ends with") },
{ symbol: "=", description: _lt("is equal to") },
{ symbol: "!=", description: _lt("is not equal to") },
{ symbol: "!=", description: _lt("is set"), value: false },
@@ -257,6 +259,10 @@ export class CustomFilterItem extends Component {
[field.name, ">=", domainValue[0]],
[field.name, "<=", domainValue[1]]
);
+ } else if (operator.symbol === "startswith") {
+ domainArray.push([field.name, '=ilike', domainValue[0] + '%']);
+ } else if (operator.symbol === "endswith") {
+ domainArray.push([field.name, '=ilike', '%' + domainValue[0]]);
} else {
domainArray.push([field.name, operator.symbol, domainValue[0]]);
}

View File

@@ -2,10 +2,13 @@
Base Usability
==============
.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:6998b819c2a5d0be20947d00a368d24aa2a1e1f2655e6463e450f2d7ad9acfcd
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
:target: https://odoo-community.org/page/development-status
@@ -13,17 +16,11 @@ Base Usability
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fodoo--usability-lightgray.png?logo=github
:target: https://github.com/OCA/odoo-usability/tree/16.0/base_usability
:alt: OCA/odoo-usability
.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png
:target: https://translation.odoo-community.org/projects/odoo-usability-16-0/odoo-usability-16-0-base_usability
:alt: Translate me on Weblate
.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png
:target: https://runboat.odoo-community.org/webui/builds.html?repo=OCA/odoo-usability&target_branch=16.0
:alt: Try me on Runboat
.. |badge3| image:: https://img.shields.io/badge/github-akretion%2Fodoo--usability-lightgray.png?logo=github
:target: https://github.com/akretion/odoo-usability/tree/18.0/base_usability_akretion
:alt: akretion/odoo-usability
|badge1| |badge2| |badge3| |badge4| |badge5|
|badge1| |badge2| |badge3|
This module adds the following functions:
@@ -60,10 +57,10 @@ This module adds the following functions:
Bug Tracker
===========
Bugs are tracked on `GitHub Issues <https://github.com/OCA/odoo-usability/issues>`_.
Bugs are tracked on `GitHub Issues <https://github.com/akretion/odoo-usability/issues>`_.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us smashing it by providing a detailed and welcomed
`feedback <https://github.com/OCA/odoo-usability/issues/new?body=module:%20base_usability%0Aversion:%2016.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
If you spotted it first, help us to smash it by providing a detailed and welcomed
`feedback <https://github.com/akretion/odoo-usability/issues/new?body=module:%20base_usability_akretion%0Aversion:%2018.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
Do not contact contributors directly about support or help with technical issues.
@@ -85,16 +82,6 @@ Contributors
Maintainers
~~~~~~~~~~~
This module is maintained by the OCA.
This module is part of the `akretion/odoo-usability <https://github.com/akretion/odoo-usability/tree/18.0/base_usability_akretion>`_ project on GitHub.
.. image:: https://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: https://odoo-community.org
OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.
This module is part of the `OCA/odoo-usability <https://github.com/OCA/odoo-usability/tree/16.0/base_usability>`_ project on GitHub.
You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.
You are welcome to contribute.

View File

@@ -4,7 +4,7 @@
{
'name': 'Base Usability',
'version': '16.0.1.0.0',
'version': '18.0.1.0.0',
'category': 'Partner',
'license': 'AGPL-3',
'summary': 'Better usability in base module',
@@ -21,7 +21,6 @@
'views/ir_config_parameter.xml',
'views/ir_module.xml',
'views/ir_sequence.xml',
'views/ir_property.xml',
],
'installable': True,
}

View File

@@ -4,5 +4,3 @@ from . import res_partner_bank
from . import res_company
from . import ir_mail_server
from . import ir_model
from . import ir_model_fields
from . import misc

View File

@@ -1,4 +1,4 @@
# Copyright 2015-2022 Akretion France (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).
@@ -18,24 +18,21 @@ class IrMailServer(models.Model):
smtp_ssl_certificate=None, smtp_ssl_private_key=None,
smtp_debug=False, smtp_session=None):
# Start copy from native method
if not smtp_session:
smtp_session = self.connect(
smtp = smtp_session
if not smtp:
smtp = self.connect(
smtp_server, smtp_port, smtp_user, smtp_password, smtp_encryption,
smtp_from=message['From'], ssl_certificate=smtp_ssl_certificate,
ssl_private_key=smtp_ssl_private_key,
smtp_debug=smtp_debug, mail_server_id=mail_server_id)
# _prepare_email_message() will remove the Bcc field in message
# that's why we need to save it and re-inject it in message
email_bcc = message['Bcc']
smtp_from=message['From'], ssl_certificate=smtp_ssl_certificate, ssl_private_key=smtp_ssl_private_key,
smtp_debug=smtp_debug, mail_server_id=mail_server_id,)
smtp_from, smtp_to_list, message = self._prepare_email_message(
message, smtp_session)
message['Bcc'] = email_bcc
message, smtp)
# End copy from native method
logger.info(
"Sending email from '%s' to '%s' Cc '%s' Bcc '%s' "
"with subject '%s'. smtp_to_list=%s",
"with subject '%s'",
smtp_from, message.get('To'), message.get('Cc'),
message.get('Bcc'), message.get('Subject'), smtp_to_list)
message.get('Bcc'), message.get('Subject'))
return super().send_email(
message, mail_server_id=mail_server_id,
smtp_server=smtp_server, smtp_port=smtp_port,

View File

@@ -1,4 +1,4 @@
# Copyright 2019-2022 Akretion France (http://www.akretion.com/)
# 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).
@@ -9,8 +9,6 @@ class IrModel(models.Model):
_inherit = 'ir.model'
@api.depends('name', 'model')
def name_get(self):
res = []
def _compute_display_name(self):
for rec in self:
res.append((rec.id, '%s (%s)' % (rec.name, rec.model)))
return res
rec.display_name = f'{rec.name} ({rec.model})'

View File

@@ -1,4 +1,4 @@
# Copyright 2015-2022 Akretion France (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).

View File

@@ -1,4 +1,4 @@
# Copyright 2015-2022 Akretion France (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).

View File

@@ -0,0 +1,24 @@
# 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).
from odoo import api, fields, models
class ResPartnerBank(models.Model):
_inherit = 'res.partner.bank'
# In the 'base' module, they didn't put any string, so the bank name is
# displayed as 'Name', which the string of the related field it
# points to
bank_name = fields.Char(string='Bank Name')
@api.depends('currency_id')
def _compute_display_name(self):
for acc in self:
name = acc.acc_number
if acc.currency_id:
name = f"{name} ({acc.currency_id.name})"
if acc.bank_id:
name = f"{name} - {acc.bank_id.name}"
acc.display_name = name

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, fields, models, SUPERUSER_ID
from odoo import api, fields, models
import logging
from odoo.tools.misc import format_datetime
@@ -14,11 +14,9 @@ class ResUsers(models.Model):
@api.model
def _script_partners_linked_to_users_no_company(self):
if self.env.user.id != SUPERUSER_ID:
self = self.sudo()
logger.info(
'START to set company_id=False on partners related to users')
users = self.with_context(active_test=False).search([])
users = self.sudo().with_context(active_test=False).search([])
for user in users:
if user.partner_id.company_id:
user.partner_id.write({'company_id': False})

View File

@@ -0,0 +1,3 @@
[build-system]
requires = ["whool"]
build-backend = "whool.buildapi"

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2016-2022 Akretion France (http://www.akretion.com/)
Copyright 2016-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).
-->

View File

Before

Width:  |  Height:  |  Size: 9.5 KiB

After

Width:  |  Height:  |  Size: 9.5 KiB

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