forked from Mapan/odoo17e
256 lines
11 KiB
Python
256 lines
11 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
from dateutil.relativedelta import relativedelta
|
|
from unittest.mock import patch
|
|
|
|
from odoo import fields
|
|
from odoo.exceptions import AccessError
|
|
from odoo.tools import format_date, get_timedelta
|
|
from odoo.tests.common import Form, tagged
|
|
from odoo.addons.partner_commission.tests.setup import Line, Spec, TestCommissionsSetup
|
|
from odoo.tools.misc import NON_BREAKING_SPACE
|
|
|
|
|
|
@tagged('commission_purchase', 'post_install', '-at_install')
|
|
class TestPurchaseOrder(TestCommissionsSetup):
|
|
def test_automatic_confirm(self):
|
|
"""Only purchase orders within the frequency date range and
|
|
where the amount_total is greater than the limit configure on the company should be confirmed.
|
|
Standard purchase orders should be untouched."""
|
|
# Setup.
|
|
self.company.commission_automatic_po_frequency = 'weekly'
|
|
self.referrer.grade_id = self.learning
|
|
self.referrer._onchange_grade_id()
|
|
|
|
send_mail_count = 0
|
|
|
|
# Helper.
|
|
def make_po(days_offset=0, qty=1):
|
|
inv = self.purchase(Spec(self.gold, [Line(self.crm, qty)]))
|
|
po = inv.commission_po_line_id.order_id
|
|
po.date_order = fields.Date.add(fields.Date.today(), days=days_offset)
|
|
return po
|
|
|
|
# Stub today's date.
|
|
def today(*args, **kwargs):
|
|
return fields.Date.to_date('2020-01-06')
|
|
|
|
def _patched_send_mail(*args, **kwargs):
|
|
nonlocal send_mail_count
|
|
send_mail_count += 1
|
|
|
|
# Case: OK.
|
|
with patch('odoo.fields.Date.today', today):
|
|
with patch('odoo.addons.mail.models.mail_template.MailTemplate.send_mail', _patched_send_mail):
|
|
# We test the non recurring flow: recurring_invoice is False on the product
|
|
self.crm.recurring_invoice = False
|
|
po = make_po(days_offset=-1)
|
|
self.env['purchase.order']._cron_confirm_purchase_orders()
|
|
self.assertEqual(po.state, 'purchase')
|
|
self.assertEqual(send_mail_count, 1)
|
|
|
|
# Case: NOK: standard purchase order.
|
|
# Should not be confirmed because it's not a commission purchase: commission_po_line_id is not set on the account.move.
|
|
with patch('odoo.fields.Date.today', today):
|
|
po = self.env['purchase.order'].create({
|
|
'partner_id': self.customer.id,
|
|
'company_id': self.company.id,
|
|
'currency_id': self.company.currency_id.id,
|
|
'date_order': fields.Date.subtract(fields.Date.today(), days=1),
|
|
})
|
|
self.env['purchase.order']._cron_confirm_purchase_orders()
|
|
self.assertEqual(po.state, 'draft')
|
|
|
|
# Set a minimum amount_total to auto confirm the PO
|
|
self.company.commission_po_minimum = 50
|
|
# Case: OK. amount_total = 80 > 50
|
|
with patch('odoo.fields.Date.today', today):
|
|
po = make_po(days_offset=-1, qty=20)
|
|
self.env['purchase.order']._cron_confirm_purchase_orders()
|
|
self.assertEqual(po.state, 'purchase')
|
|
|
|
# Case: NOK: amount_total = 8 < 50
|
|
with patch('odoo.fields.Date.today', today):
|
|
po = make_po(days_offset=-1, qty=2)
|
|
self.env['purchase.order']._cron_confirm_purchase_orders()
|
|
self.assertEqual(po.state, 'draft')
|
|
|
|
def test_vendor_bill_description_multi_line_format(self):
|
|
"""Description text on vendor bill should have the following format:
|
|
|
|
Commission on {{move.name}}, {{move.partner_id.name}}, {{move.amount_untaxed}} €
|
|
{{subscription.code}}, from {{date_from}} to {{subscription.recurring_next_date}} ({{number of months}})
|
|
"""
|
|
# Required for `partner_invoice_id`, `partner_shipping_id` to be visible in the view
|
|
self.salesman.groups_id += self.env.ref('account.group_delivery_invoice_address')
|
|
self.referrer.commission_plan_id = self.gold_plan
|
|
self.referrer.grade_id = self.gold
|
|
|
|
form = Form(self.env['sale.order'].with_user(self.salesman).with_context(tracking_disable=True),
|
|
view=self.env.ref('sale_subscription.sale_subscription_primary_form_view'))
|
|
form.partner_id = self.customer
|
|
form.partner_invoice_id = self.customer
|
|
form.partner_shipping_id = self.customer
|
|
form.referrer_id = self.referrer
|
|
# form.commission_plan_frozen = False
|
|
form.plan_id = self.plan_year
|
|
|
|
# Testing same rules, with cap reached, are grouped together.
|
|
with form.order_line.new() as line:
|
|
line.name = self.worker.name
|
|
line.product_id = self.worker
|
|
line.product_uom_qty = 20
|
|
|
|
# add extra note that will be copied to the invoice
|
|
# (ensure those lines without subscription start/end dates
|
|
# do not crash the commission generation)
|
|
with form.order_line.new() as line:
|
|
line.display_type = 'line_note'
|
|
line.name = "Extra order note for the customer"
|
|
|
|
so = form.save()
|
|
so.pricelist_id = self.eur_20
|
|
so.action_confirm()
|
|
inv = so._create_invoices()
|
|
inv.action_post()
|
|
inv.name = 'INV/12345/0001'
|
|
self._pay_invoice(inv)
|
|
date_from = fields.Date.today()
|
|
date_to = date_from + get_timedelta(1, 'year') - relativedelta(days=1)
|
|
|
|
expected = f"""Commission on INV/12345/0001, Customer, 2,000.00{NON_BREAKING_SPACE}€\n{so.name}, \nOdoo.sh Worker: from {format_date(self.env, date_from)} to {format_date(self.env, date_to)} (12 month(s))"""
|
|
self.assertEqual(inv.commission_po_line_id.name, expected)
|
|
|
|
def test_purchase_representative(self):
|
|
self.referrer.commission_plan_id = self.gold_plan
|
|
self.referrer.grade_id = self.gold
|
|
|
|
def make_orders(product, so_sales_rep=None, sub_sales_rep=None):
|
|
form = Form(self.env['sale.order'].with_user(self.salesman).with_context(tracking_disable=True))
|
|
form.partner_id = self.customer
|
|
form.referrer_id = self.referrer
|
|
if so_sales_rep:
|
|
form.user_id = so_sales_rep
|
|
|
|
with form.order_line.new() as line:
|
|
line.name = product.name
|
|
line.product_id = product
|
|
line.product_uom_qty = 1
|
|
|
|
so = form.save()
|
|
so.action_confirm()
|
|
|
|
inv = so._create_invoices()
|
|
inv.action_post()
|
|
|
|
if so and sub_sales_rep:
|
|
so.sudo().user_id = sub_sales_rep
|
|
|
|
self._pay_invoice(inv)
|
|
|
|
po = inv.commission_po_line_id.order_id
|
|
|
|
return so, po
|
|
|
|
with self.subTest("SO's salesperson is assigned as Purchase Representative."):
|
|
foo = self.env['product.category'].create({
|
|
'name': 'foo',
|
|
})
|
|
bar = self.env['product.product'].create({
|
|
'name': 'bar',
|
|
'categ_id': foo.id,
|
|
'list_price': 100.0,
|
|
'purchase_ok': True,
|
|
'property_account_income_id': self.account_sale.id,
|
|
'invoice_policy': 'order',
|
|
})
|
|
self.env['sale.subscription.pricing'].create({'plan_id': self.plan_month.id, 'price': 20, 'product_template_id': bar.product_tmpl_id.id})
|
|
rule = self.env['commission.rule'].create({
|
|
'plan_id': self.gold_plan.id,
|
|
'category_id': foo.id,
|
|
'product_id': bar.id,
|
|
'rate': 10.0,
|
|
})
|
|
self.gold_plan.write({'commission_rule_ids': [(4, rule.id)]})
|
|
|
|
so, po = make_orders(bar)
|
|
|
|
self.assertEqual(so.user_id, self.salesman)
|
|
self.assertEqual(po.user_id, self.salesman)
|
|
|
|
with self.subTest("Each sales representative has its own PO."):
|
|
sales_rep = self.env['res.users'].create({
|
|
'name': '...',
|
|
'login': 'sales_rep_1',
|
|
'email': 'sales_rep_1@odoo.com',
|
|
'company_id': self.company.id,
|
|
'groups_id': [(6, 0, [self.ref('sales_team.group_sale_salesman')])],
|
|
})
|
|
|
|
so, po = make_orders(bar, so_sales_rep=sales_rep)
|
|
|
|
self.assertEqual(so.user_id, sales_rep)
|
|
self.assertEqual(po.user_id, sales_rep)
|
|
|
|
def test_access_rigths(self):
|
|
|
|
def user(name, group):
|
|
return self.env['res.users'].create({
|
|
'name': name,
|
|
'login': name,
|
|
'email': f'{name}@example.com',
|
|
'company_id': self.company.id,
|
|
'groups_id': [(6, 0, [
|
|
group,
|
|
])],
|
|
})
|
|
|
|
salesman_own_docs = user('salesman_own_docs', self.ref('sales_team.group_sale_salesman'))
|
|
salesman_all_docs = user('salesman_all_docs', self.ref('sales_team.group_sale_salesman_all_leads'))
|
|
commission_user_1 = user('commission_user_1', self.ref('partner_commission.group_commission_user'))
|
|
commission_user_2 = user('commission_user_2', self.ref('partner_commission.group_commission_user'))
|
|
commission_manager = user('commission_manager', self.ref('partner_commission.group_commission_manager'))
|
|
purchase_user = user('purchase_user', self.ref('purchase.group_purchase_user'))
|
|
|
|
po = self.env['purchase.order'].create({
|
|
'partner_id': self.customer.id,
|
|
'company_id': self.company.id,
|
|
'currency_id': self.company.currency_id.id,
|
|
'date_order': fields.Date.today(),
|
|
'user_id': commission_user_1.id,
|
|
})
|
|
|
|
def assert_access_denied(users):
|
|
for usr in users:
|
|
with self.assertRaises(AccessError, msg=f'{usr.name} should be denied access.'):
|
|
Form(po.with_user(usr))
|
|
|
|
def assert_access_allowed(users):
|
|
for usr in users:
|
|
Form(po.with_user(usr))
|
|
|
|
# commission_user should grant membership of group_sale_salesman
|
|
self.assertTrue(commission_user_1.has_group('sales_team.group_sale_salesman'))
|
|
|
|
# commission_manager should grant membership of group_commission_user:
|
|
self.assertTrue(commission_manager.has_group('partner_commission.group_commission_user'))
|
|
|
|
# group_purchase_user: can access procurement.
|
|
assert_access_allowed([purchase_user])
|
|
# other groups cannot.
|
|
assert_access_denied([salesman_own_docs, salesman_all_docs, commission_user_1, commission_manager])
|
|
|
|
# change PO from procurement to commission.
|
|
po.purchase_type = 'commission'
|
|
|
|
# group_purchase_user: can access commission.
|
|
assert_access_allowed([purchase_user])
|
|
|
|
# group_commission_user: cannot access someone else's commission.
|
|
assert_access_denied([commission_user_2])
|
|
|
|
# group_commission_user: can access commissions for which he/she is the purchase representative.
|
|
# group_commission_manager: can access all commissions.
|
|
assert_access_allowed([commission_user_1, commission_manager])
|