Compare commits
85 Commits
14.0-produ
...
14.0-add-c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
55622ec6a9 | ||
|
|
f166fe93be | ||
|
|
b8a6cbcfea | ||
|
|
f6b10a7caa | ||
|
|
371229e9e5 | ||
|
|
1dbfd23524 | ||
|
|
9a9459f013 | ||
|
|
5a58ae0d9a | ||
|
|
b162227645 | ||
|
|
3c24e94122 | ||
|
|
400f316c7f | ||
|
|
86af01667a | ||
|
|
8967bf289a | ||
|
|
1fdaf52787 | ||
|
|
6907302f8e | ||
|
|
a3e23ab5e7 | ||
|
|
a850586716 | ||
|
|
fdef51ea57 | ||
|
|
806389e04b | ||
|
|
c12b496004 | ||
|
|
447b0107be | ||
|
|
f9a7983d71 | ||
|
|
870746b965 | ||
|
|
f22c6522d5 | ||
|
|
1ef97629b7 | ||
|
|
77a372b3ca | ||
|
|
221b090cc8 | ||
|
|
e4a2ff5bd4 | ||
|
|
c1d334b109 | ||
|
|
c7c9b2d341 | ||
|
|
eddab6020a | ||
|
|
d1181ca91d | ||
|
|
df673718e5 | ||
|
|
bb83765ee2 | ||
|
|
88615a0774 | ||
|
|
05e649fa86 | ||
|
|
08118ec4f5 | ||
|
|
6d496ba302 | ||
|
|
40b79890fe | ||
|
|
58b8d300b8 | ||
|
|
cdcf4eb406 | ||
|
|
a22f79ef44 | ||
|
|
99dd4de4f7 | ||
|
|
f3d6b67043 | ||
|
|
1963af114b | ||
|
|
1da4c40927 | ||
|
|
edc9db5839 | ||
|
|
882d068f1a | ||
|
|
878db1d0a1 | ||
|
|
600acd2f26 | ||
|
|
059c3b4a09 | ||
|
|
895e1d9dd0 | ||
|
|
0b3ffc804f | ||
|
|
c0a03dbb0e | ||
|
|
6e5f263283 | ||
|
|
d4ebbb28d9 | ||
|
|
7dd204e57e | ||
|
|
e1a84973da | ||
|
|
13e68ac0f5 | ||
|
|
3b17c2e5fb | ||
|
|
0be112dc84 | ||
|
|
ce2255623d | ||
|
|
2854d4fdda | ||
|
|
6c51a92acc | ||
|
|
f3910ab528 | ||
|
|
05374c4b4a | ||
|
|
279dc7c6c0 | ||
|
|
f6ddbb48ac | ||
|
|
d3bddf5fda | ||
|
|
6f3a468a7c | ||
|
|
0bfa960153 | ||
|
|
a520ccff51 | ||
|
|
fa7611eb08 | ||
|
|
b2eda2a23b | ||
|
|
74ff1b5cb5 | ||
|
|
a7b4ed65eb | ||
|
|
7dfb32c2d6 | ||
|
|
d081bb0fd2 | ||
|
|
f3fdbec140 | ||
|
|
ac54c5cc75 | ||
|
|
78c11411c3 | ||
|
|
28ce11b216 | ||
|
|
00e034dacf | ||
|
|
8510b9518a | ||
|
|
15ef5df155 |
@@ -52,6 +52,7 @@ This modules adds the following functions:
|
||||
* don't attach PDF upon invoice report generation on supplier invoices/refunds
|
||||
* Add filter on debit and credit amount for Move Lines
|
||||
* Add supplier invoice number in invoice tree view
|
||||
* Add date in outstanding payment widget on invoice form view (requires `odoo PR 84180 <https://github.com/odoo/odoo/pull/84180>`_)
|
||||
|
||||
Together with this module, I recommend the use of the following modules:
|
||||
|
||||
|
||||
@@ -19,6 +19,9 @@
|
||||
'data': [
|
||||
'views/account_account_type.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_invoice_report.xml',
|
||||
'views/account_journal.xml',
|
||||
@@ -28,10 +31,14 @@
|
||||
'views/product.xml',
|
||||
'views/res_config_settings.xml',
|
||||
'views/res_partner.xml',
|
||||
'views/res_company.xml',
|
||||
'views/account_report.xml',
|
||||
'wizard/account_invoice_mark_sent_view.xml',
|
||||
'wizard/account_group_generate_view.xml',
|
||||
'wizard/account_payment_register_views.xml',
|
||||
'security/ir.model.access.csv',
|
||||
'report/invoice_report.xml',
|
||||
],
|
||||
'qweb': ['static/src/xml/account_payment.xml'],
|
||||
'installable': True,
|
||||
}
|
||||
|
||||
@@ -6,4 +6,6 @@ from . import account_journal
|
||||
from . import account_move
|
||||
from . import account_partial_reconcile
|
||||
from . import res_partner
|
||||
from . import res_company
|
||||
from . import product
|
||||
from . import account_invoice_report
|
||||
|
||||
@@ -27,9 +27,7 @@ class AccountBankStatement(models.Model):
|
||||
|
||||
def _check_balance_end_real_same_as_computed(self):
|
||||
for stmt in self:
|
||||
if stmt.hide_bank_statement_balance:
|
||||
continue
|
||||
else:
|
||||
if not stmt.hide_bank_statement_balance:
|
||||
super(AccountBankStatement, stmt)._check_balance_end_real_same_as_computed()
|
||||
return True
|
||||
|
||||
@@ -80,7 +78,8 @@ class AccountBankStatementLine(models.Model):
|
||||
|
||||
def show_account_move(self):
|
||||
self.ensure_one()
|
||||
action = self.env.ref('account.action_move_line_form').read()[0]
|
||||
action = self.env["ir.actions.actions"]._for_xml_id(
|
||||
'account.action_move_line_form')
|
||||
# Note: this action is on account.move, not account.move.line !
|
||||
action.update({
|
||||
'views': False,
|
||||
|
||||
@@ -14,3 +14,13 @@ class AccountIncoterms(models.Model):
|
||||
for rec in self:
|
||||
res.append((rec.id, '[%s] %s' % (rec.code, rec.name)))
|
||||
return res
|
||||
|
||||
@api.model
|
||||
def name_search(self, name='', args=None, operator='ilike', limit=100):
|
||||
if args is None:
|
||||
args = []
|
||||
if name and operator == 'ilike':
|
||||
recs = self.search([('code', '=ilike', name + '%')] + args, limit=limit)
|
||||
if recs:
|
||||
return recs.name_get()
|
||||
return super().name_search(name=name, args=args, operator=operator, limit=limit)
|
||||
|
||||
17
account_usability/models/account_invoice_report.py
Normal file
17
account_usability/models/account_invoice_report.py
Normal file
@@ -0,0 +1,17 @@
|
||||
# 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
|
||||
@@ -16,6 +16,13 @@ class AccountJournal(models.Model):
|
||||
"you don't want to enter the start/end balance manually: it "
|
||||
"will prevent the display of wrong information in the accounting "
|
||||
"dashboard and on bank statements.")
|
||||
# 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(
|
||||
'name', 'currency_id', 'company_id', 'company_id.currency_id', 'code')
|
||||
|
||||
@@ -2,17 +2,17 @@
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import api, fields, models
|
||||
from odoo import api, fields, models, _
|
||||
from odoo.tools import float_is_zero
|
||||
from odoo.tools.misc import format_date
|
||||
from odoo.osv import expression
|
||||
from datetime import timedelta
|
||||
from odoo.exceptions import UserError
|
||||
|
||||
|
||||
class AccountMove(models.Model):
|
||||
_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
|
||||
# which seems a bit lazy for me...
|
||||
ref = fields.Char(states={'posted': [('readonly', True)]})
|
||||
@@ -154,13 +154,13 @@ class AccountMove(models.Model):
|
||||
""" French law requires to set sale order dates into invoice
|
||||
returned string: "sale1 (date1), sale2 (date2) ..."
|
||||
"""
|
||||
for inv in self:
|
||||
sales = inv.invoice_line_ids.mapped(
|
||||
for move in self:
|
||||
sales = move.invoice_line_ids.mapped(
|
||||
'sale_line_ids').mapped('order_id')
|
||||
dates = ["%s (%s)" % (
|
||||
x.name, format_date(inv.env, self.date_order))
|
||||
x.name, format_date(move.env, x.date_order))
|
||||
for x in sales]
|
||||
inv.sale_dates = ", ".join(dates)
|
||||
move.sale_dates = ", ".join(dates)
|
||||
|
||||
# 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)
|
||||
@@ -180,6 +180,47 @@ class AccountMove(models.Model):
|
||||
])
|
||||
move.suitable_journal_ids = self.env['account.journal'].search(domain)
|
||||
|
||||
def button_draft(self):
|
||||
super().button_draft()
|
||||
# Delete attached pdf invoice
|
||||
try:
|
||||
report_invoice = self.env['ir.actions.report']._get_report_from_name('account.report_invoice')
|
||||
except IndexError:
|
||||
report_invoice = False
|
||||
if report_invoice and report_invoice.attachment:
|
||||
for move in self.filtered(lambda x: x.move_type in ('out_invoice', 'out_refund')):
|
||||
# The pb is that the filename is dynamic and related to move.state
|
||||
# in v12, the feature was native and they used that kind of code:
|
||||
# with invoice.env.do_in_draft():
|
||||
# invoice.number, invoice.state = invoice.move_name, 'open'
|
||||
# attachment = self.env.ref('account.account_invoices').retrieve_attachment(invoice)
|
||||
# But do_in_draft() doesn't exists in v14
|
||||
# If you know how we could do that, please update the code below
|
||||
attachment = self.env['ir.attachment'].search([
|
||||
('name', '=', self._get_invoice_attachment_name()),
|
||||
('res_id', '=', move.id),
|
||||
('res_model', '=', self._name),
|
||||
('type', '=', 'binary'),
|
||||
], limit=1)
|
||||
if attachment:
|
||||
attachment.unlink()
|
||||
|
||||
def _get_invoice_attachment_name(self):
|
||||
self.ensure_one()
|
||||
return '%s.pdf' % (self.name and self.name.replace('/', '_') or 'INV')
|
||||
|
||||
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):
|
||||
_inherit = 'account.move.line'
|
||||
@@ -204,7 +245,8 @@ class AccountMoveLine(models.Model):
|
||||
|
||||
def show_account_move_form(self):
|
||||
self.ensure_one()
|
||||
action = self.env.ref('account.action_move_line_form').read()[0]
|
||||
action = self.env["ir.actions.actions"]._for_xml_id(
|
||||
'account.action_move_line_form')
|
||||
action.update({
|
||||
'res_id': self.move_id.id,
|
||||
'view_id': False,
|
||||
@@ -224,3 +266,25 @@ class AccountMoveLine(models.Model):
|
||||
rec_str = ', '.join([
|
||||
'a%d' % pr.id for pr in line.matched_debit_ids + line.matched_credit_ids])
|
||||
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()
|
||||
|
||||
21
account_usability/models/res_company.py
Normal file
21
account_usability/models/res_company.py
Normal file
@@ -0,0 +1,21 @@
|
||||
# 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")
|
||||
19
account_usability/static/src/xml/account_payment.xml
Normal file
19
account_usability/static/src/xml/account_payment.xml
Normal file
@@ -0,0 +1,19 @@
|
||||
<?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>
|
||||
@@ -31,6 +31,9 @@
|
||||
<field name="name" position="after">
|
||||
<field name="code" filter_domain="[('code', '=like', str(self)+'%')]" string="Code"/>
|
||||
</field>
|
||||
<filter name="accounttype" position="after">
|
||||
<filter name="group_groupby" string="Group" context="{'group_by': 'group_id'}"/>
|
||||
</filter>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
33
account_usability/views/account_analytic_account.xml
Normal file
33
account_usability/views/account_analytic_account.xml
Normal file
@@ -0,0 +1,33 @@
|
||||
<?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>
|
||||
22
account_usability/views/account_analytic_group.xml
Normal file
22
account_usability/views/account_analytic_group.xml
Normal file
@@ -0,0 +1,22 @@
|
||||
<?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>
|
||||
32
account_usability/views/account_group.xml
Normal file
32
account_usability/views/account_group.xml
Normal file
@@ -0,0 +1,32 @@
|
||||
<?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>
|
||||
@@ -14,26 +14,38 @@
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Invoices Analysis">
|
||||
<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_due"/>
|
||||
<field name="move_type"/>
|
||||
<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="fiscal_position_id" optional="hide"/>
|
||||
<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="product_uom_id" groups="uom.group_uom"/>
|
||||
<field name="price_subtotal" sum="1"/>
|
||||
<field name="state"/>
|
||||
<field name="payment_state" optional="hide"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<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="view_mode">pivot,graph</field>
|
||||
</record>
|
||||
|
||||
<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="view_mode">pivot,graph</field>
|
||||
</record>
|
||||
|
||||
<record id="view_account_invoice_report_pivot" model="ir.ui.view">
|
||||
|
||||
@@ -14,6 +14,17 @@
|
||||
<field name="arch" type="xml">
|
||||
<field name="bank_statements_source" position="after">
|
||||
<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>
|
||||
</record>
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
<field name="invoice_incoterm_id" position="attributes">
|
||||
<attribute name="widget">selection</attribute>
|
||||
</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>
|
||||
@@ -26,6 +29,9 @@
|
||||
</button>
|
||||
<!-- move sent field and make it visible -->
|
||||
<field name="is_move_sent" position="replace"/>
|
||||
<field name="invoice_origin" position="attributes">
|
||||
<attribute name="invisible">0</attribute>
|
||||
</field>
|
||||
<field name="invoice_origin" position="after">
|
||||
<field name="is_move_sent" attrs="{'invisible': [('move_type', 'not in', ('out_invoice', 'out_refund'))]}"/>
|
||||
</field>
|
||||
@@ -82,10 +88,11 @@
|
||||
<field name="debit" filter_domain="['|', ('debit', '=', self), ('credit', '=', self)]" string="Debit or Credit"/>
|
||||
</field>
|
||||
<filter name="unreconciled" position="before">
|
||||
<filter name="reconciled" string="Fully Reconciled" domain="[('full_reconcile_id', '!=', False)]"/>
|
||||
<filter name="reconciled" string="Fully Reconciled" domain="[('reconciled', '=', True)]"/>
|
||||
</filter>
|
||||
<filter name="unreconciled" position="attributes">
|
||||
<attribute name="string">Unreconciled or Partially Reconciled</attribute>
|
||||
<attribute name="domain">[('reconciled', '=', False), ('balance', '!=', 0), ('account_id.reconcile', '=', True)]</attribute>
|
||||
</filter>
|
||||
<!--
|
||||
<field name="name" position="attributes">
|
||||
|
||||
@@ -27,7 +27,7 @@ Here, we set all those fields on account.group_account_invoice
|
||||
</field>
|
||||
<field name="list_price" position="replace">
|
||||
<div name="list_price">
|
||||
<field name="list_price" widget='monetary' options="{'currency_field': 'currency_id'}" class="oe_inline"/>
|
||||
<field name="list_price" widget='monetary' options="{'currency_field': 'currency_id', 'field_digits': True}" class="oe_inline"/>
|
||||
<label for="sale_price_type" string=" "/>
|
||||
<field name="sale_price_type"/>
|
||||
</div>
|
||||
|
||||
27
account_usability/views/res_company.xml
Normal file
27
account_usability/views/res_company.xml
Normal file
@@ -0,0 +1,27 @@
|
||||
<?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>
|
||||
@@ -16,6 +16,9 @@
|
||||
<field name="property_account_position_id" position="attributes">
|
||||
<attribute name="widget">selection</attribute>
|
||||
</field>
|
||||
<xpath expr="//field[@name='bank_ids']/tree/field[@name='acc_number']" position="after">
|
||||
<field name="acc_type"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
23
account_usability/wizard/account_payment_register_views.xml
Normal file
23
account_usability/wizard/account_payment_register_views.xml
Normal file
@@ -0,0 +1,23 @@
|
||||
<?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>
|
||||
1
base_mail_sender_bcc/__init__.py
Normal file
1
base_mail_sender_bcc/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from . import models
|
||||
21
base_mail_sender_bcc/__manifest__.py
Normal file
21
base_mail_sender_bcc/__manifest__.py
Normal file
@@ -0,0 +1,21 @@
|
||||
# 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,
|
||||
}
|
||||
1
base_mail_sender_bcc/models/__init__.py
Normal file
1
base_mail_sender_bcc/models/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from . import ir_mail_server
|
||||
27
base_mail_sender_bcc/models/ir_mail_server.py
Normal file
27
base_mail_sender_bcc/models/ir_mail_server.py
Normal file
@@ -0,0 +1,27 @@
|
||||
# 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)
|
||||
@@ -1,14 +1,14 @@
|
||||
# Translation of Odoo Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * base_partner_one2many_phone
|
||||
# * base_partner_one2many_phone
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Odoo Server 10.0\n"
|
||||
"Project-Id-Version: Odoo Server 14.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-01-27 18:03+0000\n"
|
||||
"PO-Revision-Date: 2020-01-27 18:03+0000\n"
|
||||
"Last-Translator: <>\n"
|
||||
"POT-Creation-Date: 2021-10-29 21:12+0000\n"
|
||||
"PO-Revision-Date: 2021-10-29 21:12+0000\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
@@ -16,92 +16,120 @@ msgstr ""
|
||||
"Plural-Forms: \n"
|
||||
|
||||
#. module: base_partner_one2many_phone
|
||||
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner_phone_create_uid
|
||||
#: model:ir.model,name:base_partner_one2many_phone.model_res_partner
|
||||
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"
|
||||
msgstr ""
|
||||
|
||||
#. 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"
|
||||
msgstr ""
|
||||
|
||||
#. module: base_partner_one2many_phone
|
||||
#: 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__display_name
|
||||
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner_phone__display_name
|
||||
msgid "Display Name"
|
||||
msgstr ""
|
||||
|
||||
#. 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"
|
||||
msgstr ""
|
||||
|
||||
#. module: base_partner_one2many_phone
|
||||
#: code:addons/base_partner_one2many_phone/partner_phone.py:61
|
||||
#: code:addons/base_partner_one2many_phone/partner_phone.py:0
|
||||
#, python-format
|
||||
msgid "E-mail field must be empty when type is Primary/Secondary Phone, Primary/Secondary Mobile or Primary/Secondary Fax."
|
||||
msgid ""
|
||||
"E-mail field must be empty when type is Primary/Secondary Phone, "
|
||||
"Primary/Secondary Mobile or Primary/Secondary Fax."
|
||||
msgstr ""
|
||||
|
||||
#. module: base_partner_one2many_phone
|
||||
#: code:addons/base_partner_one2many_phone/partner_phone.py:51
|
||||
#: code:addons/base_partner_one2many_phone/partner_phone.py:0
|
||||
#, python-format
|
||||
msgid "E-mail field must have a value when type is Primary E-mail or Secondary E-mail."
|
||||
msgid ""
|
||||
"E-mail field must have a value when type is Primary E-mail or Secondary "
|
||||
"E-mail."
|
||||
msgstr ""
|
||||
|
||||
#. module: base_partner_one2many_phone
|
||||
#: 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_partner__email
|
||||
#: 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"
|
||||
msgstr ""
|
||||
|
||||
#. module: base_partner_one2many_phone
|
||||
#: 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____last_update
|
||||
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner_phone____last_update
|
||||
msgid "Last Modified on"
|
||||
msgstr ""
|
||||
|
||||
#. 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"
|
||||
msgstr ""
|
||||
|
||||
#. 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"
|
||||
msgstr ""
|
||||
|
||||
#. module: base_partner_one2many_phone
|
||||
#: 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_partner__mobile
|
||||
#: 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"
|
||||
msgstr ""
|
||||
|
||||
#. module: base_partner_one2many_phone
|
||||
#: model:ir.model,name:base_partner_one2many_phone.model_res_partner
|
||||
msgid "Partner"
|
||||
msgstr ""
|
||||
|
||||
#. module: base_partner_one2many_phone
|
||||
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner_phone_phone
|
||||
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner__phone
|
||||
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner_phone__phone
|
||||
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_users__phone
|
||||
msgid "Phone"
|
||||
msgstr ""
|
||||
|
||||
#. module: base_partner_one2many_phone
|
||||
#: code:addons/base_partner_one2many_phone/partner_phone.py:54
|
||||
#: model_terms:ir.ui.view,arch_db:base_partner_one2many_phone.res_partner_phone_form
|
||||
msgid "Phone and E-mail"
|
||||
msgstr ""
|
||||
|
||||
#. module: base_partner_one2many_phone
|
||||
#: code:addons/base_partner_one2many_phone/partner_phone.py:0
|
||||
#, python-format
|
||||
msgid "Phone field must be empty when type is Primary E-mail or Secondary E-mail."
|
||||
msgid ""
|
||||
"Phone field must be empty when type is Primary E-mail or Secondary E-mail."
|
||||
msgstr ""
|
||||
|
||||
#. module: base_partner_one2many_phone
|
||||
#: code:addons/base_partner_one2many_phone/partner_phone.py:58
|
||||
#: code:addons/base_partner_one2many_phone/partner_phone.py:0
|
||||
#, python-format
|
||||
msgid "Phone field must have a value when type is Primary/Secondary Phone, Primary/Secondary Mobile or Primary/Secondary Fax."
|
||||
msgid ""
|
||||
"Phone field must have a value when type is Primary/Secondary Phone, "
|
||||
"Primary/Secondary Mobile or Primary/Secondary Fax."
|
||||
msgstr ""
|
||||
|
||||
#. module: base_partner_one2many_phone
|
||||
#: 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
|
||||
#: model_terms:ir.ui.view,arch_db:base_partner_one2many_phone.res_partner_phone_tree
|
||||
msgid "Phones and E-mail"
|
||||
msgstr ""
|
||||
|
||||
@@ -112,63 +140,63 @@ msgid "Phones/E-mails"
|
||||
msgstr ""
|
||||
|
||||
#. module: base_partner_one2many_phone
|
||||
#: selection:res.partner.phone,type:0
|
||||
#: 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/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"
|
||||
msgstr ""
|
||||
|
||||
#. module: base_partner_one2many_phone
|
||||
#: selection:res.partner.phone,type:0
|
||||
#: model:ir.model.fields.selection,name:base_partner_one2many_phone.selection__res_partner_phone__type__7_fax_primary
|
||||
msgid "Primary Fax"
|
||||
msgstr ""
|
||||
|
||||
#. module: base_partner_one2many_phone
|
||||
#: selection:res.partner.phone,type:0
|
||||
#: model:ir.model.fields.selection,name:base_partner_one2many_phone.selection__res_partner_phone__type__5_mobile_primary
|
||||
msgid "Primary Mobile"
|
||||
msgstr ""
|
||||
|
||||
#. module: base_partner_one2many_phone
|
||||
#: selection:res.partner.phone,type:0
|
||||
#: model:ir.model.fields.selection,name:base_partner_one2many_phone.selection__res_partner_phone__type__3_phone_primary
|
||||
msgid "Primary Phone"
|
||||
msgstr ""
|
||||
|
||||
#. 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"
|
||||
msgstr ""
|
||||
|
||||
#. module: base_partner_one2many_phone
|
||||
#: model:ir.ui.view,arch_db:base_partner_one2many_phone.res_partner_phone_search
|
||||
#: model_terms:ir.ui.view,arch_db:base_partner_one2many_phone.res_partner_phone_search
|
||||
msgid "Search Phones/E-mail"
|
||||
msgstr ""
|
||||
|
||||
#. module: base_partner_one2many_phone
|
||||
#: selection:res.partner.phone,type:0
|
||||
#: model:ir.model.fields.selection,name:base_partner_one2many_phone.selection__res_partner_phone__type__2_email_secondary
|
||||
msgid "Secondary E-mail"
|
||||
msgstr ""
|
||||
|
||||
#. module: base_partner_one2many_phone
|
||||
#: selection:res.partner.phone,type:0
|
||||
#: model:ir.model.fields.selection,name:base_partner_one2many_phone.selection__res_partner_phone__type__8_fax_secondary
|
||||
msgid "Secondary Fax"
|
||||
msgstr ""
|
||||
|
||||
#. module: base_partner_one2many_phone
|
||||
#: selection:res.partner.phone,type:0
|
||||
#: model:ir.model.fields.selection,name:base_partner_one2many_phone.selection__res_partner_phone__type__6_mobile_secondary
|
||||
msgid "Secondary Mobile"
|
||||
msgstr ""
|
||||
|
||||
#. module: base_partner_one2many_phone
|
||||
#: selection:res.partner.phone,type:0
|
||||
#: model:ir.model.fields.selection,name:base_partner_one2many_phone.selection__res_partner_phone__type__4_phone_secondary
|
||||
msgid "Secondary Phone"
|
||||
msgstr ""
|
||||
|
||||
#. module: base_partner_one2many_phone
|
||||
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner_phone_type
|
||||
#: model:ir.ui.view,arch_db:base_partner_one2many_phone.res_partner_phone_search
|
||||
#: 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
|
||||
msgid "Type"
|
||||
msgstr ""
|
||||
|
||||
#. module: base_partner_one2many_phone
|
||||
#: model:ir.model,name:base_partner_one2many_phone.model_res_partner_phone
|
||||
msgid "res.partner.phone"
|
||||
msgstr ""
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
# Translation of Odoo Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * base_partner_one2many_phone
|
||||
# * base_partner_one2many_phone
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Odoo Server 10.0\n"
|
||||
"Project-Id-Version: Odoo Server 14.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-01-27 17:56+0000\n"
|
||||
"PO-Revision-Date: 2020-01-27 17:56+0000\n"
|
||||
"Last-Translator: <>\n"
|
||||
"POT-Creation-Date: 2021-10-29 21:12+0000\n"
|
||||
"PO-Revision-Date: 2021-10-29 21:12+0000\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
@@ -16,159 +16,187 @@ msgstr ""
|
||||
"Plural-Forms: \n"
|
||||
|
||||
#. module: base_partner_one2many_phone
|
||||
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner_phone_create_uid
|
||||
#: model:ir.model,name:base_partner_one2many_phone.model_res_partner
|
||||
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"
|
||||
msgstr "Créé par"
|
||||
|
||||
#. 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"
|
||||
msgstr "Créé le"
|
||||
|
||||
#. module: base_partner_one2many_phone
|
||||
#: 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__display_name
|
||||
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner_phone__display_name
|
||||
msgid "Display Name"
|
||||
msgstr "Nom à afficher"
|
||||
msgstr "Nom affiché"
|
||||
|
||||
#. 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"
|
||||
msgstr "Courriel"
|
||||
msgstr "E-Mail"
|
||||
|
||||
#. module: base_partner_one2many_phone
|
||||
#: code:addons/base_partner_one2many_phone/partner_phone.py:61
|
||||
#: code:addons/base_partner_one2many_phone/partner_phone.py:0
|
||||
#, python-format
|
||||
msgid "E-mail field must be empty when type is Primary/Secondary Phone, Primary/Secondary Mobile or Primary/Secondary Fax."
|
||||
msgstr "Le champ courriel doit être vide quand le type est tél. primaire/secondaire, portable primaire/secondaire ou fax primaire/secondaire."
|
||||
msgid ""
|
||||
"E-mail field must be empty when type is Primary/Secondary Phone, "
|
||||
"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
|
||||
#: code:addons/base_partner_one2many_phone/partner_phone.py:51
|
||||
#: code:addons/base_partner_one2many_phone/partner_phone.py:0
|
||||
#, python-format
|
||||
msgid "E-mail field must have a value when type is Primary E-mail or Secondary E-mail."
|
||||
msgstr "Le champ courriel doit être renseigné quand le type est courriel primaire ou courriel secondaire."
|
||||
msgid ""
|
||||
"E-mail field must have a value when type is Primary E-mail or Secondary "
|
||||
"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
|
||||
#: 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_partner__email
|
||||
#: 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"
|
||||
msgstr "ID"
|
||||
msgstr ""
|
||||
|
||||
#. module: base_partner_one2many_phone
|
||||
#: 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____last_update
|
||||
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner_phone____last_update
|
||||
msgid "Last Modified on"
|
||||
msgstr "Dernière modification le"
|
||||
|
||||
#. 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"
|
||||
msgstr "Dernière mise à jour par"
|
||||
msgstr "Dernière modification par"
|
||||
|
||||
#. 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"
|
||||
msgstr "Dernière mise à jour le"
|
||||
msgstr "Dernière modification le"
|
||||
|
||||
#. module: base_partner_one2many_phone
|
||||
#: 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_partner__mobile
|
||||
#: 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"
|
||||
msgstr "Note"
|
||||
|
||||
#. module: base_partner_one2many_phone
|
||||
#: model:ir.model,name:base_partner_one2many_phone.model_res_partner
|
||||
msgid "Partner"
|
||||
msgstr "Partenaire"
|
||||
|
||||
#. module: base_partner_one2many_phone
|
||||
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner_phone_phone
|
||||
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner__phone
|
||||
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner_phone__phone
|
||||
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_users__phone
|
||||
msgid "Phone"
|
||||
msgstr "Téléphone"
|
||||
msgstr "Tél."
|
||||
|
||||
#. module: base_partner_one2many_phone
|
||||
#: code:addons/base_partner_one2many_phone/partner_phone.py:54
|
||||
#: model_terms:ir.ui.view,arch_db:base_partner_one2many_phone.res_partner_phone_form
|
||||
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
|
||||
msgid "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."
|
||||
msgid ""
|
||||
"Phone field must be empty when type is Primary E-mail or Secondary E-mail."
|
||||
msgstr "Le champ Tél. doit être vide quand le type est E-mail principal ou E-mail secondaire."
|
||||
|
||||
#. module: base_partner_one2many_phone
|
||||
#: code:addons/base_partner_one2many_phone/partner_phone.py:58
|
||||
#: code:addons/base_partner_one2many_phone/partner_phone.py:0
|
||||
#, python-format
|
||||
msgid "Phone field must have a value when type is Primary/Secondary Phone, Primary/Secondary Mobile or Primary/Secondary Fax."
|
||||
msgstr "Le champ téléphone doit être renseigné quand le type est tél. primaire/secondaire, portable primaire/secondaire ou fax primaire/secondaire.."
|
||||
msgid ""
|
||||
"Phone field must have a value when type is Primary/Secondary Phone, "
|
||||
"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
|
||||
#: 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
|
||||
#: model_terms:ir.ui.view,arch_db:base_partner_one2many_phone.res_partner_phone_tree
|
||||
msgid "Phones and E-mail"
|
||||
msgstr "Téls et courriels"
|
||||
msgstr "Téls et E-mail"
|
||||
|
||||
#. module: base_partner_one2many_phone
|
||||
#: 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
|
||||
msgid "Phones/E-mails"
|
||||
msgstr "Téls/Courriels"
|
||||
msgstr "Téls/E-mails"
|
||||
|
||||
#. module: base_partner_one2many_phone
|
||||
#: selection:res.partner.phone,type:0
|
||||
#: 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/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"
|
||||
msgstr "Courriel principal"
|
||||
msgstr "E-mail principal"
|
||||
|
||||
#. module: base_partner_one2many_phone
|
||||
#: selection:res.partner.phone,type:0
|
||||
#: model:ir.model.fields.selection,name:base_partner_one2many_phone.selection__res_partner_phone__type__7_fax_primary
|
||||
msgid "Primary Fax"
|
||||
msgstr "Fax principal"
|
||||
|
||||
#. module: base_partner_one2many_phone
|
||||
#: selection:res.partner.phone,type:0
|
||||
#: model:ir.model.fields.selection,name:base_partner_one2many_phone.selection__res_partner_phone__type__5_mobile_primary
|
||||
msgid "Primary Mobile"
|
||||
msgstr "Portable principal"
|
||||
|
||||
#. module: base_partner_one2many_phone
|
||||
#: selection:res.partner.phone,type:0
|
||||
#: model:ir.model.fields.selection,name:base_partner_one2many_phone.selection__res_partner_phone__type__3_phone_primary
|
||||
msgid "Primary Phone"
|
||||
msgstr "Tél principal"
|
||||
msgstr "Tél. principal"
|
||||
|
||||
#. 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"
|
||||
msgstr "Partenaire associé"
|
||||
|
||||
#. module: base_partner_one2many_phone
|
||||
#: model:ir.ui.view,arch_db:base_partner_one2many_phone.res_partner_phone_search
|
||||
#: model_terms:ir.ui.view,arch_db:base_partner_one2many_phone.res_partner_phone_search
|
||||
msgid "Search Phones/E-mail"
|
||||
msgstr "Search Phones/E-mail"
|
||||
msgstr ""
|
||||
|
||||
#. module: base_partner_one2many_phone
|
||||
#: selection:res.partner.phone,type:0
|
||||
#: model:ir.model.fields.selection,name:base_partner_one2many_phone.selection__res_partner_phone__type__2_email_secondary
|
||||
msgid "Secondary E-mail"
|
||||
msgstr "Courriel secondaire"
|
||||
msgstr "E-mail secondaire"
|
||||
|
||||
#. module: base_partner_one2many_phone
|
||||
#: selection:res.partner.phone,type:0
|
||||
#: model:ir.model.fields.selection,name:base_partner_one2many_phone.selection__res_partner_phone__type__8_fax_secondary
|
||||
msgid "Secondary Fax"
|
||||
msgstr "Fax secondaire"
|
||||
|
||||
#. module: base_partner_one2many_phone
|
||||
#: selection:res.partner.phone,type:0
|
||||
#: model:ir.model.fields.selection,name:base_partner_one2many_phone.selection__res_partner_phone__type__6_mobile_secondary
|
||||
msgid "Secondary Mobile"
|
||||
msgstr "Portable secondaire"
|
||||
|
||||
#. module: base_partner_one2many_phone
|
||||
#: selection:res.partner.phone,type:0
|
||||
#: model:ir.model.fields.selection,name:base_partner_one2many_phone.selection__res_partner_phone__type__4_phone_secondary
|
||||
msgid "Secondary Phone"
|
||||
msgstr "Tél. secondaire"
|
||||
|
||||
#. module: base_partner_one2many_phone
|
||||
#: model:ir.model.fields,field_description:base_partner_one2many_phone.field_res_partner_phone_type
|
||||
#: model:ir.ui.view,arch_db:base_partner_one2many_phone.res_partner_phone_search
|
||||
#: 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
|
||||
msgid "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"
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
<field name="name">res.partner.phone.tree</field>
|
||||
<field name="model">res.partner.phone</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Phones and E-mail" editable="bottom">
|
||||
<tree editable="bottom">
|
||||
<field name="partner_id" invisible="not context.get('partner_phone_main_view')"/>
|
||||
<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'))]}"/>
|
||||
@@ -28,7 +28,7 @@
|
||||
<field name="name">res.partner.phone.form</field>
|
||||
<field name="model">res.partner.phone</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Phone and E-mail">
|
||||
<form>
|
||||
<group name="main">
|
||||
<field name="partner_id" invisible="not context.get('partner_phone_main_view')"/>
|
||||
<field name="type"/>
|
||||
@@ -44,7 +44,7 @@
|
||||
<field name="name">res.partner.phone.search</field>
|
||||
<field name="model">res.partner.phone</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Search Phones/E-mail">
|
||||
<search>
|
||||
<field name="phone" />
|
||||
<field name="email" />
|
||||
<group name="groupby">
|
||||
|
||||
@@ -1 +1 @@
|
||||
from . import partner
|
||||
from . import models
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
# Copyright 2017-2019 Akretion (http://www.akretion.com)
|
||||
# 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).
|
||||
|
||||
{
|
||||
'name': 'Base Partner Reference',
|
||||
'version': '12.0.1.0.0',
|
||||
'version': '14.0.1.0.0',
|
||||
'category': 'Partner',
|
||||
'license': 'AGPL-3',
|
||||
'summary': "Improve usage of partner's Internal Reference",
|
||||
@@ -21,6 +21,6 @@ Base Partner Reference
|
||||
'author': 'Akretion',
|
||||
'website': 'http://www.akretion.com',
|
||||
'depends': ['base'],
|
||||
'data': ['partner_view.xml'],
|
||||
'installable': False,
|
||||
'data': ['views/res_partner.xml'],
|
||||
'installable': True,
|
||||
}
|
||||
|
||||
1
base_partner_ref/models/__init__.py
Normal file
1
base_partner_ref/models/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from . import res_partner
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright 2017-2019 Akretion
|
||||
# Copyright 2017-2021 Akretion
|
||||
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
@@ -18,9 +18,9 @@ class ResPartner(models.Model):
|
||||
)]
|
||||
|
||||
# add 'ref' in depends
|
||||
@api.depends('is_company', 'name', 'parent_id.name', 'type', 'company_name', 'ref', 'invalidate_display_name')
|
||||
@api.depends('ref', 'invalidate_display_name')
|
||||
def _compute_display_name(self):
|
||||
super(ResPartner, self)._compute_display_name()
|
||||
super()._compute_display_name()
|
||||
|
||||
def _get_name(self):
|
||||
partner = self
|
||||
@@ -32,12 +32,13 @@ class ResPartner(models.Model):
|
||||
# END modif of native method
|
||||
if partner.company_name or partner.parent_id:
|
||||
if not name and partner.type in ['invoice', 'delivery', 'other']:
|
||||
name = dict(self.fields_get(['type'])['type']['selection'])[partner.type]
|
||||
name = dict(self.fields_get(
|
||||
['type'])['type']['selection'])[partner.type]
|
||||
if not partner.is_company:
|
||||
# START modif of native name_get() method
|
||||
company_name = partner.commercial_company_name or partner.parent_id.name
|
||||
if partner.parent_id.ref:
|
||||
company_name = u"[%s] %s" % (partner.parent_id.ref, company_name)
|
||||
company_name = "[%s] %s" % (partner.parent_id.ref, company_name)
|
||||
name = "%s, %s" % (company_name, name)
|
||||
# END modif of native name_get() method
|
||||
if self._context.get('show_address_only'):
|
||||
@@ -47,7 +48,8 @@ class ResPartner(models.Model):
|
||||
name = name.replace('\n\n', '\n')
|
||||
name = name.replace('\n\n', '\n')
|
||||
if self._context.get('address_inline'):
|
||||
name = name.replace('\n', ', ')
|
||||
splitted_names = name.split("\n")
|
||||
name = ", ".join([n for n in splitted_names if n.strip()])
|
||||
if self._context.get('show_email') and partner.email:
|
||||
name = "%s <%s>" % (name, partner.email)
|
||||
if self._context.get('html_format'):
|
||||
@@ -63,5 +65,6 @@ class ResPartner(models.Model):
|
||||
if name and operator == 'ilike':
|
||||
recs = self.search([('ref', '=', name)] + args, limit=limit)
|
||||
if recs:
|
||||
return recs.name_get()
|
||||
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)
|
||||
@@ -11,29 +11,34 @@
|
||||
<field name="name">Move ref in partner form to make it more visible</field>
|
||||
<field name="model">res.partner</field>
|
||||
<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="type" position="after">
|
||||
<field name="ref"/>
|
||||
</field>
|
||||
<xpath expr="//page[@name='sales_purchases']//field[@name='ref']" position="replace"/>
|
||||
<xpath expr="//page[@name='sales_purchases']//field[@name='ref']" position="attributes">
|
||||
<attribute name="invisible">1</attribute>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- show name and ref in separate columns -->
|
||||
<!-- ref is added in tree view by base_usability with optional="hide"
|
||||
<record id="view_partner_tree" model="ir.ui.view">
|
||||
<field name="name">Add ref in partner tree view</field>
|
||||
<field name="model">res.partner</field>
|
||||
<field name="inherit_id" ref="base.view_partner_tree"/>
|
||||
<field name="arch" type="xml">
|
||||
<!-- show name and ref in separate columns -->
|
||||
<field name="display_name" position="after">
|
||||
<field name="name"/>
|
||||
<field name="ref"/>
|
||||
<field name="ref" optional="hide"/>
|
||||
</field>
|
||||
<field name="display_name" position="attributes">
|
||||
<attribute name="invisible">1</attribute>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
-->
|
||||
|
||||
<record id="res_partner_kanban_view" model="ir.ui.view">
|
||||
<field name="name">Add ref in partner kanban view</field>
|
||||
@@ -39,6 +39,9 @@
|
||||
<field name="model">res.partner</field>
|
||||
<field name="inherit_id" ref="base.view_partner_tree"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="display_name" position="after">
|
||||
<field name="ref" optional="hide"/>
|
||||
</field>
|
||||
<field name="phone" position="after">
|
||||
<field name="mobile" optional="show" widget="phone" class="o_force_ltr"/>
|
||||
</field>
|
||||
|
||||
1
crm_usability/__init__.py
Normal file
1
crm_usability/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from . import models
|
||||
25
crm_usability/__manifest__.py
Normal file
25
crm_usability/__manifest__.py
Normal file
@@ -0,0 +1,25 @@
|
||||
# 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,
|
||||
}
|
||||
1
crm_usability/models/__init__.py
Normal file
1
crm_usability/models/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from . import crm_lead
|
||||
13
crm_usability/models/crm_lead.py
Normal file
13
crm_usability/models/crm_lead.py
Normal file
@@ -0,0 +1,13 @@
|
||||
# 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)
|
||||
BIN
crm_usability/static/description/icon.png
Normal file
BIN
crm_usability/static/description/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.5 KiB |
22
crm_usability/views/crm_lead.xml
Normal file
22
crm_usability/views/crm_lead.xml
Normal file
@@ -0,0 +1,22 @@
|
||||
<?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>
|
||||
1
delivery_usability/models/__init__.py
Normal file
1
delivery_usability/models/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from . import stock_picking
|
||||
1
hr_contract_usability/__init__.py
Normal file
1
hr_contract_usability/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from . import models
|
||||
20
hr_contract_usability/__manifest__.py
Normal file
20
hr_contract_usability/__manifest__.py
Normal file
@@ -0,0 +1,20 @@
|
||||
# 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,
|
||||
}
|
||||
1
hr_contract_usability/models/__init__.py
Normal file
1
hr_contract_usability/models/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from . import hr_payroll_structure_type
|
||||
10
hr_contract_usability/models/hr_payroll_structure_type.py
Normal file
10
hr_contract_usability/models/hr_payroll_structure_type.py
Normal file
@@ -0,0 +1,10 @@
|
||||
# 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)
|
||||
63
hr_contract_usability/views/hr_payroll_structure_type.xml
Normal file
63
hr_contract_usability/views/hr_payroll_structure_type.xml
Normal file
@@ -0,0 +1,63 @@
|
||||
<?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>
|
||||
27
link_tracker_usability/__manifest__.py
Normal file
27
link_tracker_usability/__manifest__.py
Normal file
@@ -0,0 +1,27 @@
|
||||
# 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,
|
||||
}
|
||||
45
link_tracker_usability/views/link_tracker_click.xml
Normal file
45
link_tracker_usability/views/link_tracker_click.xml
Normal file
@@ -0,0 +1,45 @@
|
||||
<?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>
|
||||
1
mass_mailing_usability/__init__.py
Normal file
1
mass_mailing_usability/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from . import models
|
||||
29
mass_mailing_usability/__manifest__.py
Normal file
29
mass_mailing_usability/__manifest__.py
Normal file
@@ -0,0 +1,29 @@
|
||||
# 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,
|
||||
}
|
||||
48
mass_mailing_usability/views/link_tracker.xml
Normal file
48
mass_mailing_usability/views/link_tracker.xml
Normal file
@@ -0,0 +1,48 @@
|
||||
<?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>
|
||||
@@ -12,16 +12,20 @@ class ProductTemplate(models.Model):
|
||||
only one BoM form or a list of BoMs."""
|
||||
self.ensure_one()
|
||||
if self.bom_count == 1:
|
||||
action = self.env.ref("mrp.mrp_bom_form_action").read()[0]
|
||||
action_xml_id = "mrp.mrp_bom_form_action"
|
||||
action = self.env["ir.actions.actions"]._for_xml_id(action_xml_id)
|
||||
bom = self.env["mrp.bom"].search([("product_tmpl_id", "=", self.id)])
|
||||
action.update({
|
||||
"context": {"default_product_tmpl_id": self.id},
|
||||
"views": False,
|
||||
"view_mode": "form,tree",
|
||||
"res_id": bom.id,
|
||||
})
|
||||
action.update(
|
||||
{
|
||||
"context": {"default_product_tmpl_id": self.id},
|
||||
"views": False,
|
||||
"view_mode": "form,tree",
|
||||
"res_id": bom.id,
|
||||
}
|
||||
)
|
||||
else:
|
||||
action = self.env.ref("mrp.template_open_bom").read()[0]
|
||||
action_xml_id = "mrp.template_open_bom"
|
||||
action = self.env["ir.actions.actions"]._for_xml_id(action_xml_id)
|
||||
return action
|
||||
|
||||
|
||||
@@ -32,9 +36,11 @@ class ProductProduct(models.Model):
|
||||
action = super().action_view_bom()
|
||||
bom_target_ids = self.env["mrp.bom"].search(action["domain"])
|
||||
if len(bom_target_ids) == 1:
|
||||
action.update({
|
||||
"views": False,
|
||||
"view_mode": "form,tree",
|
||||
"res_id": bom_target_ids[0].id,
|
||||
})
|
||||
action.update(
|
||||
{
|
||||
"views": False,
|
||||
"view_mode": "form,tree",
|
||||
"res_id": bom_target_ids[0].id,
|
||||
}
|
||||
)
|
||||
return action
|
||||
|
||||
@@ -29,4 +29,15 @@
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="mrp_production_tree_view" model="ir.ui.view">
|
||||
<field name="model">mrp.production</field>
|
||||
<field name="inherit_id" ref="mrp.mrp_production_tree_view"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="reservation_state" position="after">
|
||||
<field name="location_src_id" optional="hide" groups="stock.group_stock_multi_locations"/>
|
||||
<field name="location_dest_id" optional="hide" groups="stock.group_stock_multi_locations"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
# 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,
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
<?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>
|
||||
@@ -28,7 +28,9 @@ Akretion:
|
||||
"depends": ["point_of_sale"],
|
||||
"data": [
|
||||
"report/pos.xml",
|
||||
"views/report_pos_order.xml",
|
||||
"views/pos_category.xml",
|
||||
"views/pos_session.xml",
|
||||
"views/product.xml",
|
||||
],
|
||||
"installable": True,
|
||||
|
||||
31
pos_usability/views/pos_session.xml
Normal file
31
pos_usability/views/pos_session.xml
Normal file
@@ -0,0 +1,31 @@
|
||||
<?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>
|
||||
26
pos_usability/views/report_pos_order.xml
Normal file
26
pos_usability/views/report_pos_order.xml
Normal file
@@ -0,0 +1,26 @@
|
||||
<?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>
|
||||
@@ -32,6 +32,7 @@ This module has been written by Alexis de Lattre from Akretion <alexis.delattre@
|
||||
'views/product_pricelist_item.xml',
|
||||
'views/product_template_view.xml',
|
||||
'views/product_product.xml',
|
||||
'views/product_category_view.xml',
|
||||
],
|
||||
'installable': True,
|
||||
}
|
||||
|
||||
@@ -2,3 +2,4 @@ from . import product_product
|
||||
from . import product_template
|
||||
from . import product_supplierinfo
|
||||
from . import product_pricelist
|
||||
from . import product_category
|
||||
|
||||
13
product_usability/models/product_category.py
Normal file
13
product_usability/models/product_category.py
Normal file
@@ -0,0 +1,13 @@
|
||||
# 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)
|
||||
@@ -1,21 +1,21 @@
|
||||
# Copyright 2015-2020 Akretion (http://www.akretion.com)
|
||||
# Copyright 2015-2021 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# @author Raphaël Valyi <rvalyi@akretion.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import models, fields
|
||||
from odoo import api, models, fields
|
||||
|
||||
|
||||
class ProductProduct(models.Model):
|
||||
_inherit = 'product.product'
|
||||
|
||||
default_code = fields.Char(copy=False)
|
||||
# track_visibility='onchange',
|
||||
|
||||
# barcode = fields.Char(track_visibility='onchange',
|
||||
|
||||
# weight = fields.Float(track_visibility='onchange')
|
||||
# active = fields.Boolean(track_visibility='onchange')
|
||||
default_code = fields.Char(copy=False, tracking=10)
|
||||
barcode = fields.Char(tracking=20)
|
||||
weight = fields.Float(tracking=30)
|
||||
active = fields.Boolean(tracking=40)
|
||||
barcode_code128 = fields.Char(
|
||||
compute='_compute_barcode_code128',
|
||||
help="Barcode in Code128-B with start char, checksum and stop char")
|
||||
|
||||
_sql_constraints = [(
|
||||
# Maybe it could be better to have a constrain per company
|
||||
@@ -26,3 +26,32 @@ class ProductProduct(models.Model):
|
||||
'default_code_uniq',
|
||||
'unique(default_code)',
|
||||
'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
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright 2015-2020 Akretion (http://www.akretion.com)
|
||||
# Copyright 2015-2021 Akretion (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# @author Raphaël Valyi <rvalyi@akretion.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
@@ -21,9 +21,13 @@ class ProductTemplate(models.Model):
|
||||
# are only shown in the form view of product.template, not in the form
|
||||
# view of product.product
|
||||
name = fields.Char(tracking=10)
|
||||
categ_id = fields.Many2one(tracking=20)
|
||||
type = fields.Selection(tracking=30)
|
||||
list_price = fields.Float(tracking=40)
|
||||
sale_ok = fields.Boolean(tracking=50)
|
||||
purchase_ok = fields.Boolean(tracking=60)
|
||||
active = fields.Boolean(tracking=70)
|
||||
barcode = fields.Char(tracking=20)
|
||||
default_code = fields.Char(tracking=30)
|
||||
categ_id = fields.Many2one(tracking=40)
|
||||
type = fields.Selection(tracking=50)
|
||||
list_price = fields.Float(tracking=60)
|
||||
weight = fields.Float(tracking=70)
|
||||
sale_ok = fields.Boolean(tracking=80)
|
||||
purchase_ok = fields.Boolean(tracking=90)
|
||||
active = fields.Boolean(tracking=100)
|
||||
company_id = fields.Many2one(tracking=110)
|
||||
|
||||
19
product_usability/views/product_category_view.xml
Normal file
19
product_usability/views/product_category_view.xml
Normal file
@@ -0,0 +1,19 @@
|
||||
<?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>
|
||||
|
||||
185
purchase_usability/i18n/fr.po
Normal file
185
purchase_usability/i18n/fr.po
Normal file
@@ -0,0 +1,185 @@
|
||||
# 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"
|
||||
@@ -73,3 +73,28 @@ class PurchaseOrderLine(models.Model):
|
||||
|
||||
# for optional display in tree view
|
||||
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)
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
<attribute name="groups">analytic.group_analytic_tags</attribute>
|
||||
</xpath>
|
||||
<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"/>
|
||||
</xpath>
|
||||
</field>
|
||||
|
||||
2
sale_confirm_wizard/__init__.py
Normal file
2
sale_confirm_wizard/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
from . import models
|
||||
from . import wizard
|
||||
38
sale_confirm_wizard/__manifest__.py
Normal file
38
sale_confirm_wizard/__manifest__.py
Normal file
@@ -0,0 +1,38 @@
|
||||
# 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,
|
||||
}
|
||||
1
sale_confirm_wizard/models/__init__.py
Normal file
1
sale_confirm_wizard/models/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from . import sale_order
|
||||
17
sale_confirm_wizard/models/sale_order.py
Normal file
17
sale_confirm_wizard/models/sale_order.py
Normal file
@@ -0,0 +1,17 @@
|
||||
# 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
|
||||
2
sale_confirm_wizard/security/ir.model.access.csv
Normal file
2
sale_confirm_wizard/security/ir.model.access.csv
Normal file
@@ -0,0 +1,2 @@
|
||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_sale_confirm_wizard,Full access on sale.confirm wizard,model_sale_confirm,sales_team.group_sale_salesman,1,1,1,1
|
||||
|
24
sale_confirm_wizard/views/sale_order.xml
Normal file
24
sale_confirm_wizard/views/sale_order.xml
Normal file
@@ -0,0 +1,24 @@
|
||||
<?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>
|
||||
1
sale_confirm_wizard/wizard/__init__.py
Normal file
1
sale_confirm_wizard/wizard/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from . import sale_confirm
|
||||
78
sale_confirm_wizard/wizard/sale_confirm.py
Normal file
78
sale_confirm_wizard/wizard/sale_confirm.py
Normal file
@@ -0,0 +1,78 @@
|
||||
# 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).
|
||||
|
||||
from odoo import models, fields, api, _
|
||||
from odoo.exceptions import UserError
|
||||
from odoo.addons.base.models.res_partner import WARNING_MESSAGE
|
||||
|
||||
|
||||
class SaleConfirm(models.TransientModel):
|
||||
_name = 'sale.confirm'
|
||||
_description = 'Wizard to confirm a sale order'
|
||||
|
||||
sale_id = fields.Many2one(
|
||||
'sale.order', string='Sale Order', readonly=True)
|
||||
client_order_ref = fields.Char(string='Customer PO Number')
|
||||
payment_term_id = fields.Many2one(
|
||||
'account.payment.term', string='Payment Terms')
|
||||
partner_invoice_id = fields.Many2one(
|
||||
'res.partner', 'Invoice Address', required=True)
|
||||
show_partner_invoice_id = fields.Many2one(
|
||||
related='partner_invoice_id',
|
||||
string='Detailed Invoice Address')
|
||||
partner_shipping_id = fields.Many2one(
|
||||
'res.partner', 'Delivery Address', required=True)
|
||||
show_partner_shipping_id = fields.Many2one(
|
||||
related='partner_shipping_id',
|
||||
string='Detailed Delivery Address')
|
||||
sale_warn = fields.Selection(
|
||||
WARNING_MESSAGE, 'Sale Warning Type', readonly=True)
|
||||
sale_warn_msg = fields.Text(string='Sale Warning Message', readonly=True)
|
||||
|
||||
@api.model
|
||||
def _prepare_default_get(self, order):
|
||||
partner = order.partner_id.commercial_partner_id
|
||||
default = {
|
||||
'sale_id': order.id,
|
||||
'client_order_ref': order.client_order_ref,
|
||||
'payment_term_id': order.payment_term_id.id or False,
|
||||
'partner_invoice_id': order.partner_invoice_id.id,
|
||||
'partner_shipping_id': order.partner_shipping_id.id,
|
||||
'sale_warn_msg': partner.sale_warn_msg,
|
||||
'sale_warn': partner.sale_warn,
|
||||
}
|
||||
return default
|
||||
|
||||
@api.model
|
||||
def default_get(self, fields):
|
||||
res = super().default_get(fields)
|
||||
assert self._context.get('active_model') == 'sale.order',\
|
||||
'active_model should be sale.order'
|
||||
order = self.env['sale.order'].browse(self._context.get('active_id'))
|
||||
default = self._prepare_default_get(order)
|
||||
res.update(default)
|
||||
return res
|
||||
|
||||
def _prepare_update_so(self):
|
||||
self.ensure_one()
|
||||
return {
|
||||
'client_order_ref': self.client_order_ref,
|
||||
'payment_term_id': self.payment_term_id.id or False,
|
||||
'partner_invoice_id': self.partner_invoice_id.id,
|
||||
'partner_shipping_id': self.partner_shipping_id.id,
|
||||
}
|
||||
|
||||
def confirm(self):
|
||||
self.ensure_one()
|
||||
partner = self.sale_id.partner_id.commercial_partner_id
|
||||
if partner.sale_warn == 'block':
|
||||
raise UserError(_(
|
||||
"You cannot confirm this quotation because "
|
||||
"customer '%s' has a blocker sale warning:\n\n%s")
|
||||
% (partner.display_name, partner.sale_warn_msg))
|
||||
vals = self._prepare_update_so()
|
||||
self.sale_id.write(vals)
|
||||
# confirm sale order
|
||||
self.sale_id.action_confirm()
|
||||
return True
|
||||
54
sale_confirm_wizard/wizard/sale_confirm_view.xml
Normal file
54
sale_confirm_wizard/wizard/sale_confirm_view.xml
Normal file
@@ -0,0 +1,54 @@
|
||||
<?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="sale_confirm_form" model="ir.ui.view">
|
||||
<field name="name">sale.confirm.form</field>
|
||||
<field name="model">sale.confirm</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Confirm Order">
|
||||
<div><p>At this stage, you have received the Purchase Order from the customer and you are about to convert the related quotation to an order.</p></div>
|
||||
<group name="warn" groups="sale.group_warning_sale" attrs="{'invisible': ['|', ('sale_warn', '=', False), ('sale_warn', '=', 'no-message')]}" string="Warning" col="4">
|
||||
<field name="sale_warn" nolabel="1"/>
|
||||
<field name="sale_warn_msg" nolabel="1" colspan="3"/>
|
||||
</group>
|
||||
<group name="main" attrs="{'invisible': [('sale_warn', '=', 'block')]}">
|
||||
<field name="sale_id" invisible="1"/>
|
||||
<field name="client_order_ref"/>
|
||||
<field name="partner_invoice_id" context="{'default_type': 'invoice'}"
|
||||
groups="sale.group_delivery_invoice_address"/>
|
||||
<!-- partner_invoice_id can't show the full address because
|
||||
we are in edit mode -->
|
||||
<field name="show_partner_invoice_id" options="{'always_reload': True}"
|
||||
context="{'show_address': 1}"
|
||||
groups="sale.group_delivery_invoice_address"/>
|
||||
<field name="partner_shipping_id"
|
||||
context="{'default_type': 'delivery'}"
|
||||
groups="sale.group_delivery_invoice_address"/>
|
||||
<field name="show_partner_shipping_id" options="{'always_reload': True}"
|
||||
context="{'show_address': 1}"
|
||||
groups="sale.group_delivery_invoice_address"/>
|
||||
<field name="payment_term_id"/>
|
||||
</group>
|
||||
<footer>
|
||||
<button type="object" name="confirm"
|
||||
string="Confirm Sale" class="btn-primary" attrs="{'invisible': [('sale_warn', '=', 'block')]}"/>
|
||||
<button special="cancel" string="Annuler" class="btn-default"/>
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="sale_confirm_action" model="ir.actions.act_window">
|
||||
<field name="name">Confirm Order</field>
|
||||
<field name="res_model">sale.confirm</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="target">new</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
2
sale_order_add_bom/__init__.py
Normal file
2
sale_order_add_bom/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
from . import models
|
||||
from . import wizard
|
||||
29
sale_order_add_bom/__manifest__.py
Normal file
29
sale_order_add_bom/__manifest__.py
Normal file
@@ -0,0 +1,29 @@
|
||||
# Copyright 2016-2022 Akretion France (http://www.akretion.com/)
|
||||
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
{
|
||||
'name': 'Sale Order Add Bom',
|
||||
'version': '14.0.1.0.0',
|
||||
'category': 'Sales',
|
||||
'license': 'AGPL-3',
|
||||
'summary': 'Wizard to select a bom from a sale order',
|
||||
'description': """
|
||||
This module adds a wizard *Add Kit* on the form view of a quotation that allows the user to select a 'kit' BOM: Odoo will automatically add the components of the kit as sale order lines.
|
||||
|
||||
The wizard *Add Kit* is also available on a draft picking.
|
||||
|
||||
This module has been written by Alexis de Lattre from Akretion
|
||||
<alexis.delattre@akretion.com>.
|
||||
""",
|
||||
'author': 'Akretion',
|
||||
'website': 'https://github.com/akretion/odoo-usability',
|
||||
'depends': ['sale', 'mrp'],
|
||||
'data': [
|
||||
'wizard/sale_add_phantom_bom_view.xml',
|
||||
'views/sale_order.xml',
|
||||
'views/stock_picking.xml',
|
||||
'security/ir.model.access.csv',
|
||||
],
|
||||
'installable': True,
|
||||
}
|
||||
1
sale_order_add_bom/models/__init__.py
Normal file
1
sale_order_add_bom/models/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from . import mrp_bom
|
||||
11
sale_order_add_bom/models/mrp_bom.py
Normal file
11
sale_order_add_bom/models/mrp_bom.py
Normal file
@@ -0,0 +1,11 @@
|
||||
# Copyright 2016-2022 Akretion France (http://www.akretion.com/)
|
||||
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import models, fields
|
||||
|
||||
|
||||
class MrpBom(models.Model):
|
||||
_inherit = 'mrp.bom'
|
||||
|
||||
sale_ok = fields.Boolean(related='product_tmpl_id.sale_ok', store=True)
|
||||
3
sale_order_add_bom/security/ir.model.access.csv
Normal file
3
sale_order_add_bom/security/ir.model.access.csv
Normal file
@@ -0,0 +1,3 @@
|
||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_sale_add_phantom_bom_sale,Full access on sale.add.phantom.bom wizard to sale user,model_sale_add_phantom_bom,sales_team.group_sale_salesman,1,1,1,1
|
||||
access_sale_add_phantom_bom_stock,Full access on sale.add.phantom.bom wizard to stock user,model_sale_add_phantom_bom,stock.group_stock_user,1,1,1,1
|
||||
|
22
sale_order_add_bom/views/sale_order.xml
Normal file
22
sale_order_add_bom/views/sale_order.xml
Normal file
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2016-2022 Akretion France (http://www.akretion.com/)
|
||||
@author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
-->
|
||||
|
||||
<odoo>
|
||||
|
||||
<record id="view_order_form" model="ir.ui.view">
|
||||
<field name="name">add.bom.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 name="action_quotation_send" position="before">
|
||||
<button name="%(sale_add_phantom_bom_action)d" type="action"
|
||||
string="Add Kit" states="draft,sent"/>
|
||||
</button>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
24
sale_order_add_bom/views/stock_picking.xml
Normal file
24
sale_order_add_bom/views/stock_picking.xml
Normal file
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2021-2022 Akretion France (http://www.akretion.com/)
|
||||
@author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
-->
|
||||
|
||||
<odoo>
|
||||
<data>
|
||||
|
||||
<record id="view_picking_form" model="ir.ui.view">
|
||||
<field name="name">add.bom.stock.picking.form</field>
|
||||
<field name="model">stock.picking</field>
|
||||
<field name="inherit_id" ref="stock.view_picking_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<button name="action_confirm" position="after">
|
||||
<button name="%(sale_add_phantom_bom_action)d" type="action"
|
||||
string="Add Kit" states="draft" groups="stock.group_stock_user"/>
|
||||
</button>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</odoo>
|
||||
1
sale_order_add_bom/wizard/__init__.py
Normal file
1
sale_order_add_bom/wizard/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from . import sale_add_phantom_bom
|
||||
96
sale_order_add_bom/wizard/sale_add_phantom_bom.py
Normal file
96
sale_order_add_bom/wizard/sale_add_phantom_bom.py
Normal file
@@ -0,0 +1,96 @@
|
||||
# Copyright 2016-2022 Akretion France (http://www.akretion.com/)
|
||||
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import models, fields, api, _
|
||||
from odoo.exceptions import UserError
|
||||
from odoo.tools import float_is_zero
|
||||
|
||||
|
||||
class SaleAddPhantomBom(models.TransientModel):
|
||||
_name = 'sale.add.phantom.bom'
|
||||
_description = 'Add Kit to Quotation'
|
||||
|
||||
@api.model
|
||||
def default_get(self, fields_list):
|
||||
res = super().default_get(fields_list)
|
||||
if self._context.get('active_model') == 'sale.order':
|
||||
res['sale_id'] = self._context['active_id']
|
||||
sale = self.env['sale.order'].browse(res['sale_id'])
|
||||
res['company_id'] = sale.company_id.id
|
||||
elif self._context.get('active_model') == 'stock.picking':
|
||||
res['picking_id'] = self._context['active_id']
|
||||
picking = self.env['stock.picking'].browse(res['picking_id'])
|
||||
res['company_id'] = picking.company_id.id
|
||||
else:
|
||||
raise UserError(_(
|
||||
"The wizard can only be started from a sale order or a picking."))
|
||||
return res
|
||||
|
||||
bom_id = fields.Many2one(
|
||||
'mrp.bom', 'Kit', required=True,
|
||||
domain="['|', ('company_id', '=', False), ('company_id', '=', company_id), ('type', '=', 'phantom'), ('sale_ok', '=', True)]")
|
||||
company_id = fields.Many2one('res.company', string='Company', required=True)
|
||||
qty = fields.Integer(
|
||||
string='Number of Kits to Add', default=1, required=True)
|
||||
sale_id = fields.Many2one(
|
||||
'sale.order', string='Quotation')
|
||||
picking_id = fields.Many2one(
|
||||
'stock.picking', string='Picking')
|
||||
|
||||
@api.model
|
||||
def _prepare_sale_order_line(self, bom_line, sale_order, wizard_qty):
|
||||
qty_in_product_uom = bom_line.product_uom_id._compute_quantity(
|
||||
bom_line.product_qty,
|
||||
bom_line.product_id.uom_id)
|
||||
vals = {
|
||||
'product_id': bom_line.product_id.id,
|
||||
'product_uom_qty': qty_in_product_uom * wizard_qty,
|
||||
'order_id': sale_order.id,
|
||||
}
|
||||
# on sale.order.line, company_id is a related field
|
||||
return vals
|
||||
|
||||
@api.model
|
||||
def _prepare_stock_move(self, bom_line, picking, wizard_qty):
|
||||
product = bom_line.product_id
|
||||
qty_in_product_uom = bom_line.product_uom_id._compute_quantity(
|
||||
bom_line.product_qty, product.uom_id)
|
||||
vals = {
|
||||
'product_id': product.id,
|
||||
'product_uom_qty': qty_in_product_uom * wizard_qty,
|
||||
'product_uom': product.uom_id.id,
|
||||
'picking_id': picking.id,
|
||||
'company_id': picking.company_id.id,
|
||||
'location_id': picking.location_id.id,
|
||||
'location_dest_id': picking.location_dest_id.id,
|
||||
'name': product.partner_ref,
|
||||
}
|
||||
return vals
|
||||
|
||||
def add(self):
|
||||
self.ensure_one()
|
||||
assert self.sale_id or self.picking_id, 'No related sale_id or picking_id'
|
||||
if self.qty < 1:
|
||||
raise UserError(_(
|
||||
"The number of kits to add must be 1 or superior"))
|
||||
assert self.bom_id.type == 'phantom', 'The BOM is not a kit'
|
||||
if not self.bom_id.bom_line_ids:
|
||||
raise UserError(_("The selected kit is empty !"))
|
||||
prec = self.env['decimal.precision'].precision_get(
|
||||
'Product Unit of Measure')
|
||||
solo = self.env['sale.order.line']
|
||||
smo = self.env['stock.move']
|
||||
for line in self.bom_id.bom_line_ids:
|
||||
if float_is_zero(line.product_qty, precision_digits=prec):
|
||||
continue
|
||||
# The onchange is played in the inherit of the create()
|
||||
# of sale order line in the 'sale' module
|
||||
# TODO: if needed, we could increment existing order lines
|
||||
# with the same product instead of always creating new lines
|
||||
if self.sale_id:
|
||||
vals = self._prepare_sale_order_line(line, self.sale_id, self.qty)
|
||||
solo.create(vals)
|
||||
elif self.picking_id:
|
||||
vals = self._prepare_stock_move(line, self.picking_id, self.qty)
|
||||
smo.create(vals)
|
||||
38
sale_order_add_bom/wizard/sale_add_phantom_bom_view.xml
Normal file
38
sale_order_add_bom/wizard/sale_add_phantom_bom_view.xml
Normal file
@@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2016-2022 Akretion France (http://www.akretion.com/)
|
||||
@author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
-->
|
||||
|
||||
<odoo>
|
||||
|
||||
<record id="sale_add_phantom_bom_form" model="ir.ui.view">
|
||||
<field name="name">sale.add.phantom.bom.form</field>
|
||||
<field name="model">sale.add.phantom.bom</field>
|
||||
<field name="arch" type="xml">
|
||||
<form>
|
||||
<group name="main">
|
||||
<field name="sale_id" invisible="1"/>
|
||||
<field name="picking_id" invisible="1"/>
|
||||
<field name="company_id" invisible="1"/>
|
||||
<field name="bom_id" default_focus="1"/>
|
||||
<field name="qty"/>
|
||||
</group>
|
||||
<footer>
|
||||
<button name="add" type="object"
|
||||
class="btn-primary" string="Add"/>
|
||||
<button special="cancel" string="Cancel"/>
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="sale_add_phantom_bom_action" model="ir.actions.act_window">
|
||||
<field name="name">Add Kit</field>
|
||||
<field name="res_model">sale.add.phantom.bom</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="target">new</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -18,4 +18,25 @@
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_quotation_tree" model="ir.ui.view">
|
||||
<field name="model">sale.order</field>
|
||||
<field name="inherit_id" ref="sale_stock.view_quotation_tree"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="warehouse_id" position="after">
|
||||
<field name="route_id" optional="hide"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_order_tree" model="ir.ui.view">
|
||||
<field name="model">sale.order</field>
|
||||
<field name="inherit_id" ref="sale_stock.view_order_tree"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="warehouse_id" position="after">
|
||||
<field name="route_id" optional="hide"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
</odoo>
|
||||
|
||||
@@ -3,12 +3,12 @@
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
{
|
||||
'name': 'Sale Purchase No Product Template Menu',
|
||||
'version': '12.0.1.0.0',
|
||||
'category': 'Sale and Purchase',
|
||||
'license': 'AGPL-3',
|
||||
'summary': "Replace product.template menu entries by product.product menu entries",
|
||||
'description': """
|
||||
"name": "Sale Purchase No Product Template Menu",
|
||||
"version": "14.0.1.0.0",
|
||||
"category": "Sale and Purchase",
|
||||
"license": "AGPL-3",
|
||||
"summary": "Replace product.template menu entries by product.product menu entries",
|
||||
"description": """
|
||||
Sale Purchase No Product Template
|
||||
=================================
|
||||
|
||||
@@ -18,12 +18,12 @@ This module also switches to the tree view by default for Product menu entries,
|
||||
|
||||
This module has been written by Alexis de Lattre from Akretion <alexis.delattre@akretion.com>.
|
||||
""",
|
||||
'author': 'Akretion',
|
||||
'website': 'http://www.akretion.com',
|
||||
'depends': [
|
||||
'purchase',
|
||||
'sale',
|
||||
],
|
||||
'data': ['view.xml'],
|
||||
'installable': False,
|
||||
"author": "Akretion",
|
||||
"website": "http://www.akretion.com",
|
||||
"depends": [
|
||||
"purchase",
|
||||
"sale",
|
||||
],
|
||||
"data": ["view.xml"],
|
||||
"installable": True,
|
||||
}
|
||||
|
||||
@@ -1,19 +1,21 @@
|
||||
# Translation of Odoo Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * sale_purchase_no_product_template_menu
|
||||
# * sale_purchase_no_product_template_menu
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Odoo Server 8.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2016-05-30 15:27+0000\n"
|
||||
"PO-Revision-Date: 2016-05-30 15:27+0000\n"
|
||||
"POT-Creation-Date: \n"
|
||||
"PO-Revision-Date: 2022-03-28 17:19+0200\n"
|
||||
"Last-Translator: <>\n"
|
||||
"Language-Team: \n"
|
||||
"Language: fr\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: \n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: \n"
|
||||
"X-Generator: Poedit 3.0\n"
|
||||
|
||||
#. module: sale_purchase_no_product_template_menu
|
||||
#: model:ir.ui.menu,name:sale_purchase_no_product_template_menu.sale_config_product_template_menu
|
||||
@@ -21,13 +23,7 @@ msgid "Product Templates"
|
||||
msgstr "Modèles d'article"
|
||||
|
||||
#. module: sale_purchase_no_product_template_menu
|
||||
#: model:ir.actions.act_window,name:sale_purchase_no_product_template_menu.product_product_action_puchased
|
||||
#: model:ir.actions.act_window,name:sale_purchase_no_product_template_menu.product_product_action_purchased
|
||||
#: model:ir.actions.act_window,name:sale_purchase_no_product_template_menu.product_product_action_sell
|
||||
msgid "Products"
|
||||
msgstr "Articles"
|
||||
|
||||
#. module: sale_purchase_no_product_template_menu
|
||||
#: view:product.product:sale_purchase_no_product_template_menu.product_normal_form_view
|
||||
msgid "{'invisible': 1, 'required': 0}"
|
||||
msgstr "{'invisible': 1, 'required': 0}"
|
||||
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
# Translation of Odoo Server.
|
||||
# This file contains the translation of the following modules:
|
||||
# * sale_purchase_no_product_template_menu
|
||||
# * sale_purchase_no_product_template_menu
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Odoo Server 8.0\n"
|
||||
"Project-Id-Version: Odoo Server 14.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2016-05-30 15:27+0000\n"
|
||||
"PO-Revision-Date: 2016-05-30 15:27+0000\n"
|
||||
"Last-Translator: <>\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
@@ -21,13 +19,7 @@ msgid "Product Templates"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_purchase_no_product_template_menu
|
||||
#: model:ir.actions.act_window,name:sale_purchase_no_product_template_menu.product_product_action_puchased
|
||||
#: model:ir.actions.act_window,name:sale_purchase_no_product_template_menu.product_product_action_purchased
|
||||
#: model:ir.actions.act_window,name:sale_purchase_no_product_template_menu.product_product_action_sell
|
||||
msgid "Products"
|
||||
msgstr ""
|
||||
|
||||
#. module: sale_purchase_no_product_template_menu
|
||||
#: view:product.product:sale_purchase_no_product_template_menu.product_normal_form_view
|
||||
msgid "{'invisible': 1, 'required': 0}"
|
||||
msgstr ""
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
'website': 'http://www.akretion.com',
|
||||
'depends': [
|
||||
'sale',
|
||||
'account_usability', # for company view
|
||||
'base_view_inheritance_extension',
|
||||
],
|
||||
'data': [
|
||||
@@ -20,6 +21,7 @@
|
||||
'views/sale_report.xml',
|
||||
'views/product_pricelist_item.xml',
|
||||
'views/account_move.xml',
|
||||
'views/res_company.xml',
|
||||
],
|
||||
'installable': True,
|
||||
}
|
||||
|
||||
@@ -2,3 +2,4 @@ from . import sale_order
|
||||
from . import account_move
|
||||
from . import product_template
|
||||
from . import res_partner
|
||||
from . import res_company
|
||||
|
||||
13
sale_usability/models/res_company.py
Normal file
13
sale_usability/models/res_company.py
Normal file
@@ -0,0 +1,13 @@
|
||||
# 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'
|
||||
|
||||
# Similar to the field static_invoice_terms in account_usability
|
||||
static_sale_terms = fields.Text(
|
||||
translate=True, string="Legal Terms on Quotation")
|
||||
@@ -124,3 +124,14 @@ class SaleOrderLine(models.Model):
|
||||
self.env, new_price, currency_obj=pricelist.currency_id))
|
||||
}
|
||||
return res
|
||||
|
||||
def get_sale_order_line_multiline_description_sale(self, product):
|
||||
# This is useful when you want to have the product code in a dedicated
|
||||
# column in your sale 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 = product.with_context(display_default_code=False)
|
||||
return super().get_sale_order_line_multiline_description_sale(product)
|
||||
|
||||
@@ -7,24 +7,24 @@
|
||||
|
||||
<odoo>
|
||||
|
||||
<!--
|
||||
<record id="account_invoice_form" model="ir.ui.view">
|
||||
<field name="name">sale_usability.customer.invoice.form</field>
|
||||
<field name="model">account.invoice</field>
|
||||
<field name="inherit_id" ref="sale.account_invoice_form"/>
|
||||
<field name="model">account.move</field>
|
||||
<field name="inherit_id" ref="sale.account_invoice_form" />
|
||||
<field name="groups_id" eval="[(4, ref('sales_team.group_sale_manager'))]" />
|
||||
<field name="arch" type="xml">
|
||||
<div name="button_box" position="inside">
|
||||
<button name="show_sale_orders"
|
||||
type="object"
|
||||
class="oe_stat_button"
|
||||
icon="fa-pencil-square-o"
|
||||
attrs="{'invisible': [('sale_count', '=', 0)]}">
|
||||
<field name="sale_count" widget="statinfo" string="Sale Orders"/>
|
||||
<button
|
||||
name="show_sale_orders"
|
||||
type="object"
|
||||
class="oe_stat_button"
|
||||
icon="fa-pencil-square-o"
|
||||
attrs="{'invisible': [('sale_count', '=', 0)]}">
|
||||
<field name="sale_count" widget="statinfo" string="Sale Orders" />
|
||||
</button>
|
||||
</div>
|
||||
</field>
|
||||
</record>
|
||||
-->
|
||||
|
||||
<record id="view_move_form" model="ir.ui.view">
|
||||
<field name="name">sale_usability.account.move.form</field>
|
||||
|
||||
25
sale_usability/views/res_company.xml
Normal file
25
sale_usability/views/res_company.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<?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">sale_usability.res.company.form</field>
|
||||
<field name="model">res.company</field>
|
||||
<field name="inherit_id" ref="account_usability.view_company_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<group name="static_invoice_terms" position="after">
|
||||
<group name="static_sale_terms" string="Quotation Legal Terms">
|
||||
<field name="static_sale_terms" nolabel="1"/>
|
||||
</group>
|
||||
</group>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
</odoo>
|
||||
@@ -54,4 +54,9 @@
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="sale.action_order_report_all" model="ir.actions.act_window">
|
||||
<!-- native order is graph,pivot -->
|
||||
<field name="view_mode">pivot,graph</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
|
||||
1
sales_team_usability/__init__.py
Normal file
1
sales_team_usability/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from . import models
|
||||
27
sales_team_usability/__manifest__.py
Normal file
27
sales_team_usability/__manifest__.py
Normal file
@@ -0,0 +1,27 @@
|
||||
# Copyright 2021 Akretion France (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': 'Sales Teams Usability',
|
||||
'version': '14.0.1.0.0',
|
||||
'category': 'Sales/Sales',
|
||||
'license': 'AGPL-3',
|
||||
'summary': 'Sales Teams usability enhancements',
|
||||
'description': """
|
||||
Sales Teams Usability
|
||||
=====================
|
||||
|
||||
The usability improvements include:
|
||||
|
||||
* set 'name' field of crm.tag un-translatable
|
||||
|
||||
This module has been written by Alexis de Lattre from Akretion
|
||||
<alexis.delattre@akretion.com>.
|
||||
""",
|
||||
'author': 'Akretion',
|
||||
'website': 'http://www.akretion.com',
|
||||
'depends': ['sales_team'],
|
||||
'data': [],
|
||||
'installable': True,
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user