Rename 'sale.agreement' model to 'agreement'

Add type field on 'agreement': 'sale' or 'purchase'
Add agreement_id field on supplier invoices
This commit is contained in:
Alexis de Lattre
2017-09-10 22:56:58 +02:00
parent b795f33d17
commit 90fda6ba73
17 changed files with 140 additions and 84 deletions

View File

@@ -6,34 +6,35 @@
Agreement (Account) Agreement (Account)
=================== ===================
This module adds a *Sale Agreement* object with the following properties: This module adds an *Agreement* object with the following properties:
* link to a customer, * type (*Sale* or *Purchase*),
* link to a partner,
* name, * name,
* code, * code,
* signature date. * signature date.
You can link a customer invoice to a sale agreement. You can link an invoice to an agreement.
If you also install the module *agreement_sale*, you will be able to link a quotation/sale order to an agreement, and this information will be copied to the invoice. If you also install the module *agreement_sale*, you will be able to link a quotation/sale order to an agreement, and this information will be copied to the customer invoice.
A *Sale Agreement* can be used for: An *Agreement* can be used for:
* Private business contracts * Private business contracts
* Public markets * Public markets
It will allow you to group all the orders and invoices related to the same agreement and display the references of this agreement on the documents where you have to display it. For example, the *code* property of the sale agreement is used in the module *account_invoice_factur-x* (from the `edi <https://github.com/OCA/edi>`_ project) in the XML tag */CrossIndustryInvoice/SupplyChainTradeTransaction/ApplicableHeaderTradeAgreement/ContractReferencedDocument/IssuerAssignedID*. It will allow you to group all the orders and invoices related to the same agreement and display the references of this agreement on the documents where you have to display it. For example, the *code* property of the agreement is used in the module *account_invoice_factur-x* (from the `edi <https://github.com/OCA/edi>`_ project) in the XML tag */CrossIndustryInvoice/SupplyChainTradeTransaction/ApplicableHeaderTradeAgreement/ContractReferencedDocument/IssuerAssignedID*.
The main differences with the *Contract* object of Odoo: The main differences with the *Contract* object of Odoo:
* a contract is an analytic account; a sale agreement is not related to analytic accounting. * a contract is an analytic account; an agreement is not related to analytic accounting.
* on the invoice, the contract/analytic account is per-line; a sale agreement is attached to the invoice (not to the lines). * on the invoice, the contract/analytic account is per-line; an agreement is attached to the invoice (not to the lines).
* a sale agreement is a very simple object with just a few basic fields; a contract has a lot of properties and a lot of related features. * an agreement is a very simple object with just a few basic fields; a contract has a lot of properties and a lot of related features.
Configuration Configuration
============= =============
Go to the menu *Accounting > Configuration > Management > Sale Agreements* to create new agreements. Go to the menu *Accounting > Configuration > Management > Agreements* to create new agreements.
Usage Usage
===== =====

View File

@@ -4,7 +4,7 @@
{ {
'name': u'Agreement (Account)', 'name': u'Agreement (Account)',
'summary': "Adds a sale agreement object linked to a customer invoice", 'summary': "Adds an agreement object linked to an invoice",
'version': '10.0.1.0.0', 'version': '10.0.1.0.0',
'category': 'Contract', 'category': 'Contract',
'author': "Akretion,Odoo Community Association (OCA)", 'author': "Akretion,Odoo Community Association (OCA)",
@@ -13,8 +13,8 @@
'depends': ['account'], 'depends': ['account'],
'data': [ 'data': [
'security/ir.model.access.csv', 'security/ir.model.access.csv',
'security/sale_agreement_security.xml', 'security/agreement_security.xml',
'views/sale_agreement.xml', 'views/agreement.xml',
'views/account_invoice.xml', 'views/account_invoice.xml',
], ],
'demo': ['demo/demo.xml'], 'demo': ['demo/demo.xml'],

View File

@@ -7,28 +7,52 @@
<odoo noupdate="1"> <odoo noupdate="1">
<record id="market1" model="sale.agreement"> <record id="market1" model="agreement">
<field name="code">C2C-IT0042</field> <field name="code">C2C-IT0042</field>
<field name="name">Hardware IT</field> <field name="name">Hardware IT</field>
<field name="partner_id" ref="base.res_partner_12"/> <field name="partner_id" ref="base.res_partner_12"/>
<field name="type">sale</field>
<field name="signature_date">2017-09-10</field>
</record> </record>
<record id="market2" model="sale.agreement"> <record id="market2" model="agreement">
<field name="code">C2C-IT0043</field> <field name="code">C2C-IT0043</field>
<field name="name">Fiber access office Lausanne</field> <field name="name">Fiber access office Lausanne</field>
<field name="partner_id" ref="base.res_partner_12"/> <field name="partner_id" ref="base.res_partner_12"/>
<field name="type">sale</field>
<field name="signature_date" eval="time.strftime('%Y-01-01')"/>
</record> </record>
<record id="market3" model="sale.agreement"> <record id="market3" model="agreement">
<field name="code">AGR-VETO001</field> <field name="code">AGR-VETO001</field>
<field name="name">Vétérinaire</field> <field name="name">Vétérinaire</field>
<field name="partner_id" ref="base.res_partner_2"/> <field name="partner_id" ref="base.res_partner_2"/>
<field name="type">sale</field>
<field name="signature_date">2017-08-01</field>
</record> </record>
<record id="market4" model="sale.agreement"> <record id="market4" model="agreement">
<field name="code">AGR-TEL001</field> <field name="code">AGR-TEL001</field>
<field name="name">Wazo IPBX deployment and maintenance</field> <field name="name">Wazo IPBX deployment and maintenance</field>
<field name="partner_id" ref="base.res_partner_2"/> <field name="partner_id" ref="base.res_partner_2"/>
<field name="type">sale</field>
<field name="signature_date">2017-05-05</field>
</record>
<record id="market5" model="agreement">
<field name="code">BUY-VOIP012</field>
<field name="name">SIP Phones supply</field>
<field name="partner_id" ref="base.res_partner_1"/>
<field name="type">purchase</field>
<field name="signature_date" eval="time.strftime('%Y-01-01')"/>
</record>
<record id="market6" model="agreement">
<field name="code">BUY-VOIP013</field>
<field name="name">SIP-ISDN gateways</field>
<field name="partner_id" ref="base.res_partner_3"/>
<field name="type">purchase</field>
<field name="signature_date">2017-09-02</field>
</record> </record>

View File

@@ -1,4 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from . import sale_agreement from . import agreement
from . import account_invoice from . import account_invoice

View File

@@ -9,8 +9,8 @@ from odoo import models, fields, api
class AccountInvoice(models.Model): class AccountInvoice(models.Model):
_inherit = 'account.invoice' _inherit = 'account.invoice'
sale_agreement_id = fields.Many2one( agreement_id = fields.Many2one(
'sale.agreement', string='Sale Agreement', ondelete='restrict', 'agreement', string='Agreement', ondelete='restrict',
readonly=True, states={'draft': [('readonly', False)]}, readonly=True, states={'draft': [('readonly', False)]},
track_visibility='onchange') track_visibility='onchange')
@@ -21,6 +21,6 @@ class AccountInvoice(models.Model):
values = super(AccountInvoice, self)._prepare_refund( values = super(AccountInvoice, self)._prepare_refund(
invoice, date_invoice=date_invoice, date=date, invoice, date_invoice=date_invoice, date=date,
description=description, journal_id=journal_id) description=description, journal_id=journal_id)
if invoice.sale_agreement_id: if invoice.agreement_id:
values['sale_agreement_id'] = invoice.sale_agreement_id.id values['agreement_id'] = invoice.agreement_id.id
return values return values

View File

@@ -6,25 +6,32 @@
from odoo import models, fields from odoo import models, fields
class SaleAgreement(models.Model): class Agreement(models.Model):
_name = 'sale.agreement' _name = 'agreement'
_description = 'Sale Agreement' _description = 'Agreement'
code = fields.Char( code = fields.Char(
string='Code', required=True, copy=False) string='Code', required=True, copy=False)
name = fields.Char(string='Name', required=True) name = fields.Char(string='Name', required=True)
type = fields.Selection([
('sale', 'Sale'),
('purchase', 'Purchase'),
], string='Type', required=True)
partner_id = fields.Many2one( partner_id = fields.Many2one(
'res.partner', string='Customer', ondelete='restrict', required=True, 'res.partner', string='Partner', ondelete='restrict', required=True,
domain=[('customer', '=', True), ('parent_id', '=', False)]) domain=[('parent_id', '=', False)])
company_id = fields.Many2one( company_id = fields.Many2one(
'res.company', string='Company', 'res.company', string='Company',
default=lambda self: self.env['res.company']._company_default_get( default=lambda self: self.env['res.company']._company_default_get(
'sale.agreement')) 'agreement'))
active = fields.Boolean(string='Active', default=True) active = fields.Boolean(string='Active', default=True)
signature_date = fields.Date(string='Signature Date') signature_date = fields.Date(string='Signature Date')
invoice_ids = fields.One2many( out_invoice_ids = fields.One2many(
'account.invoice', 'sale_agreement_id', string='Invoices', 'account.invoice', 'agreement_id', string='Customer Invoices',
readonly=True) readonly=True, domain=[('type', 'in', ('out_invoice', 'out_refund'))])
in_invoice_ids = fields.One2many(
'account.invoice', 'agreement_id', string='Supplier Invoices',
readonly=True, domain=[('type', 'in', ('in_invoice', 'in_refund'))])
def name_get(self): def name_get(self):
res = [] res = []
@@ -38,5 +45,5 @@ class SaleAgreement(models.Model):
_sql_constraints = [( _sql_constraints = [(
'code_partner_company_unique', 'code_partner_company_unique',
'unique(code, partner_id, company_id)', 'unique(code, partner_id, company_id)',
'This sale agreement code already exists for this customer!' 'This agreement code already exists for this partner!'
)] )]

View File

@@ -7,9 +7,9 @@
<odoo noupdate="1"> <odoo noupdate="1">
<record id="sale_agreement_rule" model="ir.rule"> <record id="agreement_rule" model="ir.rule">
<field name="name">Sale Agreement multi-company</field> <field name="name">Agreement multi-company</field>
<field name="model_id" ref="model_sale_agreement"/> <field name="model_id" ref="model_agreement"/>
<field name="domain_force">['|', ('company_id', '=', False), ('company_id', 'child_of', [user.company_id.id])]</field> <field name="domain_force">['|', ('company_id', '=', False), ('company_id', 'child_of', [user.company_id.id])]</field>
</record> </record>

View File

@@ -1,3 +1,3 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_sale_agreement_read,Read access on sale.agreement to Employees,model_sale_agreement,base.group_user,1,0,0,0 access_agreement_read,Read access on agreement to Employees,model_agreement,base.group_user,1,0,0,0
access_sale_agreement_full,Full access on sale.agreement to Invoicing and Payment grp,model_sale_agreement,account.group_account_invoice,1,1,1,1 access_agreement_full,Full access on agreement to Invoicing and Payment grp,model_agreement,account.group_account_invoice,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_sale_agreement_read access_agreement_read Read access on sale.agreement to Employees Read access on agreement to Employees model_sale_agreement model_agreement base.group_user 1 0 0 0
3 access_sale_agreement_full access_agreement_full Full access on sale.agreement to Invoicing and Payment grp Full access on agreement to Invoicing and Payment grp model_sale_agreement model_agreement account.group_account_invoice 1 1 1 1

View File

@@ -8,27 +8,41 @@
<record id="invoice_form" model="ir.ui.view"> <record id="invoice_form" model="ir.ui.view">
<field name="name">sale.agreement.account.invoice.form</field> <field name="name">agreement.customer.invoice.form</field>
<field name="model">account.invoice</field> <field name="model">account.invoice</field>
<field name="inherit_id" ref="account.invoice_form"/> <field name="inherit_id" ref="account.invoice_form"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<xpath expr="//page/group/group/field[@name='name']" position="after"> <xpath expr="//page/group/group/field[@name='name']" position="after">
<field name="sale_agreement_id" <field name="agreement_id"
domain="[('partner_id', 'child_of', commercial_partner_id)]" domain="[('partner_id', 'child_of', commercial_partner_id), ('type', '=', 'sale')]"
context="{'default_partner_id': commercial_partner_id}"/> context="{'default_partner_id': commercial_partner_id, 'default_type': 'sale'}"/>
<field name="commercial_partner_id" invisible="1"/>
</xpath>
</field>
</record>
<record id="invoice_supplier_form" model="ir.ui.view">
<field name="name">agreement.supplier.invoice.form</field>
<field name="model">account.invoice</field>
<field name="inherit_id" ref="account.invoice_supplier_form"/>
<field name="arch" type="xml">
<xpath expr="//page/group/group/field[@name='company_id']" position="after">
<field name="agreement_id"
domain="[('partner_id', 'child_of', commercial_partner_id), ('type', '=', 'purchase')]"
context="{'default_partner_id': commercial_partner_id, 'default_type': 'purchase'}"/>
<field name="commercial_partner_id" invisible="1"/> <field name="commercial_partner_id" invisible="1"/>
</xpath> </xpath>
</field> </field>
</record> </record>
<record id="view_account_invoice_filter" model="ir.ui.view"> <record id="view_account_invoice_filter" model="ir.ui.view">
<field name="name">sale.agreement.account.invoice.search</field> <field name="name">agreement.account.invoice.search</field>
<field name="model">account.invoice</field> <field name="model">account.invoice</field>
<field name="inherit_id" ref="account.view_account_invoice_filter"/> <field name="inherit_id" ref="account.view_account_invoice_filter"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<group expand="0" position="inside"> <group expand="0" position="inside">
<filter string="Sale Agreements" name="sale_agreement_groupby" <filter string="Agreement" name="agreement_groupby"
context="{'group_by': 'sale_agreement_id'}"/> context="{'group_by': 'agreement_id'}"/>
</group> </group>
</field> </field>
</record> </record>

View File

@@ -7,11 +7,11 @@
<odoo> <odoo>
<record id="sale_agreement_form" model="ir.ui.view"> <record id="agreement_form" model="ir.ui.view">
<field name="name">sale.agreement.form</field> <field name="name">agreement.form</field>
<field name="model">sale.agreement</field> <field name="model">agreement</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<form string="Sale Agreement"> <form string="Agreement">
<div class="oe_button_box" name="button_box"> <div class="oe_button_box" name="button_box">
<button name="toggle_active" type="object" <button name="toggle_active" type="object"
class="oe_stat_button" icon="fa-archive"> class="oe_stat_button" icon="fa-archive">
@@ -23,55 +23,65 @@
<field name="partner_id"/> <field name="partner_id"/>
<field name="name"/> <field name="name"/>
<field name="code"/> <field name="code"/>
<field name="type"/>
<field name="signature_date"/> <field name="signature_date"/>
<field name="company_id" groups="base.group_multi_company"/> <field name="company_id" groups="base.group_multi_company"/>
</group> </group>
<group string="Invoices" name="invoices"> <group string="Customer Invoices" name="out_invoices" attrs="{'invisible': [('type', '!=', 'sale')]}">
<field name="invoice_ids" nolabel="1"/> <field name="out_invoice_ids" nolabel="1"/>
</group>
<group string="Supplier Invoices" name="in_invoices" attrs="{'invisible': [('type', '!=', 'purchase')]}">
<field name="in_invoice_ids" nolabel="1"/>
</group> </group>
</form> </form>
</field> </field>
</record> </record>
<record id="sale_agreement_tree" model="ir.ui.view"> <record id="agreement_tree" model="ir.ui.view">
<field name="name">sale.agreement.tree</field> <field name="name">agreement.tree</field>
<field name="model">sale.agreement</field> <field name="model">agreement</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<tree string="Sale Agreements"> <tree string="Agreements">
<field name="partner_id"/> <field name="partner_id"/>
<field name="code"/> <field name="code"/>
<field name="name"/> <field name="name"/>
<field name="type"/>
<field name="signature_date"/> <field name="signature_date"/>
<field name="company_id" groups="base.group_multi_company"/> <field name="company_id" groups="base.group_multi_company"/>
</tree> </tree>
</field> </field>
</record> </record>
<record id="sale_agreement_search" model="ir.ui.view"> <record id="agreement_search" model="ir.ui.view">
<field name="name">sale.agreement.search</field> <field name="name">agreement.search</field>
<field name="model">sale.agreement</field> <field name="model">agreement</field>
<field name="arch" type="xml"> <field name="arch" type="xml">
<search string="Search Sale Agreements"> <search string="Search Agreements">
<field name="name" filter_domain="['|', ('name', 'ilike', self), ('code', 'ilike', self)]" string="Name or Number"/> <field name="name" filter_domain="['|', ('name', 'ilike', self), ('code', 'ilike', self)]" string="Name or Number"/>
<field name="partner_id"/> <field name="partner_id"/>
<filter name="sale" string="Sale" domain="[('type', '=', 'sale')]"/>
<filter name="purchase" string="Purchase" domain="[('type', '=', 'purchase')]"/>
<separator/>
<filter name="inactive" string="Archived" domain="[('active', '=', False)]"/> <filter name="inactive" string="Archived" domain="[('active', '=', False)]"/>
<group name="groupby"> <group name="groupby">
<filter name="partner_groupby" string="Customer" <filter name="partner_groupby" string="Customer"
context="{'group_by': 'partner_id'}"/> context="{'group_by': 'partner_id'}"/>
<filter name="signature_date_groupby" string="Signature Date" <filter name="signature_date_groupby" string="Signature Date"
context="{'group_by': 'signature_date'}"/> context="{'group_by': 'signature_date'}"/>
<filter name="type_groupby" string="Type"
context="{'group_by': 'type'}"/>
</group> </group>
</search> </search>
</field> </field>
</record> </record>
<record id="sale_agreement_action" model="ir.actions.act_window"> <record id="agreement_action" model="ir.actions.act_window">
<field name="name">Sale Agreements</field> <field name="name">Agreements</field>
<field name="res_model">sale.agreement</field> <field name="res_model">agreement</field>
<field name="view_mode">tree,form</field> <field name="view_mode">tree,form</field>
</record> </record>
<menuitem id="sale_agreement_menu" action="sale_agreement_action" <menuitem id="agreement_menu" action="agreement_action"
parent="account.account_management_menu" sequence="100"/> parent="account.account_management_menu" sequence="100"/>
</odoo> </odoo>

View File

@@ -4,7 +4,7 @@
{ {
'name': u'Agreement (Sale)', 'name': u'Agreement (Sale)',
'summary': "Link a sale agreement to a sale order and copy to invoice", 'summary': "Link an agreement to a sale order and copy to invoice",
'version': '10.0.1.0.0', 'version': '10.0.1.0.0',
'category': 'Contract', 'category': 'Contract',
'author': "Akretion,Odoo Community Association (OCA)", 'author': "Akretion,Odoo Community Association (OCA)",
@@ -16,7 +16,7 @@
], ],
'data': [ 'data': [
'views/sale_order.xml', 'views/sale_order.xml',
'views/sale_agreement.xml', 'views/agreement.xml',
], ],
'installable': True, 'installable': True,
'auto_install': True, 'auto_install': True,

View File

@@ -1,4 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from . import sale_order from . import sale_order
from . import sale_agreement from . import agreement

View File

@@ -6,9 +6,9 @@
from odoo import models, fields from odoo import models, fields
class SaleAgreement(models.Model): class Agreement(models.Model):
_inherit = 'sale.agreement' _inherit = 'agreement'
sale_ids = fields.One2many( sale_ids = fields.One2many(
'sale.order', 'sale_agreement_id', string='Sale Orders', readonly=True, 'sale.order', 'agreement_id', string='Sale Orders', readonly=True,
domain=[('state', 'not in', ('draft', 'sent', 'cancel'))]) domain=[('state', 'not in', ('draft', 'sent', 'cancel'))])

View File

@@ -9,12 +9,12 @@ from odoo import models, fields
class SaleOrder(models.Model): class SaleOrder(models.Model):
_inherit = 'sale.order' _inherit = 'sale.order'
sale_agreement_id = fields.Many2one( agreement_id = fields.Many2one(
'sale.agreement', string='Sale Agreement', ondelete='restrict', 'agreement', string='Agreement', ondelete='restrict',
track_visibility='onchange', readonly=True, track_visibility='onchange', readonly=True,
states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}) states={'draft': [('readonly', False)], 'sent': [('readonly', False)]})
def _prepare_invoice(self): def _prepare_invoice(self):
vals = super(SaleOrder, self)._prepare_invoice() vals = super(SaleOrder, self)._prepare_invoice()
vals['sale_agreement_id'] = self.sale_agreement_id.id or False vals['agreement_id'] = self.agreement_id.id or False
return vals return vals

View File

@@ -7,12 +7,12 @@
<odoo> <odoo>
<record id="sale_agreement_form" model="ir.ui.view"> <record id="agreement_form" model="ir.ui.view">
<field name="name">sale.agreement.form</field> <field name="name">agreement.form</field>
<field name="model">sale.agreement</field> <field name="model">agreement</field>
<field name="inherit_id" ref="agreement_account.sale_agreement_form"/> <field name="inherit_id" ref="agreement_account.agreement_form"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<group name="invoices" position="after"> <group name="in_invoices" position="after">
<group name="sale_orders" string="Sales Orders"> <group name="sale_orders" string="Sales Orders">
<field name="sale_ids" nolabel="1"/> <field name="sale_ids" nolabel="1"/>
</group> </group>

View File

@@ -8,25 +8,25 @@
<record id="view_order_form" model="ir.ui.view"> <record id="view_order_form" model="ir.ui.view">
<field name="name">sale.agreement.sale.order.form</field> <field name="name">agreement.sale.order.form</field>
<field name="model">sale.order</field> <field name="model">sale.order</field>
<field name="inherit_id" ref="sale_commercial_partner.view_order_form"/> <field name="inherit_id" ref="sale_commercial_partner.view_order_form"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<field name="client_order_ref" position="after"> <field name="client_order_ref" position="after">
<field name="sale_agreement_id" <field name="agreement_id"
domain="[('partner_id', 'child_of', commercial_partner_id)]" domain="[('partner_id', 'child_of', commercial_partner_id), ('type', '=', sale')]"
context="{'default_partner_id': commercial_partner_id}"/> context="{'default_partner_id': commercial_partner_id, 'default_type', 'sale'}"/>
</field> </field>
</field> </field>
</record> </record>
<record id="view_sales_order_filter" model="ir.ui.view"> <record id="view_sales_order_filter" model="ir.ui.view">
<field name="name">sale.agreement.sale.order.search</field> <field name="name">agreement.sale.order.search</field>
<field name="model">sale.order</field> <field name="model">sale.order</field>
<field name="inherit_id" ref="sale.view_sales_order_filter"/> <field name="inherit_id" ref="sale.view_sales_order_filter"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<group expand="0" position="inside"> <group expand="0" position="inside">
<filter string="Sale Agreement" name="sale_agreement_groupby" context="{'group_by': 'sale_agreement_id'}"/> <filter string="Agreement" name="agreement_groupby" context="{'group_by': 'agreement_id'}"/>
</group> </group>
</field> </field>
</record> </record>

View File

@@ -12,6 +12,6 @@ class SaleAdvancePaymentInv(models.TransientModel):
def _create_invoice(self, order, so_line, amount): def _create_invoice(self, order, so_line, amount):
inv = super(SaleAdvancePaymentInv, self)._create_invoice( inv = super(SaleAdvancePaymentInv, self)._create_invoice(
order, so_line, amount) order, so_line, amount)
if order.sale_agreement_id: if order.agreement_id:
inv.sale_agreement_id = order.sale_agreement_id.id inv.agreement_id = order.agreement_id.id
return inv return inv