Browse Source
[IMP][10.0] contract: Add templating (#42)
[IMP][10.0] contract: Add templating (#42)
Add template functionality for contractspull/121/head
Dave Lasley
8 years ago
committed by
Pedro M. Baeza
12 changed files with 392 additions and 164 deletions
-
1contract/README.rst
-
12contract/__manifest__.py
-
7contract/models/__init__.py
-
161contract/models/account_analytic_account.py
-
71contract/models/account_analytic_contract.py
-
87contract/models/account_analytic_invoice_line.py
-
0contract/models/account_invoice.py
-
3contract/security/ir.model.access.csv
-
19contract/tests/test_contract.py
-
65contract/views/account_analytic_account_view.xml
-
118contract/views/account_analytic_contract_view.xml
-
12contract/views/account_invoice_view.xml
@ -1,6 +1,7 @@ |
|||||
# -*- coding: utf-8 -*- |
# -*- coding: utf-8 -*- |
||||
# © 2016 Carlos Dauden <carlos.dauden@tecnativa.com> |
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). |
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). |
||||
|
|
||||
from . import contract |
|
||||
from . import invoice |
|
||||
|
from . import account_analytic_contract |
||||
|
from . import account_analytic_account |
||||
|
from . import account_analytic_invoice_line |
||||
|
from . import account_invoice |
@ -0,0 +1,71 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# © 2004-2010 OpenERP SA |
||||
|
# © 2014 Angel Moya <angel.moya@domatix.com> |
||||
|
# © 2015 Pedro M. Baeza <pedro.baeza@tecnativa.com> |
||||
|
# © 2016 Carlos Dauden <carlos.dauden@tecnativa.com> |
||||
|
# Copyright 2016-2017 LasLabs Inc. |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). |
||||
|
|
||||
|
from odoo import api, fields, models |
||||
|
|
||||
|
|
||||
|
class AccountAnalyticContract(models.Model): |
||||
|
_name = 'account.analytic.contract' |
||||
|
|
||||
|
# These fields will not be synced to the contract |
||||
|
NO_SYNC = [ |
||||
|
'name', |
||||
|
] |
||||
|
|
||||
|
name = fields.Char( |
||||
|
required=True, |
||||
|
) |
||||
|
pricelist_id = fields.Many2one( |
||||
|
comodel_name='product.pricelist', |
||||
|
string='Pricelist', |
||||
|
) |
||||
|
recurring_invoice_line_ids = fields.One2many( |
||||
|
comodel_name='account.analytic.invoice.line', |
||||
|
inverse_name='analytic_account_id', |
||||
|
copy=True, |
||||
|
string='Invoice Lines', |
||||
|
) |
||||
|
recurring_rule_type = fields.Selection( |
||||
|
[('daily', 'Day(s)'), |
||||
|
('weekly', 'Week(s)'), |
||||
|
('monthly', 'Month(s)'), |
||||
|
('monthlylastday', 'Month(s) last day'), |
||||
|
('yearly', 'Year(s)'), |
||||
|
], |
||||
|
default='monthly', |
||||
|
string='Recurrence', |
||||
|
help="Specify Interval for automatic invoice generation.", |
||||
|
) |
||||
|
recurring_invoicing_type = fields.Selection( |
||||
|
[('pre-paid', 'Pre-paid'), |
||||
|
('post-paid', 'Post-paid'), |
||||
|
], |
||||
|
default='pre-paid', |
||||
|
string='Invoicing type', |
||||
|
help="Specify if process date is 'from' or 'to' invoicing date", |
||||
|
) |
||||
|
recurring_interval = fields.Integer( |
||||
|
default=1, |
||||
|
string='Repeat Every', |
||||
|
help="Repeat every (Days/Week/Month/Year)", |
||||
|
) |
||||
|
journal_id = fields.Many2one( |
||||
|
'account.journal', |
||||
|
string='Journal', |
||||
|
default=lambda s: s._default_journal(), |
||||
|
domain="[('type', '=', 'sale'),('company_id', '=', company_id)]", |
||||
|
) |
||||
|
|
||||
|
@api.model |
||||
|
def _default_journal(self): |
||||
|
company_id = self.env.context.get( |
||||
|
'company_id', self.env.user.company_id.id) |
||||
|
domain = [ |
||||
|
('type', '=', 'sale'), |
||||
|
('company_id', '=', company_id)] |
||||
|
return self.env['account.journal'].search(domain, limit=1) |
@ -0,0 +1,87 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# © 2004-2010 OpenERP SA |
||||
|
# © 2014 Angel Moya <angel.moya@domatix.com> |
||||
|
# © 2015 Pedro M. Baeza <pedro.baeza@tecnativa.com> |
||||
|
# © 2016 Carlos Dauden <carlos.dauden@tecnativa.com> |
||||
|
# Copyright 2016 LasLabs Inc. |
||||
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). |
||||
|
|
||||
|
from odoo import api, fields, models |
||||
|
from odoo.addons import decimal_precision as dp |
||||
|
from odoo.exceptions import ValidationError |
||||
|
from odoo.tools.translate import _ |
||||
|
|
||||
|
|
||||
|
class AccountAnalyticInvoiceLine(models.Model): |
||||
|
_name = 'account.analytic.invoice.line' |
||||
|
|
||||
|
product_id = fields.Many2one( |
||||
|
'product.product', string='Product', required=True) |
||||
|
analytic_account_id = fields.Many2one( |
||||
|
'account.analytic.account', string='Analytic Account') |
||||
|
name = fields.Text(string='Description', required=True) |
||||
|
quantity = fields.Float(default=1.0, required=True) |
||||
|
uom_id = fields.Many2one( |
||||
|
'product.uom', string='Unit of Measure', required=True) |
||||
|
price_unit = fields.Float('Unit Price', required=True) |
||||
|
price_subtotal = fields.Float( |
||||
|
compute='_compute_price_subtotal', |
||||
|
digits=dp.get_precision('Account'), |
||||
|
string='Sub Total') |
||||
|
discount = fields.Float( |
||||
|
string='Discount (%)', |
||||
|
digits=dp.get_precision('Discount'), |
||||
|
help='Discount that is applied in generated invoices.' |
||||
|
' It should be less or equal to 100') |
||||
|
|
||||
|
@api.multi |
||||
|
@api.depends('quantity', 'price_unit', 'discount') |
||||
|
def _compute_price_subtotal(self): |
||||
|
for line in self: |
||||
|
subtotal = line.quantity * line.price_unit |
||||
|
discount = line.discount / 100 |
||||
|
subtotal *= 1 - discount |
||||
|
if line.analytic_account_id.pricelist_id: |
||||
|
cur = line.analytic_account_id.pricelist_id.currency_id |
||||
|
line.price_subtotal = cur.round(subtotal) |
||||
|
else: |
||||
|
line.price_subtotal = subtotal |
||||
|
|
||||
|
@api.multi |
||||
|
@api.constrains('discount') |
||||
|
def _check_discount(self): |
||||
|
for line in self: |
||||
|
if line.discount > 100: |
||||
|
raise ValidationError( |
||||
|
_("Discount should be less or equal to 100")) |
||||
|
|
||||
|
@api.multi |
||||
|
@api.onchange('product_id') |
||||
|
def _onchange_product_id(self): |
||||
|
if not self.product_id: |
||||
|
return {'domain': {'uom_id': []}} |
||||
|
|
||||
|
vals = {} |
||||
|
domain = {'uom_id': [ |
||||
|
('category_id', '=', self.product_id.uom_id.category_id.id)]} |
||||
|
if not self.uom_id or (self.product_id.uom_id.category_id.id != |
||||
|
self.uom_id.category_id.id): |
||||
|
vals['uom_id'] = self.product_id.uom_id |
||||
|
|
||||
|
product = self.product_id.with_context( |
||||
|
lang=self.analytic_account_id.partner_id.lang, |
||||
|
partner=self.analytic_account_id.partner_id.id, |
||||
|
quantity=self.quantity, |
||||
|
date=self.analytic_account_id.recurring_next_date, |
||||
|
pricelist=self.analytic_account_id.pricelist_id.id, |
||||
|
uom=self.uom_id.id |
||||
|
) |
||||
|
|
||||
|
name = product.name_get()[0][1] |
||||
|
if product.description_sale: |
||||
|
name += '\n' + product.description_sale |
||||
|
vals['name'] = name |
||||
|
|
||||
|
vals['price_unit'] = product.price |
||||
|
self.update(vals) |
||||
|
return {'domain': domain} |
@ -1,4 +1,5 @@ |
|||||
"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" |
||||
|
"account_analytic_contract_manager","Recurring manager","model_account_analytic_contract","account.group_account_manager",1,1,1,1 |
||||
|
"account_analytic_contract_user","Recurring user","model_account_analytic_contract","account.group_account_user",1,0,0,0 |
||||
"account_analytic_invoice_line_manager","Recurring manager","model_account_analytic_invoice_line","account.group_account_manager",1,1,1,1 |
"account_analytic_invoice_line_manager","Recurring manager","model_account_analytic_invoice_line","account.group_account_manager",1,1,1,1 |
||||
"account_analytic_invoice_line_user","Recurring user","model_account_analytic_invoice_line","account.group_account_user",1,0,0,0 |
"account_analytic_invoice_line_user","Recurring user","model_account_analytic_invoice_line","account.group_account_user",1,0,0,0 |
||||
|
|
@ -0,0 +1,118 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<odoo> |
||||
|
|
||||
|
<record id="account_analytic_contract_view_form" model="ir.ui.view"> |
||||
|
<field name="name">Account Analytic Contract Form View</field> |
||||
|
<field name="model">account.analytic.contract</field> |
||||
|
<field name="arch" type="xml"> |
||||
|
<form string="Contract Template"> |
||||
|
<group name="group_main"> |
||||
|
<field name="name" /> |
||||
|
<group name="group_main_left"> |
||||
|
<field name="journal_id" /> |
||||
|
<field name="pricelist_id" /> |
||||
|
</group> |
||||
|
<group name="group_main_right"> |
||||
|
<field name="recurring_invoicing_type" /> |
||||
|
<label for="recurring_interval" /> |
||||
|
<div> |
||||
|
<field name="recurring_interval" |
||||
|
class="oe_inline" |
||||
|
required="True" |
||||
|
/> |
||||
|
<field name="recurring_rule_type" |
||||
|
class="oe_inline" |
||||
|
required="True" |
||||
|
/> |
||||
|
</div> |
||||
|
</group> |
||||
|
</group> |
||||
|
<group name="group_invoice_lines" string="Invoice Lines"> |
||||
|
<field name="recurring_invoice_line_ids"> |
||||
|
<tree string="Account Analytic Lines" editable="bottom"> |
||||
|
<field name="product_id" /> |
||||
|
<field name="name" /> |
||||
|
<field name="quantity" /> |
||||
|
<field name="uom_id" /> |
||||
|
<field name="price_unit" /> |
||||
|
<field name="discount" groups="sale.group_discount_per_so_line" /> |
||||
|
<field name="price_subtotal" /> |
||||
|
</tree> |
||||
|
</field> |
||||
|
</group> |
||||
|
<group name="group_legend" |
||||
|
string="Legend (for the markers inside invoice lines description)" |
||||
|
> |
||||
|
<p> <strong>#START#</strong>: Start date of the invoiced period</p> |
||||
|
<p> <strong>#END#</strong>: End date of the invoiced period</p> |
||||
|
</group> |
||||
|
</form> |
||||
|
</field> |
||||
|
</record> |
||||
|
|
||||
|
<record id="account_analytic_contract_view_tree" model="ir.ui.view"> |
||||
|
<field name="name">Account Analytic Contract Tree View</field> |
||||
|
<field name="model">account.analytic.contract</field> |
||||
|
<field name="arch" type="xml"> |
||||
|
<tree string="Contract Templates"> |
||||
|
<field name="name" /> |
||||
|
<field name="recurring_rule_type" /> |
||||
|
<field name="recurring_interval" /> |
||||
|
<field name="recurring_invoicing_type" /> |
||||
|
<field name="pricelist_id" /> |
||||
|
</tree> |
||||
|
</field> |
||||
|
</record> |
||||
|
|
||||
|
<record id="account_analytic_contract_view_search" model="ir.ui.view"> |
||||
|
<field name="name">Account Analytic Contract Search View</field> |
||||
|
<field name="model">account.analytic.contract</field> |
||||
|
<field name="arch" type="xml"> |
||||
|
<search string="Contract Templates"> |
||||
|
<field name="name" /> |
||||
|
<field name="recurring_rule_type" /> |
||||
|
<field name="recurring_interval" /> |
||||
|
<field name="recurring_invoicing_type" /> |
||||
|
<field name="pricelist_id" /> |
||||
|
<field name="journal_id" /> |
||||
|
<filter string="Recurrence" |
||||
|
context="{'group_by': 'recurring_rule_type'}" |
||||
|
/> |
||||
|
<filter string="Invoicing Type" |
||||
|
context="{'group_by': 'recurring_invoicing_type'}" |
||||
|
/> |
||||
|
<filter string="Pricelist" |
||||
|
context="{'group_by': 'pricelist_id'}" |
||||
|
/> |
||||
|
<filter string="Journal" |
||||
|
context="{'group_by': 'journal_id'}" |
||||
|
/> |
||||
|
</search> |
||||
|
</field> |
||||
|
</record> |
||||
|
|
||||
|
<record id="account_analytic_contract_action" model="ir.actions.act_window"> |
||||
|
<field name="name">Contract Templates</field> |
||||
|
<field name="res_model">account.analytic.contract</field> |
||||
|
<field name="view_type">form</field> |
||||
|
<field name="view_mode">tree,form</field> |
||||
|
<field name="help" type="html"> |
||||
|
<p class="oe_view_nocontent_create"> |
||||
|
Click to create a new contract template. |
||||
|
</p> |
||||
|
</field> |
||||
|
</record> |
||||
|
|
||||
|
<menuitem id="menu_config_contract" |
||||
|
name="Contracts" |
||||
|
sequence="1" |
||||
|
parent="account.menu_finance_configuration" |
||||
|
/> |
||||
|
|
||||
|
<menuitem id="account_analytic_contract_menu" |
||||
|
parent="menu_config_contract" |
||||
|
action="account_analytic_contract_action" |
||||
|
sequence="1" |
||||
|
/> |
||||
|
|
||||
|
</odoo> |
Write
Preview
Loading…
Cancel
Save
Reference in new issue