Skip to content

Commit

Permalink
Merge a6876a8 into e00366f
Browse files Browse the repository at this point in the history
  • Loading branch information
nikul-serpentcs committed Jan 29, 2020
2 parents e00366f + a6876a8 commit 28847a0
Show file tree
Hide file tree
Showing 10 changed files with 211 additions and 15 deletions.
4 changes: 4 additions & 0 deletions contract_sale/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ Contributors

* Levent Karakaş
* Bejaoui Souheil <souheil.bejaoui@acsone.eu>
* Serpent Consulting Services Pvt. Ltd. <support@serpentcs.com>

* Nikul Chaudhary <nikul.chaudhary.serpentcs@gmail.com>


Maintainers
~~~~~~~~~~~
Expand Down
2 changes: 1 addition & 1 deletion contract_sale/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
'Odoo Community Association (OCA)',
'website': 'https://github.com/OCA/contract',
'depends': [
'sale',
'sale_management',
'contract',
],
'data': [
Expand Down
2 changes: 2 additions & 0 deletions contract_sale_invoicing/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@
'depends': [
'contract',
'sale_management',
'product_contract',
],
'data': [
'views/contract_view.xml',
'views/sale_order.xml',
],
}
1 change: 1 addition & 0 deletions contract_sale_invoicing/models/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).

from . import sale_order
from . import contract
125 changes: 111 additions & 14 deletions contract_sale_invoicing/models/contract.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,120 @@ class ContractContract(models.Model):

invoicing_sales = fields.Boolean(
string='Invoice Pending Sales Orders',
help='If checked include sales with same analytic account to invoice '
'in contract invoice creation.',
)
help='Include sales to invoice on the contract invoice.')
filter_with = fields.Selection([
('analytic_account', 'Analytic Account'),
('contract', 'Contract')],
default='analytic_account', string='Filter with the same',
help="Select the sale orders with the same analytic account or "
"contract")
group_by = fields.Selection([
('sale_order', 'Sale Order'),
('contract', 'Contract')],
default='sale_order', string='Create one invoice per')

@api.multi
def _recurring_create_invoice(self, date_ref=False):
invoices = super()._recurring_create_invoice(date_ref)
if not self.invoicing_sales:
return invoices
sales = self.env['sale.order'].search([
('analytic_account_id', '=', self.group_id.id),
def get_sale_order_domain(self):
domain = [
('partner_invoice_id', 'child_of',
self.partner_id.commercial_partner_id.ids),
('invoice_status', '=', 'to invoice'),
('date_order', '<=',
'{} 23:59:59'.format(self.recurring_next_date)),
])
if sales:
invoice_ids = sales.action_invoice_create()
invoices |= self.env['account.invoice'].browse(invoice_ids)[:1]
]
if self.filter_with == 'analytic_account':
domain.append(('analytic_account_id', '=', self.group_id.id))
elif self.filter_with == 'contract':
domain.append(('contract_id', '=', self.id))
return domain

@api.multi
def _recurring_create_invoice(self, date_ref=False):
invoices = super()._recurring_create_invoice(date_ref)
for rec in self:
if not rec.invoicing_sales:
return invoices
so_domain = rec.get_sale_order_domain()
sales = self.env['sale.order'].search(so_domain)
if sales and rec.group_by == 'sale_order':
invoice_ids = sales.action_invoice_create()
invoices |= self.env['account.invoice'].browse(invoice_ids)[:1]

@api.multi
def _prepare_invoice_line_dict(self, contract_line_rec, invoice_line,
remain_qty):
return {
'invoice_id': False,
'uom_id': contract_line_rec.uom_id.id,
'product_id': invoice_line.get('product_id'),
'quantity': remain_qty or 0,
'discount': contract_line_rec.discount,
'contract_line_id': contract_line_rec.id,
'name': contract_line_rec.name,
'account_analytic_id': False,
'price_unit': contract_line_rec.price_unit
}

@api.multi
def _prepare_recurring_invoices_values(self, date_ref=False):
invoices_values = super()._prepare_recurring_invoices_values()
updated_invoices_values = []
for invoice_val in invoices_values:
invoice_line_values = {}
invoice_line_list = []
for invoice_line in invoice_val.get('invoice_line_ids', []):
invoice_line = invoice_line[2] or {}
contract_line_rec = self.env['contract.line'].\
browse(invoice_line.get('contract_line_id', False))
if contract_line_rec and contract_line_rec.contract_id and\
contract_line_rec.contract_id.invoicing_sales and \
contract_line_rec.contract_id.group_by == 'contract':
so_domain = \
contract_line_rec.contract_id.get_sale_order_domain()
order_ids = self.env['sale.order'].search(so_domain)
sale_order_line_product_qty = {}
for order_id in order_ids:
if not order_id.order_line.mapped('invoice_lines'):
for line in order_id.order_line:
if sale_order_line_product_qty.\
get(line.product_id.id):
sale_order_line_product_qty[
line.product_id.id
] += line.product_uom_qty
else:
sale_order_line_product_qty[
line.product_id.id
] = line.product_uom_qty
if invoice_line.get('product_id'
) in sale_order_line_product_qty:
if sale_order_line_product_qty.\
get(line.product_id.id
) > invoice_line.get('quantity'):
remain_qty = sale_order_line_product_qty.\
get(invoice_line.get('product_id')
) - invoice_line.get('quantity') or 0
invoice_line_values =\
self._prepare_invoice_line_dict(
contract_line_rec, invoice_line, remain_qty
) or {}
invoice_line_list.append(invoice_line_values)
sale_order_line_product_qty.\
pop(invoice_line.get('product_id'))
invoice_val['invoice_line_ids'] +=\
[(0, 0, invoice_line_val
)for invoice_line_val in invoice_line_list]
updated_invoices_values.append(invoice_val)
return updated_invoices_values

@api.depends('contract_line_ids')
def _compute_sale_order_count(self):
super(ContractContract, self)._compute_sale_order_count()
for rec in self:
sale_contract_count = self.env['sale.order'].search_count(
[('contract_id', '=', rec.id)])
rec.sale_order_count += sale_contract_count

@api.multi
def action_view_sales_orders(self):
res = super(ContractContract, self).action_view_sales_orders()
res['domain'] = [('contract_id', '=', self.id)]
return res
10 changes: 10 additions & 0 deletions contract_sale_invoicing/models/sale_order.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Copyright (C) 2019 Open Source Integrators
# Copyright (C) 2019 Serpent Consulting Services
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
from odoo import fields, models


class SaleOrder(models.Model):
_inherit = 'sale.order'

contract_id = fields.Many2one('contract.contract', string='Contract')
2 changes: 2 additions & 0 deletions contract_sale_invoicing/readme/CONTRIBUTORS.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@

* Carlos Dauden
* Souheil Bejaoui <souheil.bejaoui@acsone.eu>
* Nikul Chaudhary <nikul.chaudhary.serpentcs@gmail.com>
* Maxime Chambreuil <mchambreuil@opensourceintegrators.com>
62 changes: 62 additions & 0 deletions contract_sale_invoicing/tests/test_contract_sale_invoicing.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ class TestContractSaleInvoicing(TestContractBase):
@classmethod
def setUpClass(cls):
super(TestContractSaleInvoicing, cls).setUpClass()
cls.contract_obj = cls.env['contract.contract']
cls.account_invoice_line_obj = cls.env['account.invoice.line']
cls.contract.group_id = \
cls.env['account.analytic.account'].search([], limit=1)
cls.product_so = cls.env.ref(
Expand Down Expand Up @@ -45,3 +47,63 @@ def test_contract_sale_invoicing_without(self):
self.sale_order.action_confirm()
self.contract.recurring_create_invoice()
self.assertEqual(self.sale_order.invoice_status, 'to invoice')

def test_action_view_sales_orders(self):
self.contract._compute_sale_order_count()
self.contract.action_view_sales_orders()

def test_csi_group_by_so_aa(self):
contract_copy = self.contract.copy({
'filter_with': 'analytic_account',
'group_by': 'sale_order',
'invoicing_sales': True
})
so_val = {
'date_order': '2016-02-15',
'contract_id': contract_copy.id
}
sale_order_copy1 = self.sale_order.copy(so_val)
sale_order_copy2 = self.sale_order.copy(so_val)
sale_order_copy1.action_confirm()
sale_order_copy2.action_confirm()
self.contract_obj.cron_recurring_create_invoice()
contract_line_list = [contract_copy.contract_line_ids.id,
self.contract.contract_line_ids.id]
invoice_line = self.account_invoice_line_obj.search([
('contract_line_id', 'in', contract_line_list)], order='id asc')

self.assertEqual(invoice_line[0].quantity, 1)
self.assertEqual(invoice_line[0].product_id,
sale_order_copy1.order_line.product_id)
self.assertEqual(invoice_line[1].quantity, 1)
self.assertEqual(invoice_line[1].product_id,
sale_order_copy1.order_line.product_id)

def test_contract_sale_invoicing(self):
contract_copy = self.contract.copy({
'filter_with': 'contract',
'group_by': 'contract',
'invoicing_sales': True
})
so_val = {
'date_order': '2016-02-15',
'contract_id': contract_copy.id
}
sale_order_copy1 = self.sale_order.copy(so_val)
sale_order_copy2 = self.sale_order.copy(so_val)
sale_order_copy1.action_confirm()
sale_order_copy2.action_confirm()
self.contract_obj.cron_recurring_create_invoice()
contract_line_list = [contract_copy.contract_line_ids.id,
self.contract.contract_line_ids.id]
invoice_line = self.account_invoice_line_obj.search([
('contract_line_id', 'in', contract_line_list)], order='id asc')
self.assertEqual(invoice_line[0].quantity, 1)
self.assertEqual(invoice_line[0].product_id,
sale_order_copy1.order_line.product_id)
self.assertEqual(invoice_line[1].quantity, 1)
self.assertEqual(invoice_line[1].product_id,
sale_order_copy1.order_line.product_id)
self.assertEqual(invoice_line[2].quantity, 3)
self.assertEqual(invoice_line[2].product_id,
sale_order_copy1.order_line.product_id)
4 changes: 4 additions & 0 deletions contract_sale_invoicing/views/contract_view.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@
<field name="arch" type="xml">
<field name="recurring_next_date" position="after">
<field name="invoicing_sales"/>
<field name="filter_with"
attrs="{'invisible': [('invoicing_sales', '=', False)]}"/>
<field name="group_by"
attrs="{'invisible': [('invoicing_sales', '=', False)]}"/>
</field>
</field>
</record>
Expand Down
14 changes: 14 additions & 0 deletions contract_sale_invoicing/views/sale_order.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<odoo>

<record id="view_order_form_form_view" model="ir.ui.view">
<field name="name">sale.order.form.view</field>
<field name="model">sale.order</field>
<field name="inherit_id" ref="sale.view_order_form"/>
<field name="arch" type="xml">
<field name="partner_id" position="after">
<field name="contract_id" domain="[('partner_id', '=', partner_id)]"/>
</field>
</field>
</record>

</odoo>

0 comments on commit 28847a0

Please sign in to comment.