mirror of
https://github.com/OCA/contract.git
synced 2025-02-13 17:57:24 +02:00
[14.0][FIX] Travis
This commit is contained in:
@@ -1,2 +1 @@
|
|||||||
|
|
||||||
from . import models
|
from . import models
|
||||||
|
|||||||
@@ -4,18 +4,17 @@
|
|||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
'name': 'Contracts Management - Recurring Sales',
|
"name": "Contracts Management - Recurring Sales",
|
||||||
'version': '12.0.1.0.2',
|
"version": "14.0.1.0.0",
|
||||||
'category': 'Contract Management',
|
"category": "Contract Management",
|
||||||
'license': 'AGPL-3',
|
"license": "AGPL-3",
|
||||||
'author': "PESOL, "
|
"author": "PESOL, " "Odoo Community Association (OCA)",
|
||||||
"Odoo Community Association (OCA)",
|
"website": "https://github.com/OCA/contract",
|
||||||
'website': 'https://github.com/oca/contract',
|
"depends": ["contract", "sale"],
|
||||||
'depends': ['contract', 'sale'],
|
"data": [
|
||||||
'data': [
|
"data/contract_cron.xml",
|
||||||
'data/contract_cron.xml',
|
"views/contract.xml",
|
||||||
'views/contract.xml',
|
"views/contract_template.xml",
|
||||||
'views/contract_template.xml',
|
|
||||||
],
|
],
|
||||||
'installable': True,
|
"installable": True,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
<odoo>
|
<odoo>
|
||||||
|
<record id="contract_cron_for_sale" model="ir.cron">
|
||||||
<record id="contract_cron_for_sale" model="ir.cron">
|
|
||||||
<field name="name">Generate Recurring sales from Contracts</field>
|
<field name="name">Generate Recurring sales from Contracts</field>
|
||||||
<field name="model_id" ref="model_contract_contract"/>
|
<field name="model_id" ref="model_contract_contract" />
|
||||||
<field name="state">code</field>
|
<field name="state">code</field>
|
||||||
<field name="code">model.cron_recurring_create_sale()</field>
|
<field name="code">model.cron_recurring_create_sale()</field>
|
||||||
<field name="user_id" ref="base.user_root" />
|
<field name="user_id" ref="base.user_root" />
|
||||||
@@ -11,5 +10,4 @@
|
|||||||
<field name="numbercall">-1</field>
|
<field name="numbercall">-1</field>
|
||||||
<field eval="False" name="doall" />
|
<field eval="False" name="doall" />
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
</odoo>
|
</odoo>
|
||||||
|
|||||||
@@ -6,14 +6,12 @@ from odoo import fields, models
|
|||||||
|
|
||||||
|
|
||||||
class ContractAbstractContract(models.AbstractModel):
|
class ContractAbstractContract(models.AbstractModel):
|
||||||
_inherit = 'contract.abstract.contract'
|
_inherit = "contract.abstract.contract"
|
||||||
|
|
||||||
type = fields.Selection(
|
type = fields.Selection(
|
||||||
[('invoice', 'Invoice'),
|
[("invoice", "Invoice"), ("sale", "Sale")],
|
||||||
('sale', 'Sale')],
|
string="Type",
|
||||||
string='Type',
|
default="invoice",
|
||||||
default='invoice',
|
|
||||||
required=True,
|
required=True,
|
||||||
)
|
)
|
||||||
sale_autoconfirm = fields.Boolean(
|
sale_autoconfirm = fields.Boolean(string="Sale Autoconfirm")
|
||||||
string='Sale Autoconfirm')
|
|
||||||
|
|||||||
@@ -8,24 +8,26 @@
|
|||||||
# Copyright 2018 Therp BV <https://therp.nl>.
|
# Copyright 2018 Therp BV <https://therp.nl>.
|
||||||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
|
||||||
|
|
||||||
from odoo import api, fields, models, _
|
from odoo import _, api, fields, models
|
||||||
|
|
||||||
|
|
||||||
class ContractContract(models.Model):
|
class ContractContract(models.Model):
|
||||||
_inherit = 'contract.contract'
|
_inherit = "contract.contract"
|
||||||
|
|
||||||
sale_count = fields.Integer(compute="_compute_sale_count")
|
sale_count = fields.Integer(compute="_compute_sale_count")
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
def _prepare_sale(self, date_ref):
|
def _prepare_sale(self, date_ref):
|
||||||
self.ensure_one()
|
self.ensure_one()
|
||||||
sale = self.env['sale.order'].new({
|
sale = self.env["sale.order"].new(
|
||||||
'partner_id': self.partner_id,
|
{
|
||||||
'date_order': fields.Date.to_string(date_ref),
|
"partner_id": self.partner_id,
|
||||||
'origin': self.name,
|
"date_order": fields.Date.to_string(date_ref),
|
||||||
'company_id': self.company_id.id,
|
"origin": self.name,
|
||||||
'user_id': self.partner_id.user_id.id,
|
"company_id": self.company_id.id,
|
||||||
})
|
"user_id": self.partner_id.user_id.id,
|
||||||
|
}
|
||||||
|
)
|
||||||
if self.payment_term_id:
|
if self.payment_term_id:
|
||||||
sale.payment_term_id = self.payment_term_id.id
|
sale.payment_term_id = self.payment_term_id.id
|
||||||
if self.fiscal_position_id:
|
if self.fiscal_position_id:
|
||||||
@@ -37,10 +39,11 @@ class ContractContract(models.Model):
|
|||||||
@api.multi
|
@api.multi
|
||||||
def _get_related_sales(self):
|
def _get_related_sales(self):
|
||||||
self.ensure_one()
|
self.ensure_one()
|
||||||
sales = (self.env['sale.order.line']
|
sales = (
|
||||||
.search([('contract_line_id', 'in',
|
self.env["sale.order.line"]
|
||||||
self.contract_line_ids.ids)
|
.search([("contract_line_id", "in", self.contract_line_ids.ids)])
|
||||||
]).mapped('order_id'))
|
.mapped("order_id")
|
||||||
|
)
|
||||||
return sales
|
return sales
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
@@ -51,20 +54,18 @@ class ContractContract(models.Model):
|
|||||||
@api.multi
|
@api.multi
|
||||||
def action_show_sales(self):
|
def action_show_sales(self):
|
||||||
self.ensure_one()
|
self.ensure_one()
|
||||||
tree_view = self.env.ref('sale.view_order_tree',
|
tree_view = self.env.ref("sale.view_order_tree", raise_if_not_found=False)
|
||||||
raise_if_not_found=False)
|
form_view = self.env.ref("sale.view_order_form", raise_if_not_found=False)
|
||||||
form_view = self.env.ref('sale.view_order_form',
|
|
||||||
raise_if_not_found=False)
|
|
||||||
action = {
|
action = {
|
||||||
'type': 'ir.actions.act_window',
|
"type": "ir.actions.act_window",
|
||||||
'name': 'Sales Orders',
|
"name": "Sales Orders",
|
||||||
'res_model': 'sale.order',
|
"res_model": "sale.order",
|
||||||
'view_type': 'form',
|
"view_type": "form",
|
||||||
'view_mode': 'tree,kanban,form,calendar,pivot,graph,activity',
|
"view_mode": "tree,kanban,form,calendar,pivot,graph,activity",
|
||||||
'domain': [('id', 'in', self._get_related_sales().ids)],
|
"domain": [("id", "in", self._get_related_sales().ids)],
|
||||||
}
|
}
|
||||||
if tree_view and form_view:
|
if tree_view and form_view:
|
||||||
action['views'] = [(tree_view.id, 'tree'), (form_view.id, 'form')]
|
action["views"] = [(tree_view.id, "tree"), (form_view.id, "form")]
|
||||||
return action
|
return action
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
@@ -77,10 +78,10 @@ class ContractContract(models.Model):
|
|||||||
for sale_rec in sales:
|
for sale_rec in sales:
|
||||||
self.message_post(
|
self.message_post(
|
||||||
body=_(
|
body=_(
|
||||||
'Contract manually sale order: '
|
"Contract manually sale order: "
|
||||||
'<a href="#" data-oe-model="%s" data-oe-id="%s">'
|
'<a href="#" data-oe-model="%s" data-oe-id="%s">'
|
||||||
'Sale Order'
|
"Sale Order"
|
||||||
'</a>'
|
"</a>"
|
||||||
)
|
)
|
||||||
% (sale_rec._name, sale_rec.id)
|
% (sale_rec._name, sale_rec.id)
|
||||||
)
|
)
|
||||||
@@ -107,14 +108,12 @@ class ContractContract(models.Model):
|
|||||||
continue
|
continue
|
||||||
sale_values = contract._prepare_sale(date_ref)
|
sale_values = contract._prepare_sale(date_ref)
|
||||||
for line in contract_lines:
|
for line in contract_lines:
|
||||||
sale_values.setdefault('order_line', [])
|
sale_values.setdefault("order_line", [])
|
||||||
invoice_line_values = line._prepare_sale_line(
|
invoice_line_values = line._prepare_sale_line(
|
||||||
sale_values=sale_values,
|
sale_values=sale_values,
|
||||||
)
|
)
|
||||||
if invoice_line_values:
|
if invoice_line_values:
|
||||||
sale_values['order_line'].append(
|
sale_values["order_line"].append((0, 0, invoice_line_values))
|
||||||
(0, 0, invoice_line_values)
|
|
||||||
)
|
|
||||||
sales_values.append(sale_values)
|
sales_values.append(sale_values)
|
||||||
contract_lines._update_recurring_next_date()
|
contract_lines._update_recurring_next_date()
|
||||||
return sales_values
|
return sales_values
|
||||||
@@ -123,7 +122,7 @@ class ContractContract(models.Model):
|
|||||||
def _recurring_create_sale(self, date_ref=False):
|
def _recurring_create_sale(self, date_ref=False):
|
||||||
sales_values = self._prepare_recurring_sales_values(date_ref)
|
sales_values = self._prepare_recurring_sales_values(date_ref)
|
||||||
so_rec = self.env["sale.order"].create(sales_values)
|
so_rec = self.env["sale.order"].create(sales_values)
|
||||||
for rec in self.filtered(lambda c: c.sale_autoconfirm):
|
for _rec in self.filtered(lambda c: c.sale_autoconfirm):
|
||||||
so_rec.action_confirm()
|
so_rec.action_confirm()
|
||||||
return so_rec
|
return so_rec
|
||||||
|
|
||||||
@@ -132,11 +131,10 @@ class ContractContract(models.Model):
|
|||||||
if not date_ref:
|
if not date_ref:
|
||||||
date_ref = fields.Date.context_today(self)
|
date_ref = fields.Date.context_today(self)
|
||||||
domain = self._get_contracts_to_invoice_domain(date_ref)
|
domain = self._get_contracts_to_invoice_domain(date_ref)
|
||||||
domain.extend([('type', '=', 'sale')])
|
domain.extend([("type", "=", "sale")])
|
||||||
sales = self.env["sale.order"]
|
sales = self.env["sale.order"]
|
||||||
# Sales by companies, so assignation emails get correct context
|
# Sales by companies, so assignation emails get correct context
|
||||||
companies_to_sale = self.read_group(
|
companies_to_sale = self.read_group(domain, ["company_id"], ["company_id"])
|
||||||
domain, ["company_id"], ["company_id"])
|
|
||||||
for row in companies_to_sale:
|
for row in companies_to_sale:
|
||||||
contracts_to_sale = self.search(row["__domain"]).with_context(
|
contracts_to_sale = self.search(row["__domain"]).with_context(
|
||||||
allowed_company_ids=[row["company_id"][0]]
|
allowed_company_ids=[row["company_id"][0]]
|
||||||
@@ -149,15 +147,13 @@ class ContractContract(models.Model):
|
|||||||
if not date_ref:
|
if not date_ref:
|
||||||
date_ref = fields.Date.context_today(self)
|
date_ref = fields.Date.context_today(self)
|
||||||
domain = self._get_contracts_to_invoice_domain(date_ref)
|
domain = self._get_contracts_to_invoice_domain(date_ref)
|
||||||
domain.extend([('type', '=', 'invoice')])
|
domain.extend([("type", "=", "invoice")])
|
||||||
invoices = self.env["account.invoice"]
|
invoices = self.env["account.invoice"]
|
||||||
# Invoice by companies, so assignation emails get correct context
|
# Invoice by companies, so assignation emails get correct context
|
||||||
companies_to_invoice = self.read_group(
|
companies_to_invoice = self.read_group(domain, ["company_id"], ["company_id"])
|
||||||
domain, ["company_id"], ["company_id"])
|
|
||||||
for row in companies_to_invoice:
|
for row in companies_to_invoice:
|
||||||
contracts_to_invoice = self.search(row["__domain"]).with_context(
|
contracts_to_invoice = self.search(row["__domain"]).with_context(
|
||||||
allowed_company_ids=[row["company_id"][0]]
|
allowed_company_ids=[row["company_id"][0]]
|
||||||
)
|
)
|
||||||
invoices |= contracts_to_invoice._recurring_create_invoice(
|
invoices |= contracts_to_invoice._recurring_create_invoice(date_ref)
|
||||||
date_ref)
|
|
||||||
return invoices
|
return invoices
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ from odoo import api, models
|
|||||||
|
|
||||||
|
|
||||||
class ContractLine(models.Model):
|
class ContractLine(models.Model):
|
||||||
_inherit = 'contract.line'
|
_inherit = "contract.line"
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
def _prepare_sale_line(self, order_id=False, sale_values=False):
|
def _prepare_sale_line(self, order_id=False, sale_values=False):
|
||||||
@@ -14,22 +14,30 @@ class ContractLine(models.Model):
|
|||||||
self.last_date_invoiced, self.recurring_next_date
|
self.last_date_invoiced, self.recurring_next_date
|
||||||
)
|
)
|
||||||
sale_line_vals = {
|
sale_line_vals = {
|
||||||
'product_id': self.product_id.id,
|
"product_id": self.product_id.id,
|
||||||
'product_uom_qty': self._get_quantity_to_invoice(*dates),
|
"product_uom_qty": self._get_quantity_to_invoice(*dates),
|
||||||
'uom_id': self.uom_id.id,
|
"uom_id": self.uom_id.id,
|
||||||
'discount': self.discount,
|
"discount": self.discount,
|
||||||
'contract_line_id': self.id,
|
"contract_line_id": self.id,
|
||||||
'display_type': self.display_type,
|
"display_type": self.display_type,
|
||||||
}
|
}
|
||||||
if order_id:
|
if order_id:
|
||||||
sale_line_vals['order_id'] = order_id.id
|
sale_line_vals["order_id"] = order_id.id
|
||||||
order_line = self.env['sale.order.line'].with_context(
|
order_line = (
|
||||||
force_company=self.contract_id.company_id.id,
|
self.env["sale.order.line"]
|
||||||
).new(sale_line_vals)
|
.with_context(
|
||||||
if sale_values and not order_id:
|
|
||||||
sale = self.env['sale.order'].with_context(
|
|
||||||
force_company=self.contract_id.company_id.id,
|
force_company=self.contract_id.company_id.id,
|
||||||
).new(sale_values)
|
)
|
||||||
|
.new(sale_line_vals)
|
||||||
|
)
|
||||||
|
if sale_values and not order_id:
|
||||||
|
sale = (
|
||||||
|
self.env["sale.order"]
|
||||||
|
.with_context(
|
||||||
|
force_company=self.contract_id.company_id.id,
|
||||||
|
)
|
||||||
|
.new(sale_values)
|
||||||
|
)
|
||||||
order_line.order_id = sale
|
order_line.order_id = sale
|
||||||
# Get other order line values from product onchange
|
# Get other order line values from product onchange
|
||||||
order_line.product_id_change()
|
order_line.product_id_change()
|
||||||
@@ -38,10 +46,10 @@ class ContractLine(models.Model):
|
|||||||
name = self._insert_markers(dates[0], dates[1])
|
name = self._insert_markers(dates[0], dates[1])
|
||||||
sale_line_vals.update(
|
sale_line_vals.update(
|
||||||
{
|
{
|
||||||
'sequence': self.sequence,
|
"sequence": self.sequence,
|
||||||
'name': name,
|
"name": name,
|
||||||
'analytic_tag_ids': [(6, 0, self.analytic_tag_ids.ids)],
|
"analytic_tag_ids": [(6, 0, self.analytic_tag_ids.ids)],
|
||||||
'price_unit': self.price_unit,
|
"price_unit": self.price_unit,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
return sale_line_vals
|
return sale_line_vals
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ from odoo import fields, models
|
|||||||
|
|
||||||
|
|
||||||
class SaleOrderLine(models.Model):
|
class SaleOrderLine(models.Model):
|
||||||
_inherit = 'sale.order.line'
|
_inherit = "sale.order.line"
|
||||||
|
|
||||||
contract_line_id = fields.Many2one(
|
contract_line_id = fields.Many2one(
|
||||||
'contract.line', string='Contract Line', index=True
|
"contract.line", string="Contract Line", index=True
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
This module extends functionality of contracts to be able to generate sales
|
This module extends functionality of contracts to be able to generate sales
|
||||||
orders instead of invoices.
|
orders instead of invoices.
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
# Copyright 2017 Angel Moya <angel.moya@pesol.es>
|
# Copyright 2017 Angel Moya <angel.moya@pesol.es>
|
||||||
# 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 odoo.exceptions import ValidationError
|
|
||||||
from odoo import fields
|
from odoo import fields
|
||||||
|
from odoo.exceptions import ValidationError
|
||||||
from odoo.tests.common import TransactionCase
|
from odoo.tests.common import TransactionCase
|
||||||
|
|
||||||
|
|
||||||
@@ -17,95 +17,95 @@ class TestContractSale(TransactionCase):
|
|||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TestContractSale, self).setUp()
|
super(TestContractSale, self).setUp()
|
||||||
self.pricelist = self.env['product.pricelist'].create({
|
self.pricelist = self.env["product.pricelist"].create(
|
||||||
'name': 'pricelist for contract test',
|
{
|
||||||
})
|
"name": "pricelist for contract test",
|
||||||
self.partner = self.env['res.partner'].create({
|
}
|
||||||
'name': 'partner test contract',
|
|
||||||
'property_product_pricelist': self.pricelist.id,
|
|
||||||
})
|
|
||||||
self.product_1 = self.env.ref('product.product_product_1')
|
|
||||||
self.product_1.taxes_id += self.env['account.tax'].search(
|
|
||||||
[('type_tax_use', '=', 'sale')], limit=1
|
|
||||||
)
|
)
|
||||||
self.product_1.description_sale = 'Test description sale'
|
self.partner = self.env["res.partner"].create(
|
||||||
|
{
|
||||||
|
"name": "partner test contract",
|
||||||
|
"property_product_pricelist": self.pricelist.id,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
self.product_1 = self.env.ref("product.product_product_1")
|
||||||
|
self.product_1.taxes_id += self.env["account.tax"].search(
|
||||||
|
[("type_tax_use", "=", "sale")], limit=1
|
||||||
|
)
|
||||||
|
self.product_1.description_sale = "Test description sale"
|
||||||
self.line_template_vals = {
|
self.line_template_vals = {
|
||||||
'product_id': self.product_1.id,
|
"product_id": self.product_1.id,
|
||||||
'name': 'Test Contract Template',
|
"name": "Test Contract Template",
|
||||||
'quantity': 1,
|
"quantity": 1,
|
||||||
'uom_id': self.product_1.uom_id.id,
|
"uom_id": self.product_1.uom_id.id,
|
||||||
'price_unit': 100,
|
"price_unit": 100,
|
||||||
'discount': 50,
|
"discount": 50,
|
||||||
'recurring_rule_type': 'yearly',
|
"recurring_rule_type": "yearly",
|
||||||
'recurring_interval': 1,
|
"recurring_interval": 1,
|
||||||
}
|
}
|
||||||
self.template_vals = {
|
self.template_vals = {
|
||||||
'name': 'Test Contract Template',
|
"name": "Test Contract Template",
|
||||||
'contract_line_ids': [
|
"contract_line_ids": [
|
||||||
(0, 0, self.line_template_vals),
|
(0, 0, self.line_template_vals),
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
self.template = self.env['contract.template'].create(
|
self.template = self.env["contract.template"].create(self.template_vals)
|
||||||
self.template_vals
|
|
||||||
)
|
|
||||||
# For being sure of the applied price
|
# For being sure of the applied price
|
||||||
self.env['product.pricelist.item'].create(
|
self.env["product.pricelist.item"].create(
|
||||||
{
|
{
|
||||||
'pricelist_id': self.partner.property_product_pricelist.id,
|
"pricelist_id": self.partner.property_product_pricelist.id,
|
||||||
'product_id': self.product_1.id,
|
"product_id": self.product_1.id,
|
||||||
'compute_price': 'formula',
|
"compute_price": "formula",
|
||||||
'base': 'list_price',
|
"base": "list_price",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
self.contract = self.env['contract.contract'].create(
|
self.contract = self.env["contract.contract"].create(
|
||||||
{
|
{
|
||||||
'name': 'Test Contract',
|
"name": "Test Contract",
|
||||||
'partner_id': self.partner.id,
|
"partner_id": self.partner.id,
|
||||||
'pricelist_id': self.partner.property_product_pricelist.id,
|
"pricelist_id": self.partner.property_product_pricelist.id,
|
||||||
'type': 'sale',
|
"type": "sale",
|
||||||
'sale_autoconfirm': False
|
"sale_autoconfirm": False,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
self.line_vals = {
|
self.line_vals = {
|
||||||
'contract_id': self.contract.id,
|
"contract_id": self.contract.id,
|
||||||
'product_id': self.product_1.id,
|
"product_id": self.product_1.id,
|
||||||
'name': 'Services from #START# to #END#',
|
"name": "Services from #START# to #END#",
|
||||||
'quantity': 1,
|
"quantity": 1,
|
||||||
'uom_id': self.product_1.uom_id.id,
|
"uom_id": self.product_1.uom_id.id,
|
||||||
'price_unit': 100,
|
"price_unit": 100,
|
||||||
'discount': 50,
|
"discount": 50,
|
||||||
'recurring_rule_type': 'monthly',
|
"recurring_rule_type": "monthly",
|
||||||
'recurring_interval': 1,
|
"recurring_interval": 1,
|
||||||
'date_start': '2020-01-01',
|
"date_start": "2020-01-01",
|
||||||
'recurring_next_date': '2020-01-15',
|
"recurring_next_date": "2020-01-15",
|
||||||
}
|
}
|
||||||
self.contract.contract_template_id = self.template
|
self.contract.contract_template_id = self.template
|
||||||
self.contract._onchange_contract_template_id()
|
self.contract._onchange_contract_template_id()
|
||||||
self.contract_line = self.env['contract.line'].create(
|
self.contract_line = self.env["contract.line"].create(self.line_vals)
|
||||||
self.line_vals
|
self.contract2 = self.env["contract.contract"].create(
|
||||||
)
|
|
||||||
self.contract2 = self.env['contract.contract'].create(
|
|
||||||
{
|
{
|
||||||
'name': 'Test Contract 2',
|
"name": "Test Contract 2",
|
||||||
'type': 'sale',
|
"type": "sale",
|
||||||
'partner_id': self.partner.id,
|
"partner_id": self.partner.id,
|
||||||
'pricelist_id': self.partner.property_product_pricelist.id,
|
"pricelist_id": self.partner.property_product_pricelist.id,
|
||||||
'contract_type': 'purchase',
|
"contract_type": "purchase",
|
||||||
'contract_line_ids': [
|
"contract_line_ids": [
|
||||||
(
|
(
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
{
|
{
|
||||||
'product_id': self.product_1.id,
|
"product_id": self.product_1.id,
|
||||||
'name': 'Services from #START# to #END#',
|
"name": "Services from #START# to #END#",
|
||||||
'quantity': 1,
|
"quantity": 1,
|
||||||
'uom_id': self.product_1.uom_id.id,
|
"uom_id": self.product_1.uom_id.id,
|
||||||
'price_unit': 100,
|
"price_unit": 100,
|
||||||
'discount': 50,
|
"discount": 50,
|
||||||
'recurring_rule_type': 'monthly',
|
"recurring_rule_type": "monthly",
|
||||||
'recurring_interval': 1,
|
"recurring_interval": 1,
|
||||||
'date_start': '2018-02-15',
|
"date_start": "2018-02-15",
|
||||||
'recurring_next_date': '2018-02-22',
|
"recurring_next_date": "2018-02-22",
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
@@ -114,40 +114,36 @@ class TestContractSale(TransactionCase):
|
|||||||
|
|
||||||
def test_check_discount(self):
|
def test_check_discount(self):
|
||||||
with self.assertRaises(ValidationError):
|
with self.assertRaises(ValidationError):
|
||||||
self.contract_line.write({'discount': 120})
|
self.contract_line.write({"discount": 120})
|
||||||
|
|
||||||
def test_contract(self):
|
def test_contract(self):
|
||||||
recurring_next_date = to_date('2020-02-15')
|
recurring_next_date = to_date("2020-02-15")
|
||||||
self.assertAlmostEqual(self.contract_line.price_subtotal, 50.0)
|
self.assertAlmostEqual(self.contract_line.price_subtotal, 50.0)
|
||||||
res = self.contract_line._onchange_product_id()
|
res = self.contract_line._onchange_product_id()
|
||||||
self.assertIn('uom_id', res['domain'])
|
self.assertIn("uom_id", res["domain"])
|
||||||
self.contract_line.price_unit = 100.0
|
self.contract_line.price_unit = 100.0
|
||||||
self.contract.partner_id = self.partner.id
|
self.contract.partner_id = self.partner.id
|
||||||
self.contract.recurring_create_sale()
|
self.contract.recurring_create_sale()
|
||||||
self.sale_monthly = self.contract._get_related_sales()
|
self.sale_monthly = self.contract._get_related_sales()
|
||||||
self.assertTrue(self.sale_monthly)
|
self.assertTrue(self.sale_monthly)
|
||||||
self.assertEqual(
|
self.assertEqual(self.contract_line.recurring_next_date, recurring_next_date)
|
||||||
self.contract_line.recurring_next_date, recurring_next_date
|
|
||||||
)
|
|
||||||
self.order_line = self.sale_monthly.order_line[0]
|
self.order_line = self.sale_monthly.order_line[0]
|
||||||
self.assertTrue(self.order_line.tax_id)
|
self.assertTrue(self.order_line.tax_id)
|
||||||
self.assertAlmostEqual(self.order_line.price_subtotal, 50.0)
|
self.assertAlmostEqual(self.order_line.price_subtotal, 50.0)
|
||||||
self.assertEqual(self.contract.user_id, self.sale_monthly.user_id)
|
self.assertEqual(self.contract.user_id, self.sale_monthly.user_id)
|
||||||
|
|
||||||
def test_contract_autoconfirm(self):
|
def test_contract_autoconfirm(self):
|
||||||
recurring_next_date = to_date('2020-02-15')
|
recurring_next_date = to_date("2020-02-15")
|
||||||
self.contract.sale_autoconfirm = True
|
self.contract.sale_autoconfirm = True
|
||||||
self.assertAlmostEqual(self.contract_line.price_subtotal, 50.0)
|
self.assertAlmostEqual(self.contract_line.price_subtotal, 50.0)
|
||||||
res = self.contract_line._onchange_product_id()
|
res = self.contract_line._onchange_product_id()
|
||||||
self.assertIn('uom_id', res['domain'])
|
self.assertIn("uom_id", res["domain"])
|
||||||
self.contract_line.price_unit = 100.0
|
self.contract_line.price_unit = 100.0
|
||||||
self.contract.partner_id = self.partner.id
|
self.contract.partner_id = self.partner.id
|
||||||
self.contract.recurring_create_sale()
|
self.contract.recurring_create_sale()
|
||||||
self.sale_monthly = self.contract._get_related_sales()
|
self.sale_monthly = self.contract._get_related_sales()
|
||||||
self.assertTrue(self.sale_monthly)
|
self.assertTrue(self.sale_monthly)
|
||||||
self.assertEqual(
|
self.assertEqual(self.contract_line.recurring_next_date, recurring_next_date)
|
||||||
self.contract_line.recurring_next_date, recurring_next_date
|
|
||||||
)
|
|
||||||
self.order_line = self.sale_monthly.order_line[0]
|
self.order_line = self.sale_monthly.order_line[0]
|
||||||
self.assertTrue(self.order_line.tax_id)
|
self.assertTrue(self.order_line.tax_id)
|
||||||
self.assertAlmostEqual(self.order_line.price_subtotal, 50.0)
|
self.assertAlmostEqual(self.order_line.price_subtotal, 50.0)
|
||||||
@@ -160,19 +156,24 @@ class TestContractSale(TransactionCase):
|
|||||||
self.contract.contract_template_id = self.template
|
self.contract.contract_template_id = self.template
|
||||||
self.contract._onchange_contract_template_id()
|
self.contract._onchange_contract_template_id()
|
||||||
res = {
|
res = {
|
||||||
'contract_line_ids':
|
"contract_line_ids": [
|
||||||
[(0, 0, {
|
(
|
||||||
'product_id': self.product_1.id,
|
0,
|
||||||
'name': 'Test Contract Template',
|
0,
|
||||||
'quantity': 1,
|
{
|
||||||
'uom_id': self.product_1.uom_id.id,
|
"product_id": self.product_1.id,
|
||||||
'price_unit': 100,
|
"name": "Test Contract Template",
|
||||||
'discount': 50,
|
"quantity": 1,
|
||||||
'recurring_rule_type': 'yearly',
|
"uom_id": self.product_1.uom_id.id,
|
||||||
'recurring_interval': 1,
|
"price_unit": 100,
|
||||||
})]
|
"discount": 50,
|
||||||
|
"recurring_rule_type": "yearly",
|
||||||
|
"recurring_interval": 1,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
]
|
||||||
}
|
}
|
||||||
del self.template_vals['name']
|
del self.template_vals["name"]
|
||||||
self.assertDictEqual(res, self.template_vals)
|
self.assertDictEqual(res, self.template_vals)
|
||||||
|
|
||||||
def test_contract_count_sale(self):
|
def test_contract_count_sale(self):
|
||||||
@@ -183,27 +184,26 @@ class TestContractSale(TransactionCase):
|
|||||||
self.assertEqual(self.contract.sale_count, 3)
|
self.assertEqual(self.contract.sale_count, 3)
|
||||||
|
|
||||||
def test_contract_count_sale_2(self):
|
def test_contract_count_sale_2(self):
|
||||||
orders = self.env['sale.order']
|
orders = self.env["sale.order"]
|
||||||
orders |= self.contract.recurring_create_sale()
|
orders |= self.contract.recurring_create_sale()
|
||||||
orders |= self.contract.recurring_create_sale()
|
orders |= self.contract.recurring_create_sale()
|
||||||
orders |= self.contract.recurring_create_sale()
|
orders |= self.contract.recurring_create_sale()
|
||||||
action = self.contract.action_show_sales()
|
action = self.contract.action_show_sales()
|
||||||
self.assertEqual(set(action['domain'][0][2]), set(orders.ids))
|
self.assertEqual(set(action["domain"][0][2]), set(orders.ids))
|
||||||
|
|
||||||
def test_cron_recurring_create_sale(self):
|
def test_cron_recurring_create_sale(self):
|
||||||
self.contract_line.date_start = '2020-01-01'
|
self.contract_line.date_start = "2020-01-01"
|
||||||
self.contract_line.recurring_invoicing_type = 'post-paid'
|
self.contract_line.recurring_invoicing_type = "post-paid"
|
||||||
self.contract_line.date_end = '2020-03-15'
|
self.contract_line.date_end = "2020-03-15"
|
||||||
self.contract_line._onchange_date_start()
|
self.contract_line._onchange_date_start()
|
||||||
contracts = self.contract2
|
contracts = self.contract2
|
||||||
for _i in range(10):
|
for _i in range(10):
|
||||||
contracts |= self.contract.copy({'type': 'sale'})
|
contracts |= self.contract.copy({"type": "sale"})
|
||||||
self.env['contract.contract'].cron_recurring_create_sale()
|
self.env["contract.contract"].cron_recurring_create_sale()
|
||||||
order_lines = self.env['sale.order.line'].search(
|
order_lines = self.env["sale.order.line"].search(
|
||||||
[('contract_line_id', 'in',
|
[("contract_line_id", "in", contracts.mapped("contract_line_ids").ids)]
|
||||||
contracts.mapped('contract_line_ids').ids)]
|
|
||||||
)
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
len(contracts.mapped('contract_line_ids')),
|
len(contracts.mapped("contract_line_ids")),
|
||||||
len(order_lines),
|
len(order_lines),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -3,38 +3,58 @@
|
|||||||
<record id="contract_contract_form_view_recurring_sale_form" model="ir.ui.view">
|
<record id="contract_contract_form_view_recurring_sale_form" model="ir.ui.view">
|
||||||
<field name="name">contract.contract.form.recurring.sale.form</field>
|
<field name="name">contract.contract.form.recurring.sale.form</field>
|
||||||
<field name="model">contract.contract</field>
|
<field name="model">contract.contract</field>
|
||||||
<field name="inherit_id" ref="contract.contract_contract_form_view"/>
|
<field name="inherit_id" ref="contract.contract_contract_form_view" />
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<xpath expr="//group[@name='recurring_invoices']" position="after">
|
<xpath expr="//group[@name='recurring_invoices']" position="after">
|
||||||
<group name="recurring_sale_or_invoicing" string="Recurring Sales/Invoicing" col="4">
|
<group
|
||||||
<field name="type"/>
|
name="recurring_sale_or_invoicing"
|
||||||
<field name="sale_autoconfirm" attrs="{'invisible':[('type','!=', 'sale')]}" />
|
string="Recurring Sales/Invoicing"
|
||||||
|
col="4"
|
||||||
|
>
|
||||||
|
<field name="type" />
|
||||||
|
<field
|
||||||
|
name="sale_autoconfirm"
|
||||||
|
attrs="{'invisible':[('type','!=', 'sale')]}"
|
||||||
|
/>
|
||||||
</group>
|
</group>
|
||||||
</xpath>
|
</xpath>
|
||||||
<xpath expr="//button[@name='recurring_create_invoice']" position="attributes">
|
<xpath
|
||||||
<attribute name="attrs">{'invisible': ['|', ('create_invoice_visibility', '=', False),('type','!=','invoice')]}</attribute>
|
expr="//button[@name='recurring_create_invoice']"
|
||||||
</xpath>
|
position="attributes"
|
||||||
<xpath expr="//button[@name='recurring_create_invoice']" position="before">
|
>
|
||||||
<button name="recurring_create_sale"
|
<attribute
|
||||||
type="object"
|
name="attrs"
|
||||||
attrs="{'invisible': [('type','!=','sale')]}"
|
>{'invisible': ['|', ('create_invoice_visibility', '=', False),('type','!=','invoice')]}</attribute>
|
||||||
string="CREATE SALES"
|
</xpath>
|
||||||
class="oe_link"
|
<xpath expr="//button[@name='recurring_create_invoice']" position="before">
|
||||||
groups="base.group_no_one"
|
<button
|
||||||
/>
|
name="recurring_create_sale"
|
||||||
|
type="object"
|
||||||
|
attrs="{'invisible': [('type','!=','sale')]}"
|
||||||
|
string="CREATE SALES"
|
||||||
|
class="oe_link"
|
||||||
|
groups="base.group_no_one"
|
||||||
|
/>
|
||||||
|
</xpath>
|
||||||
|
<xpath
|
||||||
|
expr="//button[@name='action_show_invoices']"
|
||||||
|
position="attributes"
|
||||||
|
>
|
||||||
|
<attribute
|
||||||
|
name="attrs"
|
||||||
|
>{'invisible': [('type','!=','invoice')]}</attribute>
|
||||||
</xpath>
|
</xpath>
|
||||||
<xpath expr="//button[@name='action_show_invoices']" position="attributes">
|
|
||||||
<attribute name="attrs">{'invisible': [('type','!=','invoice')]}</attribute>
|
|
||||||
</xpath>
|
|
||||||
<xpath expr="//button[@name='action_show_invoices']" position="after">
|
<xpath expr="//button[@name='action_show_invoices']" position="after">
|
||||||
<button name="action_show_sales"
|
<button
|
||||||
type="object" icon="fa-list"
|
name="action_show_sales"
|
||||||
class="oe_stat_button" attrs="{'invisible': [('type','!=','sale')]}">
|
type="object"
|
||||||
<field string="Sales Order"
|
icon="fa-list"
|
||||||
name="sale_count"
|
class="oe_stat_button"
|
||||||
widget="statinfo"/>
|
attrs="{'invisible': [('type','!=','sale')]}"
|
||||||
|
>
|
||||||
|
<field string="Sales Order" name="sale_count" widget="statinfo" />
|
||||||
</button>
|
</button>
|
||||||
</xpath>
|
</xpath>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
|||||||
@@ -3,10 +3,10 @@
|
|||||||
<record id="contract_template_form_view_inherit_sale" model="ir.ui.view">
|
<record id="contract_template_form_view_inherit_sale" model="ir.ui.view">
|
||||||
<field name="name">contract.template form view (in contract)</field>
|
<field name="name">contract.template form view (in contract)</field>
|
||||||
<field name="model">contract.template</field>
|
<field name="model">contract.template</field>
|
||||||
<field name="inherit_id" ref="contract.contract_template_form_view"/>
|
<field name="inherit_id" ref="contract.contract_template_form_view" />
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<xpath expr="//field[@name='pricelist_id']" position="after">
|
<xpath expr="//field[@name='pricelist_id']" position="after">
|
||||||
<field name="type"/>
|
<field name="type" />
|
||||||
</xpath>
|
</xpath>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|||||||
Reference in New Issue
Block a user