Compare commits
1 Commits
12.0-fix-a
...
11.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5ba4eadc15 |
56
.gitignore
vendored
56
.gitignore
vendored
@@ -1,56 +0,0 @@
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
env/
|
||||
bin/
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.coverage
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
|
||||
# Pycharm
|
||||
.idea
|
||||
|
||||
# Mr Developer
|
||||
.mr.developer.cfg
|
||||
.project
|
||||
.pydevproject
|
||||
|
||||
# Rope
|
||||
.ropeproject
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# Backup files
|
||||
*~
|
||||
*.swp
|
||||
8
README.rst
Normal file
8
README.rst
Normal file
@@ -0,0 +1,8 @@
|
||||
Odoo Usability : 11.0 Branch
|
||||
============================
|
||||
|
||||
Branch unmaintained by Akretion.
|
||||
|
||||
Please check these forks:
|
||||
|
||||
- https://github.com/camptocamp/odoo-usability
|
||||
@@ -1,2 +0,0 @@
|
||||
from . import account_invoice
|
||||
from . import account_invoice_report
|
||||
@@ -1,24 +0,0 @@
|
||||
# Copyright 2015-2019 Akretion France (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
{
|
||||
'name': 'Account Invoice Margin',
|
||||
'version': '12.0.1.0.0',
|
||||
'category': 'Invoicing Management',
|
||||
'license': 'AGPL-3',
|
||||
'summary': 'Copy standard price on invoice line and compute margins',
|
||||
'description': """
|
||||
This module copies the field *standard_price* of the product on the invoice line when the invoice line is created. The allows the computation of the margin of the invoice.
|
||||
|
||||
This module has been written by Alexis de Lattre from Akretion
|
||||
<alexis.delattre@akretion.com>.
|
||||
""",
|
||||
'author': 'Akretion',
|
||||
'website': 'http://www.akretion.com',
|
||||
'depends': ['account'],
|
||||
'data': [
|
||||
'account_invoice_view.xml',
|
||||
],
|
||||
'installable': True,
|
||||
}
|
||||
@@ -1,152 +0,0 @@
|
||||
# Copyright 2015-2019 Akretion France (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import api, fields, models
|
||||
import odoo.addons.decimal_precision as dp
|
||||
|
||||
|
||||
class AccountInvoiceLine(models.Model):
|
||||
_inherit = 'account.invoice.line'
|
||||
|
||||
standard_price_company_currency = fields.Float(
|
||||
string='Cost Price in Company Currency', readonly=True,
|
||||
digits=dp.get_precision('Product Price'),
|
||||
help="Cost price in company currency in the unit of measure "
|
||||
"of the invoice line (which may be different from the unit "
|
||||
"of measure of the product).")
|
||||
standard_price_invoice_currency = fields.Float(
|
||||
string='Cost Price in Invoice Currency', readonly=True,
|
||||
compute='_compute_margin', store=True,
|
||||
digits=dp.get_precision('Product Price'),
|
||||
help="Cost price in invoice currency in the unit of measure "
|
||||
"of the invoice line")
|
||||
margin_invoice_currency = fields.Monetary(
|
||||
string='Margin in Invoice Currency', readonly=True, store=True,
|
||||
compute='_compute_margin', currency_field='currency_id')
|
||||
margin_company_currency = fields.Monetary(
|
||||
string='Margin in Company Currency', readonly=True, store=True,
|
||||
compute='_compute_margin', currency_field='company_currency_id')
|
||||
margin_rate = fields.Float(
|
||||
string="Margin Rate", readonly=True, store=True,
|
||||
compute='_compute_margin',
|
||||
digits=(16, 2), help="Margin rate in percentage of the sale price")
|
||||
|
||||
@api.depends(
|
||||
'standard_price_company_currency', 'invoice_id.currency_id',
|
||||
'invoice_id.type', 'invoice_id.company_id',
|
||||
'invoice_id.date_invoice', 'quantity', 'price_subtotal')
|
||||
def _compute_margin(self):
|
||||
for il in self:
|
||||
standard_price_inv_cur = 0.0
|
||||
margin_inv_cur = 0.0
|
||||
margin_comp_cur = 0.0
|
||||
margin_rate = 0.0
|
||||
inv = il.invoice_id
|
||||
if inv and inv.type in ('out_invoice', 'out_refund'):
|
||||
# it works in _get_current_rate
|
||||
# even if we set date = False in context
|
||||
# standard_price_inv_cur is in the UoM of the invoice line
|
||||
date = inv._get_currency_rate_date() or\
|
||||
fields.Date.context_today(self)
|
||||
company = inv.company_id
|
||||
company_currency = company.currency_id
|
||||
standard_price_inv_cur =\
|
||||
company_currency._convert(
|
||||
il.standard_price_company_currency,
|
||||
inv.currency_id, company, date)
|
||||
margin_inv_cur =\
|
||||
il.price_subtotal - il.quantity * standard_price_inv_cur
|
||||
margin_comp_cur = inv.currency_id._convert(
|
||||
margin_inv_cur, company_currency, company, date)
|
||||
if il.price_subtotal:
|
||||
margin_rate = 100 * margin_inv_cur / il.price_subtotal
|
||||
# for a refund, margin should be negative
|
||||
# but margin rate should stay positive
|
||||
if inv.type == 'out_refund':
|
||||
margin_inv_cur *= -1
|
||||
margin_comp_cur *= -1
|
||||
il.standard_price_invoice_currency = standard_price_inv_cur
|
||||
il.margin_invoice_currency = margin_inv_cur
|
||||
il.margin_company_currency = margin_comp_cur
|
||||
il.margin_rate = margin_rate
|
||||
|
||||
# We want to copy standard_price on invoice line for customer
|
||||
# invoice/refunds. We can't do that via on_change of product_id,
|
||||
# because it is not always played when invoice is created from code
|
||||
# => we inherit write/create
|
||||
# We write standard_price_company_currency even on supplier invoice/refunds
|
||||
# because we don't have access to the 'type' of the invoice
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
if vals.get('product_id'):
|
||||
pp = self.env['product.product'].browse(vals['product_id'])
|
||||
std_price = pp.standard_price
|
||||
inv_uom_id = vals.get('uom_id')
|
||||
if inv_uom_id and inv_uom_id != pp.uom_id.id:
|
||||
inv_uom = self.env['uom.uom'].browse(inv_uom_id)
|
||||
std_price = pp.uom_id._compute_price(
|
||||
std_price, inv_uom)
|
||||
vals['standard_price_company_currency'] = std_price
|
||||
return super(AccountInvoiceLine, self).create(vals)
|
||||
|
||||
def write(self, vals):
|
||||
if not vals:
|
||||
vals = {}
|
||||
if 'product_id' in vals or 'uom_id' in vals:
|
||||
for il in self:
|
||||
if 'product_id' in vals:
|
||||
if vals.get('product_id'):
|
||||
pp = self.env['product.product'].browse(
|
||||
vals['product_id'])
|
||||
else:
|
||||
pp = False
|
||||
else:
|
||||
pp = il.product_id or False
|
||||
# uom_id is NOT a required field
|
||||
if 'uom_id' in vals:
|
||||
if vals.get('uom_id'):
|
||||
inv_uom = self.env['uom.uom'].browse(
|
||||
vals['uom_id'])
|
||||
else:
|
||||
inv_uom = False
|
||||
else:
|
||||
inv_uom = il.uom_id or False
|
||||
std_price = 0.0
|
||||
if pp:
|
||||
std_price = pp.standard_price
|
||||
if inv_uom and inv_uom != pp.uom_id:
|
||||
std_price = pp.uom_id._compute_price(
|
||||
std_price, inv_uom)
|
||||
il.write({'standard_price_company_currency': std_price})
|
||||
return super(AccountInvoiceLine, self).write(vals)
|
||||
|
||||
|
||||
class AccountInvoice(models.Model):
|
||||
_inherit = 'account.invoice'
|
||||
|
||||
margin_invoice_currency = fields.Monetary(
|
||||
string='Margin in Invoice Currency',
|
||||
compute='_compute_margin', store=True, readonly=True,
|
||||
currency_field='currency_id')
|
||||
margin_company_currency = fields.Monetary(
|
||||
string='Margin in Company Currency',
|
||||
compute='_compute_margin', store=True, readonly=True,
|
||||
currency_field='company_currency_id')
|
||||
|
||||
@api.depends(
|
||||
'type',
|
||||
'invoice_line_ids.margin_invoice_currency',
|
||||
'invoice_line_ids.margin_company_currency')
|
||||
def _compute_margin(self):
|
||||
res = self.env['account.invoice.line'].read_group(
|
||||
[('invoice_id', 'in', self.ids)],
|
||||
['invoice_id', 'margin_invoice_currency',
|
||||
'margin_company_currency'],
|
||||
['invoice_id'])
|
||||
for re in res:
|
||||
if re['invoice_id']:
|
||||
inv = self.browse(re['invoice_id'][0])
|
||||
if inv.type in ('out_invoice', 'out_refund'):
|
||||
inv.margin_invoice_currency = re['margin_invoice_currency']
|
||||
inv.margin_company_currency = re['margin_company_currency']
|
||||
@@ -1,60 +0,0 @@
|
||||
# Copyright 2018-2019 Akretion France (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import api, fields, models
|
||||
|
||||
|
||||
class AccountInvoiceReport(models.Model):
|
||||
_inherit = 'account.invoice.report'
|
||||
|
||||
margin = fields.Float(string='Margin', readonly=True)
|
||||
# why digits=0 ??? Why is it like that in the native "account" module
|
||||
user_currency_margin = fields.Float(
|
||||
string="Margin", compute='_compute_user_currency_margin', digits=0)
|
||||
|
||||
_depends = {
|
||||
'account.invoice': [
|
||||
'account_id', 'amount_total_company_signed',
|
||||
'commercial_partner_id', 'company_id',
|
||||
'currency_id', 'date_due', 'date_invoice', 'fiscal_position_id',
|
||||
'journal_id', 'number', 'partner_bank_id', 'partner_id',
|
||||
'payment_term_id', 'residual', 'state', 'type', 'user_id',
|
||||
],
|
||||
'account.invoice.line': [
|
||||
'account_id', 'invoice_id', 'price_subtotal', 'product_id',
|
||||
'quantity', 'uom_id', 'account_analytic_id',
|
||||
'margin_company_currency',
|
||||
],
|
||||
'product.product': ['product_tmpl_id'],
|
||||
'product.template': ['categ_id'],
|
||||
'uom.uom': ['category_id', 'factor', 'name', 'uom_type'],
|
||||
'res.currency.rate': ['currency_id', 'name'],
|
||||
'res.partner': ['country_id'],
|
||||
}
|
||||
|
||||
@api.depends('currency_id', 'date', 'margin')
|
||||
def _compute_user_currency_margin(self):
|
||||
user_currency = self.env.user.company_id.currency_id
|
||||
currency_rate = self.env['res.currency.rate'].search([
|
||||
('rate', '=', 1),
|
||||
'|',
|
||||
('company_id', '=', self.env.user.company_id.id),
|
||||
('company_id', '=', False)], limit=1)
|
||||
base_currency = currency_rate.currency_id
|
||||
for record in self:
|
||||
date = record.date or fields.Date.today()
|
||||
company = record.company_id
|
||||
record.user_currency_margin = base_currency._convert(
|
||||
record.margin, user_currency, company, date)
|
||||
|
||||
# TODO check for refunds
|
||||
def _sub_select(self):
|
||||
select_str = super(AccountInvoiceReport, self)._sub_select()
|
||||
select_str += ", SUM(ail.margin_company_currency) AS margin"
|
||||
return select_str
|
||||
|
||||
def _select(self):
|
||||
select_str = super(AccountInvoiceReport, self)._select()
|
||||
select_str += ", sub.margin AS margin"
|
||||
return select_str
|
||||
@@ -1,51 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
© 2015-2017 Akretion (http://www.akretion.com/)
|
||||
@author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
-->
|
||||
|
||||
<odoo>
|
||||
|
||||
<record id="view_invoice_line_form" model="ir.ui.view">
|
||||
<field name="name">margin.account.invoice.line.form</field>
|
||||
<field name="model">account.invoice.line</field>
|
||||
<field name="inherit_id" ref="account.view_invoice_line_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='analytic_tag_ids']/.." position="inside">
|
||||
<field name="standard_price_company_currency"
|
||||
string="Cost Price in Comp. Cur."
|
||||
groups="base.group_no_one"/>
|
||||
<field name="standard_price_invoice_currency"
|
||||
string="Cost Price in Inv. Cur."
|
||||
groups="base.group_no_one"/>
|
||||
<field name="margin_invoice_currency"
|
||||
string="Margin in Inv. Cur."
|
||||
groups="base.group_no_one"/>
|
||||
<field name="margin_company_currency"
|
||||
string="Margin in Comp. Cur."
|
||||
groups="base.group_no_one"/>
|
||||
<label for="margin_rate" groups="base.group_no_one"/>
|
||||
<div name="margin_rate" groups="base.group_no_one">
|
||||
<field name="margin_rate" class="oe_inline"/> %
|
||||
</div>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="invoice_form" model="ir.ui.view">
|
||||
<field name="name">margin.account.invoice.form</field>
|
||||
<field name="model">account.invoice</field>
|
||||
<field name="inherit_id" ref="account.invoice_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="move_id" position="after">
|
||||
<field name="margin_invoice_currency"
|
||||
string="Margin in Inv. Cur." groups="base.group_no_one"/>
|
||||
<field name="margin_company_currency"
|
||||
string="Margin in Comp. Cur." groups="base.group_no_one"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
</odoo>
|
||||
@@ -1,39 +0,0 @@
|
||||
.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg
|
||||
:target: https://www.gnu.org/licenses/agpl-3.0-standalone.html
|
||||
:alt: License: AGPL-3
|
||||
|
||||
Account Invoice Update Wizard
|
||||
=============================
|
||||
|
||||
This module adds a button *Update Invoice* on Customer and Supplier invoices in
|
||||
Open or Paid state. This button starts a wizard which allows the user to update
|
||||
non-legal fields of the invoice:
|
||||
|
||||
* Source Document
|
||||
* Reference/Description
|
||||
* Payment terms (update allowed only to a payment term with same number of terms
|
||||
of the same amount and on invoices without any payment)
|
||||
* Bank Account
|
||||
* Salesman
|
||||
* Notes
|
||||
* Description of invoice lines
|
||||
* Analytic account
|
||||
* Analytic tags
|
||||
|
||||
Bug Tracker
|
||||
===========
|
||||
|
||||
Bugs are tracked on `GitHub Issues
|
||||
<https://github.com/akretion/odoo-usability/issues>`_. In case of trouble, please
|
||||
check there if your issue has already been reported. If you spotted it first,
|
||||
help us smash it by providing detailed and welcomed feedback.
|
||||
|
||||
Contributors
|
||||
------------
|
||||
|
||||
* Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
* Florian da Costa <florian.dacosta@akretion.com>
|
||||
* Matthieu Dietrich <matthieu.dietrich@camptocamp.com>
|
||||
* Yannick Vaucher <yannick.vaucher@camptocamp.com>
|
||||
* Mykhailo Panarin <m.panarin@mobilunity.com>
|
||||
* Artem Kostyuk <a.kostyuk@mobilunity.com>
|
||||
@@ -1,2 +0,0 @@
|
||||
from . import models
|
||||
from . import wizard
|
||||
@@ -1,21 +0,0 @@
|
||||
# Copyright 2017 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
|
||||
# Copyright 2018-2019 Camptocamp
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
{
|
||||
'name': 'Account Invoice Update Wizard',
|
||||
'version': '12.0.1.0.0',
|
||||
'category': 'Accounting & Finance',
|
||||
'license': 'AGPL-3',
|
||||
'summary': 'Wizard to update non-legal fields of an open/paid invoice',
|
||||
'author': 'Akretion',
|
||||
'website': 'https://github.com/akretion/odoo-usability',
|
||||
'depends': [
|
||||
'account',
|
||||
],
|
||||
'data': [
|
||||
'wizard/account_invoice_update_view.xml',
|
||||
'views/account_invoice.xml',
|
||||
],
|
||||
'installable': True,
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
from . import account_invoice
|
||||
@@ -1,22 +0,0 @@
|
||||
# Copyright 2019 Camptocamp
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import models, fields, api, _
|
||||
from odoo.exceptions import UserError
|
||||
import odoo.addons.decimal_precision as dp
|
||||
|
||||
|
||||
class AccountInvoice(models.Model):
|
||||
_inherit = 'account.invoice'
|
||||
|
||||
def prepare_update_wizard(self):
|
||||
self.ensure_one()
|
||||
wizard = self.env['account.invoice.update']
|
||||
res = wizard._prepare_default_get(self)
|
||||
action = self.env.ref(
|
||||
'account_invoice_update_wizard.account_invoice_update_action'
|
||||
).read()[0]
|
||||
action['name'] = "Update Wizard"
|
||||
action['res_id'] = wizard.create(res).id
|
||||
return action
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
from . import test_account_invoice_update_wizard
|
||||
@@ -1,196 +0,0 @@
|
||||
# Copyright 2018-2019 Camptocamp
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo.tests.common import SavepointCase
|
||||
from odoo.exceptions import UserError
|
||||
|
||||
|
||||
class TestAccountInvoiceUpdateWizard(SavepointCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
cls.customer12 = cls.env.ref('base.res_partner_12')
|
||||
cls.product16 = cls.env.ref('product.product_product_16')
|
||||
cls.product24 = cls.env.ref('product.product_product_24')
|
||||
uom_unit = cls.env.ref('uom.product_uom_categ_unit')
|
||||
|
||||
cls.invoice1 = cls.env['account.invoice'].create({
|
||||
'name': 'Test invoice',
|
||||
'partner_id': cls.customer12.id,
|
||||
})
|
||||
cls.inv_line1 = cls.env['account.invoice.line'].create({
|
||||
'invoice_id': cls.invoice1.id,
|
||||
'name': "Line1",
|
||||
'product_id': cls.product16.id,
|
||||
'product_uom_id': uom_unit.id,
|
||||
'account_id': cls.invoice1.account_id.id,
|
||||
'price_unit': 42.0,
|
||||
})
|
||||
cls.inv_line2 = cls.env['account.invoice.line'].create({
|
||||
'invoice_id': cls.invoice1.id,
|
||||
'name': "Line2",
|
||||
'product_id': cls.product24.id,
|
||||
'product_uom_id': uom_unit.id,
|
||||
'account_id': cls.invoice1.account_id.id,
|
||||
'price_unit': 1111.1,
|
||||
})
|
||||
|
||||
cls.aa1 = cls.env.ref('analytic.analytic_partners_camp_to_camp')
|
||||
cls.aa2 = cls.env.ref('analytic.analytic_nebula')
|
||||
cls.atag1 = cls.env.ref('analytic.tag_contract')
|
||||
cls.atag2 = cls.env['account.analytic.tag'].create({
|
||||
'name': 'の',
|
||||
})
|
||||
|
||||
def create_wizard(self, invoice):
|
||||
res = self.invoice1.prepare_update_wizard()
|
||||
self.wiz = self.env['account.invoice.update'].browse(res['res_id'])
|
||||
|
||||
def test_add_analytic_account_line1(self):
|
||||
""" Add analytic account on an invoice line
|
||||
after the invoice has been approved.
|
||||
|
||||
This will:
|
||||
- update the move line
|
||||
- create a new analytic line.
|
||||
"""
|
||||
self.invoice1.action_invoice_open()
|
||||
self.create_wizard(self.invoice1)
|
||||
|
||||
wiz_line = self.wiz.line_ids.filtered(
|
||||
lambda rec: rec.invoice_line_id == self.inv_line1)
|
||||
wiz_line.account_analytic_id = self.aa1
|
||||
self.wiz.run()
|
||||
|
||||
related_ml = self.invoice1.move_id.line_ids.filtered(
|
||||
lambda rec: rec.product_id == self.product16)
|
||||
self.assertEqual(related_ml.analytic_account_id, self.aa1)
|
||||
self.assertEqual(related_ml.analytic_line_ids.account_id, self.aa1)
|
||||
|
||||
def test_change_analytic_account_line1(self):
|
||||
""" Change analytic account on an invoice line
|
||||
after the invoice has been approved.
|
||||
|
||||
This will:
|
||||
- update the move line
|
||||
- update the existing analytic line."""
|
||||
self.inv_line1.account_analytic_id = self.aa2
|
||||
|
||||
self.invoice1.action_invoice_open()
|
||||
self.create_wizard(self.invoice1)
|
||||
|
||||
wiz_line = self.wiz.line_ids.filtered(
|
||||
lambda rec: rec.invoice_line_id == self.inv_line1)
|
||||
wiz_line.account_analytic_id = self.aa1
|
||||
self.wiz.run()
|
||||
|
||||
related_ml = self.invoice1.move_id.line_ids.filtered(
|
||||
lambda rec: rec.product_id == self.product16)
|
||||
self.assertEqual(related_ml.analytic_account_id, self.aa1)
|
||||
self.assertEqual(related_ml.analytic_line_ids.account_id, self.aa1)
|
||||
|
||||
def test_error_grouped_move_lines(self):
|
||||
""" Change analytic account on an invoice line
|
||||
after the invoice has been approved where both
|
||||
lines were grouped in the same move line.
|
||||
|
||||
This will raise an error.
|
||||
"""
|
||||
self.invoice1.journal_id.group_invoice_lines = True
|
||||
|
||||
self.inv_line2.product_id = self.product16
|
||||
self.inv_line2.unit_price = 42.0
|
||||
|
||||
self.invoice1.action_invoice_open()
|
||||
self.create_wizard(self.invoice1)
|
||||
|
||||
line1 = self.wiz.line_ids[0]
|
||||
line1.account_analytic_id = self.aa1
|
||||
with self.assertRaises(UserError):
|
||||
self.wiz.run()
|
||||
|
||||
def test_add_analytic_tags_line1(self):
|
||||
""" Add analytic tags on an invoice line
|
||||
after the invoice has been approved.
|
||||
|
||||
This will update move line.
|
||||
"""
|
||||
self.invoice1.action_invoice_open()
|
||||
self.create_wizard(self.invoice1)
|
||||
|
||||
wiz_line = self.wiz.line_ids.filtered(
|
||||
lambda rec: rec.invoice_line_id == self.inv_line1)
|
||||
wiz_line.analytic_tag_ids = self.atag2
|
||||
self.wiz.run()
|
||||
|
||||
related_ml = self.invoice1.move_id.line_ids.filtered(
|
||||
lambda rec: rec.product_id == self.product16)
|
||||
self.assertEqual(related_ml.analytic_tag_ids, self.atag2)
|
||||
self.assertFalse(related_ml.analytic_line_ids)
|
||||
|
||||
def test_change_analytic_tags_line1(self):
|
||||
""" Change analytic tags on an invoice line
|
||||
after the invoice has been approved.
|
||||
|
||||
It will update move line and analytic line
|
||||
"""
|
||||
self.inv_line1.account_analytic_id = self.aa2
|
||||
self.inv_line1.analytic_tag_ids = self.atag1
|
||||
|
||||
self.invoice1.action_invoice_open()
|
||||
self.create_wizard(self.invoice1)
|
||||
|
||||
wiz_line = self.wiz.line_ids.filtered(
|
||||
lambda rec: rec.invoice_line_id == self.inv_line1)
|
||||
wiz_line.analytic_tag_ids = self.atag2
|
||||
self.wiz.run()
|
||||
|
||||
related_ml = self.invoice1.move_id.line_ids.filtered(
|
||||
lambda rec: rec.product_id == self.product16)
|
||||
self.assertEqual(related_ml.analytic_tag_ids, self.atag2)
|
||||
self.assertEqual(related_ml.analytic_line_ids.tag_ids, self.atag2)
|
||||
|
||||
def test_add_analytic_info_line1(self):
|
||||
""" Add analytic account and tags on an invoice line
|
||||
after the invoice has been approved.
|
||||
|
||||
This will:
|
||||
- update move line
|
||||
- create an analytic line
|
||||
"""
|
||||
self.invoice1.action_invoice_open()
|
||||
self.create_wizard(self.invoice1)
|
||||
|
||||
wiz_line = self.wiz.line_ids.filtered(
|
||||
lambda rec: rec.invoice_line_id == self.inv_line1)
|
||||
wiz_line.account_analytic_id = self.aa1
|
||||
wiz_line.analytic_tag_ids = self.atag2
|
||||
self.wiz.run()
|
||||
|
||||
related_ml = self.invoice1.move_id.line_ids.filtered(
|
||||
lambda rec: rec.product_id == self.product16)
|
||||
self.assertEqual(related_ml.analytic_account_id, self.aa1)
|
||||
self.assertEqual(related_ml.analytic_tag_ids, self.atag2)
|
||||
self.assertEqual(related_ml.analytic_line_ids.account_id, self.aa1)
|
||||
self.assertEqual(related_ml.analytic_line_ids.tag_ids, self.atag2)
|
||||
|
||||
def test_empty_analytic_account_line1(self):
|
||||
""" Remove analytic account
|
||||
after the invoice has been approved.
|
||||
|
||||
This will raise an error as it is not implemented.
|
||||
"""
|
||||
self.inv_line1.account_analytic_id = self.aa2
|
||||
|
||||
self.invoice1.action_invoice_open()
|
||||
self.create_wizard(self.invoice1)
|
||||
|
||||
wiz_line = self.wiz.line_ids.filtered(
|
||||
lambda rec: rec.invoice_line_id == self.inv_line1)
|
||||
wiz_line.account_analytic_id = False
|
||||
self.wiz.run()
|
||||
related_ml = self.invoice1.move_id.line_ids.filtered(
|
||||
lambda rec: rec.product_id == self.product16)
|
||||
self.assertFalse(related_ml.analytic_account_id)
|
||||
self.assertFalse(related_ml.analytic_line_ids)
|
||||
@@ -1,29 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2017 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
|
||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
-->
|
||||
|
||||
<odoo>
|
||||
|
||||
<record id="invoice_supplier_form" model="ir.ui.view">
|
||||
<field name="model">account.invoice</field>
|
||||
<field name="inherit_id" ref="account.invoice_supplier_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<button name="action_invoice_draft" position="before">
|
||||
<button name="prepare_update_wizard" type="object" string="Update Invoice" states="open,paid" groups="account.group_account_invoice"/>
|
||||
</button>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="invoice_form" model="ir.ui.view">
|
||||
<field name="model">account.invoice</field>
|
||||
<field name="inherit_id" ref="account.invoice_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<button name="action_invoice_draft" position="before">
|
||||
<button name="prepare_update_wizard" type="object" string="Update Invoice" states="open,paid" groups="account.group_account_invoice"/>
|
||||
</button>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -1 +0,0 @@
|
||||
from . import account_invoice_update
|
||||
@@ -1,302 +0,0 @@
|
||||
# Copyright 2017 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
|
||||
# Copyright 2018-2019 Camptocamp
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import models, fields, api, _
|
||||
from odoo.exceptions import UserError
|
||||
import odoo.addons.decimal_precision as dp
|
||||
|
||||
|
||||
class AccountInvoiceUpdate(models.TransientModel):
|
||||
_name = 'account.invoice.update'
|
||||
_description = 'Wizard to update non-legal fields of invoice'
|
||||
|
||||
invoice_id = fields.Many2one(
|
||||
'account.invoice', string='Invoice', required=True,
|
||||
readonly=True)
|
||||
type = fields.Selection(related='invoice_id.type', readonly=True)
|
||||
company_id = fields.Many2one(
|
||||
related='invoice_id.company_id', readonly=True)
|
||||
partner_id = fields.Many2one(
|
||||
related='invoice_id.partner_id', readonly=True)
|
||||
user_id = fields.Many2one('res.users', string='Salesperson')
|
||||
payment_term_id = fields.Many2one(
|
||||
'account.payment.term', string='Payment Term')
|
||||
reference = fields.Char(string='Invoice Reference')
|
||||
name = fields.Char(string='Reference/Description')
|
||||
origin = fields.Char(string='Source Document')
|
||||
comment = fields.Text('Additional Information')
|
||||
partner_bank_id = fields.Many2one(
|
||||
'res.partner.bank', string='Bank Account')
|
||||
line_ids = fields.One2many(
|
||||
'account.invoice.line.update', 'parent_id', string='Invoice Lines')
|
||||
|
||||
@api.model
|
||||
def _simple_fields2update(self):
|
||||
'''List boolean, date, datetime, char, text fields'''
|
||||
return ['reference', 'name', 'origin', 'comment']
|
||||
|
||||
@api.model
|
||||
def _m2o_fields2update(self):
|
||||
return ['payment_term_id', 'user_id', 'partner_bank_id']
|
||||
|
||||
@api.model
|
||||
def _prepare_default_get(self, invoice):
|
||||
res = {'invoice_id': invoice.id, 'line_ids': []}
|
||||
for sfield in self._simple_fields2update():
|
||||
res[sfield] = invoice[sfield]
|
||||
for m2ofield in self._m2o_fields2update():
|
||||
res[m2ofield] = invoice[m2ofield].id or False
|
||||
for line in invoice.invoice_line_ids:
|
||||
aa_tags = line.analytic_tag_ids
|
||||
aa_tags = [(6, 0, aa_tags.ids)] if aa_tags else False
|
||||
res['line_ids'].append([0, 0, {
|
||||
'invoice_line_id': line.id,
|
||||
'name': line.name,
|
||||
'quantity': line.quantity,
|
||||
'price_subtotal': line.price_subtotal,
|
||||
'account_analytic_id': line.account_analytic_id.id,
|
||||
'analytic_tag_ids': aa_tags,
|
||||
'display_type': line.display_type,
|
||||
}])
|
||||
return res
|
||||
|
||||
@api.onchange('type')
|
||||
def type_on_change(self):
|
||||
res = {'domain': {}}
|
||||
if self.type in ('out_invoice', 'out_refund'):
|
||||
res['domain']['partner_bank_id'] =\
|
||||
"[('partner_id.ref_company_ids', 'in', [company_id])]"
|
||||
else:
|
||||
res['domain']['partner_bank_id'] =\
|
||||
"[('partner_id', '=', partner_id)]"
|
||||
return res
|
||||
|
||||
@api.multi
|
||||
def _prepare_invoice(self):
|
||||
vals = {}
|
||||
inv = self.invoice_id
|
||||
for sfield in self._simple_fields2update():
|
||||
if self[sfield] != inv[sfield]:
|
||||
vals[sfield] = self[sfield]
|
||||
for m2ofield in self._m2o_fields2update():
|
||||
if self[m2ofield] != inv[m2ofield]:
|
||||
vals[m2ofield] = self[m2ofield].id or False
|
||||
if 'payment_term_id' in vals:
|
||||
pterm_list = self.payment_term_id.compute(
|
||||
value=1, date_ref=inv.date_invoice)[0]
|
||||
if pterm_list:
|
||||
vals['date_due'] = max(line[0] for line in pterm_list)
|
||||
return vals
|
||||
|
||||
@api.model
|
||||
def _line_simple_fields2update(self):
|
||||
return ["name",]
|
||||
|
||||
@api.model
|
||||
def _line_m2o_fields2update(self):
|
||||
return ["account_analytic_id",]
|
||||
|
||||
@api.model
|
||||
def _line_m2m_fields2update(self):
|
||||
return ["analytic_tag_ids",]
|
||||
|
||||
@api.model
|
||||
def _prepare_invoice_line(self, line):
|
||||
vals = {}
|
||||
for field in self._line_simple_fields2update():
|
||||
if line[field] != line.invoice_line_id[field]:
|
||||
vals[field] = line[field]
|
||||
for field in self._line_m2o_fields2update():
|
||||
if line[field] != line.invoice_line_id[field]:
|
||||
vals[field] = line[field].id
|
||||
for field in self._line_m2m_fields2update():
|
||||
if line[field] != line.invoice_line_id[field]:
|
||||
vals[field] = [(6, 0, line[field].ids)]
|
||||
return vals
|
||||
|
||||
@api.multi
|
||||
def _prepare_move(self):
|
||||
mvals = {}
|
||||
inv = self.invoice_id
|
||||
ini_ref = inv.move_id.ref
|
||||
ref = inv.reference or inv.name
|
||||
if ini_ref != ref:
|
||||
mvals['ref'] = ref
|
||||
return mvals
|
||||
|
||||
@api.multi
|
||||
def _get_matching_inv_line(self, move_line):
|
||||
""" Find matching invoice line by product """
|
||||
# TODO make it accept more case as lines won't
|
||||
# be grouped unless journal.group_invoice_line is True
|
||||
inv_line = self.invoice_id.invoice_line_ids.filtered(
|
||||
lambda rec: rec.product_id == move_line.product_id)
|
||||
if len(inv_line) != 1:
|
||||
raise UserError(
|
||||
"Cannot match a single invoice line to move line %s" %
|
||||
move_line.name)
|
||||
return inv_line
|
||||
|
||||
@api.multi
|
||||
def _prepare_move_line(self, inv_line):
|
||||
mlvals = {}
|
||||
inv_line_upd = self.line_ids.filtered(
|
||||
lambda rec: rec.invoice_line_id == inv_line)
|
||||
|
||||
ini_aa = inv_line.account_analytic_id
|
||||
new_aa = inv_line_upd.account_analytic_id
|
||||
|
||||
if ini_aa != new_aa:
|
||||
mlvals['analytic_account_id'] = new_aa.id
|
||||
|
||||
ini_aa_tags = inv_line.analytic_tag_ids
|
||||
new_aa_tags = inv_line_upd.analytic_tag_ids
|
||||
|
||||
if ini_aa_tags != new_aa_tags:
|
||||
mlvals['analytic_tag_ids'] = [(6, None, new_aa_tags.ids)]
|
||||
return mlvals
|
||||
|
||||
@api.multi
|
||||
def _prepare_analytic_line(self, inv_line):
|
||||
alvals = {}
|
||||
inv_line_upd = self.line_ids.filtered(
|
||||
lambda rec: rec.invoice_line_id == inv_line)
|
||||
|
||||
ini_aa = inv_line.account_analytic_id
|
||||
new_aa = inv_line_upd.account_analytic_id
|
||||
|
||||
if ini_aa != new_aa:
|
||||
alvals['account_id'] = new_aa.id
|
||||
|
||||
ini_aa_tags = inv_line.analytic_tag_ids
|
||||
new_aa_tags = inv_line_upd.analytic_tag_ids
|
||||
|
||||
if ini_aa_tags != new_aa_tags:
|
||||
alvals['tag_ids'] = [(6, None, new_aa_tags.ids)]
|
||||
return alvals
|
||||
|
||||
@api.multi
|
||||
def _update_payment_term_move(self):
|
||||
self.ensure_one()
|
||||
inv = self.invoice_id
|
||||
if (
|
||||
self.payment_term_id and
|
||||
self.payment_term_id != inv.payment_term_id and
|
||||
inv.move_id):
|
||||
# I don't update pay term when the invoice is partially (or fully)
|
||||
# paid because if you have a payment term with several lines
|
||||
# of the same amount, you would also have to take into account
|
||||
# the reconcile marks to put the new maturity date on the right
|
||||
# lines
|
||||
if inv.payment_ids:
|
||||
raise UserError(_(
|
||||
"This wizard doesn't support the update of payment "
|
||||
"terms on an invoice which is partially or fully "
|
||||
"paid."))
|
||||
prec = self.env['decimal.precision'].precision_get('Account')
|
||||
term_res = self.payment_term_id.compute(
|
||||
inv.amount_total, inv.date_invoice)[0]
|
||||
new_pterm = {} # key = int(amount * 100), value = [date1, date2]
|
||||
for entry in term_res:
|
||||
amount = int(entry[1] * 10 * prec)
|
||||
if amount in new_pterm:
|
||||
new_pterm[amount].append(entry[0])
|
||||
else:
|
||||
new_pterm[amount] = [entry[0]]
|
||||
mlines = {} # key = int(amount * 100), value : [line1, line2]
|
||||
for line in inv.move_id.line_ids:
|
||||
if line.account_id == inv.account_id:
|
||||
amount = int(abs(line.credit - line.debit) * 10 * prec)
|
||||
if amount in mlines:
|
||||
mlines[amount].append(line)
|
||||
else:
|
||||
mlines[amount] = [line]
|
||||
for iamount, lines in mlines.items():
|
||||
if len(lines) != len(new_pterm.get(iamount, [])):
|
||||
raise UserError(_(
|
||||
"The original payment term '%s' doesn't have the "
|
||||
"same terms (number of terms and/or amount) as the "
|
||||
"new payment term '%s'. You can only switch to a "
|
||||
"payment term that has the same number of terms "
|
||||
"with the same amount.") % (
|
||||
inv.payment_term_id.name, self.payment_term_id.name))
|
||||
for line in lines:
|
||||
line.date_maturity = new_pterm[iamount].pop()
|
||||
|
||||
@api.multi
|
||||
def run(self):
|
||||
self.ensure_one()
|
||||
inv = self.invoice_id
|
||||
updated = False
|
||||
# re-write date_maturity on move line
|
||||
self._update_payment_term_move()
|
||||
ivals = self._prepare_invoice()
|
||||
if ivals:
|
||||
updated = True
|
||||
inv.write(ivals)
|
||||
if inv.move_id:
|
||||
mvals = self._prepare_move()
|
||||
if mvals:
|
||||
inv.move_id.write(mvals)
|
||||
for ml in inv.move_id.line_ids.filtered(
|
||||
# we are only interested in invoice lines, not tax lines
|
||||
lambda rec: bool(rec.product_id)
|
||||
):
|
||||
if ml.credit == 0.0:
|
||||
continue
|
||||
inv_line = self._get_matching_inv_line(ml)
|
||||
mlvals = self._prepare_move_line(inv_line)
|
||||
if mlvals:
|
||||
updated = True
|
||||
ml.write(mlvals)
|
||||
aalines = ml.analytic_line_ids
|
||||
alvals = self._prepare_analytic_line(inv_line)
|
||||
if aalines and alvals:
|
||||
updated = True
|
||||
if ('account_id' in alvals and
|
||||
alvals['account_id'] is False):
|
||||
former_aa = inv_line.account_analytic_id
|
||||
to_remove_aalines = aalines.filtered(
|
||||
lambda rec: rec.account_id == former_aa)
|
||||
# remove existing analytic line
|
||||
to_remove_aalines.unlink()
|
||||
else:
|
||||
aalines.write(alvals)
|
||||
elif 'account_id' in alvals:
|
||||
# Create analytic lines if analytic account
|
||||
# is added later
|
||||
ml.create_analytic_lines()
|
||||
for line in self.line_ids:
|
||||
ilvals = self._prepare_invoice_line(line)
|
||||
if ilvals:
|
||||
updated = True
|
||||
line.invoice_line_id.write(ilvals)
|
||||
if updated:
|
||||
inv.message_post(body=_(
|
||||
'Non-legal fields of invoice updated via the Invoice Update '
|
||||
'wizard.'))
|
||||
return True
|
||||
|
||||
|
||||
class AccountInvoiceLineUpdate(models.TransientModel):
|
||||
_name = 'account.invoice.line.update'
|
||||
_description = 'Update non-legal fields of invoice lines'
|
||||
|
||||
parent_id = fields.Many2one(
|
||||
'account.invoice.update', string='Wizard', ondelete='cascade')
|
||||
invoice_line_id = fields.Many2one(
|
||||
'account.invoice.line', string='Invoice Line', readonly=True)
|
||||
name = fields.Text(string='Description', required=True)
|
||||
display_type = fields.Selection([
|
||||
('line_section', "Section"),
|
||||
('line_note', "Note")], default=False, help="Technical field for UX purpose.")
|
||||
quantity = fields.Float(
|
||||
string='Quantity', digits=dp.get_precision('Product Unit of Measure'),
|
||||
readonly=True)
|
||||
price_subtotal = fields.Float(
|
||||
string='Amount', readonly=True, digits=dp.get_precision('Account'))
|
||||
account_analytic_id = fields.Many2one(
|
||||
'account.analytic.account', string='Analytic Account')
|
||||
analytic_tag_ids = fields.Many2many(
|
||||
'account.analytic.tag', string='Analytic Tags')
|
||||
@@ -1,54 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
© 2017 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
|
||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
-->
|
||||
|
||||
<odoo>
|
||||
|
||||
<record id="account_invoice_update_form" model="ir.ui.view">
|
||||
<field name="model">account.invoice.update</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Update Invoice Wizard">
|
||||
<group name="main">
|
||||
<field name="invoice_id" invisible="1"/>
|
||||
<field name="type" invisible="1"/>
|
||||
<field name="company_id" invisible="1"/>
|
||||
<field name="partner_id" invisible="1"/>
|
||||
<field name="reference" attrs="{'invisible': [('type', 'not in', ('in_invoice', 'in_refund'))]}"/>
|
||||
<field name="origin"/>
|
||||
<field name="name"/>
|
||||
<field name="payment_term_id" widget="selection"/>
|
||||
<field name="partner_bank_id"/>
|
||||
<field name="user_id"/>
|
||||
<field name="comment"/>
|
||||
</group>
|
||||
<group name="lines">
|
||||
<field name="line_ids" nolabel="1">
|
||||
<tree editable="bottom" create="false" delete="false" edit="true">
|
||||
<field name="invoice_line_id" invisible="1"/>
|
||||
<field name="display_type" invisible="1"/>
|
||||
<field name="name"/>
|
||||
<field name="quantity" attrs="{'invisible': [('display_type', '!=', False)]}"/>
|
||||
<field name="price_subtotal" attrs="{'invisible': [('display_type', '!=', False)]}"/>
|
||||
<field name="account_analytic_id" attrs="{'invisible': [('display_type', '!=', False)]}" groups="analytic.group_analytic_accounting"/>
|
||||
<field name="analytic_tag_ids" attrs="{'invisible': [('display_type', '!=', False)]}" groups="analytic.group_analytic_accounting" widget="many2many_tags"/>
|
||||
</tree>
|
||||
</field>
|
||||
</group>
|
||||
<footer>
|
||||
<button name="run" type="object" class="oe_highlight" string="Update"/>
|
||||
<button special="cancel" string="Cancel" class="oe_link"/>
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="account_invoice_update_action" model="ir.actions.act_window">
|
||||
<field name="name">Invoice Update Wizard</field>
|
||||
<field name="res_model">account.invoice.update</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="target">new</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -1,96 +0,0 @@
|
||||
=================
|
||||
Account Usability
|
||||
=================
|
||||
|
||||
.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
!! This file is generated by oca-gen-addon-readme !!
|
||||
!! changes will be overwritten. !!
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
|
||||
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
|
||||
:target: https://odoo-community.org/page/development-status
|
||||
:alt: Beta
|
||||
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
|
||||
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
|
||||
:alt: License: AGPL-3
|
||||
.. |badge3| image:: https://img.shields.io/badge/github-akretion%2Fodoo--usability-lightgray.png?logo=github
|
||||
:target: https://github.com/akretion/odoo-usability/tree/12.0/account_usability
|
||||
:alt: akretion/odoo-usability
|
||||
|
||||
|badge1| |badge2| |badge3|
|
||||
|
||||
This modules adds the following functions:
|
||||
|
||||
* Add an *Overdue* filter on invoice search view (this feature was previously
|
||||
located in te module *account_invoice_overdue_filter*)
|
||||
* Increase the default limit of 80 lines in account move and account move line view.
|
||||
* disable reconciliation "guessing"
|
||||
* fast search on *Reconcile Ref* for account move line.
|
||||
* add sale dates to invoice report to be compliant with
|
||||
https://www.service-public.fr/professionnels-entreprises/vosdroits/F31808
|
||||
* Sale date on qweb invoices
|
||||
* A wizard to mark several invoices as sent at once (forward from v8)
|
||||
* Default date for Account Move Reversal is now D+1 instead of today
|
||||
* Track more fields on invoice (see details in account.py)
|
||||
* Add boolean fields `has_discount` and `has_attachment` on invoice
|
||||
* Add button "Delete line qty = 0" on supplier invoice
|
||||
* Cut name_get() of invoice if too long
|
||||
* A script for if Odoo screws up invoice attachment filename
|
||||
* help functions for py3o reports
|
||||
* Show code on name_get of journal
|
||||
* add direct search of journal using code
|
||||
* add copy=False on some fields
|
||||
* Add unicity constraint on analytic codes per company
|
||||
* Better default values on account move
|
||||
* Add link from account move line to invoice
|
||||
* Add start_date and end_date on bank statements
|
||||
* Add transfer_account_id to invoicing config page
|
||||
* Improve domain reconciliation widget
|
||||
* account.reconcile.model don't copy name to label via onchange
|
||||
* Add method to get fiscal position without partner_id
|
||||
* Restore drill-through on sale and invoice reports
|
||||
* 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
|
||||
|
||||
Together with this module, I recommend the use of the following modules:
|
||||
|
||||
* account_invoice_supplier_ref_unique (OCA project account-invoicing)
|
||||
* account_move_line_no_default_search (OCA project account-financial-tools)
|
||||
* invoice_fiscal_position_update (OCA project account-invoicing)
|
||||
|
||||
**Table of contents**
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
|
||||
Bug Tracker
|
||||
===========
|
||||
|
||||
Bugs are tracked on `GitHub Issues <https://github.com/akretion/odoo-usability/issues>`_.
|
||||
In case of trouble, please check there if your issue has already been reported.
|
||||
If you spotted it first, help us smashing it by providing a detailed and welcomed
|
||||
`feedback <https://github.com/akretion/odoo-usability/issues/new?body=module:%20account_usability%0Aversion:%2012.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
|
||||
|
||||
Do not contact contributors directly about support or help with technical issues.
|
||||
|
||||
Credits
|
||||
=======
|
||||
|
||||
Authors
|
||||
~~~~~~~
|
||||
|
||||
* Akretion
|
||||
|
||||
Contributors
|
||||
~~~~~~~~~~~~
|
||||
|
||||
* Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
* David Beal <david.beal@akretion.com>
|
||||
|
||||
Maintainers
|
||||
~~~~~~~~~~~
|
||||
|
||||
This module is part of the `akretion/odoo-usability <https://github.com/akretion/odoo-usability/tree/12.0/account_usability>`_ project on GitHub.
|
||||
|
||||
You are welcome to contribute.
|
||||
@@ -1,4 +0,0 @@
|
||||
from . import account
|
||||
#from . import account_invoice_report
|
||||
from . import partner
|
||||
from . import wizard
|
||||
@@ -1,28 +0,0 @@
|
||||
# Copyright 2015-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).
|
||||
|
||||
{
|
||||
'name': 'Account Usability',
|
||||
'version': '12.0.1.0.0',
|
||||
'category': 'Accounting & Finance',
|
||||
'license': 'AGPL-3',
|
||||
'summary': 'Small usability enhancements in account module',
|
||||
'author': 'Akretion',
|
||||
'website': 'http://www.akretion.com',
|
||||
'depends': [
|
||||
'account',
|
||||
'base_view_inheritance_extension',
|
||||
'base_usability', # needed only to access base_usability.group_nobody
|
||||
# in v12, I may create a module only for group_nobody
|
||||
],
|
||||
'data': [
|
||||
'account_view.xml',
|
||||
'account_report.xml',
|
||||
'account_invoice_report_view.xml',
|
||||
'partner_view.xml',
|
||||
'wizard/account_invoice_mark_sent_view.xml',
|
||||
'report/invoice_report.xml',
|
||||
],
|
||||
'installable': True,
|
||||
}
|
||||
@@ -1,706 +0,0 @@
|
||||
# Copyright 2015-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).
|
||||
|
||||
from odoo import models, fields, api, _
|
||||
from odoo.tools import float_compare, float_is_zero
|
||||
from odoo.tools.misc import formatLang
|
||||
from odoo.exceptions import UserError, ValidationError
|
||||
from odoo.osv import expression
|
||||
from odoo import SUPERUSER_ID
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class AccountInvoice(models.Model):
|
||||
_inherit = 'account.invoice'
|
||||
|
||||
origin = fields.Char(track_visibility='onchange')
|
||||
reference = fields.Char(track_visibility='onchange')
|
||||
sent = fields.Boolean(track_visibility='onchange')
|
||||
date_invoice = fields.Date(track_visibility='onchange')
|
||||
date_due = fields.Date(track_visibility='onchange')
|
||||
payment_term_id = fields.Many2one(track_visibility='onchange')
|
||||
account_id = fields.Many2one(track_visibility='onchange')
|
||||
journal_id = fields.Many2one(track_visibility='onchange')
|
||||
partner_bank_id = fields.Many2one(track_visibility='onchange')
|
||||
fiscal_position_id = fields.Many2one(track_visibility='onchange')
|
||||
amount_total = fields.Monetary(track_visibility='onchange')
|
||||
# I want to see the number of cancelled invoice in chatter
|
||||
move_id = fields.Many2one(track_visibility='onchange')
|
||||
# for invoice report
|
||||
has_discount = fields.Boolean(
|
||||
compute='_compute_has_discount', readonly=True)
|
||||
# has_attachment is useful for those who use attachment to archive
|
||||
# supplier invoices. It allows them to find supplier invoices
|
||||
# that don't have any attachment
|
||||
has_attachment = fields.Boolean(
|
||||
compute='_compute_has_attachment',
|
||||
search='_search_has_attachment', readonly=True)
|
||||
sale_dates = fields.Char(
|
||||
compute="_compute_sales_dates", readonly=True,
|
||||
help="This information appears on invoice qweb report "
|
||||
"(you may use it for your own report)")
|
||||
|
||||
def _compute_has_discount(self):
|
||||
prec = self.env['decimal.precision'].precision_get('Discount')
|
||||
for inv in self:
|
||||
has_discount = False
|
||||
for line in inv.invoice_line_ids:
|
||||
if not float_is_zero(line.discount, precision_digits=prec):
|
||||
has_discount = True
|
||||
break
|
||||
inv.has_discount = has_discount
|
||||
|
||||
def _compute_has_attachment(self):
|
||||
iao = self.env['ir.attachment']
|
||||
for inv in self:
|
||||
if iao.search([
|
||||
('res_model', '=', 'account.invoice'),
|
||||
('res_id', '=', inv.id),
|
||||
('type', '=', 'binary'),
|
||||
('company_id', '=', inv.company_id.id)], limit=1):
|
||||
inv.has_attachment = True
|
||||
else:
|
||||
inv.has_attachment = False
|
||||
|
||||
def _search_has_attachment(self, operator, value):
|
||||
att_inv_ids = {}
|
||||
if operator == '=':
|
||||
search_res = self.env['ir.attachment'].search_read([
|
||||
('res_model', '=', 'account.invoice'),
|
||||
('type', '=', 'binary'),
|
||||
('res_id', '!=', False)], ['res_id'])
|
||||
for att in search_res:
|
||||
att_inv_ids[att['res_id']] = True
|
||||
res = [('id', value and 'in' or 'not in', list(att_inv_ids))]
|
||||
return res
|
||||
|
||||
# when you have an invoice created from a lot of sale orders, the 'name'
|
||||
# field is very large, which makes the name_get() of that invoice very big
|
||||
# which screws-up the form view of that invoice because of the link at the
|
||||
# top of the screen
|
||||
# That's why we have to cut the name_get() when it's too long
|
||||
def name_get(self):
|
||||
old_res = super().name_get()
|
||||
res = []
|
||||
for old_re in old_res:
|
||||
name = old_re[1]
|
||||
if name and len(name) > 100:
|
||||
# nice cut
|
||||
name = u'%s ...' % ', '.join(name.split(', ')[:3])
|
||||
# if not enough, hard cut
|
||||
if len(name) > 120:
|
||||
name = u'%s ...' % old_re[1][:120]
|
||||
res.append((old_re[0], name))
|
||||
return res
|
||||
|
||||
# I really hate to see a "/" in the 'name' field of the account.move.line
|
||||
# generated from customer invoices linked to the partners' account because:
|
||||
# 1) the label of an account move line is an important field, we can't
|
||||
# write a rubbish '/' in it !
|
||||
# 2) the 'name' field of the account.move.line is used in the overdue
|
||||
# letter, and '/' is not meaningful for our customer !
|
||||
# TODO mig to v12
|
||||
# def action_move_create(self):
|
||||
# res = super().action_move_create()
|
||||
# for inv in self:
|
||||
# self._cr.execute(
|
||||
# "UPDATE account_move_line SET name= "
|
||||
# "CASE WHEN name='/' THEN %s "
|
||||
# "ELSE %s||' - '||name END "
|
||||
# "WHERE move_id=%s", (inv.number, inv.number, inv.move_id.id))
|
||||
# self.invalidate_cache()
|
||||
# return res
|
||||
|
||||
def delete_lines_qty_zero(self):
|
||||
lines = self.env['account.invoice.line'].search([
|
||||
('invoice_id', 'in', self.ids), ('quantity', '=', 0)])
|
||||
lines.unlink()
|
||||
return True
|
||||
|
||||
def fix_invoice_attachment_filename(self):
|
||||
# This script is designed to fix attachment of invoices
|
||||
# badly generated by Odoo v8. I found this problem in Nov 2018 at
|
||||
# Encres Dubuit when investigating a bug where Odoo would create a
|
||||
# new attachment when printing an old invoice that already had the
|
||||
# PDF of the invoice as attachment
|
||||
logger.info('START fix customer invoice attachment filename')
|
||||
# Run this script as admin to fix problem in all companies
|
||||
self = self.sudo()
|
||||
attachs = self.env['ir.attachment'].search([
|
||||
('res_model', '=', 'account.invoice'),
|
||||
('res_id', '!=', False),
|
||||
('type', '=', 'binary'),
|
||||
('name', '=like', 'INV%.pdf'),
|
||||
('datas_fname', '=like', 'INV%.pdf.pdf')])
|
||||
for attach in attachs:
|
||||
inv = self.browse(attach.res_id)
|
||||
if inv.type in ('out_invoice', 'out_refund'):
|
||||
attach.datas_fname = attach.name
|
||||
logger.info(
|
||||
'Fixed field datas_fname of attachment ID %s name %s',
|
||||
attach.id, attach.name)
|
||||
logger.info('END fix customer invoice attachment filename')
|
||||
|
||||
# for report
|
||||
def py3o_lines_layout(self):
|
||||
self.ensure_one()
|
||||
res = []
|
||||
has_sections = False
|
||||
subtotal = 0.0
|
||||
sign = self.type == 'out_refund' and -1 or 1
|
||||
for line in self.invoice_line_ids:
|
||||
if line.display_type == 'line_section':
|
||||
# insert line
|
||||
if has_sections:
|
||||
res.append({'subtotal': subtotal})
|
||||
subtotal = 0.0 # reset counter
|
||||
has_sections = True
|
||||
else:
|
||||
if not line.display_type:
|
||||
subtotal += line.price_subtotal * sign
|
||||
res.append({'line': line})
|
||||
if has_sections: # insert last subtotal line
|
||||
res.append({'subtotal': subtotal})
|
||||
# res:
|
||||
# [
|
||||
# {'line': account_invoice_line(1) with display_type=='line_section'},
|
||||
# {'line': account_invoice_line(2) without display_type},
|
||||
# {'line': account_invoice_line(3) without display_type},
|
||||
# {'line': account_invoice_line(4) with display_type=='line_note'},
|
||||
# {'subtotal': 8932.23},
|
||||
# ]
|
||||
return res
|
||||
|
||||
def _compute_sales_dates(self):
|
||||
""" 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(
|
||||
'sale_line_ids').mapped('order_id')
|
||||
lang = inv.partner_id.commercial_partner_id.lang
|
||||
date_format = self.env["res.lang"]._lang_get(
|
||||
lang or "").date_format
|
||||
dates = ["%s%s" % (
|
||||
x.name,
|
||||
x.confirmation_date and " (%s)" %
|
||||
# only when confirmation_date display it
|
||||
x.confirmation_date.strftime(date_format) or "")
|
||||
for x in sales]
|
||||
inv.sale_dates = ", ".join(dates)
|
||||
|
||||
|
||||
class AccountInvoiceLine(models.Model):
|
||||
_inherit = 'account.invoice.line'
|
||||
|
||||
# In the 'account' module, we have related stored field for:
|
||||
# company_id, partner_id, currency_id
|
||||
invoice_type = fields.Selection(store=True)
|
||||
date_invoice = fields.Date(
|
||||
related='invoice_id.date_invoice', store=True, readonly=True)
|
||||
commercial_partner_id = fields.Many2one(
|
||||
related='invoice_id.partner_id.commercial_partner_id',
|
||||
store=True, readonly=True, compute_sudo=True)
|
||||
state = fields.Selection(
|
||||
related='invoice_id.state', store=True, readonly=True,
|
||||
string='Invoice State')
|
||||
invoice_number = fields.Char(
|
||||
related='invoice_id.move_id.name', store=True, readonly=True,
|
||||
string='Invoice Number')
|
||||
|
||||
|
||||
class AccountJournal(models.Model):
|
||||
_inherit = 'account.journal'
|
||||
|
||||
hide_bank_statement_balance = fields.Boolean(
|
||||
string='Hide Bank Statement Balance',
|
||||
help="You may want to enable this option when your bank "
|
||||
"journal is generated from a bank statement file that "
|
||||
"doesn't handle start/end balance (QIF for instance) and "
|
||||
"you don't want to enter the start/end balance manually: it "
|
||||
"will prevent the display of wrong information in the accounting "
|
||||
"dashboard and on bank statements.")
|
||||
|
||||
@api.depends(
|
||||
'name', 'currency_id', 'company_id', 'company_id.currency_id', 'code')
|
||||
def name_get(self):
|
||||
res = []
|
||||
if self._context.get('journal_show_code_only'):
|
||||
for journal in self:
|
||||
res.append((journal.id, journal.code))
|
||||
return res
|
||||
else:
|
||||
for journal in self:
|
||||
currency = journal.currency_id or\
|
||||
journal.company_id.currency_id
|
||||
name = "[%s] %s (%s)" % (
|
||||
journal.code, journal.name, currency.name)
|
||||
res.append((journal.id, name))
|
||||
return res
|
||||
|
||||
@api.constrains('default_credit_account_id', 'default_debit_account_id')
|
||||
def _check_account_type_on_bank_journal(self):
|
||||
bank_acc_type = self.env.ref('account.data_account_type_liquidity')
|
||||
for jrl in self:
|
||||
if jrl.type in ('bank', 'cash'):
|
||||
if (
|
||||
jrl.default_debit_account_id and
|
||||
jrl.default_debit_account_id.user_type_id !=
|
||||
bank_acc_type):
|
||||
raise ValidationError(_(
|
||||
"On journal '%s', the default debit account '%s' "
|
||||
"should be configured with Type = 'Bank and Cash'.")
|
||||
% (jrl.display_name,
|
||||
jrl.default_debit_account_id.display_name))
|
||||
if (
|
||||
jrl.default_credit_account_id and
|
||||
jrl.default_credit_account_id.user_type_id !=
|
||||
bank_acc_type):
|
||||
raise ValidationError(_(
|
||||
"On journal '%s', the default credit account '%s' "
|
||||
"should be configured with Type = 'Bank and Cash'.")
|
||||
% (jrl.display_name,
|
||||
jrl.default_credit_account_id.display_name))
|
||||
|
||||
|
||||
class AccountAccount(models.Model):
|
||||
_inherit = 'account.account'
|
||||
|
||||
@api.depends('name', 'code')
|
||||
def name_get(self):
|
||||
if self._context.get('account_account_show_code_only'):
|
||||
res = []
|
||||
for record in self:
|
||||
res.append((record.id, record.code))
|
||||
return res
|
||||
else:
|
||||
return super().name_get()
|
||||
|
||||
# https://github.com/odoo/odoo/issues/23040
|
||||
# TODO mig to v12
|
||||
def fix_bank_account_types(self):
|
||||
aao = self.env['account.account']
|
||||
companies = self.env['res.company'].search([])
|
||||
if len(companies) > 1 and self.env.user.id != SUPERUSER_ID:
|
||||
raise UserError(
|
||||
"In multi-company setups, you should run this "
|
||||
"script as admin user")
|
||||
logger.info("START the script 'fix bank and cash account types'")
|
||||
bank_type = self.env.ref('account.data_account_type_liquidity')
|
||||
asset_type = self.env.ref('account.data_account_type_current_assets')
|
||||
journals = self.env['account.journal'].search(
|
||||
[('type', 'in', ('bank', 'cash'))], order='company_id')
|
||||
journal_accounts_bank_type = aao
|
||||
for journal in journals:
|
||||
for account in [
|
||||
journal.default_credit_account_id,
|
||||
journal.default_debit_account_id]:
|
||||
if account:
|
||||
if account.user_type_id != bank_type:
|
||||
account.user_type_id = bank_type.id
|
||||
logger.info(
|
||||
'Company %s: Account %s updated to Bank '
|
||||
'and Cash type',
|
||||
account.company_id.display_name, account.code)
|
||||
if account not in journal_accounts_bank_type:
|
||||
journal_accounts_bank_type += account
|
||||
accounts = aao.search([
|
||||
('user_type_id', '=', bank_type.id)], order='company_id, code')
|
||||
for account in accounts:
|
||||
if account not in journal_accounts_bank_type:
|
||||
account.user_type_id = asset_type.id
|
||||
logger.info(
|
||||
'Company %s: Account %s updated to Current Asset type',
|
||||
account.company_id.display_name, account.code)
|
||||
logger.info("END of the script 'fix bank and cash account types'")
|
||||
return True
|
||||
|
||||
# TODO mig to v12
|
||||
@api.model
|
||||
def create_account_groups(self, level=2, name_prefix=u'Comptes '):
|
||||
'''Should be launched by a script. Make sure the account_group module is installed
|
||||
(the account_usability module doesn't depend on it currently'''
|
||||
assert level >= 1
|
||||
assert isinstance(level, int)
|
||||
companies = self.env['res.company'].search([])
|
||||
if len(companies) > 1:
|
||||
logger.info(
|
||||
'Multi-company detected: running script create_account_groups '
|
||||
'as admin')
|
||||
self = self.sudo()
|
||||
ago = self.env['account.group']
|
||||
groups = ago.search([])
|
||||
if groups:
|
||||
raise UserError(_("Some account groups already exists"))
|
||||
accounts = self.search([])
|
||||
struct = {'childs': {}}
|
||||
for account in accounts:
|
||||
assert len(account.code) > level
|
||||
n = 1
|
||||
parent = struct
|
||||
gparent = False
|
||||
while n <= level:
|
||||
group_code = account.code[:n]
|
||||
if group_code not in parent['childs']:
|
||||
new_group = ago.create({
|
||||
'name': u'%s%s' % (name_prefix or '', group_code),
|
||||
'code_prefix': group_code,
|
||||
'parent_id': gparent and gparent.id or False,
|
||||
})
|
||||
parent['childs'][group_code] = {'obj': new_group, 'childs': {}}
|
||||
parent = parent['childs'][group_code]
|
||||
gparent = parent['obj']
|
||||
n += 1
|
||||
account.group_id = gparent.id
|
||||
|
||||
|
||||
class AccountAnalyticAccount(models.Model):
|
||||
_inherit = 'account.analytic.account'
|
||||
|
||||
def name_get(self):
|
||||
if self._context.get('analytic_account_show_code_only'):
|
||||
res = []
|
||||
for record in self:
|
||||
res.append((record.id, record.code or record.name))
|
||||
return res
|
||||
else:
|
||||
return super().name_get()
|
||||
|
||||
_sql_constraints = [(
|
||||
'code_company_unique',
|
||||
'unique(code, company_id)',
|
||||
'An analytic account with the same code already '
|
||||
'exists in the same company!')]
|
||||
|
||||
|
||||
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)]})
|
||||
date = fields.Date(copy=False)
|
||||
default_account_id = fields.Many2one(
|
||||
related='journal_id.default_debit_account_id', readonly=True)
|
||||
default_credit = fields.Float(
|
||||
compute='_compute_default_credit_debit', readonly=True)
|
||||
default_debit = fields.Float(
|
||||
compute='_compute_default_credit_debit', readonly=True)
|
||||
|
||||
@api.depends('line_ids.credit', 'line_ids.debit')
|
||||
def _compute_default_credit_debit(self):
|
||||
for move in self:
|
||||
total_debit = total_credit = default_debit = default_credit = 0.0
|
||||
for l in move.line_ids:
|
||||
total_debit += l.debit
|
||||
total_credit += l.credit
|
||||
# I could use float_compare, but I don't think it's really needed
|
||||
# in this context
|
||||
if total_debit > total_credit:
|
||||
default_credit = total_debit - total_credit
|
||||
else:
|
||||
default_debit = total_credit - total_debit
|
||||
move.default_credit = default_credit
|
||||
move.default_debit = default_debit
|
||||
|
||||
|
||||
class AccountMoveLine(models.Model):
|
||||
_inherit = 'account.move.line'
|
||||
# Native order:
|
||||
# _order = "date desc, id desc"
|
||||
# Problem: when you manually create a journal entry, the
|
||||
# order of the lines is inverted when you save ! It is quite annoying for
|
||||
# the user...
|
||||
_order = "date desc, id asc"
|
||||
|
||||
# Update field only to add a string (there is no string in account module)
|
||||
invoice_id = fields.Many2one(string='Invoice')
|
||||
account_reconcile = fields.Boolean(
|
||||
related='account_id.reconcile', readonly=True)
|
||||
full_reconcile_id = fields.Many2one(string='Full Reconcile')
|
||||
matched_debit_ids = fields.One2many(string='Partial Reconcile Debit')
|
||||
matched_credit_ids = fields.One2many(string='Partial Reconcile Credit')
|
||||
reconcile_string = fields.Char(
|
||||
compute='_compute_reconcile_string', string='Reconcile', store=True)
|
||||
|
||||
@api.onchange('credit')
|
||||
def _credit_onchange(self):
|
||||
prec = self.env['decimal.precision'].precision_get('Account')
|
||||
if (
|
||||
not float_is_zero(self.credit, precision_digits=prec) and
|
||||
not float_is_zero(self.debit, precision_digits=prec)):
|
||||
self.debit = 0
|
||||
|
||||
@api.onchange('debit')
|
||||
def _debit_onchange(self):
|
||||
prec = self.env['decimal.precision'].precision_get('Account')
|
||||
if (
|
||||
not float_is_zero(self.debit, precision_digits=prec) and
|
||||
not float_is_zero(self.credit, precision_digits=prec)):
|
||||
self.credit = 0
|
||||
|
||||
@api.onchange('currency_id', 'amount_currency')
|
||||
def _amount_currency_change(self):
|
||||
prec = self.env['decimal.precision'].precision_get('Account')
|
||||
if (
|
||||
self.currency_id and
|
||||
self.amount_currency and
|
||||
float_is_zero(self.credit, precision_digits=prec) and
|
||||
float_is_zero(self.debit, precision_digits=prec)):
|
||||
date = self.date or None
|
||||
amount_company_currency = self.currency_id.with_context(
|
||||
date=date).compute(
|
||||
self.amount_currency, self.env.user.company_id.currency_id)
|
||||
precision = self.env['decimal.precision'].precision_get('Account')
|
||||
if float_compare(
|
||||
amount_company_currency, 0,
|
||||
precision_digits=precision) == -1:
|
||||
self.debit = amount_company_currency * -1
|
||||
else:
|
||||
self.credit = amount_company_currency
|
||||
|
||||
def show_account_move_form(self):
|
||||
self.ensure_one()
|
||||
action = self.env['ir.actions.act_window'].for_xml_id(
|
||||
'account', 'action_move_line_form')
|
||||
action.update({
|
||||
'res_id': self.move_id.id,
|
||||
'view_id': False,
|
||||
'views': False,
|
||||
'view_mode': 'form,tree',
|
||||
})
|
||||
return action
|
||||
|
||||
@api.depends(
|
||||
'full_reconcile_id', 'matched_debit_ids', 'matched_credit_ids')
|
||||
def _compute_reconcile_string(self):
|
||||
for line in self:
|
||||
rec_str = False
|
||||
if line.full_reconcile_id:
|
||||
rec_str = line.full_reconcile_id.name
|
||||
else:
|
||||
rec_str = ', '.join([
|
||||
'a%d' % pr.id for pr in line.matched_debit_ids + line.matched_credit_ids])
|
||||
line.reconcile_string = rec_str
|
||||
|
||||
|
||||
class AccountPartialReconcile(models.Model):
|
||||
_inherit = "account.partial.reconcile"
|
||||
_rec_name = "id"
|
||||
|
||||
def name_get(self):
|
||||
res = []
|
||||
for rec in self:
|
||||
# There is no seq for partial rec, so I simulate one with the ID
|
||||
# Prefix for full rec: 'A' (upper case)
|
||||
# Prefix for partial rec: 'a' (lower case)
|
||||
amount_fmt = formatLang(self.env, rec.amount, currency_obj=rec.company_currency_id)
|
||||
name = 'a%d (%s)' % (rec.id, amount_fmt)
|
||||
res.append((rec.id, name))
|
||||
return res
|
||||
|
||||
|
||||
class AccountBankStatement(models.Model):
|
||||
_inherit = 'account.bank.statement'
|
||||
|
||||
start_date = fields.Date(
|
||||
compute='_compute_dates', string='Start Date', readonly=True,
|
||||
store=True)
|
||||
end_date = fields.Date(
|
||||
compute='_compute_dates', string='End Date', readonly=True,
|
||||
store=True)
|
||||
hide_bank_statement_balance = fields.Boolean(
|
||||
related='journal_id.hide_bank_statement_balance', readonly=True)
|
||||
|
||||
@api.depends('line_ids.date')
|
||||
def _compute_dates(self):
|
||||
for st in self:
|
||||
dates = [line.date for line in st.line_ids]
|
||||
st.start_date = dates and min(dates) or False
|
||||
st.end_date = dates and max(dates) or False
|
||||
|
||||
def _balance_check(self):
|
||||
for stmt in self:
|
||||
if stmt.hide_bank_statement_balance:
|
||||
continue
|
||||
else:
|
||||
super(AccountBankStatement, stmt)._balance_check()
|
||||
return True
|
||||
|
||||
@api.depends('name', 'start_date', 'end_date')
|
||||
def name_get(self):
|
||||
res = []
|
||||
for statement in self:
|
||||
name = "%s (%s => %s)" % (
|
||||
statement.name, statement.start_date, statement.end_date)
|
||||
res.append((statement.id, name))
|
||||
return res
|
||||
|
||||
|
||||
class AccountBankStatementLine(models.Model):
|
||||
_inherit = 'account.bank.statement.line'
|
||||
# Native order is:
|
||||
# _order = 'statement_id desc, sequence, id desc'
|
||||
_order = 'statement_id desc, date desc, sequence, id desc'
|
||||
|
||||
# Disable guessing for reconciliation
|
||||
# because my experience with several customers shows that it is a problem
|
||||
# in the following scenario : move line 'x' has been "guessed" by OpenERP
|
||||
# to be reconciled with a statement line 'Y' at the end of the bank
|
||||
# statement, but it is a mistake because it should be reconciled with
|
||||
# statement line 'B' at the beginning of the bank statement
|
||||
# When the user is on statement line 'B', he tries to select
|
||||
# move line 'x', but it can't find it... because it is already "reserved"
|
||||
# by the guess of OpenERP for statement line 'Y' ! To solve this problem,
|
||||
# the user must go to statement line 'Y' and unselect move line 'x'
|
||||
# and then come back on statement line 'B' and select move line 'A'...
|
||||
# but non super-expert users can't do that because it is impossible to
|
||||
# figure out that the fact that the user can't find move line 'x'
|
||||
# is caused by this.
|
||||
# Set search_reconciliation_proposition to False by default
|
||||
# TODO: re-write in v10
|
||||
# def get_data_for_reconciliations(
|
||||
# self, cr, uid, ids, excluded_ids=None,
|
||||
# search_reconciliation_proposition=False, context=None):
|
||||
# # Make variable name shorted for PEP8 !
|
||||
# search_rec_prop = search_reconciliation_proposition
|
||||
# return super().\
|
||||
# get_data_for_reconciliations(
|
||||
# cr, uid, ids, excluded_ids=excluded_ids,
|
||||
# search_reconciliation_proposition=search_rec_prop,
|
||||
# context=context)
|
||||
|
||||
def _prepare_reconciliation_move(self, move_ref):
|
||||
vals = super()._prepare_reconciliation_move(move_ref)
|
||||
# By default, ref contains the name of the statement + name of the
|
||||
# statement line. It causes 2 problems:
|
||||
# 1) The 'ref' field is too big
|
||||
# 2) The name of the statement line is already written in the name of
|
||||
# the move line -> not useful to have the info 2 times
|
||||
# In the end, I think it's better to just put nothing (we could write
|
||||
# the name of the statement which has the account number, but it
|
||||
# doesn't bring any useful info to the accountant)
|
||||
# The only "good" thing to do would be to have a sequence per
|
||||
# statement line and write it in this 'ref' field
|
||||
# But that would required an additionnal field on statement lines
|
||||
vals['ref'] = False
|
||||
return vals
|
||||
|
||||
def show_account_move(self):
|
||||
self.ensure_one()
|
||||
action = self.env['ir.actions.act_window'].for_xml_id(
|
||||
'account', 'action_move_line_form')
|
||||
if self.journal_entry_ids:
|
||||
action.update({
|
||||
'views': False,
|
||||
'view_id': False,
|
||||
'view_mode': 'form,tree',
|
||||
'res_id': self.journal_entry_ids[0].move_id.id,
|
||||
})
|
||||
return action
|
||||
else:
|
||||
raise UserError(_(
|
||||
'No journal entry linked to this bank statement line.'))
|
||||
|
||||
|
||||
class AccountFiscalPosition(models.Model):
|
||||
_inherit = 'account.fiscal.position'
|
||||
|
||||
# TODO mig to v12 ?
|
||||
@api.model
|
||||
def get_fiscal_position_no_partner(
|
||||
self, company_id=None, vat_subjected=False, country_id=None):
|
||||
'''This method is inspired by the method get_fiscal_position()
|
||||
in odoo/addons/account/partner.py : it uses the same algo
|
||||
but without a real partner.
|
||||
Returns a recordset of fiscal position, or False'''
|
||||
domains = [[
|
||||
('auto_apply', '=', True),
|
||||
('vat_required', '=', vat_subjected),
|
||||
('company_id', '=', company_id)]]
|
||||
if vat_subjected:
|
||||
domains += [[
|
||||
('auto_apply', '=', True),
|
||||
('vat_required', '=', False),
|
||||
('company_id', '=', company_id)]]
|
||||
|
||||
for domain in domains:
|
||||
if country_id:
|
||||
fps = self.search(
|
||||
domain + [('country_id', '=', country_id)], limit=1)
|
||||
if fps:
|
||||
return fps[0]
|
||||
|
||||
fps = self.search(
|
||||
domain +
|
||||
[('country_group_id.country_ids', '=', country_id)],
|
||||
limit=1)
|
||||
if fps:
|
||||
return fps[0]
|
||||
|
||||
fps = self.search(
|
||||
domain +
|
||||
[('country_id', '=', None), ('country_group_id', '=', None)],
|
||||
limit=1)
|
||||
if fps:
|
||||
return fps[0]
|
||||
return False
|
||||
|
||||
|
||||
class AccountReconcileModel(models.Model):
|
||||
_inherit = 'account.reconcile.model'
|
||||
|
||||
@api.onchange('name')
|
||||
def onchange_name(self):
|
||||
# Do NOT copy by default name on label
|
||||
# Because it's much better to have the bank statement line label as
|
||||
# label of the counter-part move line, then the label of the button
|
||||
assert True # Stupid line of code just to have something...
|
||||
|
||||
|
||||
class AccountIncoterms(models.Model):
|
||||
_inherit = 'account.incoterms'
|
||||
|
||||
@api.depends('code', 'name')
|
||||
def name_get(self):
|
||||
res = []
|
||||
for rec in self:
|
||||
res.append((rec.id, '[%s] %s' % (rec.code, rec.name)))
|
||||
return res
|
||||
|
||||
|
||||
class AccountReconciliation(models.AbstractModel):
|
||||
_inherit = 'account.reconciliation.widget'
|
||||
|
||||
# Add ability to filter by account code in the work interface of the
|
||||
# bank statement
|
||||
@api.model
|
||||
def _domain_move_lines(self, search_str):
|
||||
str_domain = super()._domain_move_lines(search_str)
|
||||
account_code_domain = [('account_id.code', '=ilike', search_str + '%')]
|
||||
str_domain = expression.OR([str_domain, account_code_domain])
|
||||
return str_domain
|
||||
|
||||
@api.model
|
||||
def _domain_move_lines_for_reconciliation(
|
||||
self, st_line, aml_accounts, partner_id,
|
||||
excluded_ids=None, search_str=False):
|
||||
domain = super()._domain_move_lines_for_reconciliation(
|
||||
st_line, aml_accounts, partner_id,
|
||||
excluded_ids=excluded_ids, search_str=search_str)
|
||||
# We want to replace a domain item by another one
|
||||
position = domain.index(('payment_id', '<>', False))
|
||||
domain[position] = ['journal_id', '=', st_line.journal_id.id]
|
||||
return domain
|
||||
|
||||
|
||||
class ResConfigSettings(models.TransientModel):
|
||||
_inherit = 'res.config.settings'
|
||||
|
||||
transfer_account_id = fields.Many2one(
|
||||
related='company_id.transfer_account_id', readonly=False)
|
||||
@@ -1,26 +0,0 @@
|
||||
# Copyright 2018-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).
|
||||
|
||||
from odoo import models, fields
|
||||
|
||||
|
||||
class AccountInvoiceReport(models.Model):
|
||||
_inherit = 'account.invoice.report'
|
||||
|
||||
number = fields.Char(string="Number", readonly=True)
|
||||
|
||||
def _sub_select(self):
|
||||
select_str = super(AccountInvoiceReport, self)._sub_select()
|
||||
select_str += ", ai.number"
|
||||
return select_str
|
||||
|
||||
def _select(self):
|
||||
select_str = super(AccountInvoiceReport, self)._select()
|
||||
select_str += ", sub.number"
|
||||
return select_str
|
||||
|
||||
def _group_by(self):
|
||||
group_by_str = super(AccountInvoiceReport, self)._group_by()
|
||||
group_by_str += ", ai.number"
|
||||
return group_by_str
|
||||
@@ -1,51 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2018 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="account_invoice_report_tree" model="ir.ui.view">
|
||||
<field name="name">usability.account.invoice.report.tree</field>
|
||||
<field name="model">account.invoice.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Invoices Analysis">
|
||||
<field name="number"/>
|
||||
<field name="date"/>
|
||||
<field name="date_due"/>
|
||||
<field name="type"/>
|
||||
<field name="commercial_partner_id"/>
|
||||
<field name="user_id"/>
|
||||
<field name="product_id"/>
|
||||
<field name="product_qty" sum="1"/>
|
||||
<field name="uom_name" groups="uom.group_uom"/>
|
||||
<field name="price_total" sum="1"/>
|
||||
<field name="state"/>
|
||||
</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, 'search_default_year': 1}</field> <!-- Remove group_by_no_leaf, which breaks tree view -->
|
||||
</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, 'search_default_year': 1}</field> <!-- Remove group_by_no_leaf, which breaks tree view -->
|
||||
</record>
|
||||
|
||||
<record id="view_account_invoice_report_pivot" model="ir.ui.view">
|
||||
<field name="name">usability.account.invoice.report</field>
|
||||
<field name="model">account.invoice.report</field>
|
||||
<field name="inherit_id" ref="account.view_account_invoice_report_pivot"/>
|
||||
<field name="arch" type="xml">
|
||||
<pivot position="attributes">
|
||||
<attribute name="disable_linking"></attribute>
|
||||
</pivot>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
</odoo>
|
||||
@@ -1,15 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2018-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="account.account_invoices" model="ir.actions.report">
|
||||
<!-- Don't attach on supplier invoices/refunds ! -->
|
||||
<field name="attachment">(object.type in ('out_invoice', 'out_refund')) and (object.state in ('open','in_payment','paid')) and ('INV'+(object.number or '').replace('/','')+'.pdf')</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -1,13 +0,0 @@
|
||||
diff --git a/addons/account/static/src/js/reconciliation/reconciliation_renderer.js b/addons/account/static/src/js/reconciliation/reconciliation_renderer.js
|
||||
index 53f28e0c620..1721d01edf9 100644
|
||||
--- a/addons/account/static/src/js/reconciliation/reconciliation_renderer.js
|
||||
+++ b/addons/account/static/src/js/reconciliation/reconciliation_renderer.js
|
||||
@@ -514,7 +514,7 @@ var LineRenderer = Widget.extend(FieldManagerMixin, {
|
||||
}
|
||||
return this.model.makeRecord('account.bank.statement.line', [field], {
|
||||
partner_id: {
|
||||
- domain: ["|", ["is_company", "=", true], ["parent_id", "=", false], "|", ["customer", "=", true], ["supplier", "=", true]],
|
||||
+ domain: ["|", ["is_company", "=", true], ["parent_id", "=", false]],
|
||||
options: {
|
||||
no_open: true
|
||||
}
|
||||
@@ -1,619 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2015-2019 Akretion France (http://www.akretion.com/)
|
||||
@author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
-->
|
||||
|
||||
<odoo>
|
||||
|
||||
<!-- INVOICE -->
|
||||
<record id="invoice_supplier_form" model="ir.ui.view">
|
||||
<field name="name">account_usability.supplier.invoice.form</field>
|
||||
<field name="model">account.invoice</field>
|
||||
<field name="inherit_id" ref="account.invoice_supplier_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="fiscal_position_id" position="attributes">
|
||||
<attribute name="widget">selection</attribute>
|
||||
</field>
|
||||
<field name="incoterm_id" position="attributes">
|
||||
<attribute name="widget">selection</attribute>
|
||||
</field>
|
||||
<field name="invoice_line_ids" position="before">
|
||||
<button name="delete_lines_qty_zero" states="draft" string="⇒ Delete lines qty=0" type="object" class="oe_link oe_right" groups="account.group_account_invoice"/>
|
||||
</field>
|
||||
<xpath expr="//field[@name='tax_line_ids']/tree/field[@name='amount']" position="before">
|
||||
<field name="base" readonly="1"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="invoice_form" model="ir.ui.view">
|
||||
<field name="name">account_usability.invoice.form</field>
|
||||
<field name="model">account.invoice</field>
|
||||
<field name="inherit_id" ref="account.invoice_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="fiscal_position_id" position="attributes">
|
||||
<attribute name="widget">selection</attribute>
|
||||
</field>
|
||||
<field name="incoterm_id" position="attributes">
|
||||
<attribute name="widget">selection</attribute>
|
||||
</field>
|
||||
<!-- move sent field and make it visible -->
|
||||
<field name="sent" position="replace"/>
|
||||
<field name="move_id" position="before">
|
||||
<field name="sent"/>
|
||||
</field>
|
||||
<xpath expr="//field[@name='tax_line_ids']/tree/field[@name='amount']" position="before">
|
||||
<field name="base" readonly="1"/>
|
||||
</xpath>
|
||||
<!-- Warning: there are 2 invoice_print buttons in the native view... probably a bug -->
|
||||
<!--
|
||||
<xpath expr="//button[@name='invoice_print']" position="attributes">
|
||||
<attribute name="attrs">{'invisible': [('state', 'not in', ('open', 'paid'))]}</attribute>
|
||||
</xpath>
|
||||
<xpath expr="//button[@name='invoice_print'][2]" position="attributes">
|
||||
<attribute name="attrs">{'invisible': True}</attribute>
|
||||
</xpath> -->
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="invoice_tree" model="ir.ui.view">
|
||||
<field name="name">account_usability.invoice_tree</field>
|
||||
<field name="model">account.invoice</field>
|
||||
<field name="inherit_id" ref="account.invoice_tree"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="reference" position="attributes">
|
||||
<attribute name="invisible">not context.get('type') in ('in_invoice', 'in_refund')</attribute>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_account_invoice_filter" model="ir.ui.view">
|
||||
<field name="name">account_usability.invoice.search</field>
|
||||
<field name="model">account.invoice</field>
|
||||
<field name="inherit_id" ref="account.view_account_invoice_filter"/>
|
||||
<field name="arch" type="xml">
|
||||
<filter name="late" position="after">
|
||||
<separator/>
|
||||
<filter name="to_send" string="To Send" domain="[('sent', '=', False), ('state', 'in', ('open', 'paid'))]"/>
|
||||
<filter name="sent" string="Sent" domain="[('sent', '=', True)]"/>
|
||||
<separator/>
|
||||
<filter name="no_attachment" string="Missing Attachment" domain="[('has_attachment', '=', False)]"/>
|
||||
</filter>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Having a menu entry on invoice lines is often very usefull for odoo user:
|
||||
they can search in their lines, etc...
|
||||
So I enhance the generic views and add actions, but I don't add menu entries here ;
|
||||
the creation of the corresponding menu entry should be done in the customer-specifc
|
||||
module -->
|
||||
<record id="view_invoice_line_tree" model="ir.ui.view">
|
||||
<field name="name">account_usability.invoice_line_tree</field>
|
||||
<field name="model">account.invoice.line</field>
|
||||
<field name="inherit_id" ref="account.view_invoice_line_tree"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="name" position="before">
|
||||
<field name="partner_id" invisible="not context.get('show_invoice_fields')"/>
|
||||
<field name="date_invoice" invisible="not context.get('show_invoice_fields')"/>
|
||||
<field name="invoice_number" invisible="not context.get('show_invoice_fields')"/>
|
||||
</field>
|
||||
<field name="currency_id" position="after">
|
||||
<field name="state" invisible="not context.get('show_invoice_fields')"/>
|
||||
<field name="invoice_type" invisible="1"/>
|
||||
</field>
|
||||
<field name="quantity" position="attributes">
|
||||
<attribute name="sum">1</attribute>
|
||||
</field>
|
||||
<xpath expr="/tree" position="attributes">
|
||||
<attribute name="decoration-info">state == 'draft'</attribute>
|
||||
<attribute name="decoration-muted">state == 'cancel'</attribute>
|
||||
<attribute name="edit">0</attribute>
|
||||
<attribute name="create">0</attribute>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="account_invoice_line_search" model="ir.ui.view">
|
||||
<field name="name">account_usability.invoice_line_search</field>
|
||||
<field name="model">account.invoice.line</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Search Invoice Lines">
|
||||
<field name="partner_id"/>
|
||||
<field name="product_id"/>
|
||||
<field name="account_id"/>
|
||||
<field name="invoice_number"/>
|
||||
<field name="name"/>
|
||||
<filter name="out_invoice" string="Customer Invoices"
|
||||
domain="[('invoice_type', '=', 'out_invoice')]"/>
|
||||
<filter name="out_refund" string="Customer Refunds"
|
||||
domain="[('invoice_type', '=', 'out_refund')]"/>
|
||||
<filter name="in_invoice" string="Supplier Invoices"
|
||||
domain="[('invoice_type', '=', 'in_invoice')]"/>
|
||||
<filter name="in_refund" string="Supplier Refunds"
|
||||
domain="[('invoice_type', '=', 'in_refund')]"/>
|
||||
<separator/>
|
||||
<filter name="draft" string="Draft" domain="[('state', '=', 'draft')]"/>
|
||||
<filter name="unpaid" string="Not Paid" domain="[('state', '=', 'open')]"/>
|
||||
<filter name="paid" string="Paid" domain="[('state', '=', 'paid')]"/>
|
||||
|
||||
<group string="Group By" name="groupby">
|
||||
<filter name="partner_groupby" string="Partner"
|
||||
context="{'group_by': 'partner_id'}"/>
|
||||
<filter name="date_groupby" string="Invoice Date"
|
||||
context="{'group_by': 'date_invoice'}"/>
|
||||
<filter name="product_groupby" string="Product"
|
||||
context="{'group_by': 'product_id'}"/>
|
||||
<filter name="account_groupby" string="Account"
|
||||
context="{'group_by': 'account_id'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="out_invoice_line_action" model="ir.actions.act_window">
|
||||
<field name="name">Customer Invoice Lines</field>
|
||||
<field name="res_model">account.invoice.line</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="domain">[('invoice_type', '=', 'out_invoice')]</field>
|
||||
<field name="context">{'show_invoice_fields': True}</field>
|
||||
</record>
|
||||
|
||||
<record id="out_refund_line_action" model="ir.actions.act_window">
|
||||
<field name="name">Customer Refund Lines</field>
|
||||
<field name="res_model">account.invoice.line</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="domain">[('invoice_type', '=', 'out_refund')]</field>
|
||||
<field name="context">{'show_invoice_fields': True}</field>
|
||||
</record>
|
||||
|
||||
<record id="out_invoice_refund_line_action" model="ir.actions.act_window">
|
||||
<field name="name">Customer Invoice Lines</field>
|
||||
<field name="res_model">account.invoice.line</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="domain">[('invoice_type', 'in', ('out_invoice', 'out_refund'))]</field>
|
||||
<field name="context">{'show_invoice_fields': True}</field>
|
||||
</record>
|
||||
|
||||
<record id="in_invoice_line_action" model="ir.actions.act_window">
|
||||
<field name="name">Supplier Invoice Lines</field>
|
||||
<field name="res_model">account.invoice.line</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="domain">[('invoice_type', '=', 'in_invoice')]</field>
|
||||
<field name="context">{'show_invoice_fields': True}</field>
|
||||
</record>
|
||||
|
||||
<record id="in_refund_line_action" model="ir.actions.act_window">
|
||||
<field name="name">Supplier Refund Lines</field>
|
||||
<field name="res_model">account.invoice.line</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="domain">[('invoice_type', '=', 'in_refund')]</field>
|
||||
<field name="context">{'show_invoice_fields': True}</field>
|
||||
</record>
|
||||
|
||||
<record id="in_invoice_refund_line_action" model="ir.actions.act_window">
|
||||
<field name="name">Supplier Invoice Lines</field>
|
||||
<field name="res_model">account.invoice.line</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="domain">[('invoice_type', 'in', ('in_invoice', 'in_refund'))]</field>
|
||||
<field name="context">{'show_invoice_fields': True}</field>
|
||||
</record>
|
||||
|
||||
<record id="account_invoice_report_tree" model="ir.ui.view">
|
||||
<field name="name">usability.account.invoice.report.tree</field>
|
||||
<field name="model">account.invoice.report</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Invoices Analysis">
|
||||
<field name="date"/>
|
||||
<field name="commercial_partner_id"/>
|
||||
<field name="type"/>
|
||||
<field name="product_id"/>
|
||||
<field name="product_qty" sum="1"/>
|
||||
<field name="price_total" sum="1"/>
|
||||
<field name="state"/>
|
||||
<field name="currency_id" invisible="1"/>
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="account.action_account_invoice_report_all_supp" model="ir.actions.act_window">
|
||||
<field name="view_mode">pivot,graph,tree</field>
|
||||
<field name="context">{'search_default_current':1, 'search_default_supplier':1, 'search_default_year': 1}</field>
|
||||
</record>
|
||||
|
||||
<record id="account.action_account_invoice_report_all" model="ir.actions.act_window">
|
||||
<field name="view_mode">pivot,graph,tree</field>
|
||||
<field name="context">{'search_default_current':1, 'search_default_customer':1, 'search_default_year': 1}</field>
|
||||
</record>
|
||||
|
||||
<record id="view_account_invoice_report_pivot" model="ir.ui.view">
|
||||
<field name="name">usability.account.invoice.report.pivot</field>
|
||||
<field name="model">account.invoice.report</field>
|
||||
<field name="inherit_id" ref="account.view_account_invoice_report_pivot"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="/pivot" position="attributes">
|
||||
<attribute name="disable_linking"></attribute>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_invoice_tax_form" model="ir.ui.view">
|
||||
<field name="name">usability.account.invoice.tax.form</field>
|
||||
<field name="model">account.invoice.tax</field>
|
||||
<field name="inherit_id" ref="account.view_invoice_tax_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="name" position="after">
|
||||
<field name="tax_id"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_account_payment_form" model="ir.ui.view">
|
||||
<field name="name">usability.account.payment.form</field>
|
||||
<field name="model">account.payment</field>
|
||||
<field name="inherit_id" ref="account.view_account_payment_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="communication" position="after">
|
||||
<field name="payment_reference"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- model account.move.line / Journal Items -->
|
||||
<record id="account.action_account_moves_all_a" model="ir.actions.act_window">
|
||||
<field name="limit">200</field>
|
||||
<!-- Win space, because there are already many columns -->
|
||||
<field name="context">{'journal_show_code_only': True}</field>
|
||||
</record>
|
||||
|
||||
<!-- replace group_account_manager on Journal Items-->
|
||||
<record id="account.menu_action_account_moves_all" model="ir.ui.menu">
|
||||
<field name="groups_id" eval="[(6, 0, [ref('account.group_account_user')])]"/>
|
||||
</record>
|
||||
|
||||
<!-- model account.move / Journal Entries -->
|
||||
<record id="account.action_move_journal_line" model="ir.actions.act_window">
|
||||
<field name="limit">200</field>
|
||||
<field name="context">{'view_no_maturity': True}</field> <!-- Don't filter by default on misc journal -->
|
||||
</record>
|
||||
|
||||
<record id="view_move_form" model="ir.ui.view">
|
||||
<field name="name">account_usability.account_move_form</field>
|
||||
<field name="model">account.move</field>
|
||||
<field name="inherit_id" ref="account.view_move_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="journal_id" position="after">
|
||||
<field name="default_move_line_name"/>
|
||||
<field name="default_account_id" invisible="1"/>
|
||||
<field name="default_credit" invisible="1"/>
|
||||
<field name="default_debit" invisible="1"/>
|
||||
</field>
|
||||
<xpath expr="//field[@name='line_ids']" position="attributes">
|
||||
<attribute name="context" operation="python_dict" key="default_name">default_move_line_name</attribute>
|
||||
<attribute name="context" operation="python_dict" key="default_account_id">default_account_id</attribute>
|
||||
<attribute name="context" operation="python_dict" key="default_credit">default_credit</attribute>
|
||||
<attribute name="context" operation="python_dict" key="default_debit">default_debit</attribute>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='line_ids']/tree/field[@name='credit']" position="after">
|
||||
<field name="reconcile_string"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_account_move_line_filter" model="ir.ui.view">
|
||||
<field name="name">account_usability.account_move_line_search</field>
|
||||
<field name="model">account.move.line</field>
|
||||
<field name="inherit_id" ref="account.view_account_move_line_filter"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="partner_id" position="after">
|
||||
<field name="reconcile_string" />
|
||||
<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="partial_reconciled" string="Partially Reconciled" domain="[('reconcile_partial_id', '!=', False)]"/> -->
|
||||
</filter>
|
||||
<filter name="unreconciled" position="attributes">
|
||||
<attribute name="string">Unreconciled or Partially Reconciled</attribute>
|
||||
</filter>
|
||||
<field name="name" position="attributes">
|
||||
<attribute name="string">Name or Reference</attribute>
|
||||
</field>
|
||||
<field name="partner_id" position="attributes">
|
||||
<attribute name="domain">['|', ('parent_id', '=', False), ('is_company', '=', True)]</attribute>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_move_line_form" model="ir.ui.view">
|
||||
<field name="name">account_usability.account_move_line_form</field>
|
||||
<field name="model">account.move.line</field>
|
||||
<field name="inherit_id" ref="account.view_move_line_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="quantity" position="after">
|
||||
<field name="product_id" />
|
||||
</field>
|
||||
<field name="move_id" position="after">
|
||||
<field name="invoice_id"/>
|
||||
<field name="account_reconcile" invisible="1"/>
|
||||
</field>
|
||||
<xpath expr="//field[@name='full_reconcile_id']/.." position="replace">
|
||||
<field name="full_reconcile_id" nolabel="1"/> <!-- label is already in view -->
|
||||
<field name="matched_debit_ids" readonly="1" widget="many2many_tags" attrs="{'invisible': ['|', ('full_reconcile_id', '!=', False), ('matched_debit_ids', '=', [])]}"/>
|
||||
<field name="matched_credit_ids" readonly="1" widget="many2many_tags" attrs="{'invisible': ['|', ('full_reconcile_id', '!=', False), ('matched_credit_ids', '=', [])]}"/>
|
||||
<field name="reconciled" invisible="1"/>
|
||||
<button name="open_reconcile_view" class="oe_link" type="object"
|
||||
string="-> View partially reconciled entries" colspan="2"
|
||||
attrs="{'invisible': ['|', ('full_reconcile_id', '!=', False), '&', ('matched_debit_ids', '=', []), ('matched_credit_ids', '=', [])]}"/>
|
||||
<span colspan="2" attrs="{'invisible': ['|', '|', ('full_reconcile_id', '!=', False), ('matched_debit_ids', '!=', []), ('matched_credit_ids', '!=', [])]}" class="o_form_field">No Partial Reconcile</span>
|
||||
</xpath>
|
||||
<xpath expr="//label[@for='full_reconcile_id']/.." position="attributes">
|
||||
<attribute name="attrs">{'invisible': [('account_reconcile', '=', False)]}</attribute>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_move_line_tree" model="ir.ui.view">
|
||||
<field name="name">account_usability.account_move_line_tree</field>
|
||||
<field name="model">account.move.line</field>
|
||||
<field name="inherit_id" ref="account.view_move_line_tree"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="full_reconcile_id" position="attributes">
|
||||
<attribute name="invisible">1</attribute>
|
||||
</field>
|
||||
<field name="credit" position="after">
|
||||
<field name="balance" sum="Total Balance"/>
|
||||
<field name="reconcile_string"/>
|
||||
</field>
|
||||
<field name="date_maturity" position="after">
|
||||
<button name="show_account_move_form" type="object" icon="fa-arrows-h" string="Show Journal Entry"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_account_move_filter" model="ir.ui.view">
|
||||
<field name="name">account_usability.account_move_search</field>
|
||||
<field name="model">account.move</field>
|
||||
<field name="inherit_id" ref="account.view_account_move_filter"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="partner_id" position="attributes">
|
||||
<attribute name="domain">['|', ('parent_id', '=', False), ('is_company', '=', True)]</attribute>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_account_search" model="ir.ui.view">
|
||||
<field name="name">account.account.search</field>
|
||||
<field name="model">account.account</field>
|
||||
<field name="inherit_id" ref="account.view_account_search"/>
|
||||
<field name="arch" type="xml">
|
||||
<!-- The native "name" filter uses a domain ['|', ('name','ilike',self), ('code','=like',str(self)+'%')]
|
||||
This is good because it uses '=like' on 'code', but sometimes there are digits in account names,
|
||||
so you get additionnal unexpected accounts in the result of the search -->
|
||||
<field name="name" position="after">
|
||||
<field name="code" filter_domain="[('code', '=like', str(self)+'%')]" string="Code"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_account_type_tree" model="ir.ui.view">
|
||||
<field name="name">account_usability.account_type_tree</field>
|
||||
<field name="model">account.account.type</field>
|
||||
<field name="inherit_id" ref="account.view_account_type_tree" />
|
||||
<field name="arch" type="xml">
|
||||
<field name="type" position="after">
|
||||
<field name="include_initial_balance" />
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_account_journal_form" model="ir.ui.view">
|
||||
<field name="name">usability.account.journal.form</field>
|
||||
<field name="model">account.journal</field>
|
||||
<field name="inherit_id" ref="account.view_account_journal_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="bank_statements_source" position="after">
|
||||
<field name="hide_bank_statement_balance" groups="account.group_account_user"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="account_journal_dashboard_kanban_view" model="ir.ui.view">
|
||||
<field name="name">usability.account.journal.dashboard</field>
|
||||
<field name="model">account.journal</field>
|
||||
<field name="inherit_id" ref="account.account_journal_dashboard_kanban_view"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="kanban_dashboard" position="after">
|
||||
<field name="hide_bank_statement_balance"/>
|
||||
</field>
|
||||
<xpath expr="//div[@name='latest_statement']/.." position="attributes">
|
||||
<attribute name="t-if">dashboard.last_balance != dashboard.account_balance && !record.hide_bank_statement_balance.raw_value</attribute>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_account_journal_tree" model="ir.ui.view">
|
||||
<field name="name">usability.account.journal.tree</field>
|
||||
<field name="model">account.journal</field>
|
||||
<field name="inherit_id" ref="account.view_account_journal_tree"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="name" position="after">
|
||||
<field name="code"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_account_journal_search" model="ir.ui.view">
|
||||
<field name="name">usability.account.journal.search</field>
|
||||
<field name="model">account.journal</field>
|
||||
<field name="inherit_id" ref="account.view_account_journal_search"/>
|
||||
<field name="arch" type="xml">
|
||||
<filter name="dashboard" position="after">
|
||||
<group name="groupby" string="Group By">
|
||||
<filter name="type_groupby" string="Type" context="{'group_by': 'type'}"/>
|
||||
</group>
|
||||
</filter>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_bank_statement_form" model="ir.ui.view">
|
||||
<field name="name">usability.account.bank.statement.form</field>
|
||||
<field name="model">account.bank.statement</field>
|
||||
<field name="inherit_id" ref="account.view_bank_statement_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='line_ids']/tree/field[@name='bank_account_id']" position="after">
|
||||
<!-- The cancel button is provided by the account_cancel module, but we don't want to depend on it -->
|
||||
<button name="show_account_move" type="object"
|
||||
string="View Account Move" icon="fa-arrow-right"
|
||||
attrs="{'invisible': [('journal_entry_ids', '=', [])]}"/>
|
||||
</xpath>
|
||||
<field name="date" position="after">
|
||||
<field name="start_date"/>
|
||||
<field name="end_date"/>
|
||||
<field name="hide_bank_statement_balance" invisible="1"/>
|
||||
</field>
|
||||
<field name="date" position="attributes">
|
||||
<attribute name="invisible">1</attribute>
|
||||
</field>
|
||||
<label for="balance_start" position="attributes">
|
||||
<attribute name="attrs">{'invisible': [('hide_bank_statement_balance', '=', True)]}</attribute>
|
||||
</label>
|
||||
<label for="balance_end_real" position="attributes">
|
||||
<attribute name="attrs">{'invisible': [('hide_bank_statement_balance', '=', True)]}</attribute>
|
||||
</label>
|
||||
<xpath expr="//field[@name='balance_start']/.." position="attributes">
|
||||
<attribute name="attrs">{'invisible': [('hide_bank_statement_balance', '=', True)]}</attribute>
|
||||
</xpath>
|
||||
<xpath expr="//field[@name='balance_end_real']/.." position="attributes">
|
||||
<attribute name="attrs">{'invisible': [('hide_bank_statement_balance', '=', True)]}</attribute>
|
||||
</xpath>
|
||||
<group name="sale_total" position="attributes">
|
||||
<attribute name="attrs">{'invisible': [('hide_bank_statement_balance', '=', True)]}</attribute>
|
||||
</group>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_bank_statement_tree" model="ir.ui.view">
|
||||
<field name="name">usability.account.bank.statement.tree</field>
|
||||
<field name="model">account.bank.statement</field>
|
||||
<field name="inherit_id" ref="account.view_bank_statement_tree"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="date" position="attributes">
|
||||
<attribute name="invisible">1</attribute>
|
||||
</field>
|
||||
<field name="journal_id" position="after">
|
||||
<field name="start_date"/>
|
||||
<field name="end_date"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_bank_statement_search" model="ir.ui.view">
|
||||
<field name="name">usability.account.bank.statement.search</field>
|
||||
<field name="model">account.bank.statement</field>
|
||||
<field name="inherit_id" ref="account.view_bank_statement_search"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="date" position="attributes">
|
||||
<attribute name="invisible">1</attribute>
|
||||
</field>
|
||||
<field name="date" position="after">
|
||||
<field name="start_date"/>
|
||||
<field name="end_date"/>
|
||||
</field>
|
||||
<filter name="date" position="attributes">
|
||||
<attribute name="invisible">1</attribute>
|
||||
</filter>
|
||||
<filter name="date" position="after">
|
||||
<filter name="start_date_groupby" string="Start Date"
|
||||
context="{'group_by': 'start_date'}"/>
|
||||
<filter name="end_date_groupby" string="End Date"
|
||||
context="{'group_by': 'end_date'}"/>
|
||||
</filter>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- ACCOUNT TAX -->
|
||||
<record id="view_tax_tree" model="ir.ui.view">
|
||||
<field name="model">account.tax</field>
|
||||
<field name="inherit_id" ref="account.view_tax_tree"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="company_id" position="before">
|
||||
<field name="price_include" string="Include"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- ACCOUNT TAX GROUP -->
|
||||
<!-- in the account module, there is nothing for account.tax.group : no form/tree view, no menu... -->
|
||||
<record id="account_tax_group_form" model="ir.ui.view">
|
||||
<field name="name">usability.account.tax.group.form</field>
|
||||
<field name="model">account.tax.group</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Tax Group">
|
||||
<group name="main">
|
||||
<field name="name"/>
|
||||
<field name="sequence" invisible="1"/>
|
||||
</group>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="account_tax_group_tree" model="ir.ui.view">
|
||||
<field name="name">usability.account.tax.group.tree</field>
|
||||
<field name="model">account.tax.group</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Tax Groups">
|
||||
<field name="sequence" widget="handle"/>
|
||||
<field name="name"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="account_tax_group_action" model="ir.actions.act_window">
|
||||
<field name="name">Tax Groups</field>
|
||||
<field name="res_model">account.tax.group</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
</record>
|
||||
|
||||
<menuitem id="account_tax_group_menu" action="account_tax_group_action" parent="account.account_account_menu" sequence="2"/>
|
||||
|
||||
<!-- Account config page -->
|
||||
<record id="res_config_settings_view_form" model="ir.ui.view">
|
||||
<field name="name">account_usability account config page</field>
|
||||
<field name="model">res.config.settings</field>
|
||||
<field name="inherit_id" ref="account.res_config_settings_view_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='account_bank_reconciliation_start']/../.." position="after">
|
||||
<div class="col-xs-12 col-md-6 o_setting_box">
|
||||
<div class="o_setting_left_pane"/>
|
||||
<div class="o_setting_right_pane">
|
||||
<label for="transfer_account_id"/>
|
||||
<div class="text-muted">
|
||||
Transit account when you transfer money from a bank account of your company to another bank account of your company.
|
||||
</div>
|
||||
<field name="transfer_account_id"/>
|
||||
</div>
|
||||
</div>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
<!-- Remove menu entry "Accounting > Configuration > Accounting > Bank Accounts"
|
||||
(account.journal filtered on type = 'bank' with special tree and form view)
|
||||
because it is useless and confusing -->
|
||||
<record id="account.menu_action_account_bank_journal_form" model="ir.ui.menu">
|
||||
<field name="groups_id" eval="[(6, 0, [ref('base_usability.group_nobody')])]"/>
|
||||
</record>
|
||||
|
||||
<!-- Duplicate the menu "Sales > Configuration > Contacts > Bank Accounts"
|
||||
under "Accounting > Configuration", because most users will try to find it there -->
|
||||
<menuitem id="bank_account_account_config_menu" name="Bank Accounts" parent="account.menu_finance_configuration" sequence="9"/>
|
||||
|
||||
<menuitem id="res_bank_account_config_menu" action="base.action_res_bank_form" parent="bank_account_account_config_menu" sequence="10"/>
|
||||
|
||||
<menuitem id="res_partner_bank_account_config_menu" action="base.action_res_partner_bank_account_form" parent="bank_account_account_config_menu" sequence="20"/>
|
||||
|
||||
</odoo>
|
||||
@@ -1,33 +0,0 @@
|
||||
diff --git a/addons/account/models/account_payment.py b/addons/account/models/account_payment.py
|
||||
index f38f459c533..a475d6a82c7 100644
|
||||
--- a/addons/account/models/account_payment.py
|
||||
+++ b/addons/account/models/account_payment.py
|
||||
@@ -62,6 +62,7 @@ class account_abstract_payment(models.AbstractModel):
|
||||
payment_difference = fields.Monetary(compute='_compute_payment_difference', readonly=True)
|
||||
payment_difference_handling = fields.Selection([('open', 'Keep open'), ('reconcile', 'Mark invoice as fully paid')], default='open', string="Payment Difference Handling", copy=False)
|
||||
writeoff_account_id = fields.Many2one('account.account', string="Difference Account", domain=[('deprecated', '=', False)], copy=False)
|
||||
+ writeoff_analytic_account_id = fields.Many2one('account.analytic.account', string="Difference Analytic Account", copy=False)
|
||||
writeoff_label = fields.Char(
|
||||
string='Journal Item Label',
|
||||
help='Change label of the counterpart that will hold the payment difference',
|
||||
@@ -717,6 +718,7 @@ class account_payment(models.Model):
|
||||
debit_wo, credit_wo, amount_currency_wo, currency_id = aml_obj.with_context(date=self.payment_date)._compute_amount_fields(self.payment_difference, self.currency_id, self.company_id.currency_id)
|
||||
writeoff_line['name'] = self.writeoff_label
|
||||
writeoff_line['account_id'] = self.writeoff_account_id.id
|
||||
+ writeoff_line['analytic_account_id'] = self.writeoff_analytic_account_id.id or False
|
||||
writeoff_line['debit'] = debit_wo
|
||||
writeoff_line['credit'] = credit_wo
|
||||
writeoff_line['amount_currency'] = amount_currency_wo
|
||||
diff --git a/addons/account/views/account_payment_view.xml b/addons/account/views/account_payment_view.xml
|
||||
index 07230902ee8..1359009bf23 100644
|
||||
--- a/addons/account/views/account_payment_view.xml
|
||||
+++ b/addons/account/views/account_payment_view.xml
|
||||
@@ -277,6 +277,8 @@
|
||||
<div attrs="{'invisible': [('payment_difference_handling','=','open')]}">
|
||||
<label for="writeoff_account_id" class="oe_edit_only" string="Post Difference In"/>
|
||||
<field name="writeoff_account_id" string="Post Difference In" attrs="{'required': [('payment_difference_handling', '=', 'reconcile')]}"/>
|
||||
+ <label for="writeoff_analytic_account_id" class="oe_edit_only" string="Analytic Account" groups="analytic.group_analytic_accounting"/>
|
||||
+ <field name="writeoff_analytic_account_id" groups="analytic.group_analytic_accounting"/>
|
||||
<label for="journal_id" string="Journal" attrs="{'invisible': [('amount', '!=', 0)]}"/>
|
||||
<field name="journal_id" string="Journal" widget="selection" attrs="{'invisible': [('amount', '!=', 0)]}"/>
|
||||
<label for="writeoff_label" class="oe_edit_only" string="Label"/>
|
||||
@@ -1,13 +0,0 @@
|
||||
# Copyright 2017-2019 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 models, fields
|
||||
|
||||
|
||||
class ResPartner(models.Model):
|
||||
_inherit = 'res.partner'
|
||||
|
||||
invoice_warn = fields.Selection(track_visibility='onchange')
|
||||
property_account_position_id = fields.Many2one(
|
||||
track_visibility='onchange')
|
||||
@@ -1,23 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2017-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_partner_property_form" model="ir.ui.view">
|
||||
<field name="name">account_usability.res.partner.form</field>
|
||||
<field name="model">res.partner</field>
|
||||
<field name="inherit_id" ref="account.view_partner_property_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="property_account_position_id" position="attributes">
|
||||
<attribute name="widget">selection</attribute>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
</odoo>
|
||||
@@ -1,2 +0,0 @@
|
||||
* Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
* David Beal <david.beal@akretion.com>
|
||||
@@ -1,39 +0,0 @@
|
||||
This modules adds the following functions:
|
||||
|
||||
* Add an *Overdue* filter on invoice search view (this feature was previously
|
||||
located in te module *account_invoice_overdue_filter*)
|
||||
* Increase the default limit of 80 lines in account move and account move line view.
|
||||
* disable reconciliation "guessing"
|
||||
* fast search on *Reconcile Ref* for account move line.
|
||||
* add sale dates to invoice report to be compliant with
|
||||
https://www.service-public.fr/professionnels-entreprises/vosdroits/F31808
|
||||
* Sale date on qweb invoices
|
||||
* A wizard to mark several invoices as sent at once (forward from v8)
|
||||
* Default date for Account Move Reversal is now D+1 instead of today
|
||||
* Track more fields on invoice (see details in account.py)
|
||||
* Add boolean fields `has_discount` and `has_attachment` on invoice
|
||||
* Add button "Delete line qty = 0" on supplier invoice
|
||||
* Cut name_get() of invoice if too long
|
||||
* A script for if Odoo screws up invoice attachment filename
|
||||
* help functions for py3o reports
|
||||
* Show code on name_get of journal
|
||||
* add direct search of journal using code
|
||||
* add copy=False on some fields
|
||||
* Add unicity constraint on analytic codes per company
|
||||
* Better default values on account move
|
||||
* Add link from account move line to invoice
|
||||
* Add start_date and end_date on bank statements
|
||||
* Add transfer_account_id to invoicing config page
|
||||
* Improve domain reconciliation widget
|
||||
* account.reconcile.model don't copy name to label via onchange
|
||||
* Add method to get fiscal position without partner_id
|
||||
* Restore drill-through on sale and invoice reports
|
||||
* 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
|
||||
|
||||
Together with this module, I recommend the use of the following modules:
|
||||
|
||||
* account_invoice_supplier_ref_unique (OCA project account-invoicing)
|
||||
* account_move_line_no_default_search (OCA project account-financial-tools)
|
||||
* invoice_fiscal_position_update (OCA project account-invoicing)
|
||||
@@ -1,10 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<template id="report_invoice_document" inherit_id="account.report_invoice_document">
|
||||
<xpath expr="//p[@t-field='o.origin']" position="replace">
|
||||
<p class="m-0" t-field="o.sale_dates"/>
|
||||
</xpath>
|
||||
</template>
|
||||
|
||||
</odoo>
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 9.5 KiB |
@@ -1,454 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="generator" content="Docutils 0.15.1: http://docutils.sourceforge.net/" />
|
||||
<title>Account Usability</title>
|
||||
<style type="text/css">
|
||||
|
||||
/*
|
||||
:Author: David Goodger (goodger@python.org)
|
||||
:Id: $Id: html4css1.css 7952 2016-07-26 18:15:59Z milde $
|
||||
:Copyright: This stylesheet has been placed in the public domain.
|
||||
|
||||
Default cascading style sheet for the HTML output of Docutils.
|
||||
|
||||
See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
|
||||
customize this style sheet.
|
||||
*/
|
||||
|
||||
/* used to remove borders from tables and images */
|
||||
.borderless, table.borderless td, table.borderless th {
|
||||
border: 0 }
|
||||
|
||||
table.borderless td, table.borderless th {
|
||||
/* Override padding for "table.docutils td" with "! important".
|
||||
The right padding separates the table cells. */
|
||||
padding: 0 0.5em 0 0 ! important }
|
||||
|
||||
.first {
|
||||
/* Override more specific margin styles with "! important". */
|
||||
margin-top: 0 ! important }
|
||||
|
||||
.last, .with-subtitle {
|
||||
margin-bottom: 0 ! important }
|
||||
|
||||
.hidden {
|
||||
display: none }
|
||||
|
||||
.subscript {
|
||||
vertical-align: sub;
|
||||
font-size: smaller }
|
||||
|
||||
.superscript {
|
||||
vertical-align: super;
|
||||
font-size: smaller }
|
||||
|
||||
a.toc-backref {
|
||||
text-decoration: none ;
|
||||
color: black }
|
||||
|
||||
blockquote.epigraph {
|
||||
margin: 2em 5em ; }
|
||||
|
||||
dl.docutils dd {
|
||||
margin-bottom: 0.5em }
|
||||
|
||||
object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Uncomment (and remove this text!) to get bold-faced definition list terms
|
||||
dl.docutils dt {
|
||||
font-weight: bold }
|
||||
*/
|
||||
|
||||
div.abstract {
|
||||
margin: 2em 5em }
|
||||
|
||||
div.abstract p.topic-title {
|
||||
font-weight: bold ;
|
||||
text-align: center }
|
||||
|
||||
div.admonition, div.attention, div.caution, div.danger, div.error,
|
||||
div.hint, div.important, div.note, div.tip, div.warning {
|
||||
margin: 2em ;
|
||||
border: medium outset ;
|
||||
padding: 1em }
|
||||
|
||||
div.admonition p.admonition-title, div.hint p.admonition-title,
|
||||
div.important p.admonition-title, div.note p.admonition-title,
|
||||
div.tip p.admonition-title {
|
||||
font-weight: bold ;
|
||||
font-family: sans-serif }
|
||||
|
||||
div.attention p.admonition-title, div.caution p.admonition-title,
|
||||
div.danger p.admonition-title, div.error p.admonition-title,
|
||||
div.warning p.admonition-title, .code .error {
|
||||
color: red ;
|
||||
font-weight: bold ;
|
||||
font-family: sans-serif }
|
||||
|
||||
/* Uncomment (and remove this text!) to get reduced vertical space in
|
||||
compound paragraphs.
|
||||
div.compound .compound-first, div.compound .compound-middle {
|
||||
margin-bottom: 0.5em }
|
||||
|
||||
div.compound .compound-last, div.compound .compound-middle {
|
||||
margin-top: 0.5em }
|
||||
*/
|
||||
|
||||
div.dedication {
|
||||
margin: 2em 5em ;
|
||||
text-align: center ;
|
||||
font-style: italic }
|
||||
|
||||
div.dedication p.topic-title {
|
||||
font-weight: bold ;
|
||||
font-style: normal }
|
||||
|
||||
div.figure {
|
||||
margin-left: 2em ;
|
||||
margin-right: 2em }
|
||||
|
||||
div.footer, div.header {
|
||||
clear: both;
|
||||
font-size: smaller }
|
||||
|
||||
div.line-block {
|
||||
display: block ;
|
||||
margin-top: 1em ;
|
||||
margin-bottom: 1em }
|
||||
|
||||
div.line-block div.line-block {
|
||||
margin-top: 0 ;
|
||||
margin-bottom: 0 ;
|
||||
margin-left: 1.5em }
|
||||
|
||||
div.sidebar {
|
||||
margin: 0 0 0.5em 1em ;
|
||||
border: medium outset ;
|
||||
padding: 1em ;
|
||||
background-color: #ffffee ;
|
||||
width: 40% ;
|
||||
float: right ;
|
||||
clear: right }
|
||||
|
||||
div.sidebar p.rubric {
|
||||
font-family: sans-serif ;
|
||||
font-size: medium }
|
||||
|
||||
div.system-messages {
|
||||
margin: 5em }
|
||||
|
||||
div.system-messages h1 {
|
||||
color: red }
|
||||
|
||||
div.system-message {
|
||||
border: medium outset ;
|
||||
padding: 1em }
|
||||
|
||||
div.system-message p.system-message-title {
|
||||
color: red ;
|
||||
font-weight: bold }
|
||||
|
||||
div.topic {
|
||||
margin: 2em }
|
||||
|
||||
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
|
||||
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
|
||||
margin-top: 0.4em }
|
||||
|
||||
h1.title {
|
||||
text-align: center }
|
||||
|
||||
h2.subtitle {
|
||||
text-align: center }
|
||||
|
||||
hr.docutils {
|
||||
width: 75% }
|
||||
|
||||
img.align-left, .figure.align-left, object.align-left, table.align-left {
|
||||
clear: left ;
|
||||
float: left ;
|
||||
margin-right: 1em }
|
||||
|
||||
img.align-right, .figure.align-right, object.align-right, table.align-right {
|
||||
clear: right ;
|
||||
float: right ;
|
||||
margin-left: 1em }
|
||||
|
||||
img.align-center, .figure.align-center, object.align-center {
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
table.align-center {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.align-left {
|
||||
text-align: left }
|
||||
|
||||
.align-center {
|
||||
clear: both ;
|
||||
text-align: center }
|
||||
|
||||
.align-right {
|
||||
text-align: right }
|
||||
|
||||
/* reset inner alignment in figures */
|
||||
div.align-right {
|
||||
text-align: inherit }
|
||||
|
||||
/* div.align-center * { */
|
||||
/* text-align: left } */
|
||||
|
||||
.align-top {
|
||||
vertical-align: top }
|
||||
|
||||
.align-middle {
|
||||
vertical-align: middle }
|
||||
|
||||
.align-bottom {
|
||||
vertical-align: bottom }
|
||||
|
||||
ol.simple, ul.simple {
|
||||
margin-bottom: 1em }
|
||||
|
||||
ol.arabic {
|
||||
list-style: decimal }
|
||||
|
||||
ol.loweralpha {
|
||||
list-style: lower-alpha }
|
||||
|
||||
ol.upperalpha {
|
||||
list-style: upper-alpha }
|
||||
|
||||
ol.lowerroman {
|
||||
list-style: lower-roman }
|
||||
|
||||
ol.upperroman {
|
||||
list-style: upper-roman }
|
||||
|
||||
p.attribution {
|
||||
text-align: right ;
|
||||
margin-left: 50% }
|
||||
|
||||
p.caption {
|
||||
font-style: italic }
|
||||
|
||||
p.credits {
|
||||
font-style: italic ;
|
||||
font-size: smaller }
|
||||
|
||||
p.label {
|
||||
white-space: nowrap }
|
||||
|
||||
p.rubric {
|
||||
font-weight: bold ;
|
||||
font-size: larger ;
|
||||
color: maroon ;
|
||||
text-align: center }
|
||||
|
||||
p.sidebar-title {
|
||||
font-family: sans-serif ;
|
||||
font-weight: bold ;
|
||||
font-size: larger }
|
||||
|
||||
p.sidebar-subtitle {
|
||||
font-family: sans-serif ;
|
||||
font-weight: bold }
|
||||
|
||||
p.topic-title {
|
||||
font-weight: bold }
|
||||
|
||||
pre.address {
|
||||
margin-bottom: 0 ;
|
||||
margin-top: 0 ;
|
||||
font: inherit }
|
||||
|
||||
pre.literal-block, pre.doctest-block, pre.math, pre.code {
|
||||
margin-left: 2em ;
|
||||
margin-right: 2em }
|
||||
|
||||
pre.code .ln { color: grey; } /* line numbers */
|
||||
pre.code, code { background-color: #eeeeee }
|
||||
pre.code .comment, code .comment { color: #5C6576 }
|
||||
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
|
||||
pre.code .literal.string, code .literal.string { color: #0C5404 }
|
||||
pre.code .name.builtin, code .name.builtin { color: #352B84 }
|
||||
pre.code .deleted, code .deleted { background-color: #DEB0A1}
|
||||
pre.code .inserted, code .inserted { background-color: #A3D289}
|
||||
|
||||
span.classifier {
|
||||
font-family: sans-serif ;
|
||||
font-style: oblique }
|
||||
|
||||
span.classifier-delimiter {
|
||||
font-family: sans-serif ;
|
||||
font-weight: bold }
|
||||
|
||||
span.interpreted {
|
||||
font-family: sans-serif }
|
||||
|
||||
span.option {
|
||||
white-space: nowrap }
|
||||
|
||||
span.pre {
|
||||
white-space: pre }
|
||||
|
||||
span.problematic {
|
||||
color: red }
|
||||
|
||||
span.section-subtitle {
|
||||
/* font-size relative to parent (h1..h6 element) */
|
||||
font-size: 80% }
|
||||
|
||||
table.citation {
|
||||
border-left: solid 1px gray;
|
||||
margin-left: 1px }
|
||||
|
||||
table.docinfo {
|
||||
margin: 2em 4em }
|
||||
|
||||
table.docutils {
|
||||
margin-top: 0.5em ;
|
||||
margin-bottom: 0.5em }
|
||||
|
||||
table.footnote {
|
||||
border-left: solid 1px black;
|
||||
margin-left: 1px }
|
||||
|
||||
table.docutils td, table.docutils th,
|
||||
table.docinfo td, table.docinfo th {
|
||||
padding-left: 0.5em ;
|
||||
padding-right: 0.5em ;
|
||||
vertical-align: top }
|
||||
|
||||
table.docutils th.field-name, table.docinfo th.docinfo-name {
|
||||
font-weight: bold ;
|
||||
text-align: left ;
|
||||
white-space: nowrap ;
|
||||
padding-left: 0 }
|
||||
|
||||
/* "booktabs" style (no vertical lines) */
|
||||
table.docutils.booktabs {
|
||||
border: 0px;
|
||||
border-top: 2px solid;
|
||||
border-bottom: 2px solid;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
table.docutils.booktabs * {
|
||||
border: 0px;
|
||||
}
|
||||
table.docutils.booktabs th {
|
||||
border-bottom: thin solid;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
|
||||
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
|
||||
font-size: 100% }
|
||||
|
||||
ul.auto-toc {
|
||||
list-style-type: none }
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="document" id="account-usability">
|
||||
<h1 class="title">Account Usability</h1>
|
||||
|
||||
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
!! This file is generated by oca-gen-addon-readme !!
|
||||
!! changes will be overwritten. !!
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
|
||||
<p><a class="reference external" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external" href="https://github.com/akretion/odoo-usability/tree/12.0/account_usability"><img alt="akretion/odoo-usability" src="https://img.shields.io/badge/github-akretion%2Fodoo--usability-lightgray.png?logo=github" /></a></p>
|
||||
<p>This modules adds the following functions:</p>
|
||||
<ul class="simple">
|
||||
<li>Add an <em>Overdue</em> filter on invoice search view (this feature was previously
|
||||
located in te module <em>account_invoice_overdue_filter</em>)</li>
|
||||
<li>Increase the default limit of 80 lines in account move and account move line view.</li>
|
||||
<li>disable reconciliation “guessing”</li>
|
||||
<li>fast search on <em>Reconcile Ref</em> for account move line.</li>
|
||||
<li>add sale dates to invoice report to be compliant with
|
||||
<a class="reference external" href="https://www.service-public.fr/professionnels-entreprises/vosdroits/F31808">https://www.service-public.fr/professionnels-entreprises/vosdroits/F31808</a></li>
|
||||
<li>Sale date on qweb invoices</li>
|
||||
<li>A wizard to mark several invoices as sent at once (forward from v8)</li>
|
||||
<li>Default date for Account Move Reversal is now D+1 instead of today</li>
|
||||
<li>Track more fields on invoice (see details in account.py)</li>
|
||||
<li>Add boolean fields <cite>has_discount</cite> and <cite>has_attachment</cite> on invoice</li>
|
||||
<li>Add button “Delete line qty = 0” on supplier invoice</li>
|
||||
<li>Cut name_get() of invoice if too long</li>
|
||||
<li>A script for if Odoo screws up invoice attachment filename</li>
|
||||
<li>help functions for py3o reports</li>
|
||||
<li>Show code on name_get of journal</li>
|
||||
<li>add direct search of journal using code</li>
|
||||
<li>add copy=False on some fields</li>
|
||||
<li>Add unicity constraint on analytic codes per company</li>
|
||||
<li>Better default values on account move</li>
|
||||
<li>Add link from account move line to invoice</li>
|
||||
<li>Add start_date and end_date on bank statements</li>
|
||||
<li>Add transfer_account_id to invoicing config page</li>
|
||||
<li>Improve domain reconciliation widget</li>
|
||||
<li>account.reconcile.model don’t copy name to label via onchange</li>
|
||||
<li>Add method to get fiscal position without partner_id</li>
|
||||
<li>Restore drill-through on sale and invoice reports</li>
|
||||
<li>don’t attach PDF upon invoice report generation on supplier invoices/refunds</li>
|
||||
<li>Add filter on debit and credit amount for Move Lines</li>
|
||||
<li>Add supplier invoice number in invoice tree view</li>
|
||||
</ul>
|
||||
<p>Together with this module, I recommend the use of the following modules:</p>
|
||||
<ul class="simple">
|
||||
<li>account_invoice_supplier_ref_unique (OCA project account-invoicing)</li>
|
||||
<li>account_move_line_no_default_search (OCA project account-financial-tools)</li>
|
||||
<li>invoice_fiscal_position_update (OCA project account-invoicing)</li>
|
||||
</ul>
|
||||
<p><strong>Table of contents</strong></p>
|
||||
<div class="contents local topic" id="contents">
|
||||
<ul class="simple">
|
||||
<li><a class="reference internal" href="#bug-tracker" id="id1">Bug Tracker</a></li>
|
||||
<li><a class="reference internal" href="#credits" id="id2">Credits</a><ul>
|
||||
<li><a class="reference internal" href="#authors" id="id3">Authors</a></li>
|
||||
<li><a class="reference internal" href="#contributors" id="id4">Contributors</a></li>
|
||||
<li><a class="reference internal" href="#maintainers" id="id5">Maintainers</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="bug-tracker">
|
||||
<h1><a class="toc-backref" href="#id1">Bug Tracker</a></h1>
|
||||
<p>Bugs are tracked on <a class="reference external" href="https://github.com/akretion/odoo-usability/issues">GitHub Issues</a>.
|
||||
In case of trouble, please check there if your issue has already been reported.
|
||||
If you spotted it first, help us smashing it by providing a detailed and welcomed
|
||||
<a class="reference external" href="https://github.com/akretion/odoo-usability/issues/new?body=module:%20account_usability%0Aversion:%2012.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
|
||||
<p>Do not contact contributors directly about support or help with technical issues.</p>
|
||||
</div>
|
||||
<div class="section" id="credits">
|
||||
<h1><a class="toc-backref" href="#id2">Credits</a></h1>
|
||||
<div class="section" id="authors">
|
||||
<h2><a class="toc-backref" href="#id3">Authors</a></h2>
|
||||
<ul class="simple">
|
||||
<li>Akretion</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="contributors">
|
||||
<h2><a class="toc-backref" href="#id4">Contributors</a></h2>
|
||||
<ul class="simple">
|
||||
<li>Alexis de Lattre <<a class="reference external" href="mailto:alexis.delattre@akretion.com">alexis.delattre@akretion.com</a>></li>
|
||||
<li>David Beal <<a class="reference external" href="mailto:david.beal@akretion.com">david.beal@akretion.com</a>></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="maintainers">
|
||||
<h2><a class="toc-backref" href="#id5">Maintainers</a></h2>
|
||||
<p>This module is part of the <a class="reference external" href="https://github.com/akretion/odoo-usability/tree/12.0/account_usability">akretion/odoo-usability</a> project on GitHub.</p>
|
||||
<p>You are welcome to contribute.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,2 +0,0 @@
|
||||
from . import account_invoice_mark_sent
|
||||
from . import account_move_reversal
|
||||
@@ -1,23 +0,0 @@
|
||||
# Copyright 2017-2019 Akretion France (https://akretion.com/en)
|
||||
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import models
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class AccountInvoiceMarkSent(models.TransientModel):
|
||||
_name = 'account.invoice.mark.sent'
|
||||
_description = 'Mark invoices as sent'
|
||||
|
||||
def run(self):
|
||||
assert self.env.context.get('active_model') == 'account.invoice',\
|
||||
'Source model must be invoices'
|
||||
assert self.env.context.get('active_ids'), 'No invoices selected'
|
||||
invoices = self.env['account.invoice'].search([
|
||||
('id', 'in', self.env.context.get('active_ids')),
|
||||
('state', 'in', ('open', 'paid'))])
|
||||
invoices.write({'sent': True})
|
||||
logger.info('Marking invoices with ID %s as sent', invoices.ids)
|
||||
return
|
||||
@@ -1,36 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2017-2019 Akretion France
|
||||
@author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
-->
|
||||
|
||||
<odoo>
|
||||
|
||||
<record id="account_invoice_mark_sent_form" model="ir.ui.view">
|
||||
<field name="name">account.invoice.mark.sent.form</field>
|
||||
<field name="model">account.invoice.mark.sent</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Mark invoices as sent">
|
||||
<p>
|
||||
This wizard will mark as <i>sent</i> all the selected invoices in open or paid state.
|
||||
</p>
|
||||
<footer>
|
||||
<button type="object" name="run" string="Mark as Sent" class="btn-primary"/>
|
||||
<button special="cancel" string="Cancel"/>
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<act_window id="account_invoice_mark_sent_action"
|
||||
multi="True"
|
||||
key2="client_action_multi"
|
||||
name="Mark as Sent"
|
||||
res_model="account.invoice.mark.sent"
|
||||
src_model="account.invoice"
|
||||
view_mode="form"
|
||||
target="new"
|
||||
groups="account.group_account_invoice" />
|
||||
|
||||
</odoo>
|
||||
@@ -1,24 +0,0 @@
|
||||
# Copyright 2018-2019 Akretion France (https://akretion.com/)
|
||||
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import api, fields, models
|
||||
from dateutil.relativedelta import relativedelta
|
||||
|
||||
|
||||
class AccountMoveReversal(models.TransientModel):
|
||||
_inherit = 'account.move.reversal'
|
||||
|
||||
@api.model
|
||||
def _default_date(self):
|
||||
date = None
|
||||
if (
|
||||
self._context.get('active_model') == 'account.move' and
|
||||
self._context.get('active_id')):
|
||||
move = self.env['account.move'].browse(self._context['active_id'])
|
||||
date_dt = fields.Date.from_string(move.date) +\
|
||||
relativedelta(days=1)
|
||||
date = fields.Date.to_string(date_dt)
|
||||
return date
|
||||
|
||||
date = fields.Date(default=_default_date)
|
||||
@@ -1,61 +0,0 @@
|
||||
======================
|
||||
Base Company Extension
|
||||
======================
|
||||
|
||||
.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
!! This file is generated by oca-gen-addon-readme !!
|
||||
!! changes will be overwritten. !!
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
|
||||
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
|
||||
:target: https://odoo-community.org/page/development-status
|
||||
:alt: Beta
|
||||
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
|
||||
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
|
||||
:alt: License: AGPL-3
|
||||
.. |badge3| image:: https://img.shields.io/badge/github-akretion%2Fodoo--usability-lightgray.png?logo=github
|
||||
:target: https://github.com/akretion/odoo-usability/tree/12.0/base_company_extension
|
||||
:alt: akretion/odoo-usability
|
||||
|
||||
|badge1| |badge2| |badge3|
|
||||
|
||||
This module adds the following fields to the ResCompany model:
|
||||
* Capital Amount
|
||||
* Legal Type
|
||||
|
||||
This is useful to display the legal name of the company in reports
|
||||
|
||||
**Table of contents**
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
|
||||
Bug Tracker
|
||||
===========
|
||||
|
||||
Bugs are tracked on `GitHub Issues <https://github.com/akretion/odoo-usability/issues>`_.
|
||||
In case of trouble, please check there if your issue has already been reported.
|
||||
If you spotted it first, help us smashing it by providing a detailed and welcomed
|
||||
`feedback <https://github.com/akretion/odoo-usability/issues/new?body=module:%20base_company_extension%0Aversion:%2012.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
|
||||
|
||||
Do not contact contributors directly about support or help with technical issues.
|
||||
|
||||
Credits
|
||||
=======
|
||||
|
||||
Authors
|
||||
~~~~~~~
|
||||
|
||||
* Akretion
|
||||
|
||||
Contributors
|
||||
~~~~~~~~~~~~
|
||||
|
||||
* Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
|
||||
Maintainers
|
||||
~~~~~~~~~~~
|
||||
|
||||
This module is part of the `akretion/odoo-usability <https://github.com/akretion/odoo-usability/tree/12.0/base_company_extension>`_ project on GitHub.
|
||||
|
||||
You are welcome to contribute.
|
||||
@@ -1 +0,0 @@
|
||||
from . import company
|
||||
@@ -1,18 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2014-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).
|
||||
|
||||
{
|
||||
'name': 'Base Company Extension',
|
||||
'version': '12.0.1.0.0',
|
||||
'category': 'Partner',
|
||||
'license': 'AGPL-3',
|
||||
'summary': 'Adds capital and title on company',
|
||||
'author': 'Akretion',
|
||||
'website': 'http://www.akretion.com',
|
||||
# I depend on base_usability only for _report_company_legal_name()
|
||||
'depends': ['base_usability'],
|
||||
'data': ['company_view.xml'],
|
||||
'installable': True,
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
# Copyright 2014-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).
|
||||
|
||||
from odoo import models, fields
|
||||
|
||||
|
||||
class ResCompany(models.Model):
|
||||
_inherit = "res.company"
|
||||
|
||||
capital_amount = fields.Monetary(string='Capital Amount')
|
||||
# in v9, title is only for contacts, not for companies
|
||||
legal_type = fields.Char(
|
||||
string="Legal Type", help="Type of Company, e.g. SARL, SAS, ...")
|
||||
|
||||
def _report_company_legal_name(self):
|
||||
self.ensure_one()
|
||||
if self.legal_type:
|
||||
name = u'%s %s' % (self.name, self.legal_type)
|
||||
else:
|
||||
name = self.name
|
||||
return name
|
||||
|
||||
_sql_constraints = [(
|
||||
'capital_amount_positive',
|
||||
'CHECK (capital_amount >= 0)',
|
||||
"The value of the field 'Capital Amount' must be positive."
|
||||
)]
|
||||
@@ -1,22 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2014-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_company_form" model="ir.ui.view">
|
||||
<field name="name">company.extension.form</field>
|
||||
<field name="model">res.company</field>
|
||||
<field name="inherit_id" ref="base.view_company_form" />
|
||||
<field name="arch" type="xml">
|
||||
<field name="company_registry" position="after">
|
||||
<field name="capital_amount"/>
|
||||
<field name="legal_type"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -1 +0,0 @@
|
||||
* Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
@@ -1,5 +0,0 @@
|
||||
This module adds the following fields to the ResCompany model:
|
||||
* Capital Amount
|
||||
* Legal Type
|
||||
|
||||
This is useful to display the legal name of the company in reports
|
||||
@@ -1,417 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="generator" content="Docutils 0.15.1: http://docutils.sourceforge.net/" />
|
||||
<title>Base Company Extension</title>
|
||||
<style type="text/css">
|
||||
|
||||
/*
|
||||
:Author: David Goodger (goodger@python.org)
|
||||
:Id: $Id: html4css1.css 7952 2016-07-26 18:15:59Z milde $
|
||||
:Copyright: This stylesheet has been placed in the public domain.
|
||||
|
||||
Default cascading style sheet for the HTML output of Docutils.
|
||||
|
||||
See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
|
||||
customize this style sheet.
|
||||
*/
|
||||
|
||||
/* used to remove borders from tables and images */
|
||||
.borderless, table.borderless td, table.borderless th {
|
||||
border: 0 }
|
||||
|
||||
table.borderless td, table.borderless th {
|
||||
/* Override padding for "table.docutils td" with "! important".
|
||||
The right padding separates the table cells. */
|
||||
padding: 0 0.5em 0 0 ! important }
|
||||
|
||||
.first {
|
||||
/* Override more specific margin styles with "! important". */
|
||||
margin-top: 0 ! important }
|
||||
|
||||
.last, .with-subtitle {
|
||||
margin-bottom: 0 ! important }
|
||||
|
||||
.hidden {
|
||||
display: none }
|
||||
|
||||
.subscript {
|
||||
vertical-align: sub;
|
||||
font-size: smaller }
|
||||
|
||||
.superscript {
|
||||
vertical-align: super;
|
||||
font-size: smaller }
|
||||
|
||||
a.toc-backref {
|
||||
text-decoration: none ;
|
||||
color: black }
|
||||
|
||||
blockquote.epigraph {
|
||||
margin: 2em 5em ; }
|
||||
|
||||
dl.docutils dd {
|
||||
margin-bottom: 0.5em }
|
||||
|
||||
object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Uncomment (and remove this text!) to get bold-faced definition list terms
|
||||
dl.docutils dt {
|
||||
font-weight: bold }
|
||||
*/
|
||||
|
||||
div.abstract {
|
||||
margin: 2em 5em }
|
||||
|
||||
div.abstract p.topic-title {
|
||||
font-weight: bold ;
|
||||
text-align: center }
|
||||
|
||||
div.admonition, div.attention, div.caution, div.danger, div.error,
|
||||
div.hint, div.important, div.note, div.tip, div.warning {
|
||||
margin: 2em ;
|
||||
border: medium outset ;
|
||||
padding: 1em }
|
||||
|
||||
div.admonition p.admonition-title, div.hint p.admonition-title,
|
||||
div.important p.admonition-title, div.note p.admonition-title,
|
||||
div.tip p.admonition-title {
|
||||
font-weight: bold ;
|
||||
font-family: sans-serif }
|
||||
|
||||
div.attention p.admonition-title, div.caution p.admonition-title,
|
||||
div.danger p.admonition-title, div.error p.admonition-title,
|
||||
div.warning p.admonition-title, .code .error {
|
||||
color: red ;
|
||||
font-weight: bold ;
|
||||
font-family: sans-serif }
|
||||
|
||||
/* Uncomment (and remove this text!) to get reduced vertical space in
|
||||
compound paragraphs.
|
||||
div.compound .compound-first, div.compound .compound-middle {
|
||||
margin-bottom: 0.5em }
|
||||
|
||||
div.compound .compound-last, div.compound .compound-middle {
|
||||
margin-top: 0.5em }
|
||||
*/
|
||||
|
||||
div.dedication {
|
||||
margin: 2em 5em ;
|
||||
text-align: center ;
|
||||
font-style: italic }
|
||||
|
||||
div.dedication p.topic-title {
|
||||
font-weight: bold ;
|
||||
font-style: normal }
|
||||
|
||||
div.figure {
|
||||
margin-left: 2em ;
|
||||
margin-right: 2em }
|
||||
|
||||
div.footer, div.header {
|
||||
clear: both;
|
||||
font-size: smaller }
|
||||
|
||||
div.line-block {
|
||||
display: block ;
|
||||
margin-top: 1em ;
|
||||
margin-bottom: 1em }
|
||||
|
||||
div.line-block div.line-block {
|
||||
margin-top: 0 ;
|
||||
margin-bottom: 0 ;
|
||||
margin-left: 1.5em }
|
||||
|
||||
div.sidebar {
|
||||
margin: 0 0 0.5em 1em ;
|
||||
border: medium outset ;
|
||||
padding: 1em ;
|
||||
background-color: #ffffee ;
|
||||
width: 40% ;
|
||||
float: right ;
|
||||
clear: right }
|
||||
|
||||
div.sidebar p.rubric {
|
||||
font-family: sans-serif ;
|
||||
font-size: medium }
|
||||
|
||||
div.system-messages {
|
||||
margin: 5em }
|
||||
|
||||
div.system-messages h1 {
|
||||
color: red }
|
||||
|
||||
div.system-message {
|
||||
border: medium outset ;
|
||||
padding: 1em }
|
||||
|
||||
div.system-message p.system-message-title {
|
||||
color: red ;
|
||||
font-weight: bold }
|
||||
|
||||
div.topic {
|
||||
margin: 2em }
|
||||
|
||||
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
|
||||
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
|
||||
margin-top: 0.4em }
|
||||
|
||||
h1.title {
|
||||
text-align: center }
|
||||
|
||||
h2.subtitle {
|
||||
text-align: center }
|
||||
|
||||
hr.docutils {
|
||||
width: 75% }
|
||||
|
||||
img.align-left, .figure.align-left, object.align-left, table.align-left {
|
||||
clear: left ;
|
||||
float: left ;
|
||||
margin-right: 1em }
|
||||
|
||||
img.align-right, .figure.align-right, object.align-right, table.align-right {
|
||||
clear: right ;
|
||||
float: right ;
|
||||
margin-left: 1em }
|
||||
|
||||
img.align-center, .figure.align-center, object.align-center {
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
table.align-center {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.align-left {
|
||||
text-align: left }
|
||||
|
||||
.align-center {
|
||||
clear: both ;
|
||||
text-align: center }
|
||||
|
||||
.align-right {
|
||||
text-align: right }
|
||||
|
||||
/* reset inner alignment in figures */
|
||||
div.align-right {
|
||||
text-align: inherit }
|
||||
|
||||
/* div.align-center * { */
|
||||
/* text-align: left } */
|
||||
|
||||
.align-top {
|
||||
vertical-align: top }
|
||||
|
||||
.align-middle {
|
||||
vertical-align: middle }
|
||||
|
||||
.align-bottom {
|
||||
vertical-align: bottom }
|
||||
|
||||
ol.simple, ul.simple {
|
||||
margin-bottom: 1em }
|
||||
|
||||
ol.arabic {
|
||||
list-style: decimal }
|
||||
|
||||
ol.loweralpha {
|
||||
list-style: lower-alpha }
|
||||
|
||||
ol.upperalpha {
|
||||
list-style: upper-alpha }
|
||||
|
||||
ol.lowerroman {
|
||||
list-style: lower-roman }
|
||||
|
||||
ol.upperroman {
|
||||
list-style: upper-roman }
|
||||
|
||||
p.attribution {
|
||||
text-align: right ;
|
||||
margin-left: 50% }
|
||||
|
||||
p.caption {
|
||||
font-style: italic }
|
||||
|
||||
p.credits {
|
||||
font-style: italic ;
|
||||
font-size: smaller }
|
||||
|
||||
p.label {
|
||||
white-space: nowrap }
|
||||
|
||||
p.rubric {
|
||||
font-weight: bold ;
|
||||
font-size: larger ;
|
||||
color: maroon ;
|
||||
text-align: center }
|
||||
|
||||
p.sidebar-title {
|
||||
font-family: sans-serif ;
|
||||
font-weight: bold ;
|
||||
font-size: larger }
|
||||
|
||||
p.sidebar-subtitle {
|
||||
font-family: sans-serif ;
|
||||
font-weight: bold }
|
||||
|
||||
p.topic-title {
|
||||
font-weight: bold }
|
||||
|
||||
pre.address {
|
||||
margin-bottom: 0 ;
|
||||
margin-top: 0 ;
|
||||
font: inherit }
|
||||
|
||||
pre.literal-block, pre.doctest-block, pre.math, pre.code {
|
||||
margin-left: 2em ;
|
||||
margin-right: 2em }
|
||||
|
||||
pre.code .ln { color: grey; } /* line numbers */
|
||||
pre.code, code { background-color: #eeeeee }
|
||||
pre.code .comment, code .comment { color: #5C6576 }
|
||||
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
|
||||
pre.code .literal.string, code .literal.string { color: #0C5404 }
|
||||
pre.code .name.builtin, code .name.builtin { color: #352B84 }
|
||||
pre.code .deleted, code .deleted { background-color: #DEB0A1}
|
||||
pre.code .inserted, code .inserted { background-color: #A3D289}
|
||||
|
||||
span.classifier {
|
||||
font-family: sans-serif ;
|
||||
font-style: oblique }
|
||||
|
||||
span.classifier-delimiter {
|
||||
font-family: sans-serif ;
|
||||
font-weight: bold }
|
||||
|
||||
span.interpreted {
|
||||
font-family: sans-serif }
|
||||
|
||||
span.option {
|
||||
white-space: nowrap }
|
||||
|
||||
span.pre {
|
||||
white-space: pre }
|
||||
|
||||
span.problematic {
|
||||
color: red }
|
||||
|
||||
span.section-subtitle {
|
||||
/* font-size relative to parent (h1..h6 element) */
|
||||
font-size: 80% }
|
||||
|
||||
table.citation {
|
||||
border-left: solid 1px gray;
|
||||
margin-left: 1px }
|
||||
|
||||
table.docinfo {
|
||||
margin: 2em 4em }
|
||||
|
||||
table.docutils {
|
||||
margin-top: 0.5em ;
|
||||
margin-bottom: 0.5em }
|
||||
|
||||
table.footnote {
|
||||
border-left: solid 1px black;
|
||||
margin-left: 1px }
|
||||
|
||||
table.docutils td, table.docutils th,
|
||||
table.docinfo td, table.docinfo th {
|
||||
padding-left: 0.5em ;
|
||||
padding-right: 0.5em ;
|
||||
vertical-align: top }
|
||||
|
||||
table.docutils th.field-name, table.docinfo th.docinfo-name {
|
||||
font-weight: bold ;
|
||||
text-align: left ;
|
||||
white-space: nowrap ;
|
||||
padding-left: 0 }
|
||||
|
||||
/* "booktabs" style (no vertical lines) */
|
||||
table.docutils.booktabs {
|
||||
border: 0px;
|
||||
border-top: 2px solid;
|
||||
border-bottom: 2px solid;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
table.docutils.booktabs * {
|
||||
border: 0px;
|
||||
}
|
||||
table.docutils.booktabs th {
|
||||
border-bottom: thin solid;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
|
||||
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
|
||||
font-size: 100% }
|
||||
|
||||
ul.auto-toc {
|
||||
list-style-type: none }
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="document" id="base-company-extension">
|
||||
<h1 class="title">Base Company Extension</h1>
|
||||
|
||||
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
!! This file is generated by oca-gen-addon-readme !!
|
||||
!! changes will be overwritten. !!
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
|
||||
<p><a class="reference external" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external" href="https://github.com/akretion/odoo-usability/tree/12.0/base_company_extension"><img alt="akretion/odoo-usability" src="https://img.shields.io/badge/github-akretion%2Fodoo--usability-lightgray.png?logo=github" /></a></p>
|
||||
<p>This module adds the following fields to the ResCompany model:
|
||||
* Capital Amount
|
||||
* Legal Type</p>
|
||||
<p>This is useful to display the legal name of the company in reports</p>
|
||||
<p><strong>Table of contents</strong></p>
|
||||
<div class="contents local topic" id="contents">
|
||||
<ul class="simple">
|
||||
<li><a class="reference internal" href="#bug-tracker" id="id1">Bug Tracker</a></li>
|
||||
<li><a class="reference internal" href="#credits" id="id2">Credits</a><ul>
|
||||
<li><a class="reference internal" href="#authors" id="id3">Authors</a></li>
|
||||
<li><a class="reference internal" href="#contributors" id="id4">Contributors</a></li>
|
||||
<li><a class="reference internal" href="#maintainers" id="id5">Maintainers</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="bug-tracker">
|
||||
<h1><a class="toc-backref" href="#id1">Bug Tracker</a></h1>
|
||||
<p>Bugs are tracked on <a class="reference external" href="https://github.com/akretion/odoo-usability/issues">GitHub Issues</a>.
|
||||
In case of trouble, please check there if your issue has already been reported.
|
||||
If you spotted it first, help us smashing it by providing a detailed and welcomed
|
||||
<a class="reference external" href="https://github.com/akretion/odoo-usability/issues/new?body=module:%20base_company_extension%0Aversion:%2012.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
|
||||
<p>Do not contact contributors directly about support or help with technical issues.</p>
|
||||
</div>
|
||||
<div class="section" id="credits">
|
||||
<h1><a class="toc-backref" href="#id2">Credits</a></h1>
|
||||
<div class="section" id="authors">
|
||||
<h2><a class="toc-backref" href="#id3">Authors</a></h2>
|
||||
<ul class="simple">
|
||||
<li>Akretion</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="contributors">
|
||||
<h2><a class="toc-backref" href="#id4">Contributors</a></h2>
|
||||
<ul class="simple">
|
||||
<li>Alexis de Lattre <<a class="reference external" href="mailto:alexis.delattre@akretion.com">alexis.delattre@akretion.com</a>></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="maintainers">
|
||||
<h2><a class="toc-backref" href="#id5">Maintainers</a></h2>
|
||||
<p>This module is part of the <a class="reference external" href="https://github.com/akretion/odoo-usability/tree/12.0/base_company_extension">akretion/odoo-usability</a> project on GitHub.</p>
|
||||
<p>You are welcome to contribute.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1 +0,0 @@
|
||||
from . import partner
|
||||
@@ -1,26 +0,0 @@
|
||||
# Copyright 2017-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).
|
||||
|
||||
{
|
||||
'name': 'Base Partner Reference',
|
||||
'version': '12.0.1.0.0',
|
||||
'category': 'Partner',
|
||||
'license': 'AGPL-3',
|
||||
'summary': "Improve usage of partner's Internal Reference",
|
||||
'description': """
|
||||
Base Partner Reference
|
||||
======================
|
||||
|
||||
* Adds Internal Reference in partner tree view
|
||||
|
||||
* Adds Internal Reference in name_get()
|
||||
|
||||
* Adds unicity constraint on Internal Reference
|
||||
""",
|
||||
'author': 'Akretion',
|
||||
'website': 'http://www.akretion.com',
|
||||
'depends': ['base'],
|
||||
'data': ['partner_view.xml'],
|
||||
'installable': True,
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
# Copyright 2017-2019 Akretion
|
||||
# @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 ResPartner(models.Model):
|
||||
_inherit = 'res.partner'
|
||||
|
||||
ref = fields.Char(copy=False) # To avoid blocking duplicate
|
||||
invalidate_display_name = fields.Boolean()
|
||||
|
||||
_sql_constraints = [(
|
||||
'ref_unique',
|
||||
'unique(ref)',
|
||||
'A partner already exists with this internal reference!'
|
||||
)]
|
||||
|
||||
# add 'ref' in depends
|
||||
@api.depends('is_company', 'name', 'parent_id.name', 'type', 'company_name', 'ref', 'invalidate_display_name')
|
||||
def _compute_display_name(self):
|
||||
super(ResPartner, self)._compute_display_name()
|
||||
|
||||
def _get_name(self):
|
||||
partner = self
|
||||
name = partner.name or ''
|
||||
|
||||
# START modif of native method
|
||||
if partner.ref:
|
||||
name = u"[%s] %s" % (partner.ref, name)
|
||||
# END modif of native method
|
||||
if partner.company_name or partner.parent_id:
|
||||
if not name and partner.type in ['invoice', 'delivery', 'other']:
|
||||
name = dict(self.fields_get(['type'])['type']['selection'])[partner.type]
|
||||
if not partner.is_company:
|
||||
# START modif of native name_get() method
|
||||
company_name = partner.commercial_company_name or partner.parent_id.name
|
||||
if partner.parent_id.ref:
|
||||
company_name = u"[%s] %s" % (partner.parent_id.ref, company_name)
|
||||
name = "%s, %s" % (company_name, name)
|
||||
# END modif of native name_get() method
|
||||
if self._context.get('show_address_only'):
|
||||
name = partner._display_address(without_company=True)
|
||||
if self._context.get('show_address'):
|
||||
name = name + "\n" + partner._display_address(without_company=True)
|
||||
name = name.replace('\n\n', '\n')
|
||||
name = name.replace('\n\n', '\n')
|
||||
if self._context.get('address_inline'):
|
||||
name = name.replace('\n', ', ')
|
||||
if self._context.get('show_email') and partner.email:
|
||||
name = "%s <%s>" % (name, partner.email)
|
||||
if self._context.get('html_format'):
|
||||
name = name.replace('\n', '<br/>')
|
||||
if self._context.get('show_vat') and partner.vat:
|
||||
name = "%s ‒ %s" % (name, partner.vat)
|
||||
return name
|
||||
@@ -1,52 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2017-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_partner_form" model="ir.ui.view">
|
||||
<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="arch" type="xml">
|
||||
<field name="type" position="after">
|
||||
<field name="ref"/>
|
||||
</field>
|
||||
<xpath expr="//page[@name='sales_purchases']//field[@name='ref']" position="replace"/>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<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>
|
||||
<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>
|
||||
<field name="model">res.partner</field>
|
||||
<field name="inherit_id" ref="base.res_partner_kanban_view"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="display_name" position="after">
|
||||
<field name="ref"/>
|
||||
</field>
|
||||
<li t-if="record.email.raw_value" position="after">
|
||||
<li t-if="record.ref.raw_value">Ref: <field name="ref"/></li>
|
||||
</li>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -1,82 +0,0 @@
|
||||
==============
|
||||
Base Usability
|
||||
==============
|
||||
|
||||
.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
!! This file is generated by oca-gen-addon-readme !!
|
||||
!! changes will be overwritten. !!
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
|
||||
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
|
||||
:target: https://odoo-community.org/page/development-status
|
||||
:alt: Beta
|
||||
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
|
||||
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
|
||||
:alt: License: AGPL-3
|
||||
.. |badge3| image:: https://img.shields.io/badge/github-akretion%2Fodoo--usability-lightgray.png?logo=github
|
||||
:target: https://github.com/akretion/odoo-usability/tree/12.0/base_usability
|
||||
:alt: akretion/odoo-usability
|
||||
|
||||
|badge1| |badge2| |badge3|
|
||||
|
||||
This module adds the following functions:
|
||||
|
||||
* Adds *track_visibility='onchange'* on all the important fields of the Partner object
|
||||
* By default, Odoo doesn't display the title field on all the partner form views. This module fixes it (it replaces the module base_title_on_partner)
|
||||
* Adds a log message at INFO level when sending an email via SMTP
|
||||
* Displays the local modules with installable filter
|
||||
* A group by "State" is added to module search view
|
||||
* Provides a _display_report_header method on the res.company object and _display_full_address on res.partner which are useful for reporting.
|
||||
* Add model in cron tree view
|
||||
* Add prefix field in sequence search view
|
||||
* Better search and form view for country and state
|
||||
* Display technical name of modules in kanban view
|
||||
* Change module filter to `installable`
|
||||
* Add widget=handle on sequence of res.partner.bank
|
||||
* Add city and country in partner tree view
|
||||
* Add widget="email" on email of contacts
|
||||
* Add script to fix partners related to users in multi-company setup
|
||||
* Add methods for py3o reports
|
||||
* Add name_get() on ir.model
|
||||
* Language wizard defaults to ".po"
|
||||
* Add tracking on partner fields
|
||||
* Handle lang in name_title field
|
||||
* Remove empty lines in address
|
||||
* Add bank Name field on res.partner.bank
|
||||
* Partners auto-created for users are Suppliers and not Customers
|
||||
|
||||
**Table of contents**
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
|
||||
Bug Tracker
|
||||
===========
|
||||
|
||||
Bugs are tracked on `GitHub Issues <https://github.com/akretion/odoo-usability/issues>`_.
|
||||
In case of trouble, please check there if your issue has already been reported.
|
||||
If you spotted it first, help us smashing it by providing a detailed and welcomed
|
||||
`feedback <https://github.com/akretion/odoo-usability/issues/new?body=module:%20base_usability%0Aversion:%2012.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
|
||||
|
||||
Do not contact contributors directly about support or help with technical issues.
|
||||
|
||||
Credits
|
||||
=======
|
||||
|
||||
Authors
|
||||
~~~~~~~
|
||||
|
||||
* Akretion
|
||||
|
||||
Contributors
|
||||
~~~~~~~~~~~~
|
||||
|
||||
* Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
* David Beal <david.beal@akretion.com>
|
||||
|
||||
Maintainers
|
||||
~~~~~~~~~~~
|
||||
|
||||
This module is part of the `akretion/odoo-usability <https://github.com/akretion/odoo-usability/tree/12.0/base_usability>`_ project on GitHub.
|
||||
|
||||
You are welcome to contribute.
|
||||
@@ -1 +0,0 @@
|
||||
from . import models
|
||||
@@ -1,24 +0,0 @@
|
||||
# © 2014-2016 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 Usability',
|
||||
'version': '12.0.0.1.0',
|
||||
'category': 'Partner',
|
||||
'license': 'AGPL-3',
|
||||
'summary': 'Better usability in base module',
|
||||
'author': 'Akretion',
|
||||
'website': 'http://www.akretion.com',
|
||||
'depends': ['base'],
|
||||
'data': [
|
||||
'security/group.xml',
|
||||
'views/partner_view.xml',
|
||||
'views/partner_bank_view.xml',
|
||||
'views/users_view.xml',
|
||||
'views/country_view.xml',
|
||||
'views/module_view.xml',
|
||||
'views/base_view.xml',
|
||||
],
|
||||
'installable': True,
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
diff --git a/odoo/addons/base/models/res_users.py b/odoo/addons/base/models/res_users.py
|
||||
index 083607f9..99ae8857 100644
|
||||
--- a/odoo/addons/base/models/res_users.py
|
||||
+++ b/odoo/addons/base/models/res_users.py
|
||||
@@ -426,7 +426,13 @@ class Users(models.Model):
|
||||
for user in users:
|
||||
user.partner_id.active = user.active
|
||||
if user.partner_id.company_id:
|
||||
- user.partner_id.write({'company_id': user.company_id.id})
|
||||
+ # AKRETION HACK: if you have a multi-company setup where
|
||||
+ # partners are NOT shared between companies, having
|
||||
+ # company_id=False on partners related to users
|
||||
+ # avoids a lot of trouble (you should also disable 'read'
|
||||
+ # on the ir.rule 'user rule' (XMLID base.res_users_rule)
|
||||
+ # user.partner_id.write({'company_id': user.company_id.id})
|
||||
+ user.partner_id.write({'company_id': False})
|
||||
return users
|
||||
|
||||
@api.multi
|
||||
@@ -1,6 +0,0 @@
|
||||
from . import users
|
||||
from . import partner
|
||||
from . import company
|
||||
from . import mail
|
||||
from . import misc
|
||||
from . import ir_model
|
||||
@@ -1,81 +0,0 @@
|
||||
# © 2015-2016 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import models, api, _
|
||||
|
||||
|
||||
class ResCompany(models.Model):
|
||||
_inherit = 'res.company'
|
||||
|
||||
@api.model
|
||||
def generate_line(self, fields, options, icon=True, separator=' - '):
|
||||
assert fields
|
||||
assert options
|
||||
content = []
|
||||
for field in fields:
|
||||
value = False
|
||||
if isinstance(field, tuple) and len(field) == 2:
|
||||
value = field[0]
|
||||
label = field[1]
|
||||
uicon = False
|
||||
elif isinstance(field, str) and field in options:
|
||||
value = options[field]['value']
|
||||
label = options[field].get('label')
|
||||
uicon = options[field].get('icon')
|
||||
if value:
|
||||
prefix = icon and uicon or label
|
||||
if prefix:
|
||||
content.append('%s %s' % (prefix, value))
|
||||
else:
|
||||
content.append(value)
|
||||
line = separator.join(content)
|
||||
return line
|
||||
|
||||
@api.multi
|
||||
def _prepare_header_options(self):
|
||||
self.ensure_one()
|
||||
options = {
|
||||
'phone': {
|
||||
'value': self.phone,
|
||||
# http://www.fileformat.info/info/unicode/char/1f4de/index.htm
|
||||
'icon': '\U0001F4DE',
|
||||
'label': _('Tel:')},
|
||||
'email': {
|
||||
'value': self.email,
|
||||
# http://www.fileformat.info/info/unicode/char/2709/index.htm
|
||||
'icon': '\u2709',
|
||||
'label': _('E-mail:')},
|
||||
'website': {
|
||||
'value': self.website,
|
||||
'icon': '\U0001f310',
|
||||
'label': _('Website:')},
|
||||
'vat': {
|
||||
'value': self.vat,
|
||||
'label': _('TVA :')}, # TODO translate
|
||||
}
|
||||
return options
|
||||
|
||||
def _report_company_legal_name(self):
|
||||
'''Method inherited in the module base_company_extension'''
|
||||
self.ensure_one()
|
||||
return self.name
|
||||
|
||||
# for reports
|
||||
@api.multi
|
||||
def _display_report_header(
|
||||
self, line_details=[['phone', 'website'], ['vat']],
|
||||
icon=True, line_separator=' - '):
|
||||
self.ensure_one()
|
||||
res = ''
|
||||
address = self.partner_id._display_address(without_company=True)
|
||||
address = address.replace('\n', ' - ')
|
||||
|
||||
line1 = '%s - %s' % (self._report_company_legal_name(), address)
|
||||
lines = [line1]
|
||||
options = self._prepare_header_options()
|
||||
for details in line_details:
|
||||
line = self.generate_line(
|
||||
details, options, icon=icon, separator=line_separator)
|
||||
lines.append(line)
|
||||
res = '\n'.join(lines)
|
||||
return res
|
||||
@@ -1,16 +0,0 @@
|
||||
# Copyright 2019 Akretion France (http://www.akretion.com/)
|
||||
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import api, models
|
||||
|
||||
|
||||
class IrModel(models.Model):
|
||||
_inherit = 'ir.model'
|
||||
|
||||
@api.depends('name', 'model')
|
||||
def name_get(self):
|
||||
res = []
|
||||
for rec in self:
|
||||
res.append((rec.id, '%s (%s)' % (rec.name, rec.model)))
|
||||
return res
|
||||
@@ -1,35 +0,0 @@
|
||||
# © 2015-2016 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import models, api
|
||||
from odoo.addons.base.models.ir_mail_server import extract_rfc2822_addresses
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class IrMailServer(models.Model):
|
||||
_inherit = "ir.mail_server"
|
||||
|
||||
@api.model
|
||||
def send_email(
|
||||
self, message, mail_server_id=None, smtp_server=None,
|
||||
smtp_port=None, smtp_user=None, smtp_password=None,
|
||||
smtp_encryption=None, smtp_debug=False, smtp_session=None):
|
||||
# Start copy from native method
|
||||
smtp_from = message['Return-Path'] or\
|
||||
self._get_default_bounce_address() or message['From']
|
||||
from_rfc2822 = extract_rfc2822_addresses(smtp_from)
|
||||
smtp_from = from_rfc2822[-1]
|
||||
# End copy from native method
|
||||
logger.info(
|
||||
"Sending email from '%s' to '%s' Cc '%s' Bcc '%s' "
|
||||
"with subject '%s'",
|
||||
smtp_from, message.get('To'), message.get('Cc'),
|
||||
message.get('Bcc'), message.get('Subject'))
|
||||
return super(IrMailServer, self).send_email(
|
||||
message, mail_server_id=mail_server_id,
|
||||
smtp_server=smtp_server, smtp_port=smtp_port,
|
||||
smtp_user=smtp_user, smtp_password=smtp_password,
|
||||
smtp_encryption=smtp_encryption, smtp_debug=smtp_debug,
|
||||
smtp_session=smtp_session)
|
||||
@@ -1,19 +0,0 @@
|
||||
# © 2015-2016 Akretion (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.tools import misc
|
||||
from odoo.tools import float_compare
|
||||
|
||||
|
||||
class BaseLanguageExport(models.TransientModel):
|
||||
_inherit = 'base.language.export'
|
||||
|
||||
# Default format for language files = format used by OpenERP modules
|
||||
format = fields.Selection(default='po')
|
||||
|
||||
|
||||
class BaseLanguageInstall(models.TransientModel):
|
||||
_inherit = 'base.language.install'
|
||||
|
||||
overwrite = fields.Boolean(default=True)
|
||||
@@ -1,139 +0,0 @@
|
||||
# © 2015-2016 Akretion (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, _
|
||||
|
||||
|
||||
class ResPartner(models.Model):
|
||||
_inherit = 'res.partner'
|
||||
|
||||
# track_visibility is handled in the 'mail' module, and base_usability
|
||||
# doesn't depend on 'mail', but that doesn't hurt, it will just be
|
||||
# ignored if mail is not installed
|
||||
name = fields.Char(track_visibility='onchange')
|
||||
parent_id = fields.Many2one(track_visibility='onchange')
|
||||
ref = fields.Char(track_visibility='onchange', copy=False)
|
||||
lang = fields.Selection(track_visibility='onchange')
|
||||
user_id = fields.Many2one(track_visibility='onchange')
|
||||
vat = fields.Char(track_visibility='onchange')
|
||||
customer = fields.Boolean(track_visibility='onchange')
|
||||
supplier = fields.Boolean(track_visibility='onchange')
|
||||
type = fields.Selection(track_visibility='onchange')
|
||||
street = fields.Char(track_visibility='onchange')
|
||||
street2 = fields.Char(track_visibility='onchange')
|
||||
zip = fields.Char(track_visibility='onchange')
|
||||
city = fields.Char(track_visibility='onchange')
|
||||
state_id = fields.Many2one(track_visibility='onchange')
|
||||
country_id = fields.Many2one(track_visibility='onchange')
|
||||
email = fields.Char(track_visibility='onchange')
|
||||
is_company = fields.Boolean(track_visibility='onchange')
|
||||
active = fields.Boolean(track_visibility='onchange')
|
||||
company_id = fields.Many2one(track_visibility='onchange')
|
||||
# For reports
|
||||
name_title = fields.Char(
|
||||
compute='_compute_name_title', string='Name with Title')
|
||||
|
||||
@api.multi
|
||||
@api.depends('name', 'title')
|
||||
def _compute_name_title(self):
|
||||
for partner in self:
|
||||
name_title = partner.name
|
||||
if partner.title and not partner.is_company:
|
||||
partner_lg = partner
|
||||
# If prefer to read the lang of the partner than the lang
|
||||
# of the context. That way, an English man will be displayed
|
||||
# with his title in English whatever the environment
|
||||
if partner.lang:
|
||||
partner_lg = partner.with_context(lang=partner.lang)
|
||||
title = partner_lg.title.shortcut or partner_lg.title.name
|
||||
name_title = ' '.join([title, name_title])
|
||||
partner.name_title = name_title
|
||||
|
||||
@api.multi
|
||||
def _display_address(self, without_company=False):
|
||||
'''Remove empty lines'''
|
||||
res = super(ResPartner, self)._display_address(
|
||||
without_company=without_company)
|
||||
while "\n\n" in res:
|
||||
res = res.replace('\n\n', '\n')
|
||||
return res
|
||||
|
||||
# for reports
|
||||
@api.multi
|
||||
def _display_full_address(
|
||||
self, details=[
|
||||
'company', 'name', 'address', 'phone',
|
||||
'mobile', 'email'],
|
||||
icon=True):
|
||||
self.ensure_one()
|
||||
# To make the icons work with py3o with PDF export, on the py3o server:
|
||||
# 1) sudo apt-get install fonts-symbola
|
||||
# 2) start libreoffice in xvfb (don't use --headless) (To confirm)
|
||||
if self.is_company:
|
||||
company = self.name
|
||||
name = False
|
||||
else:
|
||||
name = self.name_title
|
||||
company = self.parent_id and self.parent_id.is_company and\
|
||||
self.parent_id.name or False
|
||||
options = {
|
||||
'name': {
|
||||
'value': name,
|
||||
},
|
||||
'company': {
|
||||
'value': company,
|
||||
},
|
||||
'phone': {
|
||||
'value': self.phone,
|
||||
# http://www.fileformat.info/info/unicode/char/1f4de/index.htm
|
||||
'icon': '\U0001F4DE',
|
||||
'label': _('Tel:'),
|
||||
},
|
||||
'mobile': {
|
||||
'value': self.mobile,
|
||||
# http://www.fileformat.info/info/unicode/char/1f4f1/index.htm
|
||||
'icon': '\U0001F4F1',
|
||||
'label': _('Mobile:'),
|
||||
},
|
||||
'email': {
|
||||
'value': self.email,
|
||||
# http://www.fileformat.info/info/unicode/char/2709/index.htm
|
||||
'icon': '\u2709',
|
||||
'label': _('E-mail:'),
|
||||
},
|
||||
'website': {
|
||||
'value': self.website,
|
||||
# http://www.fileformat.info/info/unicode/char/1f310/index.htm
|
||||
'icon': '\U0001f310',
|
||||
'label': _('Website:'),
|
||||
},
|
||||
'address': {
|
||||
'value': self._display_address(without_company=True),
|
||||
}
|
||||
}
|
||||
res = []
|
||||
for detail in details:
|
||||
if options.get(detail) and options[detail]['value']:
|
||||
entry = options[detail]
|
||||
prefix = icon and entry.get('icon') or entry.get('label')
|
||||
if prefix:
|
||||
res.append('%s %s' % (prefix, entry['value']))
|
||||
else:
|
||||
res.append('%s' % entry['value'])
|
||||
res = '\n'.join(res)
|
||||
return res
|
||||
|
||||
|
||||
class ResPartnerCategory(models.Model):
|
||||
_inherit = 'res.partner.category'
|
||||
|
||||
name = fields.Char(translate=False)
|
||||
|
||||
|
||||
class ResPartnerBank(models.Model):
|
||||
_inherit = 'res.partner.bank'
|
||||
|
||||
# In the 'base' module, they didn't put any string, so the bank name is
|
||||
# displayed as 'Name', which the string of the related field it
|
||||
# points to
|
||||
bank_name = fields.Char(string='Bank Name')
|
||||
@@ -1,40 +0,0 @@
|
||||
# Copyright 2018 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
from odoo import models, api, SUPERUSER_ID, _
|
||||
from odoo.exceptions import UserError
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ResUsers(models.Model):
|
||||
_inherit = 'res.users'
|
||||
|
||||
@api.model
|
||||
def default_get(self, fields_list):
|
||||
res = super(ResUsers, self).default_get(fields_list)
|
||||
# For a new partner auto-created when you create a new user, we prefer
|
||||
# customer=False and supplier=True by default
|
||||
res.update({
|
||||
'customer': False,
|
||||
'supplier': True,
|
||||
})
|
||||
return res
|
||||
|
||||
@api.model
|
||||
def _script_partners_linked_to_users_no_company(self):
|
||||
if self.env.user.id != SUPERUSER_ID:
|
||||
raise UserError(_('You must run this script as admin user'))
|
||||
logger.info(
|
||||
'START to set company_id=False on partners related to users')
|
||||
users = self.search(
|
||||
['|', ('active', '=', True), ('active', '=', False)])
|
||||
for user in users:
|
||||
if user.partner_id.company_id:
|
||||
user.partner_id.company_id = False
|
||||
logger.info(
|
||||
'Wrote company_id=False on user %s ID %d',
|
||||
user.login, user.id)
|
||||
logger.info(
|
||||
'END setting company_id=False on partners related to users')
|
||||
return True
|
||||
@@ -1,3 +0,0 @@
|
||||
* Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
* Raphaël Valyi <rvalyi@akretion.com>
|
||||
* David Beal <david.beal@akretion.com>
|
||||
@@ -1,25 +0,0 @@
|
||||
This module adds the following functions:
|
||||
|
||||
* Adds *track_visibility='onchange'* on all the important fields of the Partner object
|
||||
* By default, Odoo doesn't display the title field on all the partner form views. This module fixes it (it replaces the module base_title_on_partner)
|
||||
* Adds a log message at INFO level when sending an email via SMTP
|
||||
* Displays the local modules with installable filter
|
||||
* A group by "State" is added to module search view
|
||||
* Provides a _display_report_header method on the res.company object and _display_full_address on res.partner which are useful for reporting.
|
||||
* Add model in cron tree view
|
||||
* Add prefix field in sequence search view
|
||||
* Better search and form view for country and state
|
||||
* Display technical name of modules in kanban view
|
||||
* Change module filter to `installable`
|
||||
* Add widget=handle on sequence of res.partner.bank
|
||||
* Add city and country in partner tree view
|
||||
* Add widget="email" on email of contacts
|
||||
* Add script to fix partners related to users in multi-company setup
|
||||
* Add methods for py3o reports
|
||||
* Add name_get() on ir.model
|
||||
* Language wizard defaults to ".po"
|
||||
* Add tracking on partner fields
|
||||
* Handle lang in name_title field
|
||||
* Remove empty lines in address
|
||||
* Add bank Name field on res.partner.bank
|
||||
* Partners auto-created for users are Suppliers and not Customers
|
||||
@@ -1,22 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
© 2016 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
|
||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
-->
|
||||
|
||||
|
||||
<odoo noupdate="1">
|
||||
|
||||
<!-- This group is used to hide menu entries to everybody,
|
||||
so you should not put any user in this group. It is used
|
||||
by the module account_hide_analytic_line, but it will certainly
|
||||
be used by other modules in the future, that's why I declare
|
||||
this group in the base_usability module
|
||||
I don't want to use the base.group_no_one for this, because a lot
|
||||
of interesing menu entries are attached to this group, so it's
|
||||
common to have several users that belong to this group -->
|
||||
<record id="group_nobody" model="res.groups">
|
||||
<field name="name">Nobody (used to hide native menus)</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 9.5 KiB |
@@ -1,440 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="generator" content="Docutils 0.15.1: http://docutils.sourceforge.net/" />
|
||||
<title>Base Usability</title>
|
||||
<style type="text/css">
|
||||
|
||||
/*
|
||||
:Author: David Goodger (goodger@python.org)
|
||||
:Id: $Id: html4css1.css 7952 2016-07-26 18:15:59Z milde $
|
||||
:Copyright: This stylesheet has been placed in the public domain.
|
||||
|
||||
Default cascading style sheet for the HTML output of Docutils.
|
||||
|
||||
See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
|
||||
customize this style sheet.
|
||||
*/
|
||||
|
||||
/* used to remove borders from tables and images */
|
||||
.borderless, table.borderless td, table.borderless th {
|
||||
border: 0 }
|
||||
|
||||
table.borderless td, table.borderless th {
|
||||
/* Override padding for "table.docutils td" with "! important".
|
||||
The right padding separates the table cells. */
|
||||
padding: 0 0.5em 0 0 ! important }
|
||||
|
||||
.first {
|
||||
/* Override more specific margin styles with "! important". */
|
||||
margin-top: 0 ! important }
|
||||
|
||||
.last, .with-subtitle {
|
||||
margin-bottom: 0 ! important }
|
||||
|
||||
.hidden {
|
||||
display: none }
|
||||
|
||||
.subscript {
|
||||
vertical-align: sub;
|
||||
font-size: smaller }
|
||||
|
||||
.superscript {
|
||||
vertical-align: super;
|
||||
font-size: smaller }
|
||||
|
||||
a.toc-backref {
|
||||
text-decoration: none ;
|
||||
color: black }
|
||||
|
||||
blockquote.epigraph {
|
||||
margin: 2em 5em ; }
|
||||
|
||||
dl.docutils dd {
|
||||
margin-bottom: 0.5em }
|
||||
|
||||
object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Uncomment (and remove this text!) to get bold-faced definition list terms
|
||||
dl.docutils dt {
|
||||
font-weight: bold }
|
||||
*/
|
||||
|
||||
div.abstract {
|
||||
margin: 2em 5em }
|
||||
|
||||
div.abstract p.topic-title {
|
||||
font-weight: bold ;
|
||||
text-align: center }
|
||||
|
||||
div.admonition, div.attention, div.caution, div.danger, div.error,
|
||||
div.hint, div.important, div.note, div.tip, div.warning {
|
||||
margin: 2em ;
|
||||
border: medium outset ;
|
||||
padding: 1em }
|
||||
|
||||
div.admonition p.admonition-title, div.hint p.admonition-title,
|
||||
div.important p.admonition-title, div.note p.admonition-title,
|
||||
div.tip p.admonition-title {
|
||||
font-weight: bold ;
|
||||
font-family: sans-serif }
|
||||
|
||||
div.attention p.admonition-title, div.caution p.admonition-title,
|
||||
div.danger p.admonition-title, div.error p.admonition-title,
|
||||
div.warning p.admonition-title, .code .error {
|
||||
color: red ;
|
||||
font-weight: bold ;
|
||||
font-family: sans-serif }
|
||||
|
||||
/* Uncomment (and remove this text!) to get reduced vertical space in
|
||||
compound paragraphs.
|
||||
div.compound .compound-first, div.compound .compound-middle {
|
||||
margin-bottom: 0.5em }
|
||||
|
||||
div.compound .compound-last, div.compound .compound-middle {
|
||||
margin-top: 0.5em }
|
||||
*/
|
||||
|
||||
div.dedication {
|
||||
margin: 2em 5em ;
|
||||
text-align: center ;
|
||||
font-style: italic }
|
||||
|
||||
div.dedication p.topic-title {
|
||||
font-weight: bold ;
|
||||
font-style: normal }
|
||||
|
||||
div.figure {
|
||||
margin-left: 2em ;
|
||||
margin-right: 2em }
|
||||
|
||||
div.footer, div.header {
|
||||
clear: both;
|
||||
font-size: smaller }
|
||||
|
||||
div.line-block {
|
||||
display: block ;
|
||||
margin-top: 1em ;
|
||||
margin-bottom: 1em }
|
||||
|
||||
div.line-block div.line-block {
|
||||
margin-top: 0 ;
|
||||
margin-bottom: 0 ;
|
||||
margin-left: 1.5em }
|
||||
|
||||
div.sidebar {
|
||||
margin: 0 0 0.5em 1em ;
|
||||
border: medium outset ;
|
||||
padding: 1em ;
|
||||
background-color: #ffffee ;
|
||||
width: 40% ;
|
||||
float: right ;
|
||||
clear: right }
|
||||
|
||||
div.sidebar p.rubric {
|
||||
font-family: sans-serif ;
|
||||
font-size: medium }
|
||||
|
||||
div.system-messages {
|
||||
margin: 5em }
|
||||
|
||||
div.system-messages h1 {
|
||||
color: red }
|
||||
|
||||
div.system-message {
|
||||
border: medium outset ;
|
||||
padding: 1em }
|
||||
|
||||
div.system-message p.system-message-title {
|
||||
color: red ;
|
||||
font-weight: bold }
|
||||
|
||||
div.topic {
|
||||
margin: 2em }
|
||||
|
||||
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
|
||||
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
|
||||
margin-top: 0.4em }
|
||||
|
||||
h1.title {
|
||||
text-align: center }
|
||||
|
||||
h2.subtitle {
|
||||
text-align: center }
|
||||
|
||||
hr.docutils {
|
||||
width: 75% }
|
||||
|
||||
img.align-left, .figure.align-left, object.align-left, table.align-left {
|
||||
clear: left ;
|
||||
float: left ;
|
||||
margin-right: 1em }
|
||||
|
||||
img.align-right, .figure.align-right, object.align-right, table.align-right {
|
||||
clear: right ;
|
||||
float: right ;
|
||||
margin-left: 1em }
|
||||
|
||||
img.align-center, .figure.align-center, object.align-center {
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
table.align-center {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.align-left {
|
||||
text-align: left }
|
||||
|
||||
.align-center {
|
||||
clear: both ;
|
||||
text-align: center }
|
||||
|
||||
.align-right {
|
||||
text-align: right }
|
||||
|
||||
/* reset inner alignment in figures */
|
||||
div.align-right {
|
||||
text-align: inherit }
|
||||
|
||||
/* div.align-center * { */
|
||||
/* text-align: left } */
|
||||
|
||||
.align-top {
|
||||
vertical-align: top }
|
||||
|
||||
.align-middle {
|
||||
vertical-align: middle }
|
||||
|
||||
.align-bottom {
|
||||
vertical-align: bottom }
|
||||
|
||||
ol.simple, ul.simple {
|
||||
margin-bottom: 1em }
|
||||
|
||||
ol.arabic {
|
||||
list-style: decimal }
|
||||
|
||||
ol.loweralpha {
|
||||
list-style: lower-alpha }
|
||||
|
||||
ol.upperalpha {
|
||||
list-style: upper-alpha }
|
||||
|
||||
ol.lowerroman {
|
||||
list-style: lower-roman }
|
||||
|
||||
ol.upperroman {
|
||||
list-style: upper-roman }
|
||||
|
||||
p.attribution {
|
||||
text-align: right ;
|
||||
margin-left: 50% }
|
||||
|
||||
p.caption {
|
||||
font-style: italic }
|
||||
|
||||
p.credits {
|
||||
font-style: italic ;
|
||||
font-size: smaller }
|
||||
|
||||
p.label {
|
||||
white-space: nowrap }
|
||||
|
||||
p.rubric {
|
||||
font-weight: bold ;
|
||||
font-size: larger ;
|
||||
color: maroon ;
|
||||
text-align: center }
|
||||
|
||||
p.sidebar-title {
|
||||
font-family: sans-serif ;
|
||||
font-weight: bold ;
|
||||
font-size: larger }
|
||||
|
||||
p.sidebar-subtitle {
|
||||
font-family: sans-serif ;
|
||||
font-weight: bold }
|
||||
|
||||
p.topic-title {
|
||||
font-weight: bold }
|
||||
|
||||
pre.address {
|
||||
margin-bottom: 0 ;
|
||||
margin-top: 0 ;
|
||||
font: inherit }
|
||||
|
||||
pre.literal-block, pre.doctest-block, pre.math, pre.code {
|
||||
margin-left: 2em ;
|
||||
margin-right: 2em }
|
||||
|
||||
pre.code .ln { color: grey; } /* line numbers */
|
||||
pre.code, code { background-color: #eeeeee }
|
||||
pre.code .comment, code .comment { color: #5C6576 }
|
||||
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
|
||||
pre.code .literal.string, code .literal.string { color: #0C5404 }
|
||||
pre.code .name.builtin, code .name.builtin { color: #352B84 }
|
||||
pre.code .deleted, code .deleted { background-color: #DEB0A1}
|
||||
pre.code .inserted, code .inserted { background-color: #A3D289}
|
||||
|
||||
span.classifier {
|
||||
font-family: sans-serif ;
|
||||
font-style: oblique }
|
||||
|
||||
span.classifier-delimiter {
|
||||
font-family: sans-serif ;
|
||||
font-weight: bold }
|
||||
|
||||
span.interpreted {
|
||||
font-family: sans-serif }
|
||||
|
||||
span.option {
|
||||
white-space: nowrap }
|
||||
|
||||
span.pre {
|
||||
white-space: pre }
|
||||
|
||||
span.problematic {
|
||||
color: red }
|
||||
|
||||
span.section-subtitle {
|
||||
/* font-size relative to parent (h1..h6 element) */
|
||||
font-size: 80% }
|
||||
|
||||
table.citation {
|
||||
border-left: solid 1px gray;
|
||||
margin-left: 1px }
|
||||
|
||||
table.docinfo {
|
||||
margin: 2em 4em }
|
||||
|
||||
table.docutils {
|
||||
margin-top: 0.5em ;
|
||||
margin-bottom: 0.5em }
|
||||
|
||||
table.footnote {
|
||||
border-left: solid 1px black;
|
||||
margin-left: 1px }
|
||||
|
||||
table.docutils td, table.docutils th,
|
||||
table.docinfo td, table.docinfo th {
|
||||
padding-left: 0.5em ;
|
||||
padding-right: 0.5em ;
|
||||
vertical-align: top }
|
||||
|
||||
table.docutils th.field-name, table.docinfo th.docinfo-name {
|
||||
font-weight: bold ;
|
||||
text-align: left ;
|
||||
white-space: nowrap ;
|
||||
padding-left: 0 }
|
||||
|
||||
/* "booktabs" style (no vertical lines) */
|
||||
table.docutils.booktabs {
|
||||
border: 0px;
|
||||
border-top: 2px solid;
|
||||
border-bottom: 2px solid;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
table.docutils.booktabs * {
|
||||
border: 0px;
|
||||
}
|
||||
table.docutils.booktabs th {
|
||||
border-bottom: thin solid;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
|
||||
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
|
||||
font-size: 100% }
|
||||
|
||||
ul.auto-toc {
|
||||
list-style-type: none }
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="document" id="base-usability">
|
||||
<h1 class="title">Base Usability</h1>
|
||||
|
||||
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
!! This file is generated by oca-gen-addon-readme !!
|
||||
!! changes will be overwritten. !!
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
|
||||
<p><a class="reference external" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external" href="https://github.com/akretion/odoo-usability/tree/12.0/base_usability"><img alt="akretion/odoo-usability" src="https://img.shields.io/badge/github-akretion%2Fodoo--usability-lightgray.png?logo=github" /></a></p>
|
||||
<p>This module adds the following functions:</p>
|
||||
<ul class="simple">
|
||||
<li>Adds <em>track_visibility=’onchange’</em> on all the important fields of the Partner object</li>
|
||||
<li>By default, Odoo doesn’t display the title field on all the partner form views. This module fixes it (it replaces the module base_title_on_partner)</li>
|
||||
<li>Adds a log message at INFO level when sending an email via SMTP</li>
|
||||
<li>Displays the local modules with installable filter</li>
|
||||
<li>A group by “State” is added to module search view</li>
|
||||
<li>Provides a _display_report_header method on the res.company object and _display_full_address on res.partner which are useful for reporting.</li>
|
||||
<li>Add model in cron tree view</li>
|
||||
<li>Add prefix field in sequence search view</li>
|
||||
<li>Better search and form view for country and state</li>
|
||||
<li>Display technical name of modules in kanban view</li>
|
||||
<li>Change module filter to <cite>installable</cite></li>
|
||||
<li>Add widget=handle on sequence of res.partner.bank</li>
|
||||
<li>Add city and country in partner tree view</li>
|
||||
<li>Add widget=”email” on email of contacts</li>
|
||||
<li>Add script to fix partners related to users in multi-company setup</li>
|
||||
<li>Add methods for py3o reports</li>
|
||||
<li>Add name_get() on ir.model</li>
|
||||
<li>Language wizard defaults to “.po”</li>
|
||||
<li>Add tracking on partner fields</li>
|
||||
<li>Handle lang in name_title field</li>
|
||||
<li>Remove empty lines in address</li>
|
||||
<li>Add bank Name field on res.partner.bank</li>
|
||||
<li>Partners auto-created for users are Suppliers and not Customers</li>
|
||||
</ul>
|
||||
<p><strong>Table of contents</strong></p>
|
||||
<div class="contents local topic" id="contents">
|
||||
<ul class="simple">
|
||||
<li><a class="reference internal" href="#bug-tracker" id="id1">Bug Tracker</a></li>
|
||||
<li><a class="reference internal" href="#credits" id="id2">Credits</a><ul>
|
||||
<li><a class="reference internal" href="#authors" id="id3">Authors</a></li>
|
||||
<li><a class="reference internal" href="#contributors" id="id4">Contributors</a></li>
|
||||
<li><a class="reference internal" href="#maintainers" id="id5">Maintainers</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="bug-tracker">
|
||||
<h1><a class="toc-backref" href="#id1">Bug Tracker</a></h1>
|
||||
<p>Bugs are tracked on <a class="reference external" href="https://github.com/akretion/odoo-usability/issues">GitHub Issues</a>.
|
||||
In case of trouble, please check there if your issue has already been reported.
|
||||
If you spotted it first, help us smashing it by providing a detailed and welcomed
|
||||
<a class="reference external" href="https://github.com/akretion/odoo-usability/issues/new?body=module:%20base_usability%0Aversion:%2012.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
|
||||
<p>Do not contact contributors directly about support or help with technical issues.</p>
|
||||
</div>
|
||||
<div class="section" id="credits">
|
||||
<h1><a class="toc-backref" href="#id2">Credits</a></h1>
|
||||
<div class="section" id="authors">
|
||||
<h2><a class="toc-backref" href="#id3">Authors</a></h2>
|
||||
<ul class="simple">
|
||||
<li>Akretion</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="contributors">
|
||||
<h2><a class="toc-backref" href="#id4">Contributors</a></h2>
|
||||
<ul class="simple">
|
||||
<li>Alexis de Lattre <<a class="reference external" href="mailto:alexis.delattre@akretion.com">alexis.delattre@akretion.com</a>></li>
|
||||
<li>David Beal <<a class="reference external" href="mailto:david.beal@akretion.com">david.beal@akretion.com</a>></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="maintainers">
|
||||
<h2><a class="toc-backref" href="#id5">Maintainers</a></h2>
|
||||
<p>This module is part of the <a class="reference external" href="https://github.com/akretion/odoo-usability/tree/12.0/base_usability">akretion/odoo-usability</a> project on GitHub.</p>
|
||||
<p>You are welcome to contribute.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,25 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<odoo>
|
||||
|
||||
<record id="ir_cron_view_tree" model="ir.ui.view">
|
||||
<field name="model">ir.cron</field>
|
||||
<field name="inherit_id" ref="base.ir_cron_view_tree"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="name" position="after">
|
||||
<field name="model_id"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_sequence_search" model="ir.ui.view">
|
||||
<field name="model">ir.sequence</field>
|
||||
<field name="inherit_id" ref="base.view_sequence_search"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="name" position="after">
|
||||
<field name="prefix"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -1,51 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
© 2015-2016 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="res_country_state_search" model="ir.ui.view">
|
||||
<field name="name">base_usability.res.country.state.search</field>
|
||||
<field name="model">res.country.state</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Search States">
|
||||
<field name="name" filter_domain="['|', ('name', 'ilike', self), ('code', '=', self)]" string="Name or Code"/>
|
||||
<field name="code"/>
|
||||
<field name="country_id"/>
|
||||
<group string="Group By" name="groupby">
|
||||
<filter name="country_groupby" string="Country" context="{'group_by': 'country_id'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="res_country_search" model="ir.ui.view">
|
||||
<field name="name">base_usability.res.country.search</field>
|
||||
<field name="model">res.country</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Search Countries">
|
||||
<field name="name" filter_domain="['|', ('name', 'ilike', self), ('code', '=', self)]" string="Name or Code"/>
|
||||
<field name="code"/>
|
||||
<field name="currency_id"/>
|
||||
<group string="Group By" name="groupby">
|
||||
<filter name="currency_groupby" string="Currency" context="{'group_by': 'currency_id'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_country_form" model="ir.ui.view">
|
||||
<field name="name">base_usability.res.country.form</field>
|
||||
<field name="model">res.country</field>
|
||||
<field name="inherit_id" ref="base.view_country_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="code" position="after">
|
||||
<field name="country_group_ids" widget="many2many_tags"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -1,39 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2015-2019 Akretion France (http://www.akretion.com/)
|
||||
@author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
-->
|
||||
|
||||
<odoo>
|
||||
|
||||
<record id="module_view_kanban" model="ir.ui.view">
|
||||
<field name="name">Better display of module technical name</field>
|
||||
<field name="model">ir.module.module</field>
|
||||
<field name="inherit_id" ref="base.module_view_kanban"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//h4[hasclass('o_kanban_record_title')]/code[@groups='base.group_no_one']" position="before">
|
||||
<br/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_module_filter" model="ir.ui.view">
|
||||
<field name="model">ir.module.module</field>
|
||||
<field name="inherit_id" ref="base.view_module_filter"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//filter[@name='extra']" position="after">
|
||||
<filter name="installable" string="Installable" domain="[('state', '!=', 'uninstallable')]"/>
|
||||
</xpath>
|
||||
<group expand="0" position="inside">
|
||||
<filter name="state_groupby" string="State" context="{'group_by': 'state'}"/>
|
||||
</group>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="base.open_module_tree" model="ir.actions.act_window">
|
||||
<field name="context">{'search_default_installable': 1}</field>
|
||||
</record>
|
||||
|
||||
|
||||
</odoo>
|
||||
@@ -1,22 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2018 Akretion (http://www.akretion.com/)
|
||||
@author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
-->
|
||||
|
||||
<odoo>
|
||||
|
||||
<record id="view_partner_bank_tree" model="ir.ui.view">
|
||||
<field name="name">base_usability.res.partner.bank.tree</field>
|
||||
<field name="model">res.partner.bank</field>
|
||||
<field name="inherit_id" ref="base.view_partner_bank_tree"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="sequence" position="attributes">
|
||||
<attribute name="invisible">0</attribute>
|
||||
<attribute name="widget">handle</attribute>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -1,66 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
© 2014-2016 Akretion (http://www.akretion.com/)
|
||||
@author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
-->
|
||||
|
||||
<odoo>
|
||||
|
||||
<record id="view_partner_form" model="ir.ui.view">
|
||||
<field name="name">base_usability.title.on.partner.form</field>
|
||||
<field name="model">res.partner</field>
|
||||
<field name="inherit_id" ref="base.view_partner_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<xpath expr="//field[@name='child_ids']/form//field[@name='email']" position="attributes">
|
||||
<attribute name="widget">email</attribute>
|
||||
</xpath>
|
||||
<!-- Show title not only on Contacts -->
|
||||
<xpath expr="//field[@name='child_ids']/form//field[@name='title']" position="attributes">
|
||||
<attribute name="attrs"></attribute>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_partner_simple_form" model="ir.ui.view">
|
||||
<field name="name">base_usability.title.on.partner.simplified.form</field>
|
||||
<field name="model">res.partner</field>
|
||||
<field name="inherit_id" ref="base.view_partner_simple_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="function" position="before">
|
||||
<field name="title"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_partner_tree" model="ir.ui.view">
|
||||
<field name="name">base_usability.res.partner.tree</field>
|
||||
<field name="model">res.partner</field>
|
||||
<field name="inherit_id" ref="base.view_partner_tree"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="country_id" position="attributes">
|
||||
<attribute name="invisible">0</attribute>
|
||||
</field>
|
||||
<field name="country_id" position="before">
|
||||
<field name="city"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_res_partner_filter" model="ir.ui.view">
|
||||
<field name="name">base_usability.partner.search.form</field>
|
||||
<field name="model">res.partner</field>
|
||||
<field name="inherit_id" ref="base.view_res_partner_filter"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="name" position="attributes">
|
||||
<attribute name="string">Name or Email or Reference</attribute>
|
||||
<!-- for 'ref', change '=' to 'start with' -->
|
||||
<attribute name="filter_domain">['|','|',('display_name','ilike',self),('ref','=ilike',self + '%'),('email','ilike',self)]</attribute>
|
||||
</field>
|
||||
<filter name="inactive" position="before">
|
||||
<separator/>
|
||||
</filter>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -1,21 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2018 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_users_tree" model="ir.ui.view">
|
||||
<field name="name">base_usability.res.users.tree</field>
|
||||
<field name="model">res.users</field>
|
||||
<field name="inherit_id" ref="base.view_users_tree"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="login_date" position="after">
|
||||
<field name="company_id" groups="base.group_multi_company"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -1,78 +0,0 @@
|
||||
============
|
||||
Company Code
|
||||
============
|
||||
|
||||
.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
!! This file is generated by oca-gen-addon-readme !!
|
||||
!! changes will be overwritten. !!
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
|
||||
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
|
||||
:target: https://odoo-community.org/page/development-status
|
||||
:alt: Beta
|
||||
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
|
||||
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
|
||||
:alt: License: AGPL-3
|
||||
.. |badge3| image:: https://img.shields.io/badge/github-akretion%2Fodoo--usability-lightgray.png?logo=github
|
||||
:target: https://github.com/akretion/odoo-usability/tree/12.0/company_code
|
||||
:alt: akretion/odoo-usability
|
||||
|
||||
|badge1| |badge2| |badge3|
|
||||
|
||||
- add `code` field to company.
|
||||
- update name_get with this field
|
||||
|
||||
**Table of contents**
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
To display your company code with `name_get()` just
|
||||
write this code in your custom code according your model
|
||||
|
||||
|
||||
```python
|
||||
|
||||
class ResPartner(models.Model):
|
||||
_inherit = 'res.partner'
|
||||
|
||||
def name_get(self):
|
||||
return self.env['res.company']._add_company_code(super())
|
||||
|
||||
```
|
||||
|
||||
Bug Tracker
|
||||
===========
|
||||
|
||||
Bugs are tracked on `GitHub Issues <https://github.com/akretion/odoo-usability/issues>`_.
|
||||
In case of trouble, please check there if your issue has already been reported.
|
||||
If you spotted it first, help us smashing it by providing a detailed and welcomed
|
||||
`feedback <https://github.com/akretion/odoo-usability/issues/new?body=module:%20company_code%0Aversion:%2012.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
|
||||
|
||||
Do not contact contributors directly about support or help with technical issues.
|
||||
|
||||
Credits
|
||||
=======
|
||||
|
||||
Authors
|
||||
~~~~~~~
|
||||
|
||||
* Akretion
|
||||
|
||||
Contributors
|
||||
~~~~~~~~~~~~
|
||||
|
||||
David Beal <david.beal@akretion.com>
|
||||
|
||||
Maintainers
|
||||
~~~~~~~~~~~
|
||||
|
||||
|
||||
|
||||
This module is part of the `akretion/odoo-usability <https://github.com/akretion/odoo-usability/tree/12.0/company_code>`_ project on GitHub.
|
||||
|
||||
|
||||
You are welcome to contribute.
|
||||
@@ -1 +0,0 @@
|
||||
from . import models
|
||||
@@ -1,20 +0,0 @@
|
||||
# Copyright 2019 David BEAL @ Akretion
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||
|
||||
{
|
||||
'name': 'Company Code',
|
||||
'summary': 'Add a code field in company',
|
||||
'version': '12.0.0.0.1',
|
||||
'author': 'Akretion',
|
||||
'maintainer': 'Akretion',
|
||||
'license': 'AGPL-3',
|
||||
'category': 'base',
|
||||
'depends': [
|
||||
'base',
|
||||
],
|
||||
'website': 'http://www.akretion.com/',
|
||||
'data': [
|
||||
'views/company_view.xml',
|
||||
],
|
||||
'installable': True,
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
from . import company
|
||||
@@ -1,33 +0,0 @@
|
||||
# Copyright 2019 David BEAL @ Akretion
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||
|
||||
from odoo import models, fields
|
||||
|
||||
|
||||
class ResCompany(models.Model):
|
||||
_inherit = 'res.company'
|
||||
|
||||
code = fields.Char(
|
||||
required=True, default='CODE',
|
||||
help="Field used in object name as suffix")
|
||||
|
||||
def _add_company_code(self, super_object):
|
||||
""
|
||||
""" Add the `code` field to your _rec_name. Use it like that:
|
||||
|
||||
def name_get(self):
|
||||
return self.env['res.company']._add_company_code(super())
|
||||
"""
|
||||
records = super_object.__self__
|
||||
if records and records[0]._name == 'res.company':
|
||||
codes = {x.id: x.code for x in records}
|
||||
else:
|
||||
codes = {x.id: x['company_id']['code'] for x in records
|
||||
if getattr(x, 'company_id')}
|
||||
if not codes:
|
||||
return super_object.name_get()
|
||||
return [(elm[0], '%s (%s)' % (elm[1], codes[elm[0]] or ''))
|
||||
for elm in super_object.name_get()]
|
||||
|
||||
def name_get(self):
|
||||
return self.env['res.company']._add_company_code(super())
|
||||
@@ -1 +0,0 @@
|
||||
David Beal <david.beal@akretion.com>
|
||||
@@ -1,2 +0,0 @@
|
||||
- add `code` field to company.
|
||||
- update name_get with this field
|
||||
@@ -1,13 +0,0 @@
|
||||
To display your company code with `name_get()` just
|
||||
write this in your custom code according to your model
|
||||
|
||||
|
||||
```python
|
||||
|
||||
class ResPartner(models.Model):
|
||||
_inherit = 'res.partner'
|
||||
|
||||
def name_get(self):
|
||||
return self.env['res.company']._add_company_code(super())
|
||||
|
||||
```
|
||||
@@ -1,415 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta name="generator" content="Docutils 0.14: http://docutils.sourceforge.net/" />
|
||||
<title>Company Code</title>
|
||||
<style type="text/css">
|
||||
|
||||
/*
|
||||
:Author: David Goodger (goodger@python.org)
|
||||
:Id: $Id: html4css1.css 7952 2016-07-26 18:15:59Z milde $
|
||||
:Copyright: This stylesheet has been placed in the public domain.
|
||||
|
||||
Default cascading style sheet for the HTML output of Docutils.
|
||||
|
||||
See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
|
||||
customize this style sheet.
|
||||
*/
|
||||
|
||||
/* used to remove borders from tables and images */
|
||||
.borderless, table.borderless td, table.borderless th {
|
||||
border: 0 }
|
||||
|
||||
table.borderless td, table.borderless th {
|
||||
/* Override padding for "table.docutils td" with "! important".
|
||||
The right padding separates the table cells. */
|
||||
padding: 0 0.5em 0 0 ! important }
|
||||
|
||||
.first {
|
||||
/* Override more specific margin styles with "! important". */
|
||||
margin-top: 0 ! important }
|
||||
|
||||
.last, .with-subtitle {
|
||||
margin-bottom: 0 ! important }
|
||||
|
||||
.hidden {
|
||||
display: none }
|
||||
|
||||
.subscript {
|
||||
vertical-align: sub;
|
||||
font-size: smaller }
|
||||
|
||||
.superscript {
|
||||
vertical-align: super;
|
||||
font-size: smaller }
|
||||
|
||||
a.toc-backref {
|
||||
text-decoration: none ;
|
||||
color: black }
|
||||
|
||||
blockquote.epigraph {
|
||||
margin: 2em 5em ; }
|
||||
|
||||
dl.docutils dd {
|
||||
margin-bottom: 0.5em }
|
||||
|
||||
object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Uncomment (and remove this text!) to get bold-faced definition list terms
|
||||
dl.docutils dt {
|
||||
font-weight: bold }
|
||||
*/
|
||||
|
||||
div.abstract {
|
||||
margin: 2em 5em }
|
||||
|
||||
div.abstract p.topic-title {
|
||||
font-weight: bold ;
|
||||
text-align: center }
|
||||
|
||||
div.admonition, div.attention, div.caution, div.danger, div.error,
|
||||
div.hint, div.important, div.note, div.tip, div.warning {
|
||||
margin: 2em ;
|
||||
border: medium outset ;
|
||||
padding: 1em }
|
||||
|
||||
div.admonition p.admonition-title, div.hint p.admonition-title,
|
||||
div.important p.admonition-title, div.note p.admonition-title,
|
||||
div.tip p.admonition-title {
|
||||
font-weight: bold ;
|
||||
font-family: sans-serif }
|
||||
|
||||
div.attention p.admonition-title, div.caution p.admonition-title,
|
||||
div.danger p.admonition-title, div.error p.admonition-title,
|
||||
div.warning p.admonition-title, .code .error {
|
||||
color: red ;
|
||||
font-weight: bold ;
|
||||
font-family: sans-serif }
|
||||
|
||||
/* Uncomment (and remove this text!) to get reduced vertical space in
|
||||
compound paragraphs.
|
||||
div.compound .compound-first, div.compound .compound-middle {
|
||||
margin-bottom: 0.5em }
|
||||
|
||||
div.compound .compound-last, div.compound .compound-middle {
|
||||
margin-top: 0.5em }
|
||||
*/
|
||||
|
||||
div.dedication {
|
||||
margin: 2em 5em ;
|
||||
text-align: center ;
|
||||
font-style: italic }
|
||||
|
||||
div.dedication p.topic-title {
|
||||
font-weight: bold ;
|
||||
font-style: normal }
|
||||
|
||||
div.figure {
|
||||
margin-left: 2em ;
|
||||
margin-right: 2em }
|
||||
|
||||
div.footer, div.header {
|
||||
clear: both;
|
||||
font-size: smaller }
|
||||
|
||||
div.line-block {
|
||||
display: block ;
|
||||
margin-top: 1em ;
|
||||
margin-bottom: 1em }
|
||||
|
||||
div.line-block div.line-block {
|
||||
margin-top: 0 ;
|
||||
margin-bottom: 0 ;
|
||||
margin-left: 1.5em }
|
||||
|
||||
div.sidebar {
|
||||
margin: 0 0 0.5em 1em ;
|
||||
border: medium outset ;
|
||||
padding: 1em ;
|
||||
background-color: #ffffee ;
|
||||
width: 40% ;
|
||||
float: right ;
|
||||
clear: right }
|
||||
|
||||
div.sidebar p.rubric {
|
||||
font-family: sans-serif ;
|
||||
font-size: medium }
|
||||
|
||||
div.system-messages {
|
||||
margin: 5em }
|
||||
|
||||
div.system-messages h1 {
|
||||
color: red }
|
||||
|
||||
div.system-message {
|
||||
border: medium outset ;
|
||||
padding: 1em }
|
||||
|
||||
div.system-message p.system-message-title {
|
||||
color: red ;
|
||||
font-weight: bold }
|
||||
|
||||
div.topic {
|
||||
margin: 2em }
|
||||
|
||||
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
|
||||
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
|
||||
margin-top: 0.4em }
|
||||
|
||||
h1.title {
|
||||
text-align: center }
|
||||
|
||||
h2.subtitle {
|
||||
text-align: center }
|
||||
|
||||
hr.docutils {
|
||||
width: 75% }
|
||||
|
||||
img.align-left, .figure.align-left, object.align-left, table.align-left {
|
||||
clear: left ;
|
||||
float: left ;
|
||||
margin-right: 1em }
|
||||
|
||||
img.align-right, .figure.align-right, object.align-right, table.align-right {
|
||||
clear: right ;
|
||||
float: right ;
|
||||
margin-left: 1em }
|
||||
|
||||
img.align-center, .figure.align-center, object.align-center {
|
||||
display: block;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
table.align-center {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.align-left {
|
||||
text-align: left }
|
||||
|
||||
.align-center {
|
||||
clear: both ;
|
||||
text-align: center }
|
||||
|
||||
.align-right {
|
||||
text-align: right }
|
||||
|
||||
/* reset inner alignment in figures */
|
||||
div.align-right {
|
||||
text-align: inherit }
|
||||
|
||||
/* div.align-center * { */
|
||||
/* text-align: left } */
|
||||
|
||||
.align-top {
|
||||
vertical-align: top }
|
||||
|
||||
.align-middle {
|
||||
vertical-align: middle }
|
||||
|
||||
.align-bottom {
|
||||
vertical-align: bottom }
|
||||
|
||||
ol.simple, ul.simple {
|
||||
margin-bottom: 1em }
|
||||
|
||||
ol.arabic {
|
||||
list-style: decimal }
|
||||
|
||||
ol.loweralpha {
|
||||
list-style: lower-alpha }
|
||||
|
||||
ol.upperalpha {
|
||||
list-style: upper-alpha }
|
||||
|
||||
ol.lowerroman {
|
||||
list-style: lower-roman }
|
||||
|
||||
ol.upperroman {
|
||||
list-style: upper-roman }
|
||||
|
||||
p.attribution {
|
||||
text-align: right ;
|
||||
margin-left: 50% }
|
||||
|
||||
p.caption {
|
||||
font-style: italic }
|
||||
|
||||
p.credits {
|
||||
font-style: italic ;
|
||||
font-size: smaller }
|
||||
|
||||
p.label {
|
||||
white-space: nowrap }
|
||||
|
||||
p.rubric {
|
||||
font-weight: bold ;
|
||||
font-size: larger ;
|
||||
color: maroon ;
|
||||
text-align: center }
|
||||
|
||||
p.sidebar-title {
|
||||
font-family: sans-serif ;
|
||||
font-weight: bold ;
|
||||
font-size: larger }
|
||||
|
||||
p.sidebar-subtitle {
|
||||
font-family: sans-serif ;
|
||||
font-weight: bold }
|
||||
|
||||
p.topic-title {
|
||||
font-weight: bold }
|
||||
|
||||
pre.address {
|
||||
margin-bottom: 0 ;
|
||||
margin-top: 0 ;
|
||||
font: inherit }
|
||||
|
||||
pre.literal-block, pre.doctest-block, pre.math, pre.code {
|
||||
margin-left: 2em ;
|
||||
margin-right: 2em }
|
||||
|
||||
pre.code .ln { color: grey; } /* line numbers */
|
||||
pre.code, code { background-color: #eeeeee }
|
||||
pre.code .comment, code .comment { color: #5C6576 }
|
||||
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
|
||||
pre.code .literal.string, code .literal.string { color: #0C5404 }
|
||||
pre.code .name.builtin, code .name.builtin { color: #352B84 }
|
||||
pre.code .deleted, code .deleted { background-color: #DEB0A1}
|
||||
pre.code .inserted, code .inserted { background-color: #A3D289}
|
||||
|
||||
span.classifier {
|
||||
font-family: sans-serif ;
|
||||
font-style: oblique }
|
||||
|
||||
span.classifier-delimiter {
|
||||
font-family: sans-serif ;
|
||||
font-weight: bold }
|
||||
|
||||
span.interpreted {
|
||||
font-family: sans-serif }
|
||||
|
||||
span.option {
|
||||
white-space: nowrap }
|
||||
|
||||
span.pre {
|
||||
white-space: pre }
|
||||
|
||||
span.problematic {
|
||||
color: red }
|
||||
|
||||
span.section-subtitle {
|
||||
/* font-size relative to parent (h1..h6 element) */
|
||||
font-size: 80% }
|
||||
|
||||
table.citation {
|
||||
border-left: solid 1px gray;
|
||||
margin-left: 1px }
|
||||
|
||||
table.docinfo {
|
||||
margin: 2em 4em }
|
||||
|
||||
table.docutils {
|
||||
margin-top: 0.5em ;
|
||||
margin-bottom: 0.5em }
|
||||
|
||||
table.footnote {
|
||||
border-left: solid 1px black;
|
||||
margin-left: 1px }
|
||||
|
||||
table.docutils td, table.docutils th,
|
||||
table.docinfo td, table.docinfo th {
|
||||
padding-left: 0.5em ;
|
||||
padding-right: 0.5em ;
|
||||
vertical-align: top }
|
||||
|
||||
table.docutils th.field-name, table.docinfo th.docinfo-name {
|
||||
font-weight: bold ;
|
||||
text-align: left ;
|
||||
white-space: nowrap ;
|
||||
padding-left: 0 }
|
||||
|
||||
/* "booktabs" style (no vertical lines) */
|
||||
table.docutils.booktabs {
|
||||
border: 0px;
|
||||
border-top: 2px solid;
|
||||
border-bottom: 2px solid;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
table.docutils.booktabs * {
|
||||
border: 0px;
|
||||
}
|
||||
table.docutils.booktabs th {
|
||||
border-bottom: thin solid;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
|
||||
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
|
||||
font-size: 100% }
|
||||
|
||||
ul.auto-toc {
|
||||
list-style-type: none }
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="document" id="company-code">
|
||||
<h1 class="title">Company Code</h1>
|
||||
|
||||
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
!! This file is generated by oca-gen-addon-readme !!
|
||||
!! changes will be overwritten. !!
|
||||
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
|
||||
<p><a class="reference external" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external" href="https://github.com/akretion/odoo-usability/tree/12.0/company_code"><img alt="akretion/odoo-usability" src="https://img.shields.io/badge/github-akretion%2Fodoo--usability-lightgray.png?logo=github" /></a></p>
|
||||
<ul class="simple">
|
||||
<li>add <cite>code</cite> field to company.</li>
|
||||
<li>update name_get with this field</li>
|
||||
</ul>
|
||||
<p><strong>Table of contents</strong></p>
|
||||
<div class="contents local topic" id="contents">
|
||||
<ul class="simple">
|
||||
<li><a class="reference internal" href="#bug-tracker" id="id1">Bug Tracker</a></li>
|
||||
<li><a class="reference internal" href="#credits" id="id2">Credits</a><ul>
|
||||
<li><a class="reference internal" href="#authors" id="id3">Authors</a></li>
|
||||
<li><a class="reference internal" href="#contributors" id="id4">Contributors</a></li>
|
||||
<li><a class="reference internal" href="#maintainers" id="id5">Maintainers</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="bug-tracker">
|
||||
<h1><a class="toc-backref" href="#id1">Bug Tracker</a></h1>
|
||||
<p>Bugs are tracked on <a class="reference external" href="https://github.com/akretion/odoo-usability/issues">GitHub Issues</a>.
|
||||
In case of trouble, please check there if your issue has already been reported.
|
||||
If you spotted it first, help us smashing it by providing a detailed and welcomed
|
||||
<a class="reference external" href="https://github.com/akretion/odoo-usability/issues/new?body=module:%20company_code%0Aversion:%2012.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
|
||||
<p>Do not contact contributors directly about support or help with technical issues.</p>
|
||||
</div>
|
||||
<div class="section" id="credits">
|
||||
<h1><a class="toc-backref" href="#id2">Credits</a></h1>
|
||||
<div class="section" id="authors">
|
||||
<h2><a class="toc-backref" href="#id3">Authors</a></h2>
|
||||
<ul class="simple">
|
||||
<li>Akretion</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="section" id="contributors">
|
||||
<h2><a class="toc-backref" href="#id4">Contributors</a></h2>
|
||||
<p>David Beal <<a class="reference external" href="mailto:david.beal@akretion.com">david.beal@akretion.com</a>></p>
|
||||
</div>
|
||||
<div class="section" id="maintainers">
|
||||
<h2><a class="toc-backref" href="#id5">Maintainers</a></h2>
|
||||
<p>This module is part of the <a class="reference external" href="https://github.com/akretion/odoo-usability/tree/12.0/company_code">akretion/odoo-usability</a> project on GitHub.</p>
|
||||
<p>You are welcome to contribute.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,14 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
|
||||
<record id="view_company_form" model="ir.ui.view">
|
||||
<field name="model">res.company</field>
|
||||
<field name="inherit_id" ref="base.view_company_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="partner_id" position="before">
|
||||
<field name="code"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -1 +0,0 @@
|
||||
from . import stock
|
||||
@@ -1,29 +0,0 @@
|
||||
# Copyright 2018-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).
|
||||
|
||||
{
|
||||
'name': 'Delivery Usability',
|
||||
'version': '12.0.1.0.0',
|
||||
'category': 'Stock',
|
||||
'license': 'AGPL-3',
|
||||
'summary': 'Several usability enhancements in Delivery',
|
||||
'description': """
|
||||
Delivery Usability
|
||||
===================
|
||||
|
||||
The usability enhancements include:
|
||||
* allow modification of carrier and it's tracking ref. on a done picking
|
||||
* display field 'invoice_shipping_on_delivery' on sale.order form view
|
||||
|
||||
This module has been written by Alexis de Lattre from Akretion <alexis.delattre@akretion.com>.
|
||||
""",
|
||||
'author': 'Akretion',
|
||||
'website': 'http://www.akretion.com',
|
||||
'depends': ['delivery'],
|
||||
'data': [
|
||||
'sale_view.xml',
|
||||
'stock_view.xml',
|
||||
],
|
||||
'installable': True,
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2018-2019 Akretion
|
||||
@author: Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
-->
|
||||
|
||||
<odoo>
|
||||
|
||||
|
||||
<record id="view_order_form_with_carrier" model="ir.ui.view">
|
||||
<field name="name">delivery_usability.sale.order.form</field>
|
||||
<field name="model">sale.order</field>
|
||||
<field name="inherit_id" ref="delivery.view_order_form_with_carrier"/>
|
||||
<field name="arch" type="xml">
|
||||
<group name="sale_pay" position="inside">
|
||||
<field name="invoice_shipping_on_delivery"/>
|
||||
</group>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
</odoo>
|
||||
@@ -1,12 +0,0 @@
|
||||
# Copyright 2018-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).
|
||||
|
||||
from odoo import fields, models
|
||||
|
||||
|
||||
class StockPicking(models.Model):
|
||||
_inherit = 'stock.picking'
|
||||
|
||||
carrier_id = fields.Many2one(track_visibility='onchange')
|
||||
carrier_tracking_ref = fields.Char(track_visibility='onchange')
|
||||
@@ -1,26 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2018 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
|
||||
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
-->
|
||||
|
||||
<odoo>
|
||||
|
||||
<record id="view_picking_withcarrier_out_form" model="ir.ui.view">
|
||||
<field name="name">delivery_usability.stock.picking.form</field>
|
||||
<field name="model">stock.picking</field>
|
||||
<field name="inherit_id" ref="delivery.view_picking_withcarrier_out_form"/>
|
||||
<field name="arch" type="xml">
|
||||
<field name="carrier_id" position="attributes">
|
||||
<!-- Sometimes we have to modify carrier_id when state is done
|
||||
so remove readonly when state = done from view and add tracking on_change in
|
||||
field definition -->
|
||||
<attribute name="attrs">{}</attribute>
|
||||
</field>
|
||||
<field name="carrier_tracking_ref" position="attributes">
|
||||
<attribute name="attrs">{}</attribute>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</odoo>
|
||||
@@ -1,31 +0,0 @@
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
{
|
||||
'name': 'Developer Menu',
|
||||
'version': '12.0.0.0.0',
|
||||
'category': 'Tools',
|
||||
'license': 'AGPL-3',
|
||||
'summary': "Menu Shortcut for developer usage",
|
||||
'description': """
|
||||
Developer menu
|
||||
==============
|
||||
|
||||
Add a menu which gather main technical used menus
|
||||
|
||||
How to use it
|
||||
-------------
|
||||
|
||||
Ensure you're in ERP manager group and go to configuration page
|
||||
near `Technical` menu
|
||||
|
||||
This module has been written by David Béal
|
||||
from Akretion <david.beal@akretion.com>.
|
||||
""",
|
||||
'author': 'Akretion',
|
||||
'website': 'http://www.akretion.com',
|
||||
'depends': ['mail'],
|
||||
'data': [
|
||||
'menu_view.xml'
|
||||
],
|
||||
'installable': True,
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<odoo>
|
||||
|
||||
<menuitem id="conf_tech" parent="base.menu_administration" name="🧰" groups="base.group_erp_manager" sequence="100"/>
|
||||
<menuitem id="model" name="Model" parent="conf_tech" action="base.action_model_model" sequence="10"/>
|
||||
<menuitem id="view" name="View" parent="conf_tech" action="base.action_ui_view" sequence="20" />
|
||||
<menuitem id="rec_rule" name="Record Rule" parent="conf_tech" action="base.action_rule" sequence="30" />
|
||||
<menuitem id="menu" name="Menu" parent="conf_tech" action="base.grant_menu_access" sequence="100" />
|
||||
<menuitem id="seq" name="Sequence" parent="conf_tech" action="base.ir_sequence_form" sequence="100" />
|
||||
<menuitem id="model_data" name="Model Data" parent="conf_tech" action="base.action_model_data" sequence="100" />
|
||||
<menuitem id="param" name="Param" parent="conf_tech" action="base.ir_config_list_action" sequence="100" />
|
||||
<menuitem id="cron" name="Cron" parent="conf_tech" action="base.ir_cron_act" sequence="100" />
|
||||
<menuitem id="window" name="Act Window" parent="conf_tech" action="base.ir_action_window" sequence="100" />
|
||||
<menuitem id="server" name="Act Server" parent="conf_tech" action="base.action_server_action" sequence="100" />
|
||||
<menuitem id="report" name="Report" parent="conf_tech" action="base.ir_action_report" sequence="100" />
|
||||
<menuitem id="mail_tmpl" name="Mail Tmpl" parent="conf_tech" action="mail.action_email_template_tree_all" sequence="100" />
|
||||
<menuitem id="property" name="Property" parent="conf_tech" action="base.ir_property_form" sequence="100" />
|
||||
|
||||
|
||||
</odoo>
|
||||
@@ -1 +0,0 @@
|
||||
from .hooks import web_m2x_options_create
|
||||
@@ -1,25 +0,0 @@
|
||||
# Copyright 2014-2019 Akretion France (http://www.akretion.com)
|
||||
# @author Alexis de Lattre <alexis.delattre@akretion.com>
|
||||
|
||||
{
|
||||
'name': 'Eradicate Quick Create',
|
||||
'version': '12.0.2.0.0',
|
||||
'category': 'Tools',
|
||||
'license': 'AGPL-3',
|
||||
'summary': 'Disable quick create on all objects',
|
||||
'description': """
|
||||
Eradicate Quick Create
|
||||
======================
|
||||
|
||||
Disable quick create on all objects of Odoo.
|
||||
|
||||
This new version of the module uses the module *web_m2x_options* from the OCA *web* project instead of the module *base_optional_quick_create* from the OCA project *server-ux*.
|
||||
|
||||
This module has been written by Alexis de Lattre from Akretion <alexis.delattre@akretion.com>.
|
||||
""",
|
||||
'author': 'Akretion',
|
||||
'website': 'http://www.akretion.com',
|
||||
'depends': ['web_m2x_options'],
|
||||
'post_init_hook': 'web_m2x_options_create',
|
||||
'installable': True,
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
# Copyright 2019 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 SUPERUSER_ID
|
||||
from odoo.api import Environment
|
||||
|
||||
|
||||
def web_m2x_options_create(cr, registry):
|
||||
env = Environment(cr, SUPERUSER_ID, {})
|
||||
config_parameter = env['ir.config_parameter'].search(
|
||||
[('key', '=', 'web_m2x_options.create')])
|
||||
if config_parameter and config_parameter.value != 'False':
|
||||
config_parameter.value = 'False'
|
||||
else:
|
||||
env['ir.config_parameter'].create({
|
||||
'key': 'web_m2x_options.create',
|
||||
'value': 'False',
|
||||
})
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 4.6 KiB |
@@ -1,4 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from . import intrastat_product_type
|
||||
from .post_install import set_intrastat_type_on_products
|
||||
@@ -1,27 +0,0 @@
|
||||
# Copyright 2016-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).
|
||||
|
||||
{
|
||||
'name': 'Intrastat Product Type',
|
||||
'version': '12.0.1.0.0',
|
||||
'category': 'Accounting',
|
||||
'license': 'AGPL-3',
|
||||
'summary': 'Adds a special field Intrastat Type on Products',
|
||||
'description': """
|
||||
Intrastat Product Type
|
||||
======================
|
||||
|
||||
This module is designed for a very special usage scenario. Some companies want to handle the delivery of services the same way as they handle the delivery of goods ; they want to show the services in the delivery note, etc. So, those companies configure the services with Type = *Consumable*. This works well to have the services on the outgoing pickings, but it is a problem for the intrastat declarations.
|
||||
|
||||
This module adds a field *Intrastat Type* on the Product Form with 2 possible options: *Product* or *Service*. The intrastat declaration will use this field instead of the native *Type* field.
|
||||
|
||||
This module has been written by Alexis de Lattre from Akretion <alexis.delattre@akretion.com>.
|
||||
""",
|
||||
'author': 'Akretion',
|
||||
'website': 'http://www.akretion.com',
|
||||
'depends': ['intrastat_product', 'l10n_fr_intrastat_service'],
|
||||
'data': ['product_view.xml'],
|
||||
'post_init_hook': 'set_intrastat_type_on_products',
|
||||
'installable': True,
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2016-2019 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 models, fields, api, _
|
||||
from odoo.exceptions import ValidationError
|
||||
|
||||
|
||||
class ProductTemplate(models.Model):
|
||||
_inherit = 'product.template'
|
||||
|
||||
intrastat_type = fields.Selection([
|
||||
('product', 'Product'),
|
||||
('service', 'Service'),
|
||||
], string='Intrastat Type', default='product', required=True,
|
||||
help="Type of product used for the intrastat declarations. "
|
||||
"For example, you can configure a product with "
|
||||
"'Product Type' = 'Consumable' and 'Intrastat Type' = 'Service'.")
|
||||
|
||||
@api.multi
|
||||
@api.constrains('type', 'intrastat_type')
|
||||
def check_intrastat_type(self):
|
||||
for pt in self:
|
||||
if pt.intrastat_type == 'product' and pt.type == 'service':
|
||||
raise ValidationError(_(
|
||||
"On the product %s, you cannot set Product Type to "
|
||||
"'Service' and Intrastat Type to 'Product'.") % pt.name)
|
||||
if pt.intrastat_type == 'service' and pt.type == 'product':
|
||||
raise ValidationError(_(
|
||||
"On the product %s, you cannot set Intrastat Type to "
|
||||
"'Service' and Product Type to 'Stockable product' "
|
||||
"(but you can set Product Type to 'Consumable' or "
|
||||
"'Service').") % pt.name)
|
||||
|
||||
@api.onchange('type')
|
||||
def intrastat_type_onchange(self):
|
||||
if self.type in ('product', 'consu'):
|
||||
self.intrastat_type = 'product'
|
||||
elif self.type == 'service':
|
||||
self.intrastat_type = 'service'
|
||||
|
||||
@api.model
|
||||
def create(self, vals):
|
||||
if vals.get('type'):
|
||||
if not vals.get('intrastat_type'):
|
||||
if vals['type'] in ('product', 'consu'):
|
||||
vals['intrastat_type'] = 'product'
|
||||
elif vals['type'] == 'service':
|
||||
vals['intrastat_type'] = 'service'
|
||||
elif (
|
||||
vals.get('intrastat_type') == 'product' and
|
||||
vals['type'] == 'service'):
|
||||
# usefull because intrastat_type = 'product' by default and
|
||||
# wizards in other modules that don't depend on this module
|
||||
# (e.g. sale_rental) may create a product with only
|
||||
# {'type': 'service'} and no 'intrastat_type'
|
||||
vals['intrastat_type'] = 'service'
|
||||
return super(ProductTemplate, self).create(vals)
|
||||
|
||||
|
||||
class L10nFrIntrastatServiceDeclaration(models.Model):
|
||||
_inherit = "l10n.fr.intrastat.service.declaration"
|
||||
|
||||
def _is_service(self, invoice_line):
|
||||
if invoice_line.product_id.intrastat_type == 'service':
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
class IntrastatProductDeclaration(models.Model):
|
||||
_inherit = 'intrastat.product.declaration'
|
||||
|
||||
def _is_product(self, invoice_line):
|
||||
if (
|
||||
invoice_line.product_id and
|
||||
invoice_line.product_id.intrastat_type == 'product'):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
@@ -1,10 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright 2016-2019 Akretion (Alexis de Lattre <alexis.delattre@akretion.com>)
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
|
||||
|
||||
def set_intrastat_type_on_products(cr, registry):
|
||||
cr.execute(
|
||||
"UPDATE product_template SET intrastat_type='service' "
|
||||
"WHERE type='service'")
|
||||
return
|
||||
@@ -1,23 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2016-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="product_template_form_view" model="ir.ui.view">
|
||||
<field name="name">intrastat_product_type.product.template.form</field>
|
||||
<field name="model">product.template</field>
|
||||
<field name="inherit_id" ref="product.product_template_form_view" />
|
||||
<field name="arch" type="xml">
|
||||
<field name="type" position="after">
|
||||
<field name="intrastat_type"/>
|
||||
</field>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
</odoo>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user