Compare commits

..

1 Commits

Author SHA1 Message Date
clementmbr
2bfde2e346 [IMP] add a button on kanban to open child partner 2021-06-01 14:50:19 +02:00
167 changed files with 489 additions and 3524 deletions

View File

@@ -52,7 +52,6 @@ This modules adds the following functions:
* don't attach PDF upon invoice report generation on supplier invoices/refunds * don't attach PDF upon invoice report generation on supplier invoices/refunds
* Add filter on debit and credit amount for Move Lines * Add filter on debit and credit amount for Move Lines
* Add supplier invoice number in invoice tree view * 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: Together with this module, I recommend the use of the following modules:

View File

@@ -19,9 +19,6 @@
'data': [ 'data': [
'views/account_account_type.xml', 'views/account_account_type.xml',
'views/account_account.xml', 'views/account_account.xml',
'views/account_group.xml',
'views/account_analytic_account.xml',
'views/account_analytic_group.xml',
'views/account_bank_statement.xml', 'views/account_bank_statement.xml',
'views/account_invoice_report.xml', 'views/account_invoice_report.xml',
'views/account_journal.xml', 'views/account_journal.xml',
@@ -31,14 +28,10 @@
'views/product.xml', 'views/product.xml',
'views/res_config_settings.xml', 'views/res_config_settings.xml',
'views/res_partner.xml', 'views/res_partner.xml',
'views/res_company.xml',
'views/account_report.xml', 'views/account_report.xml',
'wizard/account_invoice_mark_sent_view.xml', 'wizard/account_invoice_mark_sent_view.xml',
'wizard/account_group_generate_view.xml', 'wizard/account_group_generate_view.xml',
'wizard/account_payment_register_views.xml',
'security/ir.model.access.csv', 'security/ir.model.access.csv',
'report/invoice_report.xml',
], ],
'qweb': ['static/src/xml/account_payment.xml'],
'installable': True, 'installable': True,
} }

View File

@@ -6,6 +6,4 @@ from . import account_journal
from . import account_move from . import account_move
from . import account_partial_reconcile from . import account_partial_reconcile
from . import res_partner from . import res_partner
from . import res_company
from . import product from . import product
from . import account_invoice_report

View File

@@ -27,7 +27,9 @@ class AccountBankStatement(models.Model):
def _check_balance_end_real_same_as_computed(self): def _check_balance_end_real_same_as_computed(self):
for stmt in self: for stmt in self:
if not stmt.hide_bank_statement_balance: if stmt.hide_bank_statement_balance:
continue
else:
super(AccountBankStatement, stmt)._check_balance_end_real_same_as_computed() super(AccountBankStatement, stmt)._check_balance_end_real_same_as_computed()
return True return True
@@ -78,8 +80,7 @@ class AccountBankStatementLine(models.Model):
def show_account_move(self): def show_account_move(self):
self.ensure_one() self.ensure_one()
action = self.env["ir.actions.actions"]._for_xml_id( action = self.env.ref('account.action_move_line_form').read()[0]
'account.action_move_line_form')
# Note: this action is on account.move, not account.move.line ! # Note: this action is on account.move, not account.move.line !
action.update({ action.update({
'views': False, 'views': False,

View File

@@ -14,13 +14,3 @@ class AccountIncoterms(models.Model):
for rec in self: for rec in self:
res.append((rec.id, '[%s] %s' % (rec.code, rec.name))) res.append((rec.id, '[%s] %s' % (rec.code, rec.name)))
return res 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,17 +0,0 @@
# Copyright 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, fields, models
class AccountInvoiceReport(models.Model):
_inherit = 'account.invoice.report'
industry_id = fields.Many2one('res.partner.industry', string='Partner Industry', readonly=True)
@api.model
def _select(self):
res = super()._select()
res += ", COALESCE(partner.industry_id, commercial_partner.industry_id) AS industry_id"
return res

View File

@@ -16,13 +16,6 @@ class AccountJournal(models.Model):
"you don't want to enter the start/end balance manually: it " "you don't want to enter the start/end balance manually: it "
"will prevent the display of wrong information in the accounting " "will prevent the display of wrong information in the accounting "
"dashboard and on bank statements.") "dashboard and on bank statements.")
# Used to set default user_type_id on account fields
account_type_current_liabilities_id = fields.Many2one(
'account.account.type',
default=lambda self: self.env.ref('account.data_account_type_current_liabilities').id)
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( @api.depends(
'name', 'currency_id', 'company_id', 'company_id.currency_id', 'code') 'name', 'currency_id', 'company_id', 'company_id.currency_id', 'code')

View File

@@ -2,17 +2,17 @@
# @author Alexis de Lattre <alexis.delattre@akretion.com> # @author Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import api, fields, models, _ from odoo import api, fields, models
from odoo.tools import float_is_zero from odoo.tools import float_is_zero
from odoo.tools.misc import format_date from odoo.tools.misc import format_date
from odoo.osv import expression from odoo.osv import expression
from datetime import timedelta
from odoo.exceptions import UserError
class AccountMove(models.Model): class AccountMove(models.Model):
_inherit = 'account.move' _inherit = 'account.move'
default_move_line_name = fields.Char(
string='Default Label', states={'posted': [('readonly', True)]})
# By default, we can still modify "ref" when account move is posted # By default, we can still modify "ref" when account move is posted
# which seems a bit lazy for me... # which seems a bit lazy for me...
ref = fields.Char(states={'posted': [('readonly', True)]}) ref = fields.Char(states={'posted': [('readonly', True)]})
@@ -123,11 +123,7 @@ class AccountMove(models.Model):
has_sections = False has_sections = False
subtotal = 0.0 subtotal = 0.0
sign = self.move_type == 'out_refund' and -1 or 1 sign = self.move_type == 'out_refund' and -1 or 1
# Warning: the order of invoice line is forced in the view for line in self.invoice_line_ids:
# <tree editable="bottom" default_order="sequence, date desc, move_name desc, id"
# it's not the same as the _order in the class AccountMoveLine
lines = self.env['account.move.line'].search([('exclude_from_invoice_tab', '=', False), ('move_id', '=', self.id)], order="sequence, date desc, move_name desc, id")
for line in lines:
if line.display_type == 'line_section': if line.display_type == 'line_section':
# insert line # insert line
if has_sections: if has_sections:
@@ -154,13 +150,13 @@ class AccountMove(models.Model):
""" French law requires to set sale order dates into invoice """ French law requires to set sale order dates into invoice
returned string: "sale1 (date1), sale2 (date2) ..." returned string: "sale1 (date1), sale2 (date2) ..."
""" """
for move in self: for inv in self:
sales = move.invoice_line_ids.mapped( sales = inv.invoice_line_ids.mapped(
'sale_line_ids').mapped('order_id') 'sale_line_ids').mapped('order_id')
dates = ["%s (%s)" % ( dates = ["%s (%s)" % (
x.name, format_date(move.env, x.date_order)) x.name, format_date(inv.env, self.date_order))
for x in sales] for x in sales]
move.sale_dates = ", ".join(dates) inv.sale_dates = ", ".join(dates)
# allow to manually create moves not only in general journals, # allow to manually create moves not only in general journals,
# but also in cash journal and check journals (= bank journals not linked to a bank account) # but also in cash journal and check journals (= bank journals not linked to a bank account)
@@ -180,47 +176,6 @@ class AccountMove(models.Model):
]) ])
move.suitable_journal_ids = self.env['account.journal'].search(domain) move.suitable_journal_ids = self.env['account.journal'].search(domain)
def button_draft(self):
super().button_draft()
# Delete attached pdf invoice
try:
report_invoice = self.env['ir.actions.report']._get_report_from_name('account.report_invoice')
except IndexError:
report_invoice = False
if report_invoice and report_invoice.attachment:
for move in self.filtered(lambda x: x.move_type in ('out_invoice', 'out_refund')):
# The pb is that the filename is dynamic and related to move.state
# in v12, the feature was native and they used that kind of code:
# with invoice.env.do_in_draft():
# invoice.number, invoice.state = invoice.move_name, 'open'
# attachment = self.env.ref('account.account_invoices').retrieve_attachment(invoice)
# But do_in_draft() doesn't exists in v14
# If you know how we could do that, please update the code below
attachment = self.env['ir.attachment'].search([
('name', '=', self._get_invoice_attachment_name()),
('res_id', '=', move.id),
('res_model', '=', self._name),
('type', '=', 'binary'),
], limit=1)
if attachment:
attachment.unlink()
def _get_invoice_attachment_name(self):
self.ensure_one()
return '%s.pdf' % (self.name and self.name.replace('/', '_') or 'INV')
def _get_accounting_date(self, invoice_date, has_tax):
# 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
return date
class AccountMoveLine(models.Model): class AccountMoveLine(models.Model):
_inherit = 'account.move.line' _inherit = 'account.move.line'
@@ -245,8 +200,7 @@ class AccountMoveLine(models.Model):
def show_account_move_form(self): def show_account_move_form(self):
self.ensure_one() self.ensure_one()
action = self.env["ir.actions.actions"]._for_xml_id( action = self.env.ref('account.action_move_line_form').read()[0]
'account.action_move_line_form')
action.update({ action.update({
'res_id': self.move_id.id, 'res_id': self.move_id.id,
'view_id': False, 'view_id': False,
@@ -266,25 +220,3 @@ class AccountMoveLine(models.Model):
rec_str = ', '.join([ rec_str = ', '.join([
'a%d' % pr.id for pr in line.matched_debit_ids + line.matched_credit_ids]) 'a%d' % pr.id for pr in line.matched_debit_ids + line.matched_credit_ids])
line.reconcile_string = rec_str line.reconcile_string = rec_str
def _get_computed_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()._get_computed_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

@@ -1,21 +0,0 @@
# Copyright 2021 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 fields, models
class ResCompany(models.Model):
_inherit = 'res.company'
# There is a native field invoice_terms which is displayed on res.config.settings
# when the ir.config_parameter account.use_invoice_terms is True
# 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"
# 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_'
static_invoice_terms = fields.Text(
translate=True, string="Legal Terms on Invoice")

View File

@@ -1,19 +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).
-->
<templates id="template" xml:space="preserve">
<!-- Requires https://github.com/odoo/odoo/pull/84180 -->
<t t-extend="ShowPaymentInfo" >
<t t-jquery="td:first" t-operation="after">
<td style="max-width: 25em;" id="outstanding-date">
<div class="oe_form_field" style="margin-right: 5px; text-overflow: ellipsis; overflow: hidden; white-space: nowrap;"><t t-esc="line.date"></t></div>
</td>
</t>
</t>
</templates>

View File

@@ -31,9 +31,6 @@
<field name="name" position="after"> <field name="name" position="after">
<field name="code" filter_domain="[('code', '=like', str(self)+'%')]" string="Code"/> <field name="code" filter_domain="[('code', '=like', str(self)+'%')]" string="Code"/>
</field> </field>
<filter name="accounttype" position="after">
<filter name="group_groupby" string="Group" context="{'group_by': 'group_id'}"/>
</filter>
</field> </field>
</record> </record>

View File

@@ -1,33 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2015-2021 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="view_account_analytic_account_list" model="ir.ui.view">
<field name="model">account.analytic.account</field>
<field name="inherit_id" ref="analytic.view_account_analytic_account_list"/>
<field name="arch" type="xml">
<field name="code" position="after">
<field name="group_id" optional="show"/>
</field>
</field>
</record>
<record id="view_account_analytic_account_search" model="ir.ui.view">
<field name="model">account.analytic.account</field>
<field name="inherit_id" ref="analytic.view_account_analytic_account_search"/>
<field name="arch" type="xml">
<filter name="associatedpartner" position="before">
<filter name="group_groupby" string="Group" context="{'group_by': 'group_id'}"/>
</filter>
</field>
</record>
</odoo>

View File

@@ -1,22 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2021 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="account_analytic_group_tree_view" model="ir.ui.view">
<field name="model">account.analytic.group</field>
<field name="inherit_id" ref="analytic.account_analytic_group_tree_view"/>
<field name="arch" type="xml">
<field name="name" position="after">
<field name="parent_id" optional="show"/>
</field>
</field>
</record>
</odoo>

View File

@@ -1,32 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2021 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="view_account_group_form" model="ir.ui.view">
<field name="model">account.group</field>
<field name="inherit_id" ref="account.view_account_group_form"/>
<field name="arch" type="xml">
<field name="name" position="after">
<field name="parent_id"/>
</field>
</field>
</record>
<record id="view_account_group_tree" model="ir.ui.view">
<field name="model">account.group</field>
<field name="inherit_id" ref="account.view_account_group_tree"/>
<field name="arch" type="xml">
<field name="name" position="after">
<field name="parent_id" optional="show"/>
</field>
</field>
</record>
</odoo>

View File

@@ -14,38 +14,26 @@
<field name="arch" type="xml"> <field name="arch" type="xml">
<tree string="Invoices Analysis"> <tree string="Invoices Analysis">
<field name="move_id"/> <field name="move_id"/>
<field name="journal_id" optional="hide"/>
<field name="company_id" optional="hide" groups="base.group_multi_company"/>
<field name="invoice_date"/> <field name="invoice_date"/>
<field name="invoice_date_due"/> <field name="invoice_date_due"/>
<field name="move_type"/> <field name="move_type"/>
<field name="commercial_partner_id"/> <field name="commercial_partner_id"/>
<field name="partner_id" optional="hide"/>
<field name="country_id" optional="hide"/>
<field name="industry_id" optional="hide"/>
<field name="invoice_user_id"/> <field name="invoice_user_id"/>
<field name="fiscal_position_id" optional="hide"/>
<field name="product_id"/> <field name="product_id"/>
<field name="product_categ_id" optional="hide"/>
<field name="account_id" optional="hide"/>
<field name="analytic_account_id" optional="hide" groups="analytic.group_analytic_accounting"/>
<field name="quantity" sum="1"/> <field name="quantity" sum="1"/>
<field name="product_uom_id" groups="uom.group_uom"/> <field name="product_uom_id" groups="uom.group_uom"/>
<field name="price_subtotal" sum="1"/> <field name="price_subtotal" sum="1"/>
<field name="state"/> <field name="state"/>
<field name="payment_state" optional="hide"/>
</tree> </tree>
</field> </field>
</record> </record>
<record id="account.action_account_invoice_report_all_supp" model="ir.actions.act_window"> <record id="account.action_account_invoice_report_all_supp" model="ir.actions.act_window">
<field name="context">{'search_default_current': 1, 'search_default_supplier': 1, 'group_by': ['invoice_date']}</field> <!-- Remove group_by_no_leaf, which breaks tree view --> <field name="context">{'search_default_current': 1, 'search_default_supplier': 1, 'group_by': ['invoice_date']}</field> <!-- Remove group_by_no_leaf, which breaks tree view -->
<field name="view_mode">pivot,graph</field>
</record> </record>
<record id="account.action_account_invoice_report_all" model="ir.actions.act_window"> <record id="account.action_account_invoice_report_all" model="ir.actions.act_window">
<field name="context">{'search_default_current': 1, 'search_default_customer': 1, 'group_by': ['invoice_date']}</field> <!-- Remove group_by_no_leaf, which breaks tree view --> <field name="context">{'search_default_current': 1, 'search_default_customer': 1, 'group_by': ['invoice_date']}</field> <!-- Remove group_by_no_leaf, which breaks tree view -->
<field name="view_mode">pivot,graph</field>
</record> </record>
<record id="view_account_invoice_report_pivot" model="ir.ui.view"> <record id="view_account_invoice_report_pivot" model="ir.ui.view">

View File

@@ -14,17 +14,6 @@
<field name="arch" type="xml"> <field name="arch" type="xml">
<field name="bank_statements_source" position="after"> <field name="bank_statements_source" position="after">
<field name="hide_bank_statement_balance" groups="account.group_account_readonly"/> <field name="hide_bank_statement_balance" groups="account.group_account_readonly"/>
<field name="account_type_current_liabilities_id" invisible="1"/>
<field name="account_type_current_assets_id" invisible="1"/>
</field>
<field name="suspense_account_id" position="attributes">
<attribute name="context">{'default_user_type_id': account_type_current_liabilities_id, 'default_reconcile': True}</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>
</field> </field>
</record> </record>

View File

@@ -18,20 +18,8 @@
<field name="invoice_incoterm_id" position="attributes"> <field name="invoice_incoterm_id" position="attributes">
<attribute name="widget">selection</attribute> <attribute name="widget">selection</attribute>
</field> </field>
<button name="action_register_payment" 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>
<button name="preview_invoice" position="attributes">
<attribute name="attrs">{'invisible': 1}</attribute>
</button>
<!-- move sent field and make it visible --> <!-- move sent field and make it visible -->
<field name="is_move_sent" position="replace"/> <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="invoice_origin" position="after">
<field name="is_move_sent" attrs="{'invisible': [('move_type', 'not in', ('out_invoice', 'out_refund'))]}"/> <field name="is_move_sent" attrs="{'invisible': [('move_type', 'not in', ('out_invoice', 'out_refund'))]}"/>
</field> </field>
@@ -88,11 +76,10 @@
<field name="debit" filter_domain="['|', ('debit', '=', self), ('credit', '=', self)]" string="Debit or Credit"/> <field name="debit" filter_domain="['|', ('debit', '=', self), ('credit', '=', self)]" string="Debit or Credit"/>
</field> </field>
<filter name="unreconciled" position="before"> <filter name="unreconciled" position="before">
<filter name="reconciled" string="Fully Reconciled" domain="[('reconciled', '=', True)]"/> <filter name="reconciled" string="Fully Reconciled" domain="[('full_reconcile_id', '!=', False)]"/>
</filter> </filter>
<filter name="unreconciled" position="attributes"> <filter name="unreconciled" position="attributes">
<attribute name="string">Unreconciled or Partially Reconciled</attribute> <attribute name="string">Unreconciled or Partially Reconciled</attribute>
<attribute name="domain">[('reconciled', '=', False), ('balance', '!=', 0), ('account_id.reconcile', '=', True)]</attribute>
</filter> </filter>
<!-- <!--
<field name="name" position="attributes"> <field name="name" position="attributes">

View File

@@ -27,7 +27,7 @@ Here, we set all those fields on account.group_account_invoice
</field> </field>
<field name="list_price" position="replace"> <field name="list_price" position="replace">
<div name="list_price"> <div name="list_price">
<field name="list_price" widget='monetary' options="{'currency_field': 'currency_id', 'field_digits': True}" class="oe_inline"/> <field name="list_price" widget='monetary' options="{'currency_field': 'currency_id'}" class="oe_inline"/>
<label for="sale_price_type" string=" "/> <label for="sale_price_type" string=" "/>
<field name="sale_price_type"/> <field name="sale_price_type"/>
</div> </div>

View File

@@ -1,27 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2021 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_company_form" model="ir.ui.view">
<field name="name">account_usability.res.company.form</field>
<field name="model">res.company</field>
<field name="inherit_id" ref="base.view_company_form"/>
<field name="arch" type="xml">
<notebook position="inside">
<page string="Legal Terms" name="legal_terms">
<group string="Invoice Legal Terms" name="static_invoice_terms">
<field name="static_invoice_terms" nolabel="1"/>
</group>
</page>
</notebook>
</field>
</record>
</odoo>

View File

@@ -16,9 +16,6 @@
<field name="property_account_position_id" position="attributes"> <field name="property_account_position_id" position="attributes">
<attribute name="widget">selection</attribute> <attribute name="widget">selection</attribute>
</field> </field>
<xpath expr="//field[@name='bank_ids']/tree/field[@name='acc_number']" position="after">
<field name="acc_type"/>
</xpath>
</field> </field>
</record> </record>

View File

@@ -1,23 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2021 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 +0,0 @@
from . import models

View File

@@ -1,62 +0,0 @@
# Copyright 2020-2021 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': 'Base Dynamic List',
'version': '14.0.1.0.0',
'category': 'Tools',
'license': 'AGPL-3',
'summary': 'Dynamic lists',
'description': """
Base Dynamic List
=================
Very often during an Odoo implementation, we need to add selection fields on a native objet, and we don't want to have a hard-coded selection list (fields.Selection), but a selection list that can be changed by users (Many2one field). For that, the developper needs to add a new object (with just a 'name' and 'sequence' field) with a form/tree view. The goal of this module is to speed-up this process by defining a dynamic list object that already has all the required views.
This module provides several ready-to-go objects:
* simple list : fields *name*, *sequence* and *active*
* translatable list : fields *name* with translate=True, *sequence* and *active*
* code list : fields *code* (unique), *name*, *sequence* and *active*
* translatable code list : fields *code* (unique), *name* with translate=True, *sequence* and *active*
These objects are readable by the employee group. The system group has full rights on it.
To use it, you need to do 2 or 3 things :
1) Add an entry in the domain field and the object you selected:
domain = fields.Selection(selection_add=[('risk.type', "Risk Type")], ondelete={"risk.type": "cascade"})
2) Add the many2one field on your object:
risk_type_id = fields.Many2one(
'dynamic.list', string="Risk Type",
ondelete='restrict', domain=[('domain', '=', 'risk.type')])
3) Optionally, you can add a dedicated action and a menu entry (otherwize, you can use the generic menu entry under *Settings > Technical > Dynamic Lists*:
<record id="dynamic_list_risk_type_action" model="ir.actions.act_window">
<field name="name">Risk Type</field>
<field name="res_model">dynamic.list</field>
<field name="view_mode">tree,form</field>
<field name="domain">[('domain', '=', 'risk.type')]</field>
<field name="context">{'default_domain': 'risk.type'}</field>
</record>
<menuitem id="dynamic_list_risk_type_menu" action="dynamic_list_risk_type_action"
parent="parent_menu_xmlid"/>
Limitation: when you want to have different access rights on these lists depending on the source object, you should prefer to use dedicated objects.
""",
'author': 'Akretion',
'website': 'http://www.akretion.com',
'depends': ['base'],
'data': [
'security/ir.model.access.csv',
'views/dynamic_list.xml',
],
'installable': True,
}

View File

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

View File

@@ -1,115 +0,0 @@
# Copyright 2020-2021 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 DynamicList(models.Model):
_name = 'dynamic.list'
_description = 'Dynamic List (non translatable)'
_order = 'sequence, id'
name = fields.Char(required=True)
sequence = fields.Integer(default=10)
active = fields.Boolean(default=True)
domain = fields.Selection([], string='Domain', required=True, index=True)
_sql_constraint = [(
'domain_name_uniq',
'unique(domain, name)',
'This entry already exists!'
)]
class DynamicListTranslate(models.Model):
_name = 'dynamic.list.translate'
_description = 'Translatable Dynamic List'
_order = 'sequence, id'
name = fields.Char(translate=True, required=True)
sequence = fields.Integer(default=10)
active = fields.Boolean(default=True)
domain = fields.Selection([], string='Domain', required=True, index=True)
_sql_constraint = [(
'domain_name_uniq',
'unique(domain, name)',
'This entry already exists!'
)]
class DynamicListCode(models.Model):
_name = 'dynamic.list.code'
_description = 'Dynamic list with code'
_order = 'sequence, id'
code = fields.Char(required=True)
name = fields.Char(translate=True, required=True)
sequence = fields.Integer(default=10)
active = fields.Boolean(default=True)
domain = fields.Selection([], string='Domain', required=True, index=True)
_sql_constraint = [(
'domain_code_uniq',
'unique(domain, code)',
'This 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=80):
if args is None:
args = []
if name and operator == 'ilike':
recs = self.search(
[('code', '=', name)] + args, limit=limit)
if recs:
return recs.name_get()
return super().name_search(
name=name, args=args, operator=operator, limit=limit)
class DynamicListCodeTranslate(models.Model):
_name = 'dynamic.list.code.translate'
_description = 'Translatable dynamic list with code'
_order = 'sequence, id'
code = fields.Char(required=True)
name = fields.Char(translate=True, required=True)
sequence = fields.Integer(default=10)
active = fields.Boolean(default=True)
domain = fields.Selection([], string='Domain', required=True, index=True)
_sql_constraint = [(
'domain_code_uniq',
'unique(domain, code)',
'This 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=80):
if args is None:
args = []
if name and operator == 'ilike':
recs = self.search(
[('code', '=', 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,9 +0,0 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_dynamic_list_read,Read access on dynamic.list to employees,model_dynamic_list,base.group_user,1,0,0,0
access_dynamic_list_full,Full access to dynamic.list to System group,model_dynamic_list,base.group_system,1,1,1,1
access_dynamic_list_translate_read,Read access on dynamic.list.translate to employees,model_dynamic_list_translate,base.group_user,1,0,0,0
access_dynamic_list_translate_full,Full access to dynamic.list.translate to System group,model_dynamic_list_translate,base.group_system,1,1,1,1
access_dynamic_list_code_read,Read access on dynamic.list.code to employees,model_dynamic_list_code,base.group_user,1,0,0,0
access_dynamic_list_code_full,Full access to dynamic.list.code to System group,model_dynamic_list_code,base.group_system,1,1,1,1
access_dynamic_list_code_translate_read,Read access on dynamic.list.code.translate to employees,model_dynamic_list_code_translate,base.group_user,1,0,0,0
access_dynamic_list_code_translate_full,Full access to dynamic.list.code.translate to System group,model_dynamic_list_code_translate,base.group_system,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_dynamic_list_read Read access on dynamic.list to employees model_dynamic_list base.group_user 1 0 0 0
3 access_dynamic_list_full Full access to dynamic.list to System group model_dynamic_list base.group_system 1 1 1 1
4 access_dynamic_list_translate_read Read access on dynamic.list.translate to employees model_dynamic_list_translate base.group_user 1 0 0 0
5 access_dynamic_list_translate_full Full access to dynamic.list.translate to System group model_dynamic_list_translate base.group_system 1 1 1 1
6 access_dynamic_list_code_read Read access on dynamic.list.code to employees model_dynamic_list_code base.group_user 1 0 0 0
7 access_dynamic_list_code_full Full access to dynamic.list.code to System group model_dynamic_list_code base.group_system 1 1 1 1
8 access_dynamic_list_code_translate_read Read access on dynamic.list.code.translate to employees model_dynamic_list_code_translate base.group_user 1 0 0 0
9 access_dynamic_list_code_translate_full Full access to dynamic.list.code.translate to System group model_dynamic_list_code_translate base.group_system 1 1 1 1

View File

@@ -1,220 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2020-2021 Akretion France (http://www.akretion.com/)
@author: Alexis de Lattre <alexis.delattre@akretion.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
-->
<odoo>
<menuitem id="dynamic_list_root_menu" name="Dynamic Lists" parent="base.menu_custom" sequence="100"/>
<record id="dynamic_list_form" model="ir.ui.view">
<field name="model">dynamic.list</field>
<field name="arch" type="xml">
<form>
<sheet>
<widget name="web_ribbon" title="Archived" bg_color="bg-danger" attrs="{'invisible': [('active', '=', True)]}"/>
<group name="main">
<field name="name"/>
<field name="domain" invisible="not context.get('dynamic_list_main_view')"/>
<field name="active" invisible="1"/>
</group>
</sheet>
</form>
</field>
</record>
<record id="dynamic_list_tree" model="ir.ui.view">
<field name="model">dynamic.list</field>
<field name="arch" type="xml">
<tree>
<field name="sequence" widget="handle"/>
<field name="name"/>
<field name="domain" invisible="not context.get('dynamic_list_main_view')"/>
</tree>
</field>
</record>
<record id="dynamic_list_search" model="ir.ui.view">
<field name="model">dynamic.list</field>
<field name="arch" type="xml">
<search>
<field name="name"/>
<separator/>
<filter string="Archived" name="inactive" domain="[('active', '=', False)]"/>
<group string="Group By" name="groupby">
<filter name="domain_groupby" string="Domain" context="{'group_by': 'domain'}"/>
</group>
</search>
</field>
</record>
<record id="dynamic_list_action" model="ir.actions.act_window">
<field name="name">Simple List</field>
<field name="res_model">dynamic.list</field>
<field name="view_mode">tree,form</field>
<field name="context">{'dynamic_list_main_view': True, 'search_default_domain_groupby': True}</field>
</record>
<menuitem id="dynamic_list_menu" action="dynamic_list_action" parent="dynamic_list_root_menu" sequence="10"/>
<record id="dynamic_list_translate_form" model="ir.ui.view">
<field name="model">dynamic.list.translate</field>
<field name="arch" type="xml">
<form>
<sheet>
<widget name="web_ribbon" title="Archived" bg_color="bg-danger" attrs="{'invisible': [('active', '=', True)]}"/>
<group name="main">
<field name="name"/>
<field name="domain" invisible="not context.get('dynamic_list_translate_main_view')"/>
<field name="active" invisible="1"/>
</group>
</sheet>
</form>
</field>
</record>
<record id="dynamic_list_translate_tree" model="ir.ui.view">
<field name="model">dynamic.list.translate</field>
<field name="arch" type="xml">
<tree>
<field name="sequence" widget="handle"/>
<field name="name"/>
<field name="domain" invisible="not context.get('dynamic_list_translate_main_view')"/>
</tree>
</field>
</record>
<record id="dynamic_list_translate_search" model="ir.ui.view">
<field name="model">dynamic.list.translate</field>
<field name="arch" type="xml">
<search>
<field name="name"/>
<separator/>
<filter string="Archived" name="inactive" domain="[('active', '=', False)]"/>
<group string="Group By" name="groupby">
<filter name="domain_groupby" string="Domain" context="{'group_by': 'domain'}"/>
</group>
</search>
</field>
</record>
<record id="dynamic_list_translate_action" model="ir.actions.act_window">
<field name="name">Translatable Simple List</field>
<field name="res_model">dynamic.list.translate</field>
<field name="view_mode">tree,form</field>
<field name="context">{'dynamic_list_translate_main_view': True, 'search_default_domain_groupby': True}</field>
</record>
<menuitem id="dynamic_list_translate_menu" action="dynamic_list_translate_action" parent="dynamic_list_root_menu" sequence="20"/>
<record id="dynamic_list_code_form" model="ir.ui.view">
<field name="model">dynamic.list.code</field>
<field name="arch" type="xml">
<form>
<sheet>
<widget name="web_ribbon" title="Archived" bg_color="bg-danger" attrs="{'invisible': [('active', '=', True)]}"/>
<group name="main">
<field name="code"/>
<field name="name"/>
<field name="domain" invisible="not context.get('dynamic_list_code_main_view')"/>
<field name="active" invisible="1"/>
</group>
</sheet>
</form>
</field>
</record>
<record id="dynamic_list_code_tree" model="ir.ui.view">
<field name="model">dynamic.list.code</field>
<field name="arch" type="xml">
<tree>
<field name="sequence" widget="handle"/>
<field name="code"/>
<field name="name"/>
<field name="domain" invisible="not context.get('dynamic_list_code_main_view')"/>
</tree>
</field>
</record>
<record id="dynamic_list_code_search" model="ir.ui.view">
<field name="model">dynamic.list.code</field>
<field name="arch" type="xml">
<search>
<field name="name" string="Name or Code" filter_domain="['|', ('name', 'ilike', self), ('code', 'ilike', self)]"/>
<separator/>
<filter string="Archived" name="inactive" domain="[('active', '=', False)]"/>
<field name="code"/>
<group string="Group By" name="groupby">
<filter name="domain_groupby" string="Domain" context="{'group_by': 'domain'}"/>
</group>
</search>
</field>
</record>
<record id="dynamic_list_code_action" model="ir.actions.act_window">
<field name="name">Code List</field>
<field name="res_model">dynamic.list.code</field>
<field name="view_mode">tree,form</field>
<field name="context">{'dynamic_list_code_main_view': True, 'search_default_domain_groupby': True}</field>
</record>
<menuitem id="dynamic_list_code_menu" action="dynamic_list_code_action" parent="dynamic_list_root_menu" sequence="30"/>
<record id="dynamic_list_code_translate_form" model="ir.ui.view">
<field name="model">dynamic.list.code.translate</field>
<field name="arch" type="xml">
<form>
<sheet>
<widget name="web_ribbon" title="Archived" bg_color="bg-danger" attrs="{'invisible': [('active', '=', True)]}"/>
<group name="main">
<field name="code"/>
<field name="name"/>
<field name="domain" invisible="not context.get('dynamic_list_code_translate_main_view')"/>
<field name="active" invisible="1"/>
</group>
</sheet>
</form>
</field>
</record>
<record id="dynamic_list_code_translate_tree" model="ir.ui.view">
<field name="model">dynamic.list.code.translate</field>
<field name="arch" type="xml">
<tree>
<field name="sequence" widget="handle"/>
<field name="code"/>
<field name="name"/>
<field name="domain" invisible="not context.get('dynamic_list_code_translate_main_view')"/>
</tree>
</field>
</record>
<record id="dynamic_list_code_translate_search" model="ir.ui.view">
<field name="model">dynamic.list.code.translate</field>
<field name="arch" type="xml">
<search>
<field name="name" string="Name or Code" filter_domain="['|', ('name', 'ilike', self), ('code', 'ilike', self)]"/>
<field name="code"/>
<separator/>
<filter string="Archived" name="inactive" domain="[('active', '=', False)]"/>
<group string="Group By" name="groupby">
<filter name="domain_groupby" string="Domain" context="{'group_by': 'domain'}"/>
</group>
</search>
</field>
</record>
<record id="dynamic_list_code_translate_action" model="ir.actions.act_window">
<field name="name">Translatable Code List</field>
<field name="res_model">dynamic.list.code.translate</field>
<field name="view_mode">tree,form</field>
<field name="context">{'dynamic_list_code_translate_main_view': True, 'search_default_domain_groupby': True}</field>
</record>
<menuitem id="dynamic_list_code_translate_menu" action="dynamic_list_code_translate_action" parent="dynamic_list_root_menu" sequence="40"/>
</odoo>

View File

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

View File

@@ -1,21 +0,0 @@
# Copyright 2017-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).
{
'name': 'Mail Sender Bcc',
'version': '14.0.1.0.0',
'category': 'Mail',
'license': 'AGPL-3',
'summary': "Always send a copy of the mail to the sender",
'description': """
Mail Sender Bcc
===============
With this module, when Odoo sends an outgoing email, it adds the sender as Bcc (blind copy) of the email.
""",
'author': 'Akretion',
'website': 'https://github.com/akretion/odoo-usability',
'depends': ['base'],
'installable': True,
}

View File

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

View File

@@ -1,27 +0,0 @@
# Copyright 2017-2022 Akretion France
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import models
class IrMailServer(models.Model):
_inherit = 'ir.mail_server'
def build_email(
self, email_from, email_to, subject, body, email_cc=None,
email_bcc=None, reply_to=False, attachments=None,
message_id=None, references=None, object_id=False,
subtype='plain', headers=None,
body_alternative=None, subtype_alternative='plain'):
if email_from:
if email_bcc is None:
email_bcc = [email_from]
elif isinstance(email_bcc, list) and email_from not in email_bcc:
email_bcc.append(email_from)
return super().build_email(
email_from, email_to, subject, body, email_cc=email_cc,
email_bcc=email_bcc, reply_to=reply_to, attachments=attachments,
message_id=message_id, references=references, object_id=object_id,
subtype=subtype, headers=headers,
body_alternative=body_alternative, subtype_alternative=subtype_alternative)

View File

@@ -4,11 +4,11 @@
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Odoo Server 14.0\n" "Project-Id-Version: Odoo Server 10.0\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-10-29 21:12+0000\n" "POT-Creation-Date: 2020-01-27 18:03+0000\n"
"PO-Revision-Date: 2021-10-29 21:12+0000\n" "PO-Revision-Date: 2020-01-27 18:03+0000\n"
"Last-Translator: \n" "Last-Translator: <>\n"
"Language-Team: \n" "Language-Team: \n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
@@ -16,120 +16,92 @@ msgstr ""
"Plural-Forms: \n" "Plural-Forms: \n"
#. module: base_partner_one2many_phone #. module: base_partner_one2many_phone
#: model:ir.model,name:base_partner_one2many_phone.model_res_partner #: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner_phone_create_uid
msgid "Contact"
msgstr ""
#. module: base_partner_one2many_phone
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner_phone__create_uid
msgid "Created by" msgid "Created by"
msgstr "" msgstr ""
#. module: base_partner_one2many_phone #. module: base_partner_one2many_phone
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner_phone__create_date #: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner_phone_create_date
msgid "Created on" msgid "Created on"
msgstr "" msgstr ""
#. module: base_partner_one2many_phone #. module: base_partner_one2many_phone
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner__display_name #: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner_phone_display_name
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner_phone__display_name
msgid "Display Name" msgid "Display Name"
msgstr "" msgstr ""
#. module: base_partner_one2many_phone #. module: base_partner_one2many_phone
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner_phone__email #: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner_phone_email
msgid "E-Mail" msgid "E-Mail"
msgstr "" msgstr ""
#. module: base_partner_one2many_phone #. module: base_partner_one2many_phone
#: code:addons/base_partner_one2many_phone/partner_phone.py:0 #: code:addons/base_partner_one2many_phone/partner_phone.py:61
#, python-format #, python-format
msgid "" msgid "E-mail field must be empty when type is Primary/Secondary Phone, Primary/Secondary Mobile or Primary/Secondary Fax."
"E-mail field must be empty when type is Primary/Secondary Phone, "
"Primary/Secondary Mobile or Primary/Secondary Fax."
msgstr "" msgstr ""
#. module: base_partner_one2many_phone #. module: base_partner_one2many_phone
#: code:addons/base_partner_one2many_phone/partner_phone.py:0 #: code:addons/base_partner_one2many_phone/partner_phone.py:51
#, python-format #, python-format
msgid "" msgid "E-mail field must have a value when type is Primary E-mail or Secondary E-mail."
"E-mail field must have a value when type is Primary E-mail or Secondary "
"E-mail."
msgstr "" msgstr ""
#. module: base_partner_one2many_phone #. module: base_partner_one2many_phone
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner__email #: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner_phone_id
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_users__email
msgid "Email"
msgstr ""
#. module: base_partner_one2many_phone
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner__id
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner_phone__id
msgid "ID" msgid "ID"
msgstr "" msgstr ""
#. module: base_partner_one2many_phone #. module: base_partner_one2many_phone
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner____last_update #: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner_phone___last_update
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner_phone____last_update
msgid "Last Modified on" msgid "Last Modified on"
msgstr "" msgstr ""
#. module: base_partner_one2many_phone #. module: base_partner_one2many_phone
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner_phone__write_uid #: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner_phone_write_uid
msgid "Last Updated by" msgid "Last Updated by"
msgstr "" msgstr ""
#. module: base_partner_one2many_phone #. module: base_partner_one2many_phone
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner_phone__write_date #: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner_phone_write_date
msgid "Last Updated on" msgid "Last Updated on"
msgstr "" msgstr ""
#. module: base_partner_one2many_phone #. module: base_partner_one2many_phone
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner__mobile #: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner_phone_note
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_users__mobile
msgid "Mobile"
msgstr ""
#. module: base_partner_one2many_phone
#: model:ir.model,name:base_partner_one2many_phone.model_res_partner_phone
msgid "Multiple emails and phones for partners"
msgstr ""
#. module: base_partner_one2many_phone
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner_phone__note
msgid "Note" msgid "Note"
msgstr "" msgstr ""
#. module: base_partner_one2many_phone #. module: base_partner_one2many_phone
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner__phone #: model:ir.model,name:base_partner_one2many_phone.model_res_partner
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner_phone__phone msgid "Partner"
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_users__phone msgstr ""
#. module: base_partner_one2many_phone
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner_phone_phone
msgid "Phone" msgid "Phone"
msgstr "" msgstr ""
#. module: base_partner_one2many_phone #. module: base_partner_one2many_phone
#: model_terms:ir.ui.view,arch_db:base_partner_one2many_phone.res_partner_phone_form #: code:addons/base_partner_one2many_phone/partner_phone.py:54
msgid "Phone and E-mail"
msgstr ""
#. module: base_partner_one2many_phone
#: code:addons/base_partner_one2many_phone/partner_phone.py:0
#, python-format #, python-format
msgid "" msgid "Phone field must be empty when type is Primary E-mail or Secondary E-mail."
"Phone field must be empty when type is Primary E-mail or Secondary E-mail."
msgstr "" msgstr ""
#. module: base_partner_one2many_phone #. module: base_partner_one2many_phone
#: code:addons/base_partner_one2many_phone/partner_phone.py:0 #: code:addons/base_partner_one2many_phone/partner_phone.py:58
#, python-format #, python-format
msgid "" msgid "Phone field must have a value when type is Primary/Secondary Phone, Primary/Secondary Mobile or Primary/Secondary Fax."
"Phone field must have a value when type is Primary/Secondary Phone, "
"Primary/Secondary Mobile or Primary/Secondary Fax."
msgstr "" msgstr ""
#. module: base_partner_one2many_phone #. module: base_partner_one2many_phone
#: model_terms:ir.ui.view,arch_db:base_partner_one2many_phone.res_partner_phone_tree #: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner_phone_ids
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_users_phone_ids
msgid "Phones"
msgstr ""
#. module: base_partner_one2many_phone
#: model:ir.ui.view,arch_db:base_partner_one2many_phone.res_partner_phone_tree
msgid "Phones and E-mail" msgid "Phones and E-mail"
msgstr "" msgstr ""
@@ -140,63 +112,63 @@ msgid "Phones/E-mails"
msgstr "" msgstr ""
#. module: base_partner_one2many_phone #. module: base_partner_one2many_phone
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner__phone_ids #: selection:res.partner.phone,type:0
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_users__phone_ids
msgid "Phones/Emails"
msgstr ""
#. module: base_partner_one2many_phone
#: model:ir.model.fields.selection,name:base_partner_one2many_phone.selection__res_partner_phone__type__1_email_primary
msgid "Primary E-mail" msgid "Primary E-mail"
msgstr "" msgstr ""
#. module: base_partner_one2many_phone #. module: base_partner_one2many_phone
#: model:ir.model.fields.selection,name:base_partner_one2many_phone.selection__res_partner_phone__type__7_fax_primary #: selection:res.partner.phone,type:0
msgid "Primary Fax" msgid "Primary Fax"
msgstr "" msgstr ""
#. module: base_partner_one2many_phone #. module: base_partner_one2many_phone
#: model:ir.model.fields.selection,name:base_partner_one2many_phone.selection__res_partner_phone__type__5_mobile_primary #: selection:res.partner.phone,type:0
msgid "Primary Mobile" msgid "Primary Mobile"
msgstr "" msgstr ""
#. module: base_partner_one2many_phone #. module: base_partner_one2many_phone
#: model:ir.model.fields.selection,name:base_partner_one2many_phone.selection__res_partner_phone__type__3_phone_primary #: selection:res.partner.phone,type:0
msgid "Primary Phone" msgid "Primary Phone"
msgstr "" msgstr ""
#. module: base_partner_one2many_phone #. module: base_partner_one2many_phone
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner_phone__partner_id #: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner_phone_partner_id
msgid "Related Partner" msgid "Related Partner"
msgstr "" msgstr ""
#. module: base_partner_one2many_phone #. module: base_partner_one2many_phone
#: model_terms:ir.ui.view,arch_db:base_partner_one2many_phone.res_partner_phone_search #: model:ir.ui.view,arch_db:base_partner_one2many_phone.res_partner_phone_search
msgid "Search Phones/E-mail" msgid "Search Phones/E-mail"
msgstr "" msgstr ""
#. module: base_partner_one2many_phone #. module: base_partner_one2many_phone
#: model:ir.model.fields.selection,name:base_partner_one2many_phone.selection__res_partner_phone__type__2_email_secondary #: selection:res.partner.phone,type:0
msgid "Secondary E-mail" msgid "Secondary E-mail"
msgstr "" msgstr ""
#. module: base_partner_one2many_phone #. module: base_partner_one2many_phone
#: model:ir.model.fields.selection,name:base_partner_one2many_phone.selection__res_partner_phone__type__8_fax_secondary #: selection:res.partner.phone,type:0
msgid "Secondary Fax" msgid "Secondary Fax"
msgstr "" msgstr ""
#. module: base_partner_one2many_phone #. module: base_partner_one2many_phone
#: model:ir.model.fields.selection,name:base_partner_one2many_phone.selection__res_partner_phone__type__6_mobile_secondary #: selection:res.partner.phone,type:0
msgid "Secondary Mobile" msgid "Secondary Mobile"
msgstr "" msgstr ""
#. module: base_partner_one2many_phone #. module: base_partner_one2many_phone
#: model:ir.model.fields.selection,name:base_partner_one2many_phone.selection__res_partner_phone__type__4_phone_secondary #: selection:res.partner.phone,type:0
msgid "Secondary Phone" msgid "Secondary Phone"
msgstr "" msgstr ""
#. module: base_partner_one2many_phone #. module: base_partner_one2many_phone
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner_phone__type #: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner_phone_type
#: model_terms:ir.ui.view,arch_db:base_partner_one2many_phone.res_partner_phone_search #: model:ir.ui.view,arch_db:base_partner_one2many_phone.res_partner_phone_search
msgid "Type" msgid "Type"
msgstr "" msgstr ""
#. module: base_partner_one2many_phone
#: model:ir.model,name:base_partner_one2many_phone.model_res_partner_phone
msgid "res.partner.phone"
msgstr ""

View File

@@ -4,11 +4,11 @@
# #
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Odoo Server 14.0\n" "Project-Id-Version: Odoo Server 10.0\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-10-29 21:12+0000\n" "POT-Creation-Date: 2020-01-27 17:56+0000\n"
"PO-Revision-Date: 2021-10-29 21:12+0000\n" "PO-Revision-Date: 2020-01-27 17:56+0000\n"
"Last-Translator: \n" "Last-Translator: <>\n"
"Language-Team: \n" "Language-Team: \n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
@@ -16,187 +16,159 @@ msgstr ""
"Plural-Forms: \n" "Plural-Forms: \n"
#. module: base_partner_one2many_phone #. module: base_partner_one2many_phone
#: model:ir.model,name:base_partner_one2many_phone.model_res_partner #: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner_phone_create_uid
msgid "Contact"
msgstr "Contact"
#. module: base_partner_one2many_phone
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner_phone__create_uid
msgid "Created by" msgid "Created by"
msgstr "Créé par" msgstr "Créé par"
#. module: base_partner_one2many_phone #. module: base_partner_one2many_phone
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner_phone__create_date #: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner_phone_create_date
msgid "Created on" msgid "Created on"
msgstr "Créé le" msgstr "Créé le"
#. module: base_partner_one2many_phone #. module: base_partner_one2many_phone
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner__display_name #: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner_phone_display_name
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner_phone__display_name
msgid "Display Name" msgid "Display Name"
msgstr "Nom affiché" msgstr "Nom à afficher"
#. module: base_partner_one2many_phone #. module: base_partner_one2many_phone
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner_phone__email #: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner_phone_email
msgid "E-Mail" msgid "E-Mail"
msgstr "E-Mail" msgstr "Courriel"
#. module: base_partner_one2many_phone #. module: base_partner_one2many_phone
#: code:addons/base_partner_one2many_phone/partner_phone.py:0 #: code:addons/base_partner_one2many_phone/partner_phone.py:61
#, python-format #, python-format
msgid "" msgid "E-mail field must be empty when type is Primary/Secondary Phone, Primary/Secondary Mobile or Primary/Secondary Fax."
"E-mail field must be empty when type is Primary/Secondary Phone, " msgstr "Le champ courriel doit être vide quand le type est tél. primaire/secondaire, portable primaire/secondaire ou fax primaire/secondaire."
"Primary/Secondary Mobile or Primary/Secondary Fax."
msgstr "Le champ E-mail doit être vide quand le type est Tél. principal/secondaire, Portable principal/secondaire ou Fax principal/secondaire."
#. module: base_partner_one2many_phone #. module: base_partner_one2many_phone
#: code:addons/base_partner_one2many_phone/partner_phone.py:0 #: code:addons/base_partner_one2many_phone/partner_phone.py:51
#, python-format #, python-format
msgid "" msgid "E-mail field must have a value when type is Primary E-mail or Secondary E-mail."
"E-mail field must have a value when type is Primary E-mail or Secondary " msgstr "Le champ courriel doit être renseigné quand le type est courriel primaire ou courriel secondaire."
"E-mail."
msgstr "Le champ E-mail doit avoir une valeur quand le type est E-mail principal ou secondaire."
#. module: base_partner_one2many_phone #. module: base_partner_one2many_phone
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner__email #: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner_phone_id
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_users__email
msgid "Email"
msgstr "E-mail"
#. module: base_partner_one2many_phone
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner__id
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner_phone__id
msgid "ID" msgid "ID"
msgstr "" msgstr "ID"
#. module: base_partner_one2many_phone #. module: base_partner_one2many_phone
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner____last_update #: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner_phone___last_update
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner_phone____last_update
msgid "Last Modified on" msgid "Last Modified on"
msgstr "Dernière modification le" msgstr "Dernière modification le"
#. module: base_partner_one2many_phone #. module: base_partner_one2many_phone
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner_phone__write_uid #: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner_phone_write_uid
msgid "Last Updated by" msgid "Last Updated by"
msgstr "Dernière modification par" msgstr "Dernière mise à jour par"
#. module: base_partner_one2many_phone #. module: base_partner_one2many_phone
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner_phone__write_date #: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner_phone_write_date
msgid "Last Updated on" msgid "Last Updated on"
msgstr "Dernière modification le" msgstr "Dernière mise à jour le"
#. module: base_partner_one2many_phone #. module: base_partner_one2many_phone
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner__mobile #: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner_phone_note
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_users__mobile
msgid "Mobile"
msgstr "Portable"
#. module: base_partner_one2many_phone
#: model:ir.model,name:base_partner_one2many_phone.model_res_partner_phone
msgid "Multiple emails and phones for partners"
msgstr "Multiples e-mails et téléphones pour les partenaires"
#. module: base_partner_one2many_phone
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner_phone__note
msgid "Note" msgid "Note"
msgstr "Note" msgstr "Note"
#. module: base_partner_one2many_phone #. module: base_partner_one2many_phone
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner__phone #: model:ir.model,name:base_partner_one2many_phone.model_res_partner
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner_phone__phone msgid "Partner"
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_users__phone msgstr "Partenaire"
#. module: base_partner_one2many_phone
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner_phone_phone
msgid "Phone" msgid "Phone"
msgstr "Tél." msgstr "Téléphone"
#. module: base_partner_one2many_phone #. module: base_partner_one2many_phone
#: model_terms:ir.ui.view,arch_db:base_partner_one2many_phone.res_partner_phone_form #: code:addons/base_partner_one2many_phone/partner_phone.py:54
msgid "Phone and E-mail"
msgstr "Tél. et E-mail"
#. module: base_partner_one2many_phone
#: code:addons/base_partner_one2many_phone/partner_phone.py:0
#, python-format #, python-format
msgid "" msgid "Phone field must be empty when type is Primary E-mail or Secondary E-mail."
"Phone field must be empty when type is Primary E-mail or Secondary E-mail." msgstr "Le champ téléphone doit être vide quand le type est courriel primaire ou courriel secondaire."
msgstr "Le champ Tél. doit être vide quand le type est E-mail principal ou E-mail secondaire."
#. module: base_partner_one2many_phone #. module: base_partner_one2many_phone
#: code:addons/base_partner_one2many_phone/partner_phone.py:0 #: code:addons/base_partner_one2many_phone/partner_phone.py:58
#, python-format #, python-format
msgid "" msgid "Phone field must have a value when type is Primary/Secondary Phone, Primary/Secondary Mobile or Primary/Secondary Fax."
"Phone field must have a value when type is Primary/Secondary Phone, " msgstr "Le champ téléphone doit être renseigné quand le type est tél. primaire/secondaire, portable primaire/secondaire ou fax primaire/secondaire.."
"Primary/Secondary Mobile or Primary/Secondary Fax."
msgstr "Le champ Tél. doit avoir une valeur quand le type est Tél. principal/secondaire, Portable principal/secondaire ou Fax principal/secondaire."
#. module: base_partner_one2many_phone #. module: base_partner_one2many_phone
#: model_terms:ir.ui.view,arch_db:base_partner_one2many_phone.res_partner_phone_tree #: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner_phone_ids
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_users_phone_ids
msgid "Phones"
msgstr "Téléphones"
#. module: base_partner_one2many_phone
#: model:ir.ui.view,arch_db:base_partner_one2many_phone.res_partner_phone_tree
msgid "Phones and E-mail" msgid "Phones and E-mail"
msgstr "Téls et E-mail" msgstr "Téls et courriels"
#. module: base_partner_one2many_phone #. module: base_partner_one2many_phone
#: model:ir.actions.act_window,name:base_partner_one2many_phone.res_partner_phone_action #: model:ir.actions.act_window,name:base_partner_one2many_phone.res_partner_phone_action
#: model:ir.ui.menu,name:base_partner_one2many_phone.res_partner_phone_menu #: model:ir.ui.menu,name:base_partner_one2many_phone.res_partner_phone_menu
msgid "Phones/E-mails" msgid "Phones/E-mails"
msgstr "Téls/E-mails" msgstr "Téls/Courriels"
#. module: base_partner_one2many_phone #. module: base_partner_one2many_phone
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner__phone_ids #: selection:res.partner.phone,type:0
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_users__phone_ids
msgid "Phones/Emails"
msgstr "Téls/E-mails"
#. module: base_partner_one2many_phone
#: model:ir.model.fields.selection,name:base_partner_one2many_phone.selection__res_partner_phone__type__1_email_primary
msgid "Primary E-mail" msgid "Primary E-mail"
msgstr "E-mail principal" msgstr "Courriel principal"
#. module: base_partner_one2many_phone #. module: base_partner_one2many_phone
#: model:ir.model.fields.selection,name:base_partner_one2many_phone.selection__res_partner_phone__type__7_fax_primary #: selection:res.partner.phone,type:0
msgid "Primary Fax" msgid "Primary Fax"
msgstr "Fax principal" msgstr "Fax principal"
#. module: base_partner_one2many_phone #. module: base_partner_one2many_phone
#: model:ir.model.fields.selection,name:base_partner_one2many_phone.selection__res_partner_phone__type__5_mobile_primary #: selection:res.partner.phone,type:0
msgid "Primary Mobile" msgid "Primary Mobile"
msgstr "Portable principal" msgstr "Portable principal"
#. module: base_partner_one2many_phone #. module: base_partner_one2many_phone
#: model:ir.model.fields.selection,name:base_partner_one2many_phone.selection__res_partner_phone__type__3_phone_primary #: selection:res.partner.phone,type:0
msgid "Primary Phone" msgid "Primary Phone"
msgstr "Tél. principal" msgstr "Tél principal"
#. module: base_partner_one2many_phone #. module: base_partner_one2many_phone
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner_phone__partner_id #: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner_phone_partner_id
msgid "Related Partner" msgid "Related Partner"
msgstr "Partenaire associé" msgstr "Partenaire associé"
#. module: base_partner_one2many_phone #. module: base_partner_one2many_phone
#: model_terms:ir.ui.view,arch_db:base_partner_one2many_phone.res_partner_phone_search #: model:ir.ui.view,arch_db:base_partner_one2many_phone.res_partner_phone_search
msgid "Search Phones/E-mail" msgid "Search Phones/E-mail"
msgstr "" msgstr "Search Phones/E-mail"
#. module: base_partner_one2many_phone #. module: base_partner_one2many_phone
#: model:ir.model.fields.selection,name:base_partner_one2many_phone.selection__res_partner_phone__type__2_email_secondary #: selection:res.partner.phone,type:0
msgid "Secondary E-mail" msgid "Secondary E-mail"
msgstr "E-mail secondaire" msgstr "Courriel secondaire"
#. module: base_partner_one2many_phone #. module: base_partner_one2many_phone
#: model:ir.model.fields.selection,name:base_partner_one2many_phone.selection__res_partner_phone__type__8_fax_secondary #: selection:res.partner.phone,type:0
msgid "Secondary Fax" msgid "Secondary Fax"
msgstr "Fax secondaire" msgstr "Fax secondaire"
#. module: base_partner_one2many_phone #. module: base_partner_one2many_phone
#: model:ir.model.fields.selection,name:base_partner_one2many_phone.selection__res_partner_phone__type__6_mobile_secondary #: selection:res.partner.phone,type:0
msgid "Secondary Mobile" msgid "Secondary Mobile"
msgstr "Portable secondaire" msgstr "Portable secondaire"
#. module: base_partner_one2many_phone #. module: base_partner_one2many_phone
#: model:ir.model.fields.selection,name:base_partner_one2many_phone.selection__res_partner_phone__type__4_phone_secondary #: selection:res.partner.phone,type:0
msgid "Secondary Phone" msgid "Secondary Phone"
msgstr "Tél. secondaire" msgstr "Tél. secondaire"
#. module: base_partner_one2many_phone #. module: base_partner_one2many_phone
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner_phone__type #: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner_phone_type
#: model_terms:ir.ui.view,arch_db:base_partner_one2many_phone.res_partner_phone_search #: model:ir.ui.view,arch_db:base_partner_one2many_phone.res_partner_phone_search
msgid "Type" msgid "Type"
msgstr "Type" msgstr "Type"
#. module: base_partner_one2many_phone
#: model:ir.model,name:base_partner_one2many_phone.model_res_partner_phone
msgid "res.partner.phone"
msgstr "res.partner.phone"

View File

@@ -46,7 +46,7 @@ class ResPartnerPhone(models.Model):
@api.onchange('phone', 'partner_id') @api.onchange('phone', 'partner_id')
def _onchange_phone_validation(self): def _onchange_phone_validation(self):
if self.phone: if self.phone:
self.phone = self.phone_format(self.phone, country=self.partner_id.country_id) self.phone = self.phone_format(self.phone)
@api.constrains('type', 'phone', 'email') @api.constrains('type', 'phone', 'email')
def _check_partner_phone(self): def _check_partner_phone(self):

View File

@@ -14,7 +14,7 @@
<field name="name">res.partner.phone.tree</field> <field name="name">res.partner.phone.tree</field>
<field name="model">res.partner.phone</field> <field name="model">res.partner.phone</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<tree editable="bottom"> <tree string="Phones and E-mail" editable="bottom">
<field name="partner_id" invisible="not context.get('partner_phone_main_view')"/> <field name="partner_id" invisible="not context.get('partner_phone_main_view')"/>
<field name="type"/> <field name="type"/>
<field name="phone" widget="phone" options="{'enable_sms': false}" attrs="{'required': [('type', 'not in', ('1_email_primary', '2_email_secondary'))], 'readonly': [('type', 'in', ('1_email_primary', '2_email_secondary'))]}"/> <field name="phone" widget="phone" options="{'enable_sms': false}" attrs="{'required': [('type', 'not in', ('1_email_primary', '2_email_secondary'))], 'readonly': [('type', 'in', ('1_email_primary', '2_email_secondary'))]}"/>
@@ -28,7 +28,7 @@
<field name="name">res.partner.phone.form</field> <field name="name">res.partner.phone.form</field>
<field name="model">res.partner.phone</field> <field name="model">res.partner.phone</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<form> <form string="Phone and E-mail">
<group name="main"> <group name="main">
<field name="partner_id" invisible="not context.get('partner_phone_main_view')"/> <field name="partner_id" invisible="not context.get('partner_phone_main_view')"/>
<field name="type"/> <field name="type"/>
@@ -44,7 +44,7 @@
<field name="name">res.partner.phone.search</field> <field name="name">res.partner.phone.search</field>
<field name="model">res.partner.phone</field> <field name="model">res.partner.phone</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<search> <search string="Search Phones/E-mail">
<field name="phone" /> <field name="phone" />
<field name="email" /> <field name="email" />
<group name="groupby"> <group name="groupby">

View File

@@ -1 +1 @@
from . import models from . import partner

View File

@@ -1,10 +1,10 @@
# Copyright 2017-2021 Akretion (http://www.akretion.com) # Copyright 2017-2019 Akretion (http://www.akretion.com)
# @author Alexis de Lattre <alexis.delattre@akretion.com> # @author Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{ {
'name': 'Base Partner Reference', 'name': 'Base Partner Reference',
'version': '14.0.1.0.0', 'version': '12.0.1.0.0',
'category': 'Partner', 'category': 'Partner',
'license': 'AGPL-3', 'license': 'AGPL-3',
'summary': "Improve usage of partner's Internal Reference", 'summary': "Improve usage of partner's Internal Reference",
@@ -21,6 +21,6 @@ Base Partner Reference
'author': 'Akretion', 'author': 'Akretion',
'website': 'http://www.akretion.com', 'website': 'http://www.akretion.com',
'depends': ['base'], 'depends': ['base'],
'data': ['views/res_partner.xml'], 'data': ['partner_view.xml'],
'installable': True, 'installable': False,
} }

View File

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

View File

@@ -1,4 +1,4 @@
# Copyright 2017-2021 Akretion # Copyright 2017-2019 Akretion
# @author: Alexis de Lattre <alexis.delattre@akretion.com> # @author: Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
@@ -18,9 +18,9 @@ class ResPartner(models.Model):
)] )]
# add 'ref' in depends # add 'ref' in depends
@api.depends('ref', 'invalidate_display_name') @api.depends('is_company', 'name', 'parent_id.name', 'type', 'company_name', 'ref', 'invalidate_display_name')
def _compute_display_name(self): def _compute_display_name(self):
super()._compute_display_name() super(ResPartner, self)._compute_display_name()
def _get_name(self): def _get_name(self):
partner = self partner = self
@@ -28,17 +28,16 @@ class ResPartner(models.Model):
# START modif of native method # START modif of native method
if partner.ref: if partner.ref:
name = "[%s] %s" % (partner.ref, name) name = u"[%s] %s" % (partner.ref, name)
# END modif of native method # END modif of native method
if partner.company_name or partner.parent_id: if partner.company_name or partner.parent_id:
if not name and partner.type in ['invoice', 'delivery', 'other']: if not name and partner.type in ['invoice', 'delivery', 'other']:
name = dict(self.fields_get( name = dict(self.fields_get(['type'])['type']['selection'])[partner.type]
['type'])['type']['selection'])[partner.type]
if not partner.is_company: if not partner.is_company:
# START modif of native name_get() method # START modif of native name_get() method
company_name = partner.commercial_company_name or partner.parent_id.name company_name = partner.commercial_company_name or partner.parent_id.name
if partner.parent_id.ref: if partner.parent_id.ref:
company_name = "[%s] %s" % (partner.parent_id.ref, company_name) company_name = u"[%s] %s" % (partner.parent_id.ref, company_name)
name = "%s, %s" % (company_name, name) name = "%s, %s" % (company_name, name)
# END modif of native name_get() method # END modif of native name_get() method
if self._context.get('show_address_only'): if self._context.get('show_address_only'):
@@ -48,8 +47,7 @@ class ResPartner(models.Model):
name = name.replace('\n\n', '\n') name = name.replace('\n\n', '\n')
name = name.replace('\n\n', '\n') name = name.replace('\n\n', '\n')
if self._context.get('address_inline'): if self._context.get('address_inline'):
splitted_names = name.split("\n") name = name.replace('\n', ', ')
name = ", ".join([n for n in splitted_names if n.strip()])
if self._context.get('show_email') and partner.email: if self._context.get('show_email') and partner.email:
name = "%s <%s>" % (name, partner.email) name = "%s <%s>" % (name, partner.email)
if self._context.get('html_format'): if self._context.get('html_format'):
@@ -57,14 +55,3 @@ class ResPartner(models.Model):
if self._context.get('show_vat') and partner.vat: if self._context.get('show_vat') and partner.vat:
name = "%s %s" % (name, partner.vat) name = "%s %s" % (name, partner.vat)
return name return name
@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)

View File

@@ -11,34 +11,29 @@
<field name="name">Move ref in partner form to make it more visible</field> <field name="name">Move ref in partner form to make it more visible</field>
<field name="model">res.partner</field> <field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_partner_form"/> <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="arch" type="xml">
<field name="type" position="after"> <field name="type" position="after">
<field name="ref"/> <field name="ref"/>
</field> </field>
<xpath expr="//page[@name='sales_purchases']//field[@name='ref']" position="attributes"> <xpath expr="//page[@name='sales_purchases']//field[@name='ref']" position="replace"/>
<attribute name="invisible">1</attribute>
</xpath>
</field> </field>
</record> </record>
<!-- show name and ref in separate columns -->
<!-- ref is added in tree view by base_usability with optional="hide"
<record id="view_partner_tree" model="ir.ui.view"> <record id="view_partner_tree" model="ir.ui.view">
<field name="name">Add ref in partner tree view</field> <field name="name">Add ref in partner tree view</field>
<field name="model">res.partner</field> <field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_partner_tree"/> <field name="inherit_id" ref="base.view_partner_tree"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<!-- show name and ref in separate columns -->
<field name="display_name" position="after"> <field name="display_name" position="after">
<field name="name"/> <field name="name"/>
<field name="ref" optional="hide"/> <field name="ref"/>
</field> </field>
<field name="display_name" position="attributes"> <field name="display_name" position="attributes">
<attribute name="invisible">1</attribute> <attribute name="invisible">1</attribute>
</field> </field>
</field> </field>
</record> </record>
-->
<record id="res_partner_kanban_view" model="ir.ui.view"> <record id="res_partner_kanban_view" model="ir.ui.view">
<field name="name">Add ref in partner kanban view</field> <field name="name">Add ref in partner kanban view</field>

View File

@@ -10,7 +10,7 @@
'summary': 'Better usability in base module', 'summary': 'Better usability in base module',
'author': 'Akretion', 'author': 'Akretion',
'website': 'http://www.akretion.com', 'website': 'http://www.akretion.com',
'depends': ['base'], 'depends': ['base', 'contacts'],
'data': [ 'data': [
'security/group.xml', 'security/group.xml',
'security/ir.model.access.csv', 'security/ir.model.access.csv',

View File

@@ -6,8 +6,8 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Odoo Server 14.0\n" "Project-Id-Version: Odoo Server 14.0\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-07-01 10:02+0000\n" "POT-Creation-Date: 2021-02-17 16:55+0000\n"
"PO-Revision-Date: 2021-07-01 10:02+0000\n" "PO-Revision-Date: 2021-02-17 16:55+0000\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: \n" "Language-Team: \n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"

View File

@@ -6,9 +6,9 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Odoo Server 14.0\n" "Project-Id-Version: Odoo Server 14.0\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-07-01 10:02+0000\n" "POT-Creation-Date: 2021-02-17 16:55+0000\n"
"PO-Revision-Date: 2021-07-01 12:15+0200\n" "PO-Revision-Date: 2021-02-17 16:55+0000\n"
"Last-Translator: Alexis de Lattre <alexis@via.ecp.fr>\n" "Last-Translator: \n"
"Language-Team: \n" "Language-Team: \n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
@@ -33,15 +33,16 @@ msgstr "Sociétés"
#. module: base_usability #. module: base_usability
#: model:ir.model,name:base_usability.model_res_partner #: model:ir.model,name:base_usability.model_res_partner
msgid "Contact" msgid "Contact"
msgstr "Contact" msgstr ""
#. module: base_usability #. module: base_usability
#: model_terms:ir.ui.view,arch_db:base_usability.res_country_search #: model_terms:ir.ui.view,arch_db:base_usability.res_country_search
msgid "Currency" msgid "Currency"
msgstr "Devise" msgstr "Monnaie"
#. module: base_usability #. module: base_usability
#: code:addons/base_usability/models/res_partner.py:0 #: code:addons/base_usability/models/res_partner.py:0
#: code:addons/base_usability/models/res_partner.py:0
#, python-format #, python-format
msgid "Customer Number:" msgid "Customer Number:"
msgstr "N° client :" msgstr "N° client :"
@@ -67,7 +68,7 @@ msgstr "E-mail :"
#. module: base_usability #. module: base_usability
#: model_terms:ir.ui.view,arch_db:base_usability.res_country_search #: model_terms:ir.ui.view,arch_db:base_usability.res_country_search
msgid "Group By" msgid "Group By"
msgstr "Grouper par" msgstr ""
#. module: base_usability #. module: base_usability
#: model:ir.model.fields,field_description:base_usability.field_ir_mail_server__id #: model:ir.model.fields,field_description:base_usability.field_ir_mail_server__id
@@ -78,12 +79,12 @@ msgstr "Grouper par"
#: model:ir.model.fields,field_description:base_usability.field_res_partner_category__id #: model:ir.model.fields,field_description:base_usability.field_res_partner_category__id
#: model:ir.model.fields,field_description:base_usability.field_res_users__id #: model:ir.model.fields,field_description:base_usability.field_res_users__id
msgid "ID" msgid "ID"
msgstr "ID" msgstr ""
#. module: base_usability #. module: base_usability
#: model_terms:ir.ui.view,arch_db:base_usability.view_module_filter #: model_terms:ir.ui.view,arch_db:base_usability.view_module_filter
msgid "Installable" msgid "Installable"
msgstr "Installable" msgstr ""
#. module: base_usability #. module: base_usability
#: model:ir.model.fields,field_description:base_usability.field_ir_mail_server____last_update #: model:ir.model.fields,field_description:base_usability.field_ir_mail_server____last_update
@@ -99,7 +100,7 @@ msgstr "Dernière modification le"
#. module: base_usability #. module: base_usability
#: model:ir.model,name:base_usability.model_ir_mail_server #: model:ir.model,name:base_usability.model_ir_mail_server
msgid "Mail Server" msgid "Mail Server"
msgstr "Serveur mail" msgstr "Serveur d'email"
#. module: base_usability #. module: base_usability
#: code:addons/base_usability/models/res_partner.py:0 #: code:addons/base_usability/models/res_partner.py:0
@@ -131,7 +132,7 @@ msgstr "Nom avec titre"
#. module: base_usability #. module: base_usability
#: model:res.groups,name:base_usability.group_nobody #: model:res.groups,name:base_usability.group_nobody
msgid "Nobody (used to hide native menus)" msgid "Nobody (used to hide native menus)"
msgstr "Personne (utilisé pour cacher des entrées de menu natifs)" msgstr ""
#. module: base_usability #. module: base_usability
#: model:ir.model,name:base_usability.model_res_partner_category #: model:ir.model,name:base_usability.model_res_partner_category
@@ -151,6 +152,7 @@ msgstr ""
#. module: base_usability #. module: base_usability
#: code:addons/base_usability/models/res_partner.py:0 #: code:addons/base_usability/models/res_partner.py:0
#: code:addons/base_usability/models/res_partner.py:0
#, python-format #, python-format
msgid "Supplier Number:" msgid "Supplier Number:"
msgstr "N° fournisseur :" msgstr "N° fournisseur :"

View File

@@ -4,5 +4,4 @@ from . import res_partner_bank
from . import res_partner_category from . import res_partner_category
from . import res_company from . import res_company
from . import ir_mail_server from . import ir_mail_server
from . import ir_actions_report
from . import ir_model from . import ir_model

View File

@@ -1,15 +0,0 @@
# Copyright 2021 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 IrActionsReport(models.Model):
_inherit = "ir.actions.report"
# since v13, print_report_name is a translatable field
# It means that you can't set the value via an inherit of
# ir.actions.report as XML
# I think it was easier when this field was not translatable
print_report_name = fields.Char(translate=False)

View File

@@ -8,9 +8,25 @@ from odoo import models, fields, api, _
class ResPartner(models.Model): class ResPartner(models.Model):
_inherit = 'res.partner' _inherit = 'res.partner'
# tracking=True is handled in the 'mail' module, and base_usability # track_visibility is handled in the 'mail' module, and base_usability
# doesn't depend on 'mail', so adding tracking on res.partner fields # doesn't depend on 'mail', but that doesn't hurt, it will just be
# has been moved to mail_usability # ignored if mail is not installed
# TODO move to mail module
# name = fields.Char(tracking=True)
# parent_id = fields.Many2one(tracking=True)
# ref = fields.Char(tracking=True)
# lang = fields.Selection(tracking=True)
# user_id = fields.Many2one(tracking=True)
# vat = fields.Char(tracking=True)
# street = fields.Char(tracking=True)
# street2 = fields.Char(tracking=True)
# zip = fields.Char(tracking=True)
# city = fields.Char(tracking=True)
# state_id = fields.Many2one(tracking=True)
# country_id = fields.Many2one(tracking=True)
# is_company = fields.Boolean(tracking=True)
# active = fields.Boolean(tracking=True)
# company_id = fields.Many2one(tracking=True)
ref = fields.Char(copy=False) ref = fields.Char(copy=False)
# For reports # For reports
name_title = fields.Char( name_title = fields.Char(

View File

@@ -25,7 +25,7 @@
<field name="name">base_usability.res.country.search</field> <field name="name">base_usability.res.country.search</field>
<field name="model">res.country</field> <field name="model">res.country</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<search> <search string="Search Countries">
<field name="name" filter_domain="['|', ('name', 'ilike', self), ('code', '=', self)]" string="Name or Code"/> <field name="name" filter_domain="['|', ('name', 'ilike', self), ('code', '=', self)]" string="Name or Code"/>
<field name="code"/> <field name="code"/>
<field name="currency_id"/> <field name="currency_id"/>

View File

@@ -20,6 +20,15 @@
<div attrs="{'invisible': [('same_vat_partner_id', '=', False)]}" position="attributes"> <div attrs="{'invisible': [('same_vat_partner_id', '=', False)]}" position="attributes">
<attribute name="class">alert alert-warning</attribute> <attribute name="class">alert alert-warning</attribute>
</div> </div>
<!-- Add a kanban button to open child partner -->
<xpath expr="//field[@name='child_ids']//kanban/templates/t/div" position="inside">
<div class="o_dropdown_kanban">
<a class="btn" role="button" title="Open"
t-att-href="'/web#id=' + record.id.raw_value + '&amp;action=%(contacts.action_contacts)d' + '&amp;menu_id=%(contacts.menu_contacts)d' + '&amp;view_type=form&amp;cids=1&amp;model=res.partner'">
<span class="fa fa-external-link" />
</a>
</div>
</xpath>
</field> </field>
</record> </record>
@@ -39,9 +48,6 @@
<field name="model">res.partner</field> <field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_partner_tree"/> <field name="inherit_id" ref="base.view_partner_tree"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<field name="display_name" position="after">
<field name="ref" optional="hide"/>
</field>
<field name="phone" position="after"> <field name="phone" position="after">
<field name="mobile" optional="show" widget="phone" class="o_force_ltr"/> <field name="mobile" optional="show" widget="phone" class="o_force_ltr"/>
</field> </field>

View File

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

View File

@@ -1,25 +0,0 @@
# Copyright 2016-2021 Akretion (http://www.akretion.com)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
# @author Alexis de Lattre <alexis.delattre@akretion.com>
{
'name': 'CRM Usability',
'version': '14.0.1.0.0',
'category': 'Customer Relationship Management',
'license': 'AGPL-3',
'summary': 'CRM usability enhancements',
'description': """
CRM Usability
=============
This module has been written by Alexis de Lattre from Akretion
<alexis.delattre@akretion.com>.
""",
'author': 'Akretion',
'website': 'http://www.akretion.com',
'depends': ['crm'],
'data': [
'views/crm_lead.xml',
],
'installable': True,
}

View File

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

View File

@@ -1,13 +0,0 @@
# Copyright 2017-2021 Akretion (http://www.akretion.com)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
# @author Alexis de Lattre <alexis.delattre@akretion.com>
from odoo import fields, models
class CrmLead(models.Model):
_inherit = 'crm.lead'
probability = fields.Float(tracking=100)
date_deadline = fields.Date(tracking=110)
name = fields.Char(tracking=1)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.5 KiB

View File

@@ -1,22 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2017-2021 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>
<!-- SEARCH OPPOR -->
<record id="view_crm_case_opportunities_filter" model="ir.ui.view">
<field name="name">usability.crm.lead.opportunity.search</field>
<field name="model">crm.lead</field>
<field name="inherit_id" ref="crm.view_crm_case_opportunities_filter"/>
<field name="arch" type="xml">
<filter name="saleschannel" position="after">
<filter name="partner_groupby" string="Customer" context="{'group_by': 'partner_id'}"/>
</filter>
</field>
</record>
</odoo>

View File

@@ -1 +1 @@
from . import models from . import stock

View File

@@ -1,10 +1,10 @@
# Copyright 2018-2021 Akretion (http://www.akretion.com) # Copyright 2018-2019 Akretion (http://www.akretion.com)
# @author Alexis de Lattre <alexis.delattre@akretion.com> # @author Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{ {
'name': 'Delivery Usability', 'name': 'Delivery Usability',
'version': '14.0.1.0.0', 'version': '12.0.1.0.0',
'category': 'Stock', 'category': 'Stock',
'license': 'AGPL-3', 'license': 'AGPL-3',
'summary': 'Several usability enhancements in Delivery', 'summary': 'Several usability enhancements in Delivery',
@@ -14,6 +14,7 @@ Delivery Usability
The usability enhancements include: The usability enhancements include:
* allow modification of carrier and it's tracking ref. on a done picking * allow modification of carrier and it's tracking ref. on a done picking
* display field 'invoice_shipping_on_delivery' on sale.order form view
This module has been written by Alexis de Lattre from Akretion <alexis.delattre@akretion.com>. This module has been written by Alexis de Lattre from Akretion <alexis.delattre@akretion.com>.
""", """,
@@ -21,7 +22,8 @@ This module has been written by Alexis de Lattre from Akretion <alexis.delattre@
'website': 'http://www.akretion.com', 'website': 'http://www.akretion.com',
'depends': ['delivery'], 'depends': ['delivery'],
'data': [ 'data': [
'views/stock_picking.xml', 'sale_view.xml',
'stock_view.xml',
], ],
'installable': True, 'installable': False,
} }

View File

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

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2018-2019 Akretion
@author: Alexis de Lattre <alexis.delattre@akretion.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
-->
<odoo>
<record id="view_order_form_with_carrier" model="ir.ui.view">
<field name="name">delivery_usability.sale.order.form</field>
<field name="model">sale.order</field>
<field name="inherit_id" ref="delivery.view_order_form_with_carrier"/>
<field name="arch" type="xml">
<group name="sale_pay" position="inside">
<field name="invoice_shipping_on_delivery"/>
</group>
</field>
</record>
</odoo>

View File

@@ -1,4 +1,4 @@
# Copyright 2018-2021 Akretion (http://www.akretion.com) # Copyright 2018-2019 Akretion (http://www.akretion.com)
# @author Alexis de Lattre <alexis.delattre@akretion.com> # @author Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
@@ -8,5 +8,5 @@ from odoo import fields, models
class StockPicking(models.Model): class StockPicking(models.Model):
_inherit = 'stock.picking' _inherit = 'stock.picking'
carrier_id = fields.Many2one(tracking=True) carrier_id = fields.Many2one(track_visibility='onchange')
carrier_tracking_ref = fields.Char(tracking=True) carrier_tracking_ref = fields.Char(track_visibility='onchange')

View File

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

View File

@@ -1,9 +1,9 @@
# Copyright 2014-2021 Akretion France (http://www.akretion.com) # Copyright 2014-2019 Akretion France (http://www.akretion.com)
# @author Alexis de Lattre <alexis.delattre@akretion.com> # @author Alexis de Lattre <alexis.delattre@akretion.com>
{ {
'name': 'Eradicate Quick Create', 'name': 'Eradicate Quick Create',
'version': '14.0.1.0.0', 'version': '12.0.2.0.0',
'category': 'Tools', 'category': 'Tools',
'license': 'AGPL-3', 'license': 'AGPL-3',
'summary': 'Disable quick create on all objects', 'summary': 'Disable quick create on all objects',
@@ -13,7 +13,7 @@ Eradicate Quick Create
Disable quick create on all objects of Odoo. Disable quick create on all objects of Odoo.
This module uses the module *web_m2x_options* from the OCA *web* project (in v10 and lower, it was using the module *base_optional_quick_create* from the OCA project *server-ux*). This new version of the module uses the module *web_m2x_options* from the OCA *web* project instead of the module *base_optional_quick_create* from the OCA project *server-ux*.
This module has been written by Alexis de Lattre from Akretion <alexis.delattre@akretion.com>. This module has been written by Alexis de Lattre from Akretion <alexis.delattre@akretion.com>.
""", """,
@@ -21,5 +21,5 @@ This module has been written by Alexis de Lattre from Akretion <alexis.delattre@
'website': 'http://www.akretion.com', 'website': 'http://www.akretion.com',
'depends': ['web_m2x_options'], 'depends': ['web_m2x_options'],
'post_init_hook': 'web_m2x_options_create', 'post_init_hook': 'web_m2x_options_create',
'installable': True, 'installable': False,
} }

View File

@@ -1,4 +1,4 @@
# Copyright 2019-2021 Akretion France # Copyright 2019 Akretion France
# @author: Alexis de Lattre <alexis.delattre@akretion.com> # @author: Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
@@ -11,7 +11,7 @@ def web_m2x_options_create(cr, registry):
config_parameter = env['ir.config_parameter'].search( config_parameter = env['ir.config_parameter'].search(
[('key', '=', 'web_m2x_options.create')]) [('key', '=', 'web_m2x_options.create')])
if config_parameter and config_parameter.value != 'False': if config_parameter and config_parameter.value != 'False':
config_parameter.write({'value': 'False'}) config_parameter.value = 'False'
else: else:
env['ir.config_parameter'].create({ env['ir.config_parameter'].create({
'key': 'web_m2x_options.create', 'key': 'web_m2x_options.create',

View File

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

View File

@@ -1,20 +0,0 @@
# Copyright 2021 Akretion (http://www.akretion.com)
# @author Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{
'name': 'HR Contract Usability',
'version': '14.0.1.0.0',
'category': 'Human Resources/Contracts',
'license': 'AGPL-3',
'summary': 'Usability improvements on HR Contract module',
'author': 'Akretion',
'website': 'http://www.akretion.com',
'depends': [
'hr_contract',
],
'data': [
'views/hr_payroll_structure_type.xml',
],
'installable': True,
}

View File

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

View File

@@ -1,10 +0,0 @@
# Copyright 2021 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 fields, models
class HrPayrollStructureType(models.Model):
_inherit = 'hr.payroll.structure.type'
active = fields.Boolean(default=True)

View File

@@ -1,63 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2021 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="hr_payroll_structure_type_form" model="ir.ui.view">
<field name="model">hr.payroll.structure.type</field>
<field name="arch" type="xml">
<form>
<widget name="web_ribbon" title="Archived" bg_color="bg-danger" attrs="{'invisible': [('active', '=', True)]}"/>
<group name="main">
<field name="name"/>
<field name="default_resource_calendar_id"/>
<field name="active" invisible="1"/>
<field name="country_id"/>
</group>
</form>
</field>
</record>
<record id="hr_payroll_structure_type_tree" model="ir.ui.view">
<field name="model">hr.payroll.structure.type</field>
<field name="arch" type="xml">
<tree>
<field name="name"/>
<field name="default_resource_calendar_id" optional="show"/>
<field name="country_id"/>
</tree>
</field>
</record>
<record id="hr_payroll_structure_type_search" model="ir.ui.view">
<field name="model">hr.payroll.structure.type</field>
<field name="arch" type="xml">
<search>
<field name="name"/>
<separator/>
<filter string="Archived" name="inactive" domain="[('active', '=', False)]"/>
<group name="groupby">
<filter name="country_groupby" string="Country" context="{'group_by': 'country_id'}"/>
</group>
</search>
</field>
</record>
<record id="hr_payroll_structure_type_action" model="ir.actions.act_window">
<field name="name">Salary Structure Types</field>
<field name="res_model">hr.payroll.structure.type</field>
<field name="view_mode">tree,form</field>
</record>
<menuitem
id="hr_payroll_structure_type_menu"
action="hr_payroll_structure_type_action"
parent="hr_contract.menu_human_resources_configuration_contract"
sequence="10"/>
</odoo>

View File

@@ -1,27 +0,0 @@
# Copyright 2019-2021 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': 'Link Tracker Usability',
'version': '14.0.1.0.0',
'category': 'Marketing',
'license': 'AGPL-3',
'summary': 'Improve usability for link tracker',
'description': """
Link Tracker Usability
======================
Several small usability improvements.
This module has been written by Alexis de Lattre from Akretion
<alexis.delattre@akretion.com>.
""",
'author': 'Akretion',
'website': 'http://www.akretion.com',
'depends': ['link_tracker'],
'data': [
'views/link_tracker_click.xml',
],
'installable': True,
}

View File

@@ -1,45 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2019-2021 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="link_tracker_click_view_tree" model="ir.ui.view">
<field name="name">usability.link.tracker.click.tree</field>
<field name="model">link.tracker.click</field>
<field name="inherit_id" ref="link_tracker.link_tracker_click_view_tree"/>
<field name="arch" type="xml">
<field name="country_id" position="after">
<field name="create_date" string="Click Date"/>
</field>
</field>
</record>
<record id="link_tracker_click_view_form" model="ir.ui.view">
<field name="name">usability.link.tracker.click.form</field>
<field name="model">link.tracker.click</field>
<field name="inherit_id" ref="link_tracker.link_tracker_click_view_form"/>
<field name="arch" type="xml">
<field name="country_id" position="after">
<field name="create_date" string="Click Date"/>
</field>
</field>
</record>
<record id="link_tracker_click_view_search" model="ir.ui.view">
<field name="name">usability.link.tracker.click.search</field>
<field name="model">link.tracker.click</field>
<field name="inherit_id" ref="link_tracker.link_tracker_click_view_search"/>
<field name="arch" type="xml">
<filter name="groupby_link_id" position="before">
<filter name="create_date_groupby" string="Click Date" context="{'group_by': 'create_date'}"/>
</filter>
</field>
</record>
</odoo>

View File

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

View File

@@ -1,32 +0,0 @@
# Copyright 2016-2021 Akretion France (http://www.akretion.com)
# @author Benoît Guillot <benoit.guillot@akretion.com>
# @author Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{
'name': 'Mail Usability',
'version': '14.0.1.0.0',
'category': 'Productivity/Discuss',
'license': 'AGPL-3',
'summary': 'Usability improvements on mails',
'description': """
Mail Usability
==============
Small usability improvements on mails:
* remove link in mail footer (TODO mig v14)
* remove 'sent by' in notification footer (TODO mig v14)
""",
'author': 'Akretion',
'website': 'http://www.akretion.com',
'depends': ['mail'],
'data': [
#'views/mail_view.xml',
#'data/mail_data.xml',
#'wizard/email_template_preview_view.xml',
#'wizard/mail_compose_message_view.xml',
],
'installable': True,
}

View File

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

View File

@@ -1,11 +0,0 @@
# Copyright 2018-2021 Akretion France (http://www.akretion.com).
# @author Sébastien BEAU <sebastien.beau@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import fields, models
class MailTemplate(models.Model):
_inherit = 'mail.template'
auto_delete = fields.Boolean(default=False)

View File

@@ -1,26 +0,0 @@
# Copyright 2015-2021 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 models, fields
class ResPartner(models.Model):
_inherit = 'res.partner'
# tracking=True is handled in the 'mail' module, so it's better
# to have this in mail_usability than in base_usability
name = fields.Char(tracking=True)
parent_id = fields.Many2one(tracking=True)
ref = fields.Char(tracking=True)
lang = fields.Selection(tracking=True)
vat = fields.Char(tracking=True)
street = fields.Char(tracking=True)
street2 = fields.Char(tracking=True)
zip = fields.Char(tracking=True)
city = fields.Char(tracking=True)
state_id = fields.Many2one(tracking=True)
country_id = fields.Many2one(tracking=True)
is_company = fields.Boolean(tracking=True)
active = fields.Boolean(tracking=True)
company_id = fields.Many2one(tracking=True)

View File

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

View File

@@ -1,29 +0,0 @@
# Copyright 2019-2021 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': 'Mass Mailing Campaigns Usability',
'version': '14.0.1.0.0',
'category': 'Marketing',
'license': 'AGPL-3',
'summary': 'Improve usability of mass mailing campaigns',
'description': """
Mass Mailing Campaigns Usability
================================
Several small usability improvements on the module mass_mailing:
* show fields on link.tracker.click that are not displayed by default
This module has been written by Alexis de Lattre from Akretion
<alexis.delattre@akretion.com>.
""",
'author': 'Akretion',
'website': 'http://www.akretion.com',
'depends': ['mass_mailing', 'link_tracker_usability'],
'data': [
# 'views/link_tracker.xml',
],
'installable': False,
}

View File

@@ -1,48 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2019 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_link_tracker_click_tree" model="ir.ui.view">
<field name="name">mm.usability.link.tracker.click.tree</field>
<field name="model">link.tracker.click</field>
<field name="inherit_id" ref="link_tracker.view_link_tracker_click_tree"/>
<field name="arch" type="xml">
<field name="country_id" position="after">
<field name="mass_mailing_id"/>
<field name="mail_stat_recipient"/>
</field>
</field>
</record>
<record id="view_link_tracker_click_form" model="ir.ui.view">
<field name="name">mm.usability.link.tracker.click.form</field>
<field name="model">link.tracker.click</field>
<field name="inherit_id" ref="link_tracker.view_link_tracker_click_form"/>
<field name="arch" type="xml">
<field name="country_id" position="after">
<field name="mass_mailing_id"/>
<field name="mass_mailing_campaign_id"/>
<field name="mail_stat_id"/>
<field name="mail_stat_recipient"/>
</field>
</field>
</record>
<record id="link_tracker_click_search" model="ir.ui.view">
<field name="name">mm.usability.link.tracker.click.search</field>
<field name="model">link.tracker.click</field>
<field name="inherit_id" ref="link_tracker_usability.link_tracker_click_search"/>
<field name="arch" type="xml">
<field name="link_id" position="after">
<field name="mail_stat_recipient"/>
</field>
</field>
</record>
</odoo>

View File

@@ -12,20 +12,16 @@ class ProductTemplate(models.Model):
only one BoM form or a list of BoMs.""" only one BoM form or a list of BoMs."""
self.ensure_one() self.ensure_one()
if self.bom_count == 1: if self.bom_count == 1:
action_xml_id = "mrp.mrp_bom_form_action" action = self.env.ref("mrp.mrp_bom_form_action").read()[0]
action = self.env["ir.actions.actions"]._for_xml_id(action_xml_id)
bom = self.env["mrp.bom"].search([("product_tmpl_id", "=", self.id)]) bom = self.env["mrp.bom"].search([("product_tmpl_id", "=", self.id)])
action.update( action.update({
{
"context": {"default_product_tmpl_id": self.id}, "context": {"default_product_tmpl_id": self.id},
"views": False, "views": False,
"view_mode": "form,tree", "view_mode": "form,tree",
"res_id": bom.id, "res_id": bom.id,
} })
)
else: else:
action_xml_id = "mrp.template_open_bom" action = self.env.ref("mrp.template_open_bom").read()[0]
action = self.env["ir.actions.actions"]._for_xml_id(action_xml_id)
return action return action
@@ -36,11 +32,9 @@ class ProductProduct(models.Model):
action = super().action_view_bom() action = super().action_view_bom()
bom_target_ids = self.env["mrp.bom"].search(action["domain"]) bom_target_ids = self.env["mrp.bom"].search(action["domain"])
if len(bom_target_ids) == 1: if len(bom_target_ids) == 1:
action.update( action.update({
{
"views": False, "views": False,
"view_mode": "form,tree", "view_mode": "form,tree",
"res_id": bom_target_ids[0].id, "res_id": bom_target_ids[0].id,
} })
)
return action return action

View File

@@ -0,0 +1,28 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
{
'name': 'POS No Product Template Menu',
'version': '12.0.1.0.0',
'category': 'Point of sale',
'license': 'AGPL-3',
'summary': "Replace product.template menu entries by product.product menu",
'description': """
POS No Product Template
=======================
This module replaces the menu entry for product.template by menu entries
for product.product in the *Point Of Sale > Product* menu.
This module also switches to the tree view by default
for Product menu entries, instead of the kanban view.
This module has been written by David Béal
from Akretion <david.beal@akretion.com>.
""",
'author': 'Akretion',
'website': 'http://www.akretion.com',
'depends': ['point_of_sale', 'sale_purchase_no_product_template_menu'],
'auto_install': True,
'data': ['pos_view.xml'],
'installable': False,
}

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="product_product_action_pos" model="ir.actions.act_window">
<field name="name">Products</field>
<field name="res_model">product.product</field>
<field name="view_mode">kanban,tree,form</field>
<field name="context">{'default_available_in_pos': True, 'search_default_filter_to_availabe_pos': 1}</field>
</record>
<record id="point_of_sale.menu_pos_products" model="ir.ui.menu">
<field name="action" ref="product_product_action_pos"/>
</record>
</odoo>

View File

@@ -28,9 +28,7 @@ Akretion:
"depends": ["point_of_sale"], "depends": ["point_of_sale"],
"data": [ "data": [
"report/pos.xml", "report/pos.xml",
"views/report_pos_order.xml",
"views/pos_category.xml", "views/pos_category.xml",
"views/pos_session.xml",
"views/product.xml", "views/product.xml",
], ],
"installable": True, "installable": True,

View File

@@ -1,31 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2021 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="view_pos_session_form" model="ir.ui.view">
<field name="model">pos.session</field>
<field name="inherit_id" ref="point_of_sale.view_pos_session_form"/>
<field name="arch" type="xml">
<button name="show_journal_items" position="after">
<button name="%(point_of_sale.action_report_pos_order_all)d" type="action" class="oe_stat_button" icon="fa-table" string="Stats" context="{'search_default_session_id': active_id}"/>
</button>
</field>
</record>
<record id="view_pos_session_tree" model="ir.ui.view">
<field name="model">pos.session</field>
<field name="inherit_id" ref="point_of_sale.view_pos_session_tree"/>
<field name="arch" type="xml">
<field name="state" position="attributes">
<attribute name="decoration-success">state == 'opened'</attribute>
</field>
</field>
</record>
</odoo>

View File

@@ -1,26 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2021 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="view_report_pos_order_search" model="ir.ui.view">
<field name="model">report.pos.order</field>
<field name="inherit_id" ref="point_of_sale.view_report_pos_order_search"/>
<field name="arch" type="xml">
<field name="product_categ_id" position="after">
<field name="session_id"/>
</field>
</field>
</record>
<record id="point_of_sale.action_report_pos_order_all" model="ir.actions.act_window">
<field name="view_mode">pivot,graph</field> <!-- invert native order -->
</record>
</odoo>

View File

@@ -32,7 +32,6 @@ This module has been written by Alexis de Lattre from Akretion <alexis.delattre@
'views/product_pricelist_item.xml', 'views/product_pricelist_item.xml',
'views/product_template_view.xml', 'views/product_template_view.xml',
'views/product_product.xml', 'views/product_product.xml',
'views/product_category_view.xml',
], ],
'installable': True, 'installable': True,
} }

View File

@@ -2,4 +2,3 @@ from . import product_product
from . import product_template from . import product_template
from . import product_supplierinfo from . import product_supplierinfo
from . import product_pricelist from . import product_pricelist
from . import product_category

View File

@@ -1,13 +0,0 @@
# Copyright 2022 Akretion (https://www.akretion.com).
# @author Sébastien BEAU <sebastien.beau@akretion.com>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import fields, models
class ProductCategory(models.Model):
_inherit = ['product.category', "mail.thread", "mail.activity.mixin"]
_name = 'product.category'
name = fields.Char(tracking=10)
parent_id = fields.Many2one(tracking=20)

View File

@@ -1,21 +1,21 @@
# Copyright 2015-2021 Akretion (http://www.akretion.com) # Copyright 2015-2020 Akretion (http://www.akretion.com)
# @author Alexis de Lattre <alexis.delattre@akretion.com> # @author Alexis de Lattre <alexis.delattre@akretion.com>
# @author Raphaël Valyi <rvalyi@akretion.com> # @author Raphaël Valyi <rvalyi@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import api, models, fields from odoo import models, fields
class ProductProduct(models.Model): class ProductProduct(models.Model):
_inherit = 'product.product' _inherit = 'product.product'
default_code = fields.Char(copy=False, tracking=10) default_code = fields.Char(copy=False)
barcode = fields.Char(tracking=20) # track_visibility='onchange',
weight = fields.Float(tracking=30)
active = fields.Boolean(tracking=40) # barcode = fields.Char(track_visibility='onchange',
barcode_code128 = fields.Char(
compute='_compute_barcode_code128', # weight = fields.Float(track_visibility='onchange')
help="Barcode in Code128-B with start char, checksum and stop char") # active = fields.Boolean(track_visibility='onchange')
_sql_constraints = [( _sql_constraints = [(
# Maybe it could be better to have a constrain per company # Maybe it could be better to have a constrain per company
@@ -26,32 +26,3 @@ class ProductProduct(models.Model):
'default_code_uniq', 'default_code_uniq',
'unique(default_code)', 'unique(default_code)',
'This internal reference already exists!')] 'This internal reference already exists!')]
@api.model
def _compute_code128_checksum(self, code):
# This is NOT a full implementation of code128 checksum
csum = 104 # Start B
i = 0
for char in code:
i += 1
char_val = ord(char) - 32
csum += char_val * i
remainder = csum % 103
checksum = chr(remainder + 32)
return checksum
@api.depends('barcode')
def _compute_barcode_code128(self):
# We use Code128-B. Useful info on code128:
# https://boowiki.info/art/codes-a-barres/code-128.html
# Use code128.ttf and copy it in /usr/local/share/fonts/
startb = chr(209)
stop = chr(211)
for product in self:
code128 = False
barcode = product.barcode
if barcode and all([32 <= ord(x) <= 127 for x in barcode]):
checksum = self._compute_code128_checksum(barcode)
if checksum:
code128 = startb + barcode + checksum + stop
product.barcode_code128 = code128

View File

@@ -1,4 +1,4 @@
# Copyright 2015-2021 Akretion (http://www.akretion.com) # Copyright 2015-2020 Akretion (http://www.akretion.com)
# @author Alexis de Lattre <alexis.delattre@akretion.com> # @author Alexis de Lattre <alexis.delattre@akretion.com>
# @author Raphaël Valyi <rvalyi@akretion.com> # @author Raphaël Valyi <rvalyi@akretion.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
@@ -21,12 +21,9 @@ class ProductTemplate(models.Model):
# are only shown in the form view of product.template, not in the form # are only shown in the form view of product.template, not in the form
# view of product.product # view of product.product
name = fields.Char(tracking=10) name = fields.Char(tracking=10)
barcode = fields.Char(tracking=20) categ_id = fields.Many2one(tracking=20)
default_code = fields.Char(tracking=30) type = fields.Selection(tracking=30)
categ_id = fields.Many2one(tracking=40) list_price = fields.Float(tracking=40)
type = fields.Selection(tracking=50) sale_ok = fields.Boolean(tracking=50)
list_price = fields.Float(tracking=60) purchase_ok = fields.Boolean(tracking=60)
weight = fields.Float(tracking=70) active = fields.Boolean(tracking=70)
sale_ok = fields.Boolean(tracking=80)
purchase_ok = fields.Boolean(tracking=90)
active = fields.Boolean(tracking=100)

View File

@@ -1,19 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<record id="product_category_form_view" model="ir.ui.view">
<field name="model">product.category</field>
<field name="inherit_id" ref="product.product_category_form_view" />
<field name="arch" type="xml">
<sheet position="after">
<div class="oe_chatter">
<field name="message_follower_ids"/>
<field name="activity_ids"/>
<field name="message_ids"/>
</div>
</sheet>
</field>
</record>
</odoo>

View File

@@ -12,7 +12,7 @@
<field name="inherit_id" ref="product.product_supplierinfo_search_view"/> <field name="inherit_id" ref="product.product_supplierinfo_search_view"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<field name="product_tmpl_id" position="after"> <field name="product_tmpl_id" position="after">
<field name="product_name" filter_domain="['|', ('product_code', 'ilike', self), ('product_name', 'ilike', self)]" /> <field name="product_code"/>
</field> </field>
</field> </field>
</record> </record>

View File

@@ -1,185 +0,0 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * purchase_usability
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 14.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-11-30 13:35+0000\n"
"PO-Revision-Date: 2021-11-30 13:35+0000\n"
"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: purchase_usability
#: model_terms:ir.ui.view,arch_db:purchase_usability.purchase_order_line_search
msgid "Analytic Account"
msgstr ""
#. module: purchase_usability
#: model_terms:ir.ui.view,arch_db:purchase_usability.purchase_order_form
msgid "Are you sure you want to cancel this purchase order?"
msgstr "Êtes-vous sûr de vouloir annuler cette commande?"
#. module: purchase_usability
#: model_terms:ir.ui.view,arch_db:purchase_usability.view_purchase_order_filter
msgid "Billing Status"
msgstr ""
#. module: purchase_usability
#: model:ir.model,name:purchase_usability.model_res_partner
msgid "Contact"
msgstr ""
#. module: purchase_usability
#: model:ir.model.fields,field_description:purchase_usability.field_product_product__purchase_method
#: model:ir.model.fields,field_description:purchase_usability.field_product_template__purchase_method
msgid "Control Policy"
msgstr "Politique de contrôle"
#. module: purchase_usability
#: model:ir.model.fields,field_description:purchase_usability.field_purchase_order__currency_id
msgid "Currency"
msgstr "Devise"
#. module: purchase_usability
#: model:ir.model.fields,field_description:purchase_usability.field_purchase_order__delivery_partner_id
msgid "Delivery Partner"
msgstr ""
#. module: purchase_usability
#: model:ir.model.fields,field_description:purchase_usability.field_product_template__display_name
#: model:ir.model.fields,field_description:purchase_usability.field_purchase_order__display_name
#: model:ir.model.fields,field_description:purchase_usability.field_purchase_order_line__display_name
#: model:ir.model.fields,field_description:purchase_usability.field_res_partner__display_name
msgid "Display Name"
msgstr "Nom"
#. module: purchase_usability
#: model:ir.model.fields,field_description:purchase_usability.field_purchase_order__dest_address_id
msgid "Drop Ship Address"
msgstr "Adresse de livraison directe"
#. module: purchase_usability
#: model:ir.model.fields,field_description:purchase_usability.field_purchase_order__fiscal_position_id
msgid "Fiscal Position"
msgstr "Position fiscale"
#. module: purchase_usability
#: model:ir.model.fields,field_description:purchase_usability.field_product_template__id
#: model:ir.model.fields,field_description:purchase_usability.field_purchase_order__id
#: model:ir.model.fields,field_description:purchase_usability.field_purchase_order_line__id
#: model:ir.model.fields,field_description:purchase_usability.field_res_partner__id
msgid "ID"
msgstr ""
#. module: purchase_usability
#: model:ir.model.fields,help:purchase_usability.field_purchase_order_line__product_barcode
msgid "International Article Number used for product identification."
msgstr ""
#. module: purchase_usability
#: model:ir.model.fields,field_description:purchase_usability.field_product_template____last_update
#: model:ir.model.fields,field_description:purchase_usability.field_purchase_order____last_update
#: model:ir.model.fields,field_description:purchase_usability.field_purchase_order_line____last_update
#: model:ir.model.fields,field_description:purchase_usability.field_res_partner____last_update
msgid "Last Modified on"
msgstr "Dernière modification le"
#. module: purchase_usability
#: model:ir.model.fields,help:purchase_usability.field_product_product__purchase_method
#: model:ir.model.fields,help:purchase_usability.field_product_template__purchase_method
msgid ""
"On ordered quantities: Control bills based on ordered quantities.\n"
"On received quantities: Control bills based on received quantities."
msgstr ""
"Sur base des quantités commandées: factures de controle basées sur les quantités commandées. \n"
"Sur base des quantités reçues: factures de controle basées sur les quantités reçues."
#. module: purchase_usability
#: model:ir.model.fields,field_description:purchase_usability.field_purchase_order__payment_term_id
msgid "Payment Terms"
msgstr "Conditions de paiement"
#. module: purchase_usability
#: model_terms:ir.ui.view,arch_db:purchase_usability.purchase_order_form
msgid "Print"
msgstr "Imprimer"
#. module: purchase_usability
#: model:ir.model.fields,field_description:purchase_usability.field_purchase_order_line__product_barcode
msgid "Product Barcode"
msgstr ""
#. module: purchase_usability
#: model:ir.model,name:purchase_usability.model_product_template
msgid "Product Template"
msgstr "Modèle de produit"
#. module: purchase_usability
#: model:ir.model,name:purchase_usability.model_purchase_order
#: model:ir.model.fields,field_description:purchase_usability.field_res_partner__purchase_warn
#: model:ir.model.fields,field_description:purchase_usability.field_res_users__purchase_warn
msgid "Purchase Order"
msgstr "Commande fournisseur"
#. module: purchase_usability
#: model:ir.model,name:purchase_usability.model_purchase_order_line
msgid "Purchase Order Line"
msgstr "Ligne de commande d'achat"
#. module: purchase_usability
#: model:ir.model.fields,field_description:purchase_usability.field_product_product__purchase_line_warn
#: model:ir.model.fields,field_description:purchase_usability.field_product_template__purchase_line_warn
msgid "Purchase Order Line Warning"
msgstr "Avertissement Ligne de Commande "
#. module: purchase_usability
#: model:ir.model.fields,help:purchase_usability.field_purchase_order__dest_address_id
msgid ""
"Put an address if you want to deliver directly from the vendor to the "
"customer. Otherwise, keep empty to deliver to your own company."
msgstr ""
"Ajoutez une adresse si vous voulez livrer directement du fournisseur au "
"client. Sinon, laissez vide pour vous faire livrer à votre société."
#. module: purchase_usability
#: model:ir.model.fields,help:purchase_usability.field_purchase_order__partner_ref
msgid ""
"Reference of the sales order or bid sent by the vendor. It's used to do the "
"matching when you receive the products as this reference is usually written "
"on the delivery order sent by your vendor."
msgstr ""
"Référence de la commande client ou offre envoyée par le fournisseur. Utilisé"
" principalement pour faire la correspondance lors de la réception des "
"articles, puisque cette référence est généralement écrite sur le bon de "
"livraison envoyé par votre fournisseur."
#. module: purchase_usability
#: model_terms:ir.ui.view,arch_db:purchase_usability.view_purchase_order_filter
msgid "Reference, Origin or Vendor Reference"
msgstr ""
#. module: purchase_usability
#: model:ir.model.fields,help:purchase_usability.field_product_product__purchase_line_warn
#: model:ir.model.fields,help:purchase_usability.field_product_template__purchase_line_warn
#: model:ir.model.fields,help:purchase_usability.field_res_partner__purchase_warn
#: model:ir.model.fields,help:purchase_usability.field_res_users__purchase_warn
msgid ""
"Selecting the \"Warning\" option will notify user with the message, "
"Selecting \"Blocking Message\" will throw an exception with the message and "
"block the flow. The Message has to be written in the next field."
msgstr ""
"Sélectionner l'option 'Avertissement' notifiera l'utilisateur avec le "
"Message. Sélectionner 'Message Bloquant' lancera une exception avec le "
"message et bloquera le flux. Le Message doit être encodé dans le champ "
"suivant."
#. module: purchase_usability
#: model:ir.model.fields,field_description:purchase_usability.field_purchase_order__partner_ref
msgid "Vendor Reference"
msgstr "Référence fournisseur"

View File

@@ -24,6 +24,11 @@ class PurchaseOrder(models.Model):
for order in self: for order in self:
order.delivery_partner_id = order.dest_address_id order.delivery_partner_id = order.dest_address_id
def print_order(self):
report = self.env.ref('purchase.action_report_purchase_order')
action = report.report_action(self)
return action
# Re-write native name_get() to use amount_untaxed instead of amount_total # Re-write native name_get() to use amount_untaxed instead of amount_total
@api.depends('name', 'partner_ref') @api.depends('name', 'partner_ref')
def name_get(self): def name_get(self):
@@ -73,28 +78,3 @@ class PurchaseOrderLine(models.Model):
# for optional display in tree view # for optional display in tree view
product_barcode = fields.Char(related='product_id.barcode', string="Product Barcode") product_barcode = fields.Char(related='product_id.barcode', string="Product Barcode")
product_supplier_code = fields.Char(
compute='_compute_product_supplier_code', string='Vendor Product Code')
def _compute_product_supplier_code(self):
for line in self:
code = False
if not line.display_type and line.product_id and line.order_id:
partner_id = line.order_id.partner_id.commercial_partner_id.id
if partner_id:
for supplier_info in line.product_id.seller_ids:
if supplier_info.name.id == partner_id:
code = supplier_info.product_code
break
line.product_supplier_code = code
def _get_product_purchase_description(self, product_lang):
# This is useful when you want to have the product code in a dedicated
# column in your purchase order 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':
product_lang = product_lang.with_context(display_default_code=False)
return super()._get_product_purchase_description(product_lang)

View File

@@ -14,7 +14,7 @@
<field name="inherit_id" ref="purchase.purchase_order_form"/> <field name="inherit_id" ref="purchase.purchase_order_form"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<button name="action_rfq_send" states="purchase" position="after"> <button name="action_rfq_send" states="purchase" position="after">
<button name="%(purchase.action_report_purchase_order)d" states="purchase,done" string="Print" type="action"/> <button name="print_order" states="purchase" string="Print Order" type="object"/>
</button> </button>
<field name="fiscal_position_id" position="attributes"> <field name="fiscal_position_id" position="attributes">
<attribute name="widget">selection</attribute> <attribute name="widget">selection</attribute>
@@ -35,7 +35,6 @@
<attribute name="groups">analytic.group_analytic_tags</attribute> <attribute name="groups">analytic.group_analytic_tags</attribute>
</xpath> </xpath>
<xpath expr="//field[@name='order_line']/tree//field[@name='product_id']" position="after"> <xpath expr="//field[@name='order_line']/tree//field[@name='product_id']" position="after">
<field name="product_supplier_code" optional="hide"/>
<field name="product_barcode" optional="hide"/> <field name="product_barcode" optional="hide"/>
</xpath> </xpath>
</field> </field>

View File

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

View File

@@ -1,38 +0,0 @@
# Copyright 2017-2021 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': 'Sale Confirm Wizard',
'version': '14.0.1.0.0',
'category': 'Sales',
'license': 'AGPL-3',
'summary': 'Open a wizard when you confirm a sale order to update important info',
'description': """
Sale Confirm Wizard
===================
When you confirm a quotation, Odoo will open a small wizard where you will be able to check and update important information:
* customer PO number,
* delivery address,
* invoicing address,
* payment terms.
It will also display the sale warning if the customer's company has one. And it is a blocker warning, the user won't be able to confirm the quotation.
This module has been developped because the experience has shown, when a sales assistant confirms a quotation in Odoo, it overlooks the important information written in the customer PO that may be different from the information of the quotation in Odoo, which causes many errors in delivery and invoicing.
This module has been written by Alexis de Lattre from Akretion
<alexis.delattre@akretion.com>.
""",
'author': 'Akretion',
'website': 'http://www.akretion.com',
'depends': ['sale'],
'data': [
'wizard/sale_confirm_view.xml',
'views/sale_order.xml',
'security/ir.model.access.csv',
],
'installable': True,
}

View File

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

View File

@@ -1,17 +0,0 @@
# Copyright 2020-2021 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 models
class SaleOrder(models.Model):
_inherit = 'sale.order'
def sale_confirm_wizard_button(self):
"""This method is designed to be inherited.
For example, inherit it if you don't want to start the wizard in
some scenarios"""
action = self.sudo().env.ref(
'sale_confirm_wizard.sale_confirm_action').read()[0]
return action

View File

@@ -1,2 +0,0 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_sale_confirm_wizard,Full access on sale.confirm wizard,model_sale_confirm,sales_team.group_sale_salesman,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_sale_confirm_wizard Full access on sale.confirm wizard model_sale_confirm sales_team.group_sale_salesman 1 1 1 1

View File

@@ -1,24 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2017-2021 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="view_order_form" model="ir.ui.view">
<field name="name">sale.confirm.wizard.sale_order_form</field>
<field name="model">sale.order</field>
<field name="inherit_id" ref="sale.view_order_form"/>
<field name="arch" type="xml">
<button id="action_confirm" position="attributes">
<attribute name="name">sale_confirm_wizard_button</attribute>
</button>
<button name="action_confirm" attrs="{'invisible': [('state', 'not in', ['draft'])]}" position="attributes">
<attribute name="name">sale_confirm_wizard_button</attribute>
</button>
</field>
</record>
</odoo>

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