[MERGE/ADD] Many important fixes for contact/company management + new module account_report_company

This patch comes with a corresponding server-side patch (revision 4946 revid: odo@openerp.com-20130420032529-pvv6vuelp84bt26j)


- module-specific overrides of _commercial_fields() for all modules adding accounting/invoicing-related fields to res.partner

- corresponding changes to inherited views of res.partner form to hide these commercial fields when they are in fact "related fields" of their parent commercial entity. This mainly concerns 2 sections of the Partner form: the whole Accounting tab, and the bottom of the Sales&Purchase tabs with the pricelists and invoicing fields. These sections are replaced by a short message and a button to open the commercial entity to view/edit the fields

- a few fixes to properly delegate the resolution of various contact/address types to the corrected res.partner.address_get()

- changes to search views of the main business documents so that searching for a company name will also match its contacts

- a fix of the _find_accounting_partner() method that the account module uses to locate the partner to which journal entries must be linked - it will now use the same semantics as for "commercial entity"

- fix issue detected by Joël Grand-Guillaume in comment #34 of bug 1160365: when invoicing after delivery, the invoicing contact/address must be used rather than the main customer. Tests updated accordingly.

- add new 7.0 module "account_report_company": this module adds an extra stored field "commercial_partner_id" on Invoices to make reporting/aggregating by partner easier in the Invoice list and in the Invoice Analysis report. This module is expected to be merged in the main account module in the next major release. The module can be installed without any risk on any existing 7.0 databases.
This module also mitigates group_by issues on all models by adding a new stored function field `display_name` on res.partner that contains the name_get() result in the form "ACME, John Doe" and set it as the default _order for res.partner. This ensures that group_by entries for the same company will always be next to each other on all documents: "ACME" is directly followed by "ACME, John Doe", "ACME, John Anderson", etc. This field also replaces the `name` field in the list and kanban views of Partners, so that the display order matches the display labels.

- fixed unique constraints definition on some commercial fields on res.partner (l10n_ro)

lp bug: https://launchpad.net/bugs/1160365 fixed

bzr revid: odo@openerp.com-20130420034221-2wvf6rezwl7gog74
This commit is contained in:
Olivier Dony 2013-04-20 05:42:21 +02:00
commit 65ff677697
48 changed files with 403 additions and 57 deletions

View File

@ -1260,9 +1260,7 @@ class account_invoice(osv.osv):
ref = invoice.reference
else:
ref = self._convert_ref(cr, uid, invoice.number)
partner = invoice.partner_id
if partner.parent_id and not partner.is_company:
partner = partner.parent_id
partner = self.pool['res.partner']._find_accounting_partner(invoice.partner_id)
# Pay attention to the sign for both debit/credit AND amount_currency
l1 = {
'debit': direction * pay_amount>0 and direction * pay_amount,
@ -1733,15 +1731,17 @@ class res_partner(osv.osv):
'invoice_ids': fields.one2many('account.invoice.line', 'partner_id', 'Invoices', readonly=True),
}
def _find_accounting_partner(self, part):
def _find_accounting_partner(self, partner):
'''
Find the partner for which the accounting entries will be created
'''
# FIXME: after 7.0, to replace by function field partner.commercial_partner_id
#if the chosen partner is not a company and has a parent company, use the parent for the journal entries
#because you want to invoice 'Agrolait, accounting department' but the journal items are for 'Agrolait'
if part.parent_id and not part.is_company:
part = part.parent_id
return part
while not partner.is_company and partner.parent_id:
partner = partner.parent_id
return partner
def copy(self, cr, uid, id, default=None, context=None):
default = default or {}

View File

@ -320,7 +320,8 @@
<field string="Customer" name="partner_id"
on_change="onchange_partner_id(type,partner_id,date_invoice,payment_term, partner_bank_id,company_id)"
groups="base.group_user" context="{'search_default_customer':1, 'show_address': 1}"
options='{"always_reload": True}'/>
options='{"always_reload": True}'
domain="[('customer', '=', True)]"/>
<field name="fiscal_position" widget="selection" />
</group>
<group>
@ -447,14 +448,14 @@
<field name="model">account.invoice</field>
<field name="arch" type="xml">
<search string="Search Invoice">
<field name="number" string="Invoice" filter_domain="['|','|','|', ('number','ilike',self), ('origin','ilike',self), ('supplier_invoice_number', 'ilike', self), ('partner_id', 'ilike', self)]"/>
<field name="number" string="Invoice" filter_domain="['|','|','|', ('number','ilike',self), ('origin','ilike',self), ('supplier_invoice_number', 'ilike', self), ('partner_id', 'child_of', self)]"/>
<filter name="draft" string="Draft" domain="[('state','=','draft')]" help="Draft Invoices"/>
<filter name="proforma" string="Proforma" domain="[('state','=','proforma2')]" help="Proforma Invoices" groups="account.group_proforma_invoices"/>
<filter name="invoices" string="Invoices" domain="[('state','not in',['draft','cancel'])]" help="Proforma/Open/Paid Invoices"/>
<filter name="unpaid" string="Unpaid" domain="[('state','=','open')]" help="Unpaid Invoices"/>
<separator/>
<filter domain="[('user_id','=',uid)]" help="My Invoices" icon="terp-personal"/>
<field name="partner_id"/>
<field name="partner_id" filter_domain="[('partner_id', 'child_of', self)]"/>
<field name="user_id" string="Salesperson"/>
<field name="period_id" string="Period"/>
<group expand="0" string="Group By...">

View File

@ -236,6 +236,11 @@ class res_partner(osv.osv):
'last_reconciliation_date': fields.datetime('Latest Full Reconciliation Date', help='Date on which the partner accounting entries were fully reconciled last time. It differs from the last date where a reconciliation has been made for this partner, as here we depict the fact that nothing more was to be reconciled at this date. This can be achieved in 2 different ways: either the last unreconciled debit/credit entry of this partner was reconciled, either the user pressed the button "Nothing more to reconcile" during the manual reconciliation process.')
}
def _commercial_fields(self, cr, uid, context=None):
return super(res_partner, self)._commercial_fields(cr, uid, context=context) + \
['debit_limit', 'property_account_payable', 'property_account_receivable', 'property_account_position',
'property_payment_term', 'property_supplier_payment_term', 'last_reconciliation_date']
res_partner()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -73,7 +73,7 @@
<field name="inherit_id" ref="base.view_partner_form"/>
<field name="arch" type="xml">
<page string="History" position="before" version="7.0">
<page string="Accounting" col="4">
<page string="Accounting" col="4" name="accounting" attrs="{'invisible': [('is_company','=',False),('parent_id','!=',False)]}">
<group>
<group>
<field name="property_account_position" widget="selection"/>
@ -103,6 +103,11 @@
</tree>
</field>
</page>
<page string="Accounting" name="accounting_disabled" attrs="{'invisible': ['|',('is_company','=',True),('parent_id','=',False)]}">
<div>
<p>Accounting-related settings are managed on <button name="open_commercial_entity" type="object" string="the parent company" class="oe_link"/></p>
</div>
</page>
</page>
</field>
</record>

View File

@ -31,7 +31,7 @@
<search string="Analytic Account">
<field name="name" filter_domain="['|', ('name','ilike',self), ('code','ilike',self)]" string="Analytic Account"/>
<field name="date"/>
<field name="partner_id"/>
<field name="partner_id" filter_domain="[('partner_id','child_of',self)]"/>
<field name="manager_id"/>
<field name="parent_id"/>
<field name="user_id"/>

View File

@ -186,7 +186,7 @@
<search string="Contracts">
<field name="name" filter_domain="['|', ('name','ilike',self),('code','ilike',self)]" string="Contract"/>
<field name="date"/>
<field name="partner_id"/>
<field name="partner_id" filter_domain="[('partner_id','child_of',self)]"/>
<field name="manager_id"/>
<field name="parent_id"/>
<filter name="open" string="In Progress" domain="[('state','in',('open','draft'))]" help="Contracts in progress (open, draft)"/>

View File

@ -223,7 +223,7 @@
<filter icon="terp-check" string="Current" domain="[('state','in', ('draft','open'))]" help="Assets in draft and open states"/>
<filter icon="terp-dialog-close" string="Closed" domain="[('state','=', 'close')]" help="Assets in closed state"/>
<field name="category_id"/>
<field name="partner_id"/>
<field name="partner_id" filter_domain="[('partner_id','child_of',self)]"/>
</search>
</field>
</record>

View File

@ -49,7 +49,7 @@
<field name="asset_id"/>
<field name="asset_category_id"/>
<group expand="0" string="Extended Filters...">
<field name="partner_id"/>
<field name="partner_id" filter_domain="[('partner_id','child_of',self)]"/>
<field name="company_id" groups="base.group_multi_company"/>
</group>
<group expand="1" string="Group By...">

View File

@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Business Applications
# Copyright (c) 2013 OpenERP S.A. <http://openerp.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import account_report_company
import report
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -0,0 +1,57 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Business Applications
# Copyright (c) 2013 OpenERP S.A. <http://openerp.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
{
'name': 'Invoice Analysis per Company',
'version': '1.0',
'category': 'Accounting & Finance',
'description': """
Add an extra Company dimension on Invoices for consolidated Invoice Analysis
============================================================================
By default Customer and Supplier invoices can be linked to a contact within
a company, but the company is not a direct reference in the database structure for
invoices. Journal Entries are however always linked to the company and not to
contacts, so that Accounts Payable and Receivable are always correct and consolidated
at company level.
When many different contacts/departments need to be invoiced within the same parent company,
this can make reporting by Company more difficult: reports are directly based on the
database structure and would not provide an aggregated company dimension.
This modules solves the problem by adding an explicit company reference on invoices,
automatically computed from the invoice contact, and use this new dimension
when grouping the list of Invoices or the Invoice Analysis report by Partner.
Note: this module will likely be removed for the next major OpenERP version and
directly integrated in the core accounting.
""",
'author': 'OpenERP SA',
'website': 'http://www.openerp.com',
'depends': ['account'],
'data': [
'account_invoice_view.xml',
'res_partner_view.xml',
'report/account_invoice_report_view.xml',
],
'auto_install': True,
}
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -0,0 +1,24 @@
<?xml version="1.0"?>
<openerp>
<data>
<record model="ir.ui.view" id="account_report_company_tree_view">
<field name="model">account.invoice</field>
<field name="inherit_id" ref="account.invoice_tree"/>
<field name="arch" type="xml">
<field name="partner_id" position="after">
<field name="commercial_partner_id" invisible="1"/>
</field>
</field>
</record>
<record model="ir.ui.view" id="account_report_company_search_view">
<field name="model">account.invoice</field>
<field name="inherit_id" ref="account.view_account_invoice_filter"/>
<field name="arch" type="xml">
<filter string="Partner" position="replace">
<filter name="commercial_partner_id" string="Partner" domain="[]" context="{'group_by':'commercial_partner_id'}"/>
</filter>
</field>
</record>
</data>
</openerp>

View File

@ -0,0 +1,51 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Business Applications
# Copyright (c) 2013 S.A. <http://openerp.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from openerp.osv import osv, fields
class res_partner(osv.Model):
_inherit = 'res.partner'
_order = 'display_name'
def _display_name_compute(self, cr, uid, ids, name, args, context=None):
return dict(self.name_get(cr, uid, ids, context=context))
_display_name_store_triggers = {
'res.partner': (lambda self,cr,uid,ids,context=None: self.search(cr, uid, [('id','child_of',ids)]),
['parent_id', 'is_company'], 10)
}
# indirection to avoid passing a copy of the overridable method when declaring the function field
_display_name = lambda self, *args, **kwargs: self._display_name_compute(*args, **kwargs)
_columns = {
# extra field to allow ORDER BY to match visible names
'display_name': fields.function(_display_name, type='char', string='Name', store=_display_name_store_triggers),
}
class account_invoice(osv.Model):
_inherit = 'account.invoice'
_columns = {
'commercial_partner_id': fields.related('partner_id', 'commercial_partner_id', string='Commercial Entity', type='many2one',
relation='res.partner', store=True, readonly=True,
help="The commercial entity that will be used on Journal Entries for this invoice")
}

View File

@ -0,0 +1,24 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Business Applications
# Copyright (c) 2013 OpenERP S.A. <http://openerp.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import account_invoice_report
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -0,0 +1,36 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Business Applications
# Copyright (c) 2013 OpenERP S.A. <http://openerp.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
from openerp.osv import osv, fields
class account_invoice_report(osv.Model):
_inherit = 'account.invoice.report'
_columns = {
'commercial_partner_id': fields.many2one('res.partner', 'Partner Company', help="Commercial Entity"),
}
def _select(self):
return super(account_invoice_report, self)._select() + ", sub.commercial_partner_id as commercial_partner_id"
def _sub_select(self):
return super(account_invoice_report, self)._sub_select() + ", ai.commercial_partner_id as commercial_partner_id"
def _group_by(self):
return super(account_invoice_report, self)._group_by() + ", ai.commercial_partner_id"

View File

@ -0,0 +1,24 @@
<?xml version="1.0"?>
<openerp>
<data>
<record model="ir.ui.view" id="account_report_company_invoice_report_tree_view">
<field name="model">account.invoice.report</field>
<field name="inherit_id" ref="account.view_account_invoice_report_tree"/>
<field name="arch" type="xml">
<field name="partner_id" position="after">
<field name="commercial_partner_id" invisible="1"/>
</field>
</field>
</record>
<record model="ir.ui.view" id="account_report_company_invoice_report_search_view">
<field name="model">account.invoice.report</field>
<field name="inherit_id" ref="account.view_account_invoice_report_search"/>
<field name="arch" type="xml">
<filter name="partner" position="replace">
<filter string="Partner" name="commercial_partner_id" context="{'group_by':'commercial_partner_id','residual_visible':True}"/>
</filter>
</field>
</record>
</data>
</openerp>

View File

@ -0,0 +1,24 @@
<?xml version="1.0"?>
<openerp>
<data>
<record model="ir.ui.view" id="account_report_copmany_partner_tree_view">
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_partner_tree"/>
<field name="arch" type="xml">
<field name="name" position="replace">
<field name="display_name"/>
</field>
</field>
</record>
<record model="ir.ui.view" id="account_report_copmany_partner_kanban_view">
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.res_partner_kanban_view"/>
<field name="arch" type="xml">
<xpath expr="//templates//field[@name='name']" position="replace">
<field name="display_name"/>
</xpath>
</field>
</record>
</data>
</openerp>

View File

@ -129,7 +129,7 @@
<filter icon="terp-camera_test" string="Posted" domain="[('state','=','posted')]" help="Posted Vouchers"/>
<separator/>
<filter icon="terp-gtk-jump-to-ltr" string="To Review" domain="[('state','=','posted'), ('audit','=',False)]" help="To Review"/>
<field name="partner_id"/>
<field name="partner_id" filter_domain="[('partner_id', 'child_of', self)]"/>
<field name="journal_id" context="{'journal_id': self, 'set_visible':False}" />
<field name="period_id"/>
<group expand="0" string="Group By...">

View File

@ -11,7 +11,7 @@
<field name="date"/>
<filter icon="terp-document-new" string="Draft" domain="[('state','=','draft')]" help="Draft Vouchers"/>
<filter icon="terp-camera_test" string="Posted" domain="[('state','=','posted')]" help="Posted Vouchers"/>
<field name="partner_id" string="Customer"/>
<field name="partner_id" string="Customer" filter_domain="[('partner_id','child_of',self)]"/>
<field name="journal_id" context="{'journal_id': self, 'set_visible':False}" domain="[('type','in',('bank','cash'))]"/>
<field name="period_id"/>
<group expand="0" string="Group By...">
@ -34,7 +34,7 @@
<field name="date"/>
<filter icon="terp-document-new" string="Draft" domain="[('state','=','draft')]" help="Draft Vouchers"/>
<filter icon="terp-camera_test" string="Posted" domain="[('state','=','posted')]" help="Posted Vouchers"/>
<field name="partner_id" string="Supplier"/>
<field name="partner_id" string="Supplier" filter_domain="[('partner_id','child_of',self)]"/>
<field name="journal_id" context="{'journal_id': self, 'set_visible':False}" domain="[('type','in',('bank','cash'))]"/>
<field name="period_id"/>
<group expand="0" string="Group By...">

View File

@ -10,7 +10,7 @@
<field name="date"/>
<filter icon="terp-document-new" string="Draft" domain="[('state','=','draft')]" help="Draft Vouchers"/>
<filter icon="terp-camera_test" string="Posted" domain="[('state','=','posted')]" help="Posted Vouchers"/>
<field name="partner_id" string="Supplier"/>
<field name="partner_id" string="Supplier" filter_domain="[('partner_id','child_of',self)]"/>
<field name="journal_id" context="{'journal_id': self, 'set_visible':False}" domain="[('type','in',('purchase','purchase_refund'))]"/>
<field name="period_id"/>
<group expand="0" string="Group By...">
@ -32,7 +32,7 @@
<field name="date"/>
<filter icon="terp-document-new" string="Draft" domain="[('state','=','draft')]" help="Draft Vouchers"/>
<filter icon="terp-camera_test" string="Posted" domain="[('state','=','posted')]" help="Posted Vouchers"/>
<field name="partner_id" string="Customer"/>
<field name="partner_id" string="Customer" filter_domain="[('partner_id','child_of',self)]"/>
<field name="journal_id" context="{'journal_id': self, 'set_visible':False}" domain="[('type','in',('sale','sale_refund'))]"/>
<field name="period_id"/>
<group expand="0" string="Group By...">

View File

@ -134,6 +134,9 @@ class res_partner(osv.osv):
'vat_subjected': fields.boolean('VAT Legal Statement', help="Check this box if the partner is subjected to the VAT. It will be used for the VAT legal statement.")
}
def _commercial_fields(self, cr, uid, context=None):
return super(res_partner, self)._commercial_fields(cr, uid, context=context) + ['vat_subjected']
def _construct_constraint_msg(self, cr, uid, ids, context=None):
def default_vat_check(cn, vn):
# by default, a VAT number is valid if:

View File

@ -328,7 +328,7 @@
<field name="categ_ids" string="Category" filter_domain="[('categ_ids','ilike',self)]"/>
<field name="section_id" context="{'invisible_section': False, 'default_section_id': self}"/>
<field name="user_id"/>
<field name="partner_id"/>
<field name="partner_id" filter_domain="[('partner_id','child_of',self)]"/>
<field name="create_date"/>
<field name="country_id" context="{'invisible_country': False}"/>
<separator/>
@ -546,7 +546,7 @@
<field name="categ_ids" string="Category" filter_domain="[('categ_ids','ilike', self)]"/>
<field name="section_id" context="{'invisible_section': False, 'default_section_id': self}"/>
<field name="user_id"/>
<field name="partner_id"/>
<field name="partner_id" filter_domain="[('partner_id','child_of',self)]"/>
<separator/>
<filter string="New" name="new" domain="[('state','=','draft')]" help="New Opportunities"/>
<filter string="In Progress" name="open" domain="[('state','=','open')]" help="Open Opportunities"/>

View File

@ -185,7 +185,7 @@
<separator/>
<filter string="Phone Calls Assigned to Me or My Team(s)" icon="terp-personal+" domain="['|', ('section_id.user_id','=',uid), ('user_id', '=', uid)]"
help="Phone Calls Assigned to the current user or with a team having the current user as team leader"/>
<field name="partner_id"/>
<field name="partner_id" filter_domain="[('partner_id','child_of',self)]"/>
<field name="user_id"/>
<field name="section_id" string="Sales Team"/>
<group expand="0" string="Group By...">

View File

@ -80,7 +80,7 @@
<field name="section_id" context="{'invisible_section': False}"/>
<field name="user_id" string="Salesperson"/>
<group expand="0" string="Extended Filters...">
<field name="partner_id"/>
<field name="partner_id" filter_domain="[('partner_id','child_of',self)]"/>
<field name="stage_id" domain="[('section_ids', '=', 'section_id')]" />
<field name="type_id"/>
<field name="channel_id"/>

View File

@ -62,7 +62,7 @@
<field name="section_id" string="Sales Team" context="{'invisible_section': False}"/>
<field name="user_id" string="Salesperson"/>
<group expand="0" string="Extended Filters...">
<field name="partner_id"/>
<field name="partner_id" filter_domain="[('partner_id','child_of',self)]"/>
<field name="company_id" groups="base.group_multi_company"/>
<field name="creation_date"/>
<field name="opening_date"/>

View File

@ -201,7 +201,7 @@
<filter icon="terp-gtk-media-pause" string="Pending" domain="[('state','=','pending')]"/>
<separator/>
<filter string="Unassigned Claims" icon="terp-personal-" domain="[('user_id','=', False)]" help="Unassigned Claims" />
<field name="partner_id"/>
<field name="partner_id" filter_domain="[('partner_id','child_of',self)]"/>
<field name="user_id"/>
<group expand="0" string="Group By...">
<filter string="Partner" icon="terp-partner" domain="[]" help="Partner" context="{'group_by':'partner_id'}"/>

View File

@ -63,7 +63,7 @@
<field name="user_id" string="Salesperson"/>
<field name="section_id" string="Sales Team" context="{'invisible_section': False}"/>
<group expand="0" string="Extended Filters...">
<field name="partner_id"/>
<field name="partner_id" filter_domain="[('partner_id','child_of',self)]"/>
<field name="stage_id" domain="[('section_ids', '=', 'section_id')]"/>
<field name="categ_id" domain="[('object_id.model', '=', 'crm.claim')]"/>
<field name="priority"/>

View File

@ -152,7 +152,7 @@
<separator/>
<filter string="Assigned to Me or My Sales Team(s)" icon="terp-personal+" domain="['|', ('section_id.user_id','=',uid), ('section_id.member_ids', 'in', [uid])]"
help="Helpdesk requests that are assigned to me or to one of the sale teams I manage" />
<field name="partner_id" />
<field name="partner_id" filter_domain="[('partner_id','child_of',self)]"/>
<field name="user_id"/>
<field name="section_id" string="Sales Team"/>
<group expand="0" string="Group By...">

View File

@ -62,6 +62,7 @@
<field name="user_id" string="Salesperson"/>
<field name="section_id" string="Sales Team" context="{'invisible_section': False}"/>
<field name="company_id" groups="base.group_multi_company"/>
<field name="partner_id" filter_domain="[('partner_id','child_of',self)]"/>
<group expand="0" string="Extended Filters..." groups="base.group_no_one">
<field name="priority" string="Priority"/>
<field name="categ_id"/>

View File

@ -44,6 +44,11 @@ class res_partner(osv.osv):
help='Select Algorithm to generate the Structured Communication on Outgoing Invoices.' ),
}
def _commercial_fields(self, cr, uid, context=None):
return super(res_partner, self)._commercial_fields(cr, uid, context=context) + \
['out_inv_comm_type', 'out_inv_comm_algorithm']
_default = {
'out_inv_comm_type': 'none',
}

View File

@ -28,10 +28,33 @@ class res_partner(osv.osv):
_columns = {
'nrc' : fields.char('NRC', size=16, help='Registration number at the Registry of Commerce'),
}
# The SQL constraints are no-ops but present only to display the right error message to the
# user when the partial unique indexes defined below raise errors/
# The real constraints need to be implemented with PARTIAL UNIQUE INDEXES (see auto_init),
# due to the way accounting data is delegated by contacts to their companies in OpenERP 7.0.
_sql_constraints = [
('vat_uniq', 'unique (vat)', 'The vat of the partner must be unique !'),
('nrc_uniq', 'unique (nrc)', 'The code of the partner must be unique !')
('vat_uniq', 'unique (id)', 'The vat of the partner must be unique !'),
('nrc_uniq', 'unique (id)', 'The code of the partner must be unique !')
]
def _auto_init(self, cr, context=None):
result = super(res_partner, self)._auto_init(cr, context=context)
# Real implementation of the vat/nrc constraints: only "commercial entities" need to have
# unique numbers, and the condition for being a commercial entity is "is_company or parent_id IS NULL".
# Contacts inside a company automatically have a copy of the company's commercial fields
# (see _commercial_fields()), so they are automatically consistent.
cr.execute("""
DROP INDEX IF EXISTS res_partner_vat_uniq_for_companies;
DROP INDEX IF EXISTS res_partner_nrc_uniq_for_companies;
CREATE UNIQUE INDEX res_partner_vat_uniq_for_companies ON res_partner (vat) WHERE is_company OR parent_id IS NULL;
CREATE UNIQUE INDEX res_partner_nrc_uniq_for_companies ON res_partner (nrc) WHERE is_company OR parent_id IS NULL;
""")
return result
def _commercial_fields(self, cr, uid, context=None):
return super(res_partner, self)._commercial_fields(cr, uid, context=context) + ['nrc']
res_partner()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -210,7 +210,7 @@
<separator/>
<filter icon="terp-dolar" string="Invoiced" domain="[('invoiced','=',True)]"/>
<field name="product_id"/>
<field name="partner_id"/>
<field name="partner_id" filter_domain="[('partner_id', 'child_of', self)]"/>
<group expand="0" string="Group By...">
<filter string="Partner" icon="terp-partner" domain="[]" context="{'group_by':'partner_id'}"/>
<filter string="Product" icon="terp-accessories-archiver" domain="[]" context="{'group_by':'product_id'}"/>

View File

@ -36,6 +36,9 @@ class res_partner(osv.osv):
help="This pricelist will be used, instead of the default one, for sales to the current partner"),
}
def _commercial_fields(self, cr, uid, context=None):
return super(res_partner, self)._commercial_fields(cr, uid, context=context) + ['property_product_pricelist']
res_partner()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -8,9 +8,12 @@
<field name="arch" type="xml">
<page string="Sales &amp; Purchases" position="inside">
<group>
<group name="pricelists" groups="product.group_sale_pricelist">
<group name="pricelists" groups="product.group_sale_pricelist" attrs="{'invisible': [('is_company','=',False),('parent_id','!=',False)]}">
<field name="property_product_pricelist"/>
</group>
<div name="parent_pricelists" groups="product.group_sale_pricelist" attrs="{'invisible': ['|',('is_company','=',True),('parent_id','=',False)]}">
<p>Pricelists are managed on <button name="open_commercial_entity" type="object" string="the parent company" class="oe_link"/></p>
</div>
</group>
</page>
</field>

View File

@ -182,7 +182,7 @@
<separator/>
<filter string="Project(s) Manager" domain="[('user_id','=',uid)]" help="Projects in which I am a manager" icon="terp-personal"/>
<field name="user_id" string="Project Manager"/>
<field name="partner_id" string="Contact"/>
<field name="partner_id" string="Contact" filter_domain="[('partner_id', 'child_of', self)]"/>
<group expand="0" string="Group By...">
<filter string="Manager" name="Manager" icon="terp-personal" domain="[]" context="{'group_by':'user_id'}"/>
<filter string="Contact" name="Partner" icon="terp-partner" domain="[]" context="{'group_by':'partner_id'}"/>

View File

@ -69,7 +69,7 @@
<filter icon="terp-personal-" string="Non Assigned Tasks to users" help="Non Assigned Tasks to users" domain="[('user_id','=',False)]"/>
<field name="project_id"/>
<field name="user_id"/>
<field name="partner_id" />
<field name="partner_id" filter_domain="[('partner_id', 'child_of', self)]"/>
<group expand="0" string="Extended Filters...">
<field name="priority"/>
<field name="company_id" groups="base.group_multi_company"/>

View File

@ -139,7 +139,7 @@
<field name="model">project.issue</field>
<field name="arch" type="xml">
<search string="Issue Tracker Search">
<field name="name" string="Issue" filter_domain="['|', '|',('partner_id','ilike',self),('email_from','ilike',self),('name','ilike',self)]"/>
<field name="name" string="Issue" filter_domain="['|', '|',('partner_id','child_of',self),('email_from','ilike',self),('name','ilike',self)]"/>
<field name="id"/>
<filter icon="terp-mail-message-new" string="Unread Messages" name="message_unread" domain="[('message_unread','=',True)]"/>
<separator/>
@ -150,6 +150,7 @@
<field name="user_id"/>
<field name="project_id"/>
<field name="categ_ids"/>
<field name="partner_id" filter_domain="[('partner_id', 'child_of', self)]"/>
<group expand="0" string="Group By..." >
<filter string="Responsible" icon="terp-personal" domain="[]" context="{'group_by':'user_id'}"/>
<filter string="Contact" icon="terp-partner" domain="[]" context="{'group_by':'partner_id'}"/>

View File

@ -55,7 +55,7 @@
<filter icon="terp-dialog-close" string="Done" domain="[('state','=','done')]"/>
<field name="project_id"/>
<field name="user_id"/>
<field name="partner_id"/>
<field name="partner_id" filter_domain="[('partner_id', 'child_of', self)]"/>
<field name="version_id"/>
<group expand="1" string="Group By...">
<filter string="Assigned to" name="Responsible" icon="terp-personal" domain="[]" context="{'group_by':'user_id'}" />

View File

@ -43,6 +43,9 @@ class res_partner(osv.osv):
super(res_partner, self).copy(cr, uid, id, default=default, context=context)
def _commercial_fields(self, cr, uid, context=None):
return super(res_partner, self)._commercial_fields(cr, uid, context=context) + ['property_product_pricelist_purchase']
_columns = {
'property_product_pricelist_purchase': fields.property(
'product.pricelist',

View File

@ -270,7 +270,7 @@
<filter icon="terp-emblem-important" name="exception" string="Exception" domain="[('state','in',('except_invoice','except_picking'))]" help="Purchase order which are in the exception state"/>
<separator/>
<filter icon="terp-gtk-go-back-rtl" name="not_invoiced" string="Not Invoiced" domain="[('invoice_ids','=', False)]" help="Purchase orders that include lines not invoiced."/>
<field name="partner_id"/>
<field name="partner_id" filter_domain="[('partner_id', 'child_of', self)]"/>
<field name="product_id"/>
<field name="create_uid"/>
<group expand="0" string="Group By...">
@ -297,7 +297,7 @@
<filter icon="terp-emblem-important" name="exception" string="Exception" domain="[('state','in',('except_invoice','except_picking'))]" help="Purchase orders which are in exception state"/>
<separator/>
<filter icon="terp-gtk-go-back-rtl" name="not_invoiced" string="Not Invoiced" domain="[('invoice_ids','=', False)]" help="Purchase orders that include lines not invoiced."/>
<field name="partner_id"/>
<field name="partner_id" filter_domain="[('partner_id', 'child_of', self)]"/>
<field name="product_id"/>
<field name="create_uid"/>
<group expand="0" string="Group By...">
@ -481,7 +481,7 @@
<search string="Search Purchase Order">
<field name="order_id"/>
<field name="product_id"/>
<field name="partner_id" string="Supplier"/>
<field name="partner_id" string="Supplier" filter_domain="[('partner_id', 'child_of', self)]"/>
<group expand="0" string="Group By...">
<filter string="Supplier" icon="terp-partner" domain="[]" context="{'group_by' : 'partner_id'}" />
<filter string="Product" icon="terp-accessories-archiver" domain="[]" context="{'group_by' : 'product_id'}" />

View File

@ -63,14 +63,34 @@
<field name="arch" type="xml">
<xpath expr="//label[@for='type']" position="attributes">
<attribute name="groups">sale.group_delivery_invoice_address</attribute>
</xpath>
<xpath expr="//label[@for='type']" position="attributes">
<attribute name="invisible">False</attribute>
</xpath>
<xpath expr="//div[@name='div_type']" position="attributes">
<attribute name="invisible">False</attribute>
<attribute name="groups">sale.group_delivery_invoice_address</attribute>
</xpath>
<xpath expr="//div[@name='div_type']" position="attributes">
<xpath expr="//field[@name='use_parent_address']" position="attributes">
<attribute name="invisible">False</attribute>
<attribute name="groups">sale.group_delivery_invoice_address</attribute>
</xpath>
<xpath expr="//label[@for='use_parent_address']" position="attributes">
<attribute name="invisible">False</attribute>
<attribute name="groups">sale.group_delivery_invoice_address</attribute>
</xpath>
<xpath expr="//field[@name='child_ids']//field[@name='use_parent_address']" position="attributes">
<attribute name="invisible">False</attribute>
<attribute name="groups">sale.group_delivery_invoice_address</attribute>
</xpath>
<xpath expr="//field[@name='child_ids']//label[@for='use_parent_address']" position="attributes">
<attribute name="invisible">False</attribute>
<attribute name="groups">sale.group_delivery_invoice_address</attribute>
</xpath>
<xpath expr="//field[@name='child_ids']//div[@name='div_type']" position="attributes">
<attribute name="invisible">False</attribute>
<attribute name="groups">sale.group_delivery_invoice_address</attribute>
</xpath>
<xpath expr="//field[@name='child_ids']//label[@for='type']" position="attributes">
<attribute name="invisible">False</attribute>
<attribute name="groups">sale.group_delivery_invoice_address</attribute>
</xpath>
</field>

View File

@ -314,10 +314,6 @@ class sale_order(osv.osv):
return {'value': {'partner_invoice_id': False, 'partner_shipping_id': False, 'payment_term': False, 'fiscal_position': False}}
part = self.pool.get('res.partner').browse(cr, uid, part, context=context)
#if the chosen partner is not a company and has a parent company, use the parent to choose the delivery, the
#invoicing addresses and all the fields related to the partner.
if part.parent_id and not part.is_company:
part = part.parent_id
addr = self.pool.get('res.partner').address_get(cr, uid, [part.id], ['delivery', 'invoice', 'contact'])
pricelist = part.property_product_pricelist and part.property_product_pricelist.id or False
payment_term = part.property_payment_term and part.property_payment_term.id or False

View File

@ -156,7 +156,7 @@
<field name="partner_id" on_change="onchange_partner_id(partner_id, context)" domain="[('customer','=',True)]" context="{'search_default_customer':1, 'show_address': 1}" options='{"always_reload": True}'/>
<field name="partner_invoice_id" groups="sale.group_delivery_invoice_address" context="{'default_type':'invoice'}"/>
<field name="partner_shipping_id" groups="sale.group_delivery_invoice_address" context="{'default_type':'delivery'}"/>
<field name="project_id" context="{'partner_id':partner_id, 'default_pricelist_id':pricelist_id, 'default_name':name, 'default_type': 'contract'}" groups="sale.group_analytic_accounting" domain="[('type','in',['view','normal','contract'])]"/>
<field name="project_id" context="{'partner_id':partner_invoice_id, 'default_pricelist_id':pricelist_id, 'default_name':name, 'default_type': 'contract'}" groups="sale.group_analytic_accounting" domain="[('type','in',['view','normal','contract'])]"/>
</group>
<group>
<field name="date_order"/>
@ -308,7 +308,7 @@
<filter icon="terp-dolar_ok!" string="Done" domain="[('state','=','done')]" help="Sales Order done"/>
<separator/>
<filter string="My Sales Orders" domain="[('user_id','=',uid)]" help="My Sales Orders" icon="terp-personal" name="my_sale_orders_filter"/>
<field name="partner_id"/>
<field name="partner_id" filter_domain="[('partner_id', 'child_of', self)]"/>
<field name="user_id"/>
<field name="project_id"/>
<group expand="0" string="Group By...">
@ -472,7 +472,7 @@
<separator/>
<filter string="My Sales Order Lines" icon="terp-personnal" domain="[('salesman_id','=',uid)]" help="Sales Order Lines related to a Sales Order of mine"/>
<field name="order_id"/>
<field name="order_partner_id"/>
<field name="order_partner_id" filter_domain="[('order_partner_id', 'child_of', self)]"/>
<field name="product_id"/>
<field name="salesman_id"/>
<group expand="0" string="Group By...">
@ -498,7 +498,7 @@
<separator/>
<filter string="My Sales Order Lines" icon="terp-personal" domain="[('salesman_id','=',uid)]" help="My Sales Order Lines"/>
<field name="order_id"/>
<field name="order_partner_id"/>
<field name="order_partner_id" filter_domain="[('order_partner_id', 'child_of', self)]"/>
<field name="product_id"/>
<field name="salesman_id"/>
<group expand="0" string="Group By...">

View File

@ -52,6 +52,10 @@ class res_partner(osv.osv):
group_name = "Accounting Properties",
help = "This invoicing type will be used, by default, to invoice the current partner."),
}
def _commercial_fields(self, cr, uid, context=None):
return super(res_partner, self)._commercial_fields(cr, uid, context=context) + ['property_invoice_type']
res_partner()
class picking(osv.osv):

View File

@ -146,7 +146,7 @@
<field name="inherit_id" ref="base.view_partner_form"/>
<field name="arch" type="xml">
<page string="Sales &amp; Purchases" position="inside">
<group colspan="2" col="2">
<group colspan="2" col="2" attrs="{'invisible': [('is_company','=',False),('parent_id','!=',False)]}">
<separator string="Invoicing" colspan="2"/>
<field name="property_invoice_type"/>
</group>

View File

@ -53,7 +53,7 @@ class stock_picking(osv.osv):
We select the partner of the sales order as the partner of the customer invoice
"""
if picking.sale_id:
return picking.sale_id.partner_id
return picking.sale_id.partner_invoice_id
return super(stock_picking, self)._get_partner_to_invoice(cr, uid, picking, context=context)
def _get_comment_invoice(self, cursor, user, picking):

View File

@ -5,6 +5,12 @@
-
!assert {model: sale.order, id: sale.sale_order_6, string: The amount of the Quotation is not correctly computed}:
- sum([l.price_subtotal for l in order_line]) == amount_untaxed
-
I set an explicit invoicing partner that is different from the main SO Customer
-
!python {model: sale.order, id: sale.sale_order_6}: |
order = self.browse(cr, uid, ref("sale.sale_order_6"))
order.write({'partner_invoice_id': ref('base.res_partner_address_29')})
-
I confirm the quotation with Invoice based on deliveries policy.
-
@ -110,13 +116,13 @@
!python {model: sale.order}: |
order = self.browse(cr, uid, ref("sale.sale_order_6"))
assert order.invoice_ids, "Invoice is not created."
ac = order.partner_id.property_account_receivable.id
ac = order.partner_invoice_id.property_account_receivable.id
journal_ids = self.pool.get('account.journal').search(cr, uid, [('type', '=', 'sale'), ('company_id', '=', order.company_id.id)])
for invoice in order.invoice_ids:
assert invoice.type == 'out_invoice',"Invoice should be Customer Invoice."
assert invoice.account_id.id == ac,"Invoice account is not correspond."
assert invoice.reference == order.client_order_ref or order.name,"Reference is not correspond."
assert invoice.partner_id.id == order.partner_id.id,"Customer is not correspond."
assert invoice.partner_id.id == order.partner_invoice_id.id,"Customer does not correspond."
assert invoice.currency_id.id == order.pricelist_id.currency_id.id, "Currency is not correspond."
assert invoice.comment == (order.note or ''),"Note is not correspond."
assert invoice.journal_id.id in journal_ids,"Sales Journal is not link on Invoice."

View File

@ -149,7 +149,7 @@
<field name="location_id" filter_domain="[('location_id', 'child_of', self)]"/>
<field name="company_id" groups="base.group_multi_company"/>
<group expand="0" string="Extended Filters...">
<field name="partner_id" context="{'contact_display':'partner'}"/>
<field name="partner_id" context="{'contact_display':'partner'}" filter_domain="[('partner_id', 'child_of', self)]"/>
<field name="product_categ_id" />
<field name="prodlot_id"/>
<field name="state"/>

View File

@ -807,7 +807,7 @@
<filter icon="terp-check" name="available" string="Ready" domain="[('state','=','assigned')]" help="Assigned Internal Moves"/>
<filter icon="terp-camera_test" name="confirmed" string="Waiting" domain="[('state','=','confirmed')]" help="Confirmed Internal Moves"/>
<filter icon="terp-dialog-close" name="done" string="Done" domain="[('state','=','done')]" help="Pickings already processed"/>
<field name="partner_id"/>
<field name="partner_id" filter_domain="[('partner_id','child_of',self)]"/>
<field name="product_id"/>
<field name="stock_journal_id"/>
<group expand="0" string="Group By...">
@ -934,6 +934,7 @@
<filter icon="terp-accessories-archiver-minus" string="Back Orders" domain="[('backorder_id', '!=', False)]" help="Is a Back Order"/>
<separator/>
<filter icon="terp-dolar" name="to_invoice" string="To Invoice" domain="[('invoice_state','=','2binvoiced')]" help="Delivery orders to invoice"/>
<field name="partner_id" filter_domain="[('partner_id','child_of',self)]"/>
<field name="stock_journal_id"/>
<field name="company_id" groups="base.group_multi_company"/>
<group expand="0" string="Group By...">
@ -1059,6 +1060,7 @@
<filter icon="terp-accessories-archiver-minus" string="Back Orders" domain="[('backorder_id', '!=', False)]" help="Is a Back Order"/>
<separator/>
<filter string="To Invoice" name="to_invoice" icon="terp-dolar" domain="[('invoice_state', '=', '2binvoiced')]"/>
<field name="partner_id" filter_domain="[('partner_id','child_of',self)]"/>
<field name="stock_journal_id"/>
<field name="product_id"/>
<group expand="0" string="Group By...">
@ -1370,7 +1372,7 @@
<filter icon="terp-go-today" string="Today" domain="[('date','&lt;=',time.strftime('%%Y-%%m-%%d 23:59:59')),('date','&gt;=',time.strftime('%%Y-%%m-%%d 00:00:00'))]" help="Orders processed Today or planned for Today"/>
<field name="product_id"/>
<field name="name" string="Location" filter_domain="['|',('location_id','ilike',self),('location_dest_id','ilike',self)]"/>
<field name="partner_id" string="Partner" filter_domain="[('picking_id.partner_id','ilike',self)]"/>
<field name="partner_id" string="Partner" filter_domain="[('picking_id.partner_id','child_of',self)]"/>
<field name="prodlot_id"/>
<group expand="0" string="Group By...">
<filter string="Product" name="by_product" icon="terp-accessories-archiver" domain="[]" context="{'group_by':'product_id'}"/>