[ADD] Sale Advance Pricelist module

This commit is contained in:
Haresh Chavda 2018-04-11 17:06:23 +05:30
parent b9e6c2c48e
commit 822889a722
38 changed files with 3804 additions and 0 deletions

View File

@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
# Part of flectra. See LICENSE file for full copyright and licensing details.
from . import models

View File

@ -0,0 +1,42 @@
# -*- coding: utf-8 -*-
# Part of flectra. See LICENSE file for full copyright and licensing details.
{
'name': 'Sale Advance Ecommerce Pricelist',
'version': '1.0.0',
'category': 'Sale',
'author': 'FlectraHQ',
'website': 'https://flectrahq.com',
'sequence': 25,
'summary': 'Add Price Rules, Cart Rules and Coupon Rules',
'description': """
Pricelist
=========
Main Features
-------------
* Price Rules
* Cart Rules
* Coupon Rules
* View Calculation of all discount
""",
'depends': ['sales_discount'],
'data': [
'security/ir.model.access.csv',
'data/pricelist_view.xml',
'views/pricelist_view.xml',
'views/price_rule_view.xml',
'views/sale_views.xml',
'views/sale_pricelist.xml',
],
'demo': [
'demo/res_partner_demo.xml',
'demo/price_rule_demo.xml',
'demo/cart_rule_view_data.xml',
'demo/coupon_code_demo.xml',
'demo/sale_order_demo.xml',
],
'qweb': [
"static/src/xml/discount_details_view.xml",
],
'auto_install': False
}

View File

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<flectra noupdate="1">
<!-- Pricelist with First Matched Rule -->
<record id="advance_pricelist" model="product.pricelist">
<field name="name">Advance Pricelist (First Matched Rule) </field>
<field name="sequence">2</field>
<field name="discount_policy">without_discount</field>
<field name="pricelist_type">advance</field>
<field name="currency_id" ref="base.USD"/>
</record>
<!-- Pricelist with First Matched Rule and Coupon Code -->
<record id="advance_pricelist_with_coupon" model="product.pricelist">
<field name="name">Advance Pricelist (First Matched Rule With Coupon)</field>
<field name="sequence">3</field>
<field name="discount_policy">without_discount</field>
<field name="pricelist_type">advance</field>
<field name="apply_coupon_code">true</field>
<field name="currency_id" ref="base.USD"/>
</record>
<!-- Pricelist with All Matched Rule -->
<record id="advance_pricelist_all" model="product.pricelist">
<field name="name">Advance Pricelist with All Matched Rule</field>
<field name="sequence">3</field>
<field name="discount_policy">without_discount</field>
<field name="pricelist_type">advance</field>
<field name="apply_method">all_matched_rules</field>
<field name="currency_id" ref="base.USD"/>
</record>
</flectra>

View File

@ -0,0 +1,63 @@
<?xml version="1.0" encoding="utf-8"?>
<flectra noupdate="1">
<!-- Cart Rules -->
<record id="cart_rule_1" model="cart.rule">
<field name="apply_on">subtotal_at_least</field>
<field name="sequence">1</field>
<field name="discount_percentage">6.5</field>
<field name="amt_value">2500</field>
<field name="pricelist_id" ref="advance_pricelist"/>
</record>
<record id="cart_rule_2" model="cart.rule">
<field name="apply_on">one_product_al_least</field>
<field name="sequence">2</field>
<field name="discount_percentage">5</field>
<field name="product_id" ref="product.product_product_16"/>
<field name="pricelist_id" ref="advance_pricelist"/>
<field name="start_date" eval="DateTime.now()"/>
<field name="end_date" eval="DateTime.now() + timedelta(days=1)"/>
</record>
<record id="cart_rule_3" model="cart.rule">
<field name="apply_on">subtotal_less_than</field>
<field name="sequence">1</field>
<field name="discount_percentage">2.5</field>
<field name="amt_value">3000</field>
<field name="pricelist_id" ref="advance_pricelist_with_coupon"/>
</record>
<record id="cart_rule_4" model="cart.rule">
<field name="apply_on">item_sum_qty_atleast</field>
<field name="sequence">2</field>
<field name="discount_percentage">10</field>
<field name="amt_value">7</field>
<field name="pricelist_id" ref="advance_pricelist_with_coupon"/>
</record>
<record id="cart_rule_all_1" model="cart.rule">
<field name="apply_on">item_count_atleast</field>
<field name="sequence">1</field>
<field name="discount_percentage">7</field>
<field name="amt_value">6</field>
<field name="pricelist_id" ref="advance_pricelist_all"/>
</record>
<record id="cart_rule_all_2" model="cart.rule">
<field name="apply_on">item_count_less_than</field>
<field name="sequence">2</field>
<field name="discount_percentage">4</field>
<field name="amt_value">4</field>
<field name="pricelist_id" ref="advance_pricelist_all"/>
</record>
<record id="cart_rule_all_3" model="cart.rule">
<field name="apply_on">one_categ_al_least</field>
<field name="sequence">3</field>
<field name="discount_percentage">3.5</field>
<field name="categ_id" ref="product.product_category_5"/>
<field name="pricelist_id" ref="advance_pricelist_all"/>
</record>
</flectra>

View File

@ -0,0 +1,87 @@
<?xml version="1.0" encoding="utf-8"?>
<flectra noupdate="1">
<record id="coupon_code_1" model="coupon.code">
<field name="name">Get10%</field>
<field name="coupon_code">Get10Peroff</field>
<field name="code_valid_from" eval="DateTime.now()"/>
<field name="code_valid_to" eval="DateTime.now() + timedelta(days=2)"/>
<field name="coupon_type">percent</field>
<field name="usage_limit">5</field>
<field name="discount_amount">10</field>
<field name="min_order_amount">2500</field>
<field name="apply_on">all</field>
<field name="pricelist_id" ref="advance_pricelist_with_coupon"/>
</record>
<record id="coupon_code_2" model="coupon.code">
<field name="name">Get20-Off-per-Quantity</field>
<field name="coupon_code">Get20off</field>
<field name="code_valid_from" eval="DateTime.now()"/>
<field name="code_valid_to" eval="DateTime.now() + timedelta(days=2)"/>
<field name="coupon_type">fixed_amount</field>
<field name="usage_limit">5</field>
<field name="discount_amount">20</field>
<field name="min_order_amount">2500</field>
<field name="apply_on">all</field>
<field name="pricelist_id" ref="advance_pricelist_with_coupon"/>
</record>
<record id="coupon_code_3" model="coupon.code">
<field name="name">Buy X Product Get Y Product Free</field>
<field name="coupon_code">BXGYFree</field>
<field name="code_valid_from" eval="DateTime.now()"/>
<field name="code_valid_to" eval="DateTime.now() + timedelta(days=2)"/>
<field name="coupon_type">buy_x_get_y</field>
<field name="usage_limit">5</field>
<field name="number_of_x_product">3</field>
<field name="number_of_y_product">1</field>
<field name="min_order_amount">4000</field>
<field name="apply_on">all</field>
<field name="pricelist_id" ref="advance_pricelist_with_coupon"/>
</record>
<record id="coupon_code_4" model="coupon.code">
<field name="name">Buy X Product Get Y Other Product Free</field>
<field name="coupon_code">BXGYOtherFree</field>
<field name="code_valid_from" eval="DateTime.now()"/>
<field name="code_valid_to" eval="DateTime.now() + timedelta(days=2)"/>
<field name="coupon_type">buy_x_get_y_other</field>
<field name="usage_limit">5</field>
<field name="number_of_x_product">2</field>
<field name="number_of_y_product">1</field>
<field name="other_product_id" ref="product.product_product_16"/>
<field name="min_order_amount">4000</field>
<field name="apply_on">all</field>
<field name="pricelist_id" ref="advance_pricelist_with_coupon"/>
</record>
<record id="coupon_code_5" model="coupon.code">
<field name="name">Clubbed Discount</field>
<field name="coupon_code">CD15Per</field>
<field name="code_valid_from" eval="DateTime.now()"/>
<field name="code_valid_to" eval="DateTime.now() + timedelta(days=2)"/>
<field name="coupon_type">clubbed</field>
<field name="usage_limit">5</field>
<field name="flat_discount">10</field>
<field name="extra_discount_percentage">5</field>
<field name="min_order_amount">3000</field>
<field name="apply_on">all</field>
<field name="pricelist_id" ref="advance_pricelist_with_coupon"/>
</record>
<record id="coupon_code_6" model="coupon.code">
<field name="name">Buy X Product Get Percent Free</field>
<field name="coupon_code">BXGPercentFree</field>
<field name="code_valid_from" eval="DateTime.now()"/>
<field name="code_valid_to" eval="DateTime.now() + timedelta(days=2)"/>
<field name="coupon_type">buy_x_get_percent</field>
<field name="usage_limit">3</field>
<field name="number_of_x_product">3</field>
<field name="discount_amount">7.75</field>
<field name="min_order_amount">2500</field>
<field name="apply_on">all</field>
<field name="pricelist_id" ref="advance_pricelist_with_coupon"/>
</record>
</flectra>

View File

@ -0,0 +1,125 @@
<?xml version="1.0" encoding="utf-8"?>
<flectra noupdate="1">
<!-- Price Rules: First Matched Rule without Coupon -->
<record id="price_rule_1" model="price.rule">
<field name="apply_on">all</field>
<field name="sequence">1</field>
<field name="pricelist_id" ref="advance_pricelist"/>
</record>
<!-- Product Rule Line: First Matched Rule without Coupon-->
<record id="price_rule_line_1" model="rule.line">
<field name="sequence">1</field>
<field name="min_qty">1</field>
<field name="max_qty">5</field>
<field name="rule_type">fixed_amount</field>
<field name="discount_amount">50</field>
<field name="price_rule_id" ref="price_rule_1"/>
</record>
<record id="price_rule_line_2" model="rule.line">
<field name="sequence">2</field>
<field name="min_qty">11</field>
<field name="max_qty">15</field>
<field name="rule_type">percent</field>
<field name="discount_amount">12</field>
<field name="price_rule_id" ref="price_rule_1"/>
<field name="start_date" eval="DateTime.today() - timedelta(days=4)"/>
<field name="end_date" eval="DateTime.now() + timedelta(days=3)"/>
</record>
<!-- Product Rule Line: First Matched Rule without Coupon-->
<record id="price_rule_2" model="price.rule">
<field name="apply_on">category</field>
<field name="categ_id" ref="product.product_category_5"/>
<field name="sequence">2</field>
<field name="pricelist_id" ref="advance_pricelist"/>
<field name="start_date" eval="DateTime.today() - timedelta(days=7)"/>
<field name="end_date" eval="DateTime.now() + timedelta(days=5)"/>
</record>
<record id="price_rule_line_3" model="rule.line">
<field name="sequence">1</field>
<field name="min_qty">1</field>
<field name="max_qty">5</field>
<field name="rule_type">percent</field>
<field name="discount_amount">5</field>
<field name="price_rule_id" ref="price_rule_2"/>
<field name="start_date" eval="DateTime.today() - timedelta(days=1)"/>
<field name="end_date" eval="DateTime.now() + timedelta(days=3)"/>
</record>
<record id="price_rule_line_4" model="rule.line">
<field name="sequence">2</field>
<field name="min_qty">8</field>
<field name="max_qty">15</field>
<field name="rule_type">percent</field>
<field name="discount_amount">8</field>
<field name="price_rule_id" ref="price_rule_2"/>
<field name="start_date" eval="DateTime.today() - timedelta(days=2)"/>
<field name="end_date" eval="DateTime.now() + timedelta(days=3)"/>
</record>
<!-- Price Rules: First Matched Rule with Coupon-->
<record id="price_rule_with_coupon" model="price.rule">
<field name="apply_on">all</field>
<field name="sequence">1</field>
<field name="pricelist_id" ref="advance_pricelist_with_coupon"/>
</record>
<!-- Product Rule Line: First Matched Rule with Coupon-->
<record id="price_rule_line_5" model="rule.line">
<field name="sequence">1</field>
<field name="min_qty">1</field>
<field name="max_qty">6</field>
<field name="rule_type">percent</field>
<field name="discount_amount">4.9</field>
<field name="price_rule_id" ref="price_rule_with_coupon"/>
</record>
<record id="price_rule_line_6" model="rule.line">
<field name="sequence">1</field>
<field name="min_qty">11</field>
<field name="max_qty">15</field>
<field name="rule_type">percent</field>
<field name="discount_amount">9.5</field>
<field name="price_rule_id" ref="price_rule_with_coupon"/>
</record>
<!-- Price Rules: All Matched Rule without Coupon -->
<record id="price_rule_4" model="price.rule">
<field name="apply_on">all</field>
<field name="sequence">1</field>
<field name="pricelist_id" ref="advance_pricelist_all"/>
</record>
<!-- Product Rule Line: All Matched Rule without Coupon-->
<record id="price_rule_line_all_1" model="rule.line">
<field name="sequence">1</field>
<field name="min_qty">1</field>
<field name="max_qty">3</field>
<field name="rule_type">percent</field>
<field name="discount_amount">3</field>
<field name="price_rule_id" ref="price_rule_4"/>
</record>
<record id="price_rule_line_all_2" model="rule.line">
<field name="sequence">1</field>
<field name="min_qty">4</field>
<field name="max_qty">8</field>
<field name="rule_type">percent</field>
<field name="discount_amount">5</field>
<field name="price_rule_id" ref="price_rule_4"/>
</record>
<record id="price_rule_line_all_3" model="rule.line">
<field name="sequence">1</field>
<field name="min_qty">9</field>
<field name="max_qty">15</field>
<field name="rule_type">percent</field>
<field name="discount_amount">7</field>
<field name="price_rule_id" ref="price_rule_4"/>
</record>
</flectra>

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<flectra noupdate="1">
<record id="sales_team.group_sale_salesman_all_leads" model="res.groups">
<field name="implied_ids" eval="[(4, ref('sales_team.group_sale_salesman')), (4, ref('sale.group_discount_per_so_line'))]"/>
</record>
<record id="base.main_company" model="res.company">
<field name="currency_id" ref="base.USD"/>
</record>
<record id="res_partner_advance_pricelist" model="res.partner">
<field name="name">Josheph</field>
<field eval="[(6, 0, [ref('base.res_partner_category_7'), ref('base.res_partner_category_9')])]" name="category_id"/>
<field name="is_company">1</field>
<field name="city">Baltimore</field>
<field name="zip">21201</field>
<field name="country_id" ref="base.us"/>
<field name="email">Josheph@yourcompany.example.com</field>
<field name="property_product_pricelist" ref="advance_pricelist_with_coupon"/>
</record>
</flectra>

View File

@ -0,0 +1,312 @@
<?xml version="1.0" encoding="utf-8"?>
<flectra noupdate="1">
<!-- Without Coupon Code -->
<record id="sale_order_ap_1" model="sale.order">
<field name="partner_id" ref="res_partner_advance_pricelist"/>
<field name="partner_invoice_id" ref="res_partner_advance_pricelist"/>
<field name="partner_shipping_id" ref="res_partner_advance_pricelist"/>
<field name="user_id" ref="base.user_demo"/>
<field name="pricelist_id" ref="advance_pricelist"/>
<field name="team_id" ref="sales_team.team_sales_department"/>
<field name="date_order" eval="DateTime.today() - timedelta(days=4)"/>
</record>
<record id="sale_order_line_ap_1" model="sale.order.line">
<field name="order_id" ref="sale_order_ap_1"/>
<field name="name">Graphics Card</field>
<field name="product_id" ref="product.product_product_24"/>
<field name="product_uom_qty">5</field>
<field name="product_uom" ref="product.product_uom_unit"/>
<field name="price_unit">885.0</field>
</record>
<record id="sale_order_line_ap_2" model="sale.order.line">
<field name="order_id" ref="sale_order_ap_1"/>
<field name="name">Laptop E5023</field>
<field name="product_id" ref="product.product_product_25"/>
<field name="product_uom_qty">3</field>
<field name="product_uom" ref="product.product_uom_unit"/>
<field name="price_unit">2950.00</field>
</record>
<record id="sale_order_line_ap_2_1" model="sale.order.line">
<field name="order_id" ref="sale_order_ap_1"/>
<field name="name">Computer Case</field>
<field name="product_id" ref="product.product_product_16"/>
<field name="product_uom_qty">3</field>
<field name="product_uom" ref="product.product_uom_unit"/>
<field name="price_unit">25</field>
</record>
<function model="sale.order" name="_check_cart_rules"
eval="[ref('sale_order_ap_1')]"/>
<!-- Coupon Code Percentage -->
<record id="sale_order_ap_2" model="sale.order">
<field name="partner_id" ref="res_partner_advance_pricelist"/>
<field name="partner_invoice_id" ref="res_partner_advance_pricelist"/>
<field name="partner_shipping_id" ref="res_partner_advance_pricelist"/>
<field name="user_id" ref="base.user_demo"/>
<field name="pricelist_id" ref="advance_pricelist_with_coupon"/>
<field name="team_id" ref="sales_team.team_sales_department"/>
<field name="date_order" eval="DateTime.today() - timedelta(days=2)"/>
</record>
<record id="sale_order_line_ap_3" model="sale.order.line">
<field name="order_id" ref="sale_order_ap_2"/>
<field name="name">Graphics Card</field>
<field name="product_id" ref="product.product_product_24"/>
<field name="product_uom_qty">5</field>
<field name="product_uom" ref="product.product_uom_unit"/>
<field name="price_unit">885.0</field>
</record>
<record id="sale_order_line_ap_4" model="sale.order.line">
<field name="order_id" ref="sale_order_ap_2"/>
<field name="name">Laptop E5023</field>
<field name="product_id" ref="product.product_product_25"/>
<field name="product_uom_qty">3</field>
<field name="product_uom" ref="product.product_uom_unit"/>
<field name="price_unit">2950.00</field>
</record>
<function model="sale.order" name="_check_cart_rules"
eval="[ref('sale_order_ap_2')]"/>
<record id="sale_advance_pricelist.sale_order_ap_2" model="sale.order">
<field name="have_coupon_code">Get10Peroff</field>
</record>
<function model="sale.order" name="apply_coupon_code"
eval="[ref('sale_order_ap_2')]"/>
<!-- Coupon Code Fixed -->
<record id="sale_order_ap_3" model="sale.order">
<field name="partner_id" ref="res_partner_advance_pricelist"/>
<field name="partner_invoice_id" ref="res_partner_advance_pricelist"/>
<field name="partner_shipping_id" ref="res_partner_advance_pricelist"/>
<field name="user_id" ref="base.user_demo"/>
<field name="pricelist_id" ref="advance_pricelist_with_coupon"/>
<field name="team_id" ref="sales_team.team_sales_department"/>
<field name="date_order" eval="DateTime.today() - timedelta(days=4)"/>
</record>
<record id="sale_order_line_ap_fixed_1" model="sale.order.line">
<field name="order_id" ref="sale_order_ap_3"/>
<field name="name">Graphics Card</field>
<field name="product_id" ref="product.product_product_24"/>
<field name="product_uom_qty">5</field>
<field name="product_uom" ref="product.product_uom_unit"/>
<field name="price_unit">885.0</field>
</record>
<record id="sale_order_line_ap_fixed_2" model="sale.order.line">
<field name="order_id" ref="sale_order_ap_3"/>
<field name="name">Laptop E5023</field>
<field name="product_id" ref="product.product_product_25"/>
<field name="product_uom_qty">3</field>
<field name="product_uom" ref="product.product_uom_unit"/>
<field name="price_unit">2950.00</field>
</record>
<function model="sale.order" name="_check_cart_rules"
eval="[ref('sale_order_ap_3')]"/>
<record id="sale_advance_pricelist.sale_order_ap_3" model="sale.order">
<field name="have_coupon_code">Get20off</field>
</record>
<function model="sale.order" name="apply_coupon_code"
eval="[ref('sale_order_ap_3')]"/>
<!-- Coupon Code Buy X Product Get Y Product Free -->
<record id="sale_order_ap_4" model="sale.order">
<field name="partner_id" ref="res_partner_advance_pricelist"/>
<field name="partner_invoice_id" ref="res_partner_advance_pricelist"/>
<field name="partner_shipping_id" ref="res_partner_advance_pricelist"/>
<field name="user_id" ref="base.user_demo"/>
<field name="pricelist_id" ref="advance_pricelist_with_coupon"/>
<field name="team_id" ref="sales_team.team_sales_department"/>
<field name="date_order" eval="DateTime.today() - timedelta(days=4)"/>
</record>
<record id="sale_order_line_ap_bxgy_free_1" model="sale.order.line">
<field name="order_id" ref="sale_order_ap_4"/>
<field name="name">Graphics Card</field>
<field name="product_id" ref="product.product_product_24"/>
<field name="product_uom_qty">5</field>
<field name="product_uom" ref="product.product_uom_unit"/>
<field name="price_unit">885.0</field>
</record>
<record id="sale_order_line_ap_bxgy_free_2" model="sale.order.line">
<field name="order_id" ref="sale_order_ap_4"/>
<field name="name">Laptop E5023</field>
<field name="product_id" ref="product.product_product_25"/>
<field name="product_uom_qty">3</field>
<field name="product_uom" ref="product.product_uom_unit"/>
<field name="price_unit">2950.00</field>
</record>
<function model="sale.order" name="_check_cart_rules"
eval="[ref('sale_order_ap_4')]"/>
<record id="sale_advance_pricelist.sale_order_ap_4" model="sale.order">
<field name="have_coupon_code">BXGYFree</field>
</record>
<function model="sale.order" name="apply_coupon_code"
eval="[ref('sale_order_ap_4')]"/>
<!-- Coupon Code Buy X Product Get Y Other Product Free -->
<record id="sale_order_ap_5" model="sale.order">
<field name="partner_id" ref="res_partner_advance_pricelist"/>
<field name="partner_invoice_id" ref="res_partner_advance_pricelist"/>
<field name="partner_shipping_id" ref="res_partner_advance_pricelist"/>
<field name="user_id" ref="base.user_demo"/>
<field name="pricelist_id" ref="advance_pricelist_with_coupon"/>
<field name="team_id" ref="sales_team.team_sales_department"/>
<field name="date_order" eval="DateTime.today() - timedelta(days=4)"/>
</record>
<record id="sale_order_line_ap_bxgyother_free_1" model="sale.order.line">
<field name="order_id" ref="sale_order_ap_5"/>
<field name="name">Graphics Card</field>
<field name="product_id" ref="product.product_product_24"/>
<field name="product_uom_qty">5</field>
<field name="product_uom" ref="product.product_uom_unit"/>
<field name="price_unit">885.0</field>
</record>
<record id="sale_order_line_ap_bxgyother_free_2" model="sale.order.line">
<field name="order_id" ref="sale_order_ap_5"/>
<field name="name">Laptop E5023</field>
<field name="product_id" ref="product.product_product_25"/>
<field name="product_uom_qty">3</field>
<field name="product_uom" ref="product.product_uom_unit"/>
<field name="price_unit">2950.00</field>
</record>
<function model="sale.order" name="_check_cart_rules"
eval="[ref('sale_order_ap_5')]"/>
<record id="sale_advance_pricelist.sale_order_ap_5" model="sale.order">
<field name="have_coupon_code">BXGYOtherFree</field>
</record>
<function model="sale.order" name="apply_coupon_code"
eval="[ref('sale_order_ap_5')]"/>
<!-- Coupon Code Buy X Product Get Percentage Free -->
<record id="sale_order_ap_7" model="sale.order">
<field name="partner_id" ref="res_partner_advance_pricelist"/>
<field name="partner_invoice_id" ref="res_partner_advance_pricelist"/>
<field name="partner_shipping_id" ref="res_partner_advance_pricelist"/>
<field name="user_id" ref="base.user_demo"/>
<field name="pricelist_id" ref="advance_pricelist_with_coupon"/>
<field name="team_id" ref="sales_team.team_sales_department"/>
<field name="date_order" eval="DateTime.today() - timedelta(days=4)"/>
</record>
<record id="sale_order_line_ap_bxgpfree_1" model="sale.order.line">
<field name="order_id" ref="sale_order_ap_7"/>
<field name="name">Graphics Card</field>
<field name="product_id" ref="product.product_product_24"/>
<field name="product_uom_qty">5</field>
<field name="product_uom" ref="product.product_uom_unit"/>
<field name="price_unit">885.0</field>
</record>
<record id="sale_order_line_ap_bxgpfree_2" model="sale.order.line">
<field name="order_id" ref="sale_order_ap_7"/>
<field name="name">Laptop E5023</field>
<field name="product_id" ref="product.product_product_25"/>
<field name="product_uom_qty">2</field>
<field name="product_uom" ref="product.product_uom_unit"/>
<field name="price_unit">2950.00</field>
</record>
<function model="sale.order" name="_check_cart_rules"
eval="[ref('sale_order_ap_7')]"/>
<record id="sale_advance_pricelist.sale_order_ap_7" model="sale.order">
<field name="have_coupon_code">BXGPercentFree</field>
</record>
<function model="sale.order" name="apply_coupon_code"
eval="[ref('sale_order_ap_7')]"/>
<!-- Coupon Code Clubbed Discount -->
<record id="sale_order_ap_6" model="sale.order">
<field name="partner_id" ref="res_partner_advance_pricelist"/>
<field name="partner_invoice_id" ref="res_partner_advance_pricelist"/>
<field name="partner_shipping_id" ref="res_partner_advance_pricelist"/>
<field name="user_id" ref="base.user_demo"/>
<field name="pricelist_id" ref="advance_pricelist_with_coupon"/>
<field name="team_id" ref="sales_team.team_sales_department"/>
<field name="date_order" eval="DateTime.today() - timedelta(days=4)"/>
</record>
<record id="sale_order_line_ap_clubbed_1" model="sale.order.line">
<field name="order_id" ref="sale_order_ap_6"/>
<field name="name">Graphics Card</field>
<field name="product_id" ref="product.product_product_24"/>
<field name="product_uom_qty">5</field>
<field name="product_uom" ref="product.product_uom_unit"/>
<field name="price_unit">885.0</field>
</record>
<record id="sale_order_line_ap_clubbed_2" model="sale.order.line">
<field name="order_id" ref="sale_order_ap_6"/>
<field name="name">Laptop E5023</field>
<field name="product_id" ref="product.product_product_25"/>
<field name="product_uom_qty">3</field>
<field name="product_uom" ref="product.product_uom_unit"/>
<field name="price_unit">2950.00</field>
</record>
<function model="sale.order" name="_check_cart_rules"
eval="[ref('sale_order_ap_6')]"/>
<record id="sale_advance_pricelist.sale_order_ap_6" model="sale.order">
<field name="have_coupon_code">CD15Per</field>
</record>
<function model="sale.order" name="apply_coupon_code"
eval="[ref('sale_order_ap_6')]"/>
<!-- All Matched Rules -->
<record id="sale_order_ap_all_1" model="sale.order">
<field name="partner_id" ref="res_partner_advance_pricelist"/>
<field name="partner_invoice_id" ref="res_partner_advance_pricelist"/>
<field name="partner_shipping_id" ref="res_partner_advance_pricelist"/>
<field name="user_id" ref="base.user_demo"/>
<field name="pricelist_id" ref="advance_pricelist_all"/>
<field name="team_id" ref="sales_team.team_sales_department"/>
<field name="date_order" eval="DateTime.today() - timedelta(days=4)"/>
</record>
<record id="sale_order_line_ap_all_1" model="sale.order.line">
<field name="order_id" ref="sale_order_ap_all_1"/>
<field name="name">Graphics Card</field>
<field name="product_id" ref="product.product_product_24"/>
<field name="product_uom_qty">5</field>
<field name="product_uom" ref="product.product_uom_unit"/>
<field name="price_unit">885.0</field>
</record>
<record id="sale_order_line_ap_all_2" model="sale.order.line">
<field name="order_id" ref="sale_order_ap_all_1"/>
<field name="name">Laptop E5023</field>
<field name="product_id" ref="product.product_product_25"/>
<field name="product_uom_qty">3</field>
<field name="product_uom" ref="product.product_uom_unit"/>
<field name="price_unit">2950.00</field>
</record>
<function model="sale.order" name="_check_cart_rules"
eval="[ref('sale_order_ap_all_1')]"/>
</flectra>

View File

@ -0,0 +1,607 @@
# Translation of Flectra Server.
# This file contains the translation of the following modules:
# * sale_advance_pricelist
#
msgid ""
msgstr ""
"Project-Id-Version: Flectra Server 1.1\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-04-12 05:50+0000\n"
"PO-Revision-Date: 2018-04-12 05:50+0000\n"
"Last-Translator: <>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: sale_advance_pricelist
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_coupon_code_sale_order_count
msgid "# of Sale Order"
msgstr "# of Sale Order"
#. module: sale_advance_pricelist
#: model:ir.ui.view,arch_db:sale_advance_pricelist.view_coupon_code_form
msgid "+ Extra"
msgstr "+ Extra"
#. module: sale_advance_pricelist
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_cart_rule_active
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_coupon_code_active
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_price_rule_active
msgid "Active"
msgstr "Active"
#. module: sale_advance_pricelist
#: model:product.pricelist,name:sale_advance_pricelist.advance_pricelist_with_coupon
msgid "Advance Pricelist (First Matched Rule With Coupon)"
msgstr "Advance Pricelist (First Matched Rule With Coupon)"
#. module: sale_advance_pricelist
#: model:product.pricelist,name:sale_advance_pricelist.advance_pricelist
msgid "Advance Pricelist (First Matched Rule) "
msgstr "Advance Pricelist (First Matched Rule) "
#. module: sale_advance_pricelist
#: model:product.pricelist,name:sale_advance_pricelist.advance_pricelist_all
msgid "Advance Pricelist with All Matched Rule"
msgstr "Advance Pricelist with All Matched Rule"
#. module: sale_advance_pricelist
#: selection:product.pricelist,pricelist_type:0
msgid "Advanced"
msgstr "Advanced"
#. module: sale_advance_pricelist
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_cart_rule_amt_value
msgid "Amount"
msgstr "Amount"
#. module: sale_advance_pricelist
#: model:ir.ui.view,arch_db:sale_advance_pricelist.product_pricelist_view_flectra
#: model:ir.ui.view,arch_db:sale_advance_pricelist.view_cart_rule_tree
#: model:ir.ui.view,arch_db:sale_advance_pricelist.view_coupon_code_tree
#: model:ir.ui.view,arch_db:sale_advance_pricelist.view_price_rule_tree
msgid "Applicable On"
msgstr "Applicable On"
#. module: sale_advance_pricelist
#: selection:product.pricelist,apply_method:0
msgid "Apply All Matched Rules"
msgstr "Apply All Matched Rules"
#. module: sale_advance_pricelist
#: selection:product.pricelist,apply_method:0
msgid "Apply Biggest Matched Discount"
msgstr "Apply Biggest Matched Discount"
#. module: sale_advance_pricelist
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_sale_order_line_check_coupon
msgid "Apply Coupon"
msgstr "Apply Coupon"
#. module: sale_advance_pricelist
#: model:ir.ui.view,arch_db:sale_advance_pricelist.view_order_form_flectra
msgid "Apply Coupon Code"
msgstr "Apply Coupon Code"
#. module: sale_advance_pricelist
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_product_pricelist_apply_coupon_code
msgid "Apply Coupon Code?"
msgstr "Apply Coupon Code?"
#. module: sale_advance_pricelist
#: selection:product.pricelist,apply_method:0
msgid "Apply First Matched Rule"
msgstr "Apply First Matched Rule"
#. module: sale_advance_pricelist
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_product_pricelist_apply_method
msgid "Apply Method"
msgstr "Apply Method"
#. module: sale_advance_pricelist
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_cart_rule_apply_on
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_coupon_code_apply_on
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_price_rule_apply_on
msgid "Apply On"
msgstr "Apply On"
#. module: sale_advance_pricelist
#: selection:product.pricelist,apply_method:0
msgid "Apply Smallest Matched Discount"
msgstr "Apply Smallest Matched Discount"
#. module: sale_advance_pricelist
#: selection:cart.rule,apply_on:0
msgid "At least one category in order"
msgstr "At least one category in order"
#. module: sale_advance_pricelist
#: selection:cart.rule,apply_on:0
msgid "At least one product in order"
msgstr "At least one product in order"
#. module: sale_advance_pricelist
#: selection:product.pricelist,pricelist_type:0
msgid "Basic"
msgstr "Basic"
#. module: sale_advance_pricelist
#: selection:coupon.code,coupon_type:0
msgid "Buy X Product Get Y Other Product Free"
msgstr "Buy X Product Get Y Other Product Free"
#. module: sale_advance_pricelist
#: selection:coupon.code,coupon_type:0
msgid "Buy X Product Get Y Product Free"
msgstr "Buy X Product Get Y Product Free"
#. module: sale_advance_pricelist
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_sale_order_cart_discount
msgid "Cart Discount"
msgstr "Cart Discount"
#. module: sale_advance_pricelist
#: model:ir.ui.view,arch_db:sale_advance_pricelist.view_cart_rule_form
msgid "Cart Rule"
msgstr "Cart Rule"
#. module: sale_advance_pricelist
#: model:ir.model,name:sale_advance_pricelist.model_cart_rule
#: model:ir.ui.view,arch_db:sale_advance_pricelist.product_pricelist_view_flectra
#: model:ir.ui.view,arch_db:sale_advance_pricelist.view_cart_rule_tree
msgid "Cart Rules"
msgstr "Cart Rules"
#. module: sale_advance_pricelist
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_product_pricelist_cart_rule_ids
msgid "Cart Rules Items"
msgstr "Cart Rules Items"
#. module: sale_advance_pricelist
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_cart_rule_categ_ids
msgid "Categories"
msgstr "Categories"
#. module: sale_advance_pricelist
#: selection:coupon.code,apply_on:0
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_cart_rule_categ_id
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_coupon_code_categ_id
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_coupon_code_other_categ_id
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_price_rule_categ_id
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_rule_line_categ_id
#: selection:price.rule,apply_on:0
msgid "Category"
msgstr "Category"
#. module: sale_advance_pricelist
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_sale_order_coupon_flag
msgid "Check Coupon Apply"
msgstr "Check Coupon Apply"
#. module: sale_advance_pricelist
#: selection:coupon.code,coupon_type:0
msgid "Clubbed Discount"
msgstr "Clubbed Discount"
#. module: sale_advance_pricelist
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_coupon_code_model_id
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_rule_line_model_id
#: model:ir.ui.view,arch_db:sale_advance_pricelist.view_coupon_code_form
#: model:ir.ui.view,arch_db:sale_advance_pricelist.view_price_rule_form
msgid "Condition"
msgstr "Condition"
#. module: sale_advance_pricelist
#: model:ir.ui.view,arch_db:sale_advance_pricelist.view_coupon_code_form
#: model:ir.ui.view,arch_db:sale_advance_pricelist.view_coupon_code_tree
msgid "Coupon"
msgstr "Coupon"
#. module: sale_advance_pricelist
#: model:ir.model,name:sale_advance_pricelist.model_coupon_code
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_coupon_code_coupon_code
#: model:ir.ui.view,arch_db:sale_advance_pricelist.product_pricelist_view_flectra
msgid "Coupon Code"
msgstr "Coupon Code"
#. module: sale_advance_pricelist
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_product_pricelist_coupon_code_lines
msgid "Coupon Code Items"
msgstr "Coupon Code Items"
#. module: sale_advance_pricelist
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_sale_order_coupon_code_id
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_sale_order_line_coupon_code_id
msgid "Coupon Ref"
msgstr "Coupon Ref"
#. module: sale_advance_pricelist
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_coupon_code_coupon_type
msgid "Coupon Type"
msgstr "Coupon Type"
#. module: sale_advance_pricelist
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_cart_rule_create_uid
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_coupon_code_create_uid
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_price_rule_create_uid
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_rule_line_create_uid
msgid "Created by"
msgstr "Created by"
#. module: sale_advance_pricelist
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_cart_rule_create_date
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_coupon_code_create_date
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_price_rule_create_date
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_rule_line_create_date
msgid "Created on"
msgstr "Created on"
#. module: sale_advance_pricelist
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_cart_rule_note
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_price_rule_note
msgid "Description"
msgstr "Description"
#. module: sale_advance_pricelist
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_cart_rule_discount_percentage
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_sale_order_line_dummy_discount
msgid "Discount (%)"
msgstr "Discount (%)"
#. module: sale_advance_pricelist
#: model:ir.ui.view,arch_db:sale_advance_pricelist.view_coupon_code_form
msgid "Discount ="
msgstr "Discount ="
#. module: sale_advance_pricelist
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_coupon_code_discount_amount
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_rule_line_discount_amount
msgid "Discount Amount"
msgstr "Discount Amount"
#. module: sale_advance_pricelist
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_sale_order_amount_words
msgid "Discount Amount Words"
msgstr "Discount Amount Words"
#. module: sale_advance_pricelist
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_sale_order_discount_widget
msgid "Discount Widget"
msgstr "Discount Widget"
#. module: sale_advance_pricelist
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_cart_rule_display_name
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_coupon_code_display_name
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_price_rule_display_name
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_rule_line_display_name
msgid "Display Name"
msgstr "Display Name"
#. module: sale_advance_pricelist
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_coupon_code_model_domain
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_rule_line_model_domain
msgid "Domain"
msgstr "Domain"
#. module: sale_advance_pricelist
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_cart_rule_end_date
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_price_rule_end_date
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_rule_line_end_date
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_rule_line_rule_id_end_date
msgid "End Date"
msgstr "End Date"
#. module: sale_advance_pricelist
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_coupon_code_extra_discount_percentage
msgid "Extra Discount"
msgstr "Extra Discount"
#. module: sale_advance_pricelist
#: selection:coupon.code,coupon_type:0
#: selection:rule.line,rule_type:0
msgid "Fixed Amount"
msgstr "Fixed Amount"
#. module: sale_advance_pricelist
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_coupon_code_flat_discount
msgid "Flat Discount"
msgstr "Flat Discount"
#. module: sale_advance_pricelist
#: selection:coupon.code,apply_on:0
#: selection:price.rule,apply_on:0
msgid "Global"
msgstr "Global"
#. module: sale_advance_pricelist
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_sale_order_have_coupon_code
msgid "Have Coupon Code"
msgstr "Have Coupon Code"
#. module: sale_advance_pricelist
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_cart_rule_id
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_coupon_code_id
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_price_rule_id
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_rule_line_id
msgid "ID"
msgstr "ID"
#. module: sale_advance_pricelist
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_cart_rule___last_update
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_coupon_code___last_update
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_price_rule___last_update
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_rule_line___last_update
msgid "Last Modified on"
msgstr "Last Modified on"
#. module: sale_advance_pricelist
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_cart_rule_write_uid
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_coupon_code_write_uid
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_price_rule_write_uid
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_rule_line_write_uid
msgid "Last Updated by"
msgstr "Last Updated by"
#. module: sale_advance_pricelist
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_cart_rule_write_date
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_coupon_code_write_date
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_price_rule_write_date
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_rule_line_write_date
msgid "Last Updated on"
msgstr "Last Updated on"
#. module: sale_advance_pricelist
#: selection:cart.rule,apply_on:0
msgid "Lines Count at least"
msgstr "Lines Count at least"
#. module: sale_advance_pricelist
#: selection:cart.rule,apply_on:0
msgid "Lines less than"
msgstr "Lines less than"
#. module: sale_advance_pricelist
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_rule_line_max_qty
msgid "Max. Quantity"
msgstr "Max. Quantity"
#. module: sale_advance_pricelist
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_coupon_code_min_order_amount
msgid "Min Order Amount"
msgstr "Min Order Amount"
#. module: sale_advance_pricelist
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_rule_line_min_qty
msgid "Min. Quantity"
msgstr "Min. Quantity"
#. module: sale_advance_pricelist
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_coupon_code_model_name
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_rule_line_model_name
msgid "Model Name"
msgstr "Model Name"
#. module: sale_advance_pricelist
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_cart_rule_name
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_coupon_code_name
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_price_rule_name
msgid "Name"
msgstr "Name"
#. module: sale_advance_pricelist
#: selection:cart.rule,apply_on:0
msgid "None of selected Categories"
msgstr "None of selected Categories"
#. module: sale_advance_pricelist
#: selection:cart.rule,apply_on:0
msgid "None of selected Products"
msgstr "None of selected Products"
#. module: sale_advance_pricelist
#: model:ir.ui.view,arch_db:sale_advance_pricelist.view_cart_rule_form
#: model:ir.ui.view,arch_db:sale_advance_pricelist.view_price_rule_form
msgid "Note"
msgstr "Note"
#. module: sale_advance_pricelist
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_coupon_code_number_of_x_product
msgid "Number Of X Product"
msgstr "Number Of X Product"
#. module: sale_advance_pricelist
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_coupon_code_number_of_y_product
msgid "Number Of Y Product"
msgstr "Number Of Y Product"
#. module: sale_advance_pricelist
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_coupon_code_other_product_id
msgid "Other Product"
msgstr "Other Product"
#. module: sale_advance_pricelist
#: selection:coupon.code,coupon_type:0
#: selection:rule.line,rule_type:0
msgid "Percent"
msgstr "Percent"
#. module: sale_advance_pricelist
#: model:ir.ui.view,arch_db:sale_advance_pricelist.product_pricelist_view_flectra
msgid "Price"
msgstr "Price"
#. module: sale_advance_pricelist
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_rule_line_price_rule_id
#: model:ir.ui.view,arch_db:sale_advance_pricelist.view_price_rule_form
msgid "Price Rule"
msgstr "Price Rule"
#. module: sale_advance_pricelist
#: model:ir.model,name:sale_advance_pricelist.model_price_rule
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_product_pricelist_rule_ids
#: model:ir.ui.view,arch_db:sale_advance_pricelist.product_pricelist_view_flectra
#: model:ir.ui.view,arch_db:sale_advance_pricelist.view_price_rule_tree
msgid "Price Rules"
msgstr "Price Rules"
#. module: sale_advance_pricelist
#: model:ir.model,name:sale_advance_pricelist.model_product_pricelist
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_cart_rule_pricelist_id
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_coupon_code_pricelist_id
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_price_rule_pricelist_id
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_rule_line_pricelist_id
msgid "Pricelist"
msgstr "Pricelist"
#. module: sale_advance_pricelist
#: model:ir.ui.view,arch_db:sale_advance_pricelist.product_pricelist_view_flectra
msgid "Pricelist Items"
msgstr "Pricelist Items"
#. module: sale_advance_pricelist
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_product_pricelist_pricelist_type
msgid "Pricelist Type"
msgstr "Pricelist Type"
#. module: sale_advance_pricelist
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_cart_rule_product_id
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_coupon_code_product_id
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_price_rule_product_id
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_rule_line_product_id
msgid "Product"
msgstr "Product"
#. module: sale_advance_pricelist
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_price_rule_rule_lines
#: model:ir.ui.view,arch_db:sale_advance_pricelist.view_price_rule_form
msgid "Product Rule Lines"
msgstr "Product Rule Lines"
#. module: sale_advance_pricelist
#: selection:coupon.code,apply_on:0
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_coupon_code_product_tmpl_id
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_price_rule_product_tmpl_id
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_rule_line_product_tmpl_id
#: selection:price.rule,apply_on:0
msgid "Product Template"
msgstr "Product Template"
#. module: sale_advance_pricelist
#: selection:coupon.code,apply_on:0
#: selection:price.rule,apply_on:0
msgid "Product Variant"
msgstr "Product Variant"
#. module: sale_advance_pricelist
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_cart_rule_product_ids
msgid "Products"
msgstr "Products"
#. module: sale_advance_pricelist
#: model:ir.model,name:sale_advance_pricelist.model_sale_order
msgid "Quotation"
msgstr "Quotation"
#. module: sale_advance_pricelist
#: selection:coupon.code,coupon_type:0
msgid "Range Based Discount(Buy X Product Get Percent Free)"
msgstr "Range Based Discount(Buy X Product Get Percent Free)"
#. module: sale_advance_pricelist
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_coupon_code_model_real
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_rule_line_model_real
msgid "Real Model"
msgstr "Real Model"
#. module: sale_advance_pricelist
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_coupon_code_remaining_limit
msgid "Remaining Usage Limit"
msgstr "Remaining Usage Limit"
#. module: sale_advance_pricelist
#: model:ir.ui.view,arch_db:sale_advance_pricelist.view_order_form_flectra
msgid "Remove Coupon Code"
msgstr "Remove Coupon Code"
#. module: sale_advance_pricelist
#: model:ir.ui.view,arch_db:sale_advance_pricelist.view_price_rule_form
msgid "Rule Line"
msgstr "Rule Line"
#. module: sale_advance_pricelist
#: model:ir.ui.view,arch_db:sale_advance_pricelist.view_price_rule_form
msgid "Rule Lines"
msgstr "Rule Lines"
#. module: sale_advance_pricelist
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_rule_line_rule_type
msgid "Rule Type"
msgstr "Rule Type"
#. module: sale_advance_pricelist
#: model:ir.ui.view,arch_db:sale_advance_pricelist.view_coupon_code_form
msgid "Sales"
msgstr "Sales"
#. module: sale_advance_pricelist
#: model:ir.model,name:sale_advance_pricelist.model_sale_order_line
msgid "Sales Order Line"
msgstr "Sales Order Line"
#. module: sale_advance_pricelist
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_cart_rule_sequence
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_price_rule_sequence
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_rule_line_sequence
msgid "Sequence"
msgstr "Sequence"
#. module: sale_advance_pricelist
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_cart_rule_start_date
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_price_rule_start_date
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_rule_line_rule_id_start_date
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_rule_line_start_date
msgid "Start Date"
msgstr "Start Date"
#. module: sale_advance_pricelist
#: selection:cart.rule,apply_on:0
msgid "Subtotal At Least"
msgstr "Subtotal At Least"
#. module: sale_advance_pricelist
#: selection:cart.rule,apply_on:0
msgid "Subtotal less than"
msgstr "Subtotal less than"
#. module: sale_advance_pricelist
#: selection:cart.rule,apply_on:0
msgid "Sum of Item Qty at least"
msgstr "Sum of Item Qty at least"
#. module: sale_advance_pricelist
#: selection:cart.rule,apply_on:0
msgid "Sum of Item Qty less than"
msgstr "Sum of Item Qty less than"
#. module: sale_advance_pricelist
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_coupon_code_usage_limit
msgid "Total Usage Limit"
msgstr "Total Usage Limit"
#. module: sale_advance_pricelist
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_coupon_code_code_valid_from
msgid "Valid From"
msgstr "Valid From"
#. module: sale_advance_pricelist
#: model:ir.model.fields,field_description:sale_advance_pricelist.field_coupon_code_code_valid_to
msgid "Valid To"
msgstr "Valid To"
#. module: sale_advance_pricelist
#: model:ir.model,name:sale_advance_pricelist.model_rule_line
msgid "rule.line"
msgstr "rule.line"

View File

@ -0,0 +1,6 @@
# -*- coding: utf-8 -*-
# Part of flectra. See LICENSE file for full copyright and licensing details.
from . import price_rules
from . import sale
from . import pricelist

View File

@ -0,0 +1,444 @@
# -*- coding: utf-8 -*-
# Part of flectra. See LICENSE file for full copyright and licensing details.
from flectra import api, fields, models, _
from flectra.exceptions import Warning
from flectra.tools.safe_eval import safe_eval
from flectra.tools.misc import formatLang
MODELS_LIST = [
'res.partner',
'res.partner.category',
'res.users',
'res.groups',
'res.country.state',
'res.country',
]
Cart_Option = [
('subtotal_at_least', 'Subtotal At Least'),
('subtotal_less_than', 'Subtotal less than'),
('item_count_atleast', 'Lines Count at least'),
('item_count_less_than', 'Lines less than'),
('item_sum_qty_atleast', 'Sum of Item Qty at least'),
('item_sum_qty_less_than', 'Sum of Item Qty less than'),
('one_product_al_least', 'At least one product in order'),
('none_of_sel_products', 'None of selected Products'),
('one_categ_al_least', 'At least one category in order'),
('none_of_sel_categs', 'None of selected Categories'),
]
class RulesLine(models.Model):
_name = 'rule.line'
_order = 'sequence'
sequence = fields.Integer('Sequence')
start_date = fields.Date('Start Date')
end_date = fields.Date('End Date')
min_qty = fields.Float('Min. Quantity')
max_qty = fields.Float('Max. Quantity')
rule_type = fields.Selection([
('percent', 'Percent'),
('fixed_amount', 'Fixed Amount'),
], 'Rule Type', required=True, default='percent')
discount_amount = fields.Float('Discount Amount')
price_rule_id = fields.Many2one('price.rule', 'Price Rule')
model_id = fields.Many2one(
'ir.model', string='Condition', domain=[('model', 'in', MODELS_LIST)])
model_name = fields.Char(related='model_id.model', string='Model Name')
model_domain = fields.Char(string='Domain', oldname='domain', default=[])
model_real = fields.Char(compute='_compute_model', string='Real Model')
pricelist_id = fields.Many2one(
'product.pricelist', related='price_rule_id.pricelist_id', store=True)
categ_id = fields.Many2one(
'product.category', related='price_rule_id.categ_id', store=True)
product_tmpl_id = fields.Many2one(
'product.template',
related='price_rule_id.product_tmpl_id', store=True)
product_id = fields.Many2one(
'product.product', related='price_rule_id.product_id', store=True)
rule_id_start_date = fields.Date(
related='price_rule_id.start_date', store=True)
rule_id_end_date = fields.Date(
related='price_rule_id.end_date', store=True)
@api.onchange('rule_type', 'discount_amount')
def check_percentage(self):
warning = {}
if self.rule_type == 'percent' and (
self.discount_amount > 100 or
self.discount_amount < 0):
warning.update({
'title': _("Warning"),
'message': _("Percentage should be between 0% to 100%!")})
self.discount_amount = 0.0
return {'warning': warning}
@api.depends('model_id')
def _compute_model(self):
for record in self:
if record.model_id:
record.model_real = record.model_name or 'res.partner'
@api.constrains('start_date', 'end_date',
'rule_id_start_date', 'rule_id_end_date')
def check_date(self):
for rule_line_id in self:
parent_start_date = rule_line_id.rule_id_start_date
child_start_date = rule_line_id.start_date
if parent_start_date and \
child_start_date and parent_start_date > child_start_date:
raise Warning(_("Start Date date not valid in "
"Product Rule Lines!"))
parent_end_date = rule_line_id.rule_id_end_date
child_end_date = rule_line_id.end_date
if parent_end_date and \
child_end_date and parent_end_date < child_end_date:
raise Warning(_("End Date date not valid in "
"Product Rule Lines!"))
class PriceRules(models.Model):
_name = 'price.rule'
_description = 'Price Rules'
_order = 'sequence'
@api.multi
@api.depends('apply_on', 'categ_id', 'product_tmpl_id', 'product_id')
def _get_pricerule_name_price(self):
for record in self:
if record.categ_id:
record.name = _("Category: %s") % (record.categ_id.name)
elif record.product_tmpl_id:
record.name = record.product_tmpl_id.name
elif record.product_id:
record.name = record.product_id.display_name.replace(
'[%s]' % record.product_id.code, '')
else:
record.name = _("All Products")
name = fields.Char('Name', compute='_get_pricerule_name_price')
sequence = fields.Integer('Sequence')
apply_on = fields.Selection([
('all', 'Global'),
('category', 'Category'),
('product_template', 'Product Template'),
('product', 'Product Variant')
], required=True, default='all', string="Apply On")
categ_id = fields.Many2one('product.category', 'Category')
product_tmpl_id = fields.Many2one('product.template', 'Product Template')
product_id = fields.Many2one('product.product', 'Product')
active = fields.Boolean('Active', default=True)
start_date = fields.Date('Start Date')
end_date = fields.Date('End Date')
note = fields.Text('Description')
pricelist_id = fields.Many2one('product.pricelist',
'Pricelist', index=True, ondelete='cascade')
rule_lines = fields.One2many('rule.line', 'price_rule_id',
'Product Rule Lines')
@api.onchange('apply_on')
def _onchange_apply_on(self):
if self.apply_on != 'product':
self.product_id = False
if self.apply_on != 'product_template':
self.product_tmpl_id = False
if self.apply_on != 'category':
self.categ_id = False
@api.multi
def get_rules(self, pricelist_id, date):
date = fields.Date.context_today(self)
self._cr.execute(
'SELECT rule.id '
'FROM price_rule AS rule '
'WHERE (rule.pricelist_id = %s) '
'AND (rule.start_date IS NULL OR rule.start_date<=%s) '
'AND (rule.end_date IS NULL OR rule.end_date>=%s)'
'ORDER BY rule.sequence',
(pricelist_id.id, date, date))
rules_ids = [x[0] for x in self._cr.fetchall()]
rules = self.browse(rules_ids)
return rules
class CartRules(models.Model):
_name = 'cart.rule'
_description = 'Cart Rules'
_order = 'sequence'
@api.multi
@api.depends('apply_on', 'amt_value', 'product_id', 'categ_id')
def _get_cart_name_price(self):
for record in self:
select_option = dict(Cart_Option)
if record.apply_on in ['subtotal_at_least', 'subtotal_less_than',
'item_count_atleast',
'item_count_less_than',
'item_sum_qty_atleast',
'item_sum_qty_less_than']:
record.name = select_option[record.apply_on] + ' : ' + str(
formatLang(self.env, record.amt_value, digits=2))
elif record.apply_on == 'one_product_al_least' and \
record.product_id:
record.name = select_option[record.apply_on] + ' : ' + str(
record.product_id.name)
elif record.apply_on == 'one_categ_al_least' and \
record.categ_id:
record.name = select_option[record.apply_on] + ' : ' + str(
record.categ_id.name)
elif record.apply_on:
record.name = select_option[record.apply_on]
name = fields.Char('Name', compute='_get_cart_name_price')
sequence = fields.Integer('Sequence')
active = fields.Boolean('Active', default=True)
start_date = fields.Date('Start Date')
end_date = fields.Date('End Date')
discount_percentage = fields.Float('Discount (%)')
apply_on = fields.Selection(Cart_Option, 'Apply On')
amt_value = fields.Float('Amount')
product_id = fields.Many2one('product.product', 'Product')
product_ids = fields.Many2many('product.product', column1='cart_line_id',
column2='product_id', string='Products')
categ_id = fields.Many2one('product.category', 'Category')
categ_ids = fields.Many2many('product.category', column1='cart_line_id',
column2='category_id', string='Categories')
note = fields.Text('Description')
pricelist_id = fields.Many2one('product.pricelist')
@api.onchange('discount_percentage')
def check_percentage(self):
warning = {}
if self.discount_percentage > 100 or self.discount_percentage < 0:
warning.update({
'title': _("Warning"),
'message': _("Percentage should be between 0% to 100%!")})
self.discount_percentage = 0.0
return {'warning': warning}
def _get_cart_discount_amt(self, pricelist, total=0.0,
item_count=0.0, item_sum_count=0.0,
product_ids=[], categ_ids=[], order=False):
discount_flag = False
dis_price = 0.0
if self.apply_on == 'subtotal_at_least' \
and total >= self.amt_value:
discount_flag = True
elif self.apply_on == 'subtotal_less_than' and total <= self.amt_value:
discount_flag = True
elif self.apply_on == 'item_count_atleast' \
and item_count >= self.amt_value:
discount_flag = True
elif self.apply_on == 'item_count_less_than' \
and item_count <= self.amt_value:
discount_flag = True
elif self.apply_on == 'item_sum_qty_atleast' \
and item_sum_count >= self.amt_value:
discount_flag = True
elif self.apply_on == 'item_sum_qty_less_than' \
and item_sum_count <= self.amt_value:
discount_flag = True
elif self.apply_on == 'one_product_al_least' \
and self.product_id.id in product_ids:
discount_flag = True
elif self.apply_on == 'none_of_sel_products' \
and not any(map(lambda v: v in [
x.id for x in self.product_ids],
product_ids)):
discount_flag = True
elif self.apply_on == 'one_categ_al_least' \
and self.categ_id.id in categ_ids:
discount_flag = True
elif self.apply_on == 'none_of_sel_categs' \
and not any(map(lambda v: v in [
x.id for x in self.categ_ids], categ_ids)):
discount_flag = True
if discount_flag:
dis_price = self.discount_percentage
return dis_price
class CouponCode(models.Model):
_name = 'coupon.code'
_description = 'Coupon Code'
@api.multi
def _compute_order_count(self):
sale_order_ids = self.env['sale.order'].search_count([
('coupon_code_id', '=', self.id), ('state', '=', 'sale')])
self.sale_order_count = sale_order_ids
self.remaining_limit = self.usage_limit - sale_order_ids
name = fields.Char('Name')
coupon_code = fields.Char('Coupon Code')
code_valid_from = fields.Date('Valid From')
code_valid_to = fields.Date('Valid To')
sale_order_count = fields.Integer(
compute='_compute_order_count', string='# of Sale Order')
coupon_type = fields.Selection([
('percent', 'Percent'),
('fixed_amount', 'Fixed Amount'),
('buy_x_get_y', 'Buy X Product Get Y Product Free'),
('buy_x_get_y_other', 'Buy X Product Get Y Other Product Free'),
('buy_x_get_percent', 'Range Based Discount('
'Buy X Product Get Percent Free)'),
('clubbed', 'Clubbed Discount'),
], 'Coupon Type', default='percent', required=True)
number_of_x_product = fields.Float('Number Of X Product')
number_of_y_product = fields.Float('Number Of Y Product')
other_categ_id = fields.Many2one('product.category', 'Category')
discount_amount = fields.Float('Discount Amount')
flat_discount = fields.Float('Flat Discount')
extra_discount_percentage = fields.Float('Extra Discount')
usage_limit = fields.Integer('Total Usage Limit')
remaining_limit = fields.Integer(compute='_compute_order_count',
string='Remaining Usage Limit')
min_order_amount = fields.Float('Min Order Amount')
active = fields.Boolean('Active', default=True)
apply_on = fields.Selection([
('all', 'Global'),
('category', 'Category'),
('product_template', 'Product Template'),
('product', 'Product Variant'),
], required=True, default='all', string="Apply On")
categ_id = fields.Many2one('product.category', 'Category')
product_tmpl_id = fields.Many2one('product.template', 'Product Template')
product_id = fields.Many2one('product.product', 'Product')
other_product_id = fields.Many2one('product.product', 'Other Product')
pricelist_id = fields.Many2one('product.pricelist',
'Pricelist', index=True, ondelete='cascade')
model_id = fields.Many2one('ir.model', string='Condition',
domain=[('model', 'in', MODELS_LIST)])
model_name = fields.Char(related='model_id.model', string='Model Name')
model_domain = fields.Char(string='Domain', oldname='domain', default=[])
model_real = fields.Char(compute='_compute_model', string='Real Model')
@api.onchange('apply_on')
def _onchange_apply_on(self):
if self.apply_on != 'product':
self.product_id = False
if self.apply_on != 'product_template':
self.product_tmpl_id = False
if self.apply_on != 'category':
self.categ_id = False
@api.onchange('coupon_type', 'discount_amount')
def check_percentage(self):
warning = {}
if self.coupon_type == 'percent' and self.discount_amount > 100 \
or self.discount_amount < 0:
warning.update({
'title': _("Warning"),
'message': _("Percentage should be between 0% to 100%!")})
self.discount_amount = 0.0
return {'warning': warning}
@api.onchange('flat_discount', 'extra_discount_percentage')
def check_clubbed_percentage(self):
warning = {}
percent = self.flat_discount + self.extra_discount_percentage
if percent > 100 or percent < 0:
warning.update({
'title': _("Warning"),
'message': _("Total Percentage ( Discount + Extra ) "
"should be between 0% to 100%!")})
self.flat_discount = 0.0
self.extra_discount_percentage = 0.0
return {'warning': warning}
@api.depends('model_id')
def _compute_model(self):
for record in self:
if record.model_id:
record.model_real = record.model_name or 'res.partner'
@api.multi
def view_sale_order(self):
sale_order_ids = self.env['sale.order'].search([
('coupon_code_id', '=', self.id), ('state', '=', 'sale')])
return {
'name': 'Sales Orders',
'type': 'ir.actions.act_window',
'view_type': 'form',
'view_mode': 'tree,form,kanban,pivot,graph',
'res_model': 'sale.order',
'domain': [('id', 'in', sale_order_ids.ids)],
}
@api.constrains('coupon_code')
def check_duplicate_coupon_code(self):
check_coupon_id = self.search([
('coupon_code', '=', self.coupon_code),
('id', '!=', self.id)])
if check_coupon_id:
raise Warning(_("Coupon code (%s) already exists!") % (
self.coupon_code))
@api.multi
def check_condition(self, record, partner_id):
domain = safe_eval(record.model_domain)
if record.model_real == 'res.partner':
domain += [('id', '=', partner_id.id)]
elif record.model_real == 'res.partner.category':
domain += [('id', 'in', partner_id.category_id.ids)]
elif record.model_real == 'res.users':
domain += [('id', 'in', self.env.user.id)]
elif record.model_real == 'res.groups':
domain += [('users', 'in', self.env.user.id)]
elif record.model_real == 'res.country.state':
domain += [('id', '=', partner_id.state_id.id)]
elif record.model_real == 'res.country':
domain += [('id', '=', partner_id.country_id.id)]
if self.env[record.model_real].search(domain):
return False
return True
@api.multi
def get_coupon_records(self, coupon_code, pricelist_id):
coupon_ids = []
if coupon_code:
date = fields.Date.context_today(self)
self._cr.execute(
'SELECT code.id '
'FROM coupon_code AS code '
'WHERE (code.coupon_code = %s) '
'AND (code.code_valid_from IS NULL OR '
'code.code_valid_from<=%s) '
'AND (code.code_valid_to IS NULL OR code.code_valid_to>=%s) '
'AND (code.pricelist_id = %s) ',
(coupon_code, date, date, pricelist_id.id))
coupons = [x[0] for x in self._cr.fetchall()]
coupon_ids = self.env['coupon.code'].browse(coupons)
return coupon_ids
@api.multi
def get_coupon_discount(self, line, cal_coupon):
if not line.order_id.pricelist_id.apply_coupon_code or not \
line.coupon_code_id:
return 0.0
coupon_amount = 0.0
onchange_context = True
coupon_ids = self.get_coupon_records(line.order_id.have_coupon_code,
line.order_id.pricelist_id)
for coupon_id in coupon_ids:
if coupon_id.coupon_type == 'percent' or \
coupon_id.coupon_type == 'clubbed':
discount_per = coupon_id.discount_amount
if coupon_id.coupon_type == 'clubbed':
discount_per = \
coupon_id.flat_discount + \
coupon_id.extra_discount_percentage
coupon_amount += line.order_id._get_percentage_coupon_discount(
line, coupon_id, onchange_context,
cal_coupon, discount_per, False)
elif coupon_id.coupon_type == 'fixed_amount':
coupon_amount += line.order_id._get_fixed_coupon_discount(
line, coupon_id, onchange_context, cal_coupon, False)
elif coupon_id.coupon_type == 'buy_x_get_percent' \
and line.product_uom_qty >= coupon_id.number_of_x_product:
coupon_amount += \
line.order_id.buy_x_get_percentage_coupon_discount(
line, coupon_id, onchange_context, cal_coupon, False)
return coupon_amount

View File

@ -0,0 +1,192 @@
# -*- coding: utf-8 -*-
# Part of flectra. See LICENSE file for full copyright and licensing details.
from flectra import api, fields, models
from flectra.exceptions import UserError
from itertools import chain
class Pricelist(models.Model):
_inherit = "product.pricelist"
pricelist_type = fields.Selection(
[('basic', 'Basic'),
('advance', 'Advanced'),
], 'Pricelist Type', default='basic', required=True)
apply_method = fields.Selection(
[('first_matched_rule', 'Apply First Matched Rule'),
('all_matched_rules', 'Apply All Matched Rules'),
('smallest_discount', 'Apply Smallest Matched Discount'),
('biggest_discount', 'Apply Biggest Matched Discount')
], 'Apply Method', default='first_matched_rule', required=True)
rule_ids = fields.One2many(
'price.rule', 'pricelist_id', 'Price Rules',
copy=True)
cart_rule_ids = fields.One2many(
'cart.rule', 'pricelist_id', 'Cart Rules Items',
copy=True)
apply_coupon_code = fields.Boolean('Apply Coupon Code?')
coupon_code_lines = fields.One2many(
'coupon.code', 'pricelist_id', 'Coupon Code Items',
copy=True)
def get_product_price_rule_flectra(
self, product, quantity, partner,
rule_id, price_unit, date=False, uom_id=False):
self.ensure_one()
return self._compute_price_rule_flectra(
[(product, quantity, partner)],
rule_id, price_unit, date=date, uom_id=uom_id)[product.id]
@api.multi
def _compute_price_rule_flectra(self, products_qty_partner,
rule_id, price_unit,
date=False, uom_id=False):
self.ensure_one()
if not date:
date = fields.Datetime.now()
if not uom_id and self._context.get('uom'):
uom_id = self._context['uom']
if uom_id:
products = [item[0].with_context(
uom=uom_id) for item in products_qty_partner]
products_qty_partner = [(products[index], data_struct[1],
data_struct[2])
for index, data_struct in
enumerate(products_qty_partner)]
else:
products = [item[0] for item in products_qty_partner]
if not products:
return {}
categ_ids = {}
for p in products:
categ = p.categ_id
while categ:
categ_ids[categ.id] = True
categ = categ.parent_id
categ_ids = list(categ_ids)
is_product_template = products[0]._name == "product.template"
if is_product_template:
prod_tmpl_ids = [tmpl.id for tmpl in products]
prod_ids = [p.id for p in
list(chain.from_iterable(
[t.product_variant_ids for t in products]))]
else:
prod_ids = [product.id for product in products]
prod_tmpl_ids = [
product.product_tmpl_id.id for product in products]
self._cr.execute(
'SELECT item.id '
'FROM rule_line AS item '
'LEFT JOIN product_category AS categ '
'ON item.categ_id = categ.id '
'WHERE (item.product_tmpl_id IS NULL '
'OR item.product_tmpl_id = any(%s))'
'AND (item.price_rule_id = any(%s))'
'AND (item.product_id IS NULL OR item.product_id = any(%s))'
'AND (item.categ_id IS NULL OR item.categ_id = any(%s)) '
'AND (item.pricelist_id = %s) '
'AND (item.start_date IS NULL OR item.start_date<=%s) '
'AND (item.end_date IS NULL OR item.end_date>=%s)'
'ORDER BY item.sequence,categ.parent_left desc',
(prod_tmpl_ids, rule_id.ids, prod_ids,
categ_ids, self.id, date, date))
item_ids = [x[0] for x in self._cr.fetchall()]
items = self.env['rule.line'].browse(item_ids)
results = {}
coupon_obj = self.env['coupon.code']
partner_obj = self.env['res.partner']
for product, qty, partner in products_qty_partner:
results[product.id] = 0.0
suitable_rule = False
qty_uom_id = self._context.get('uom') or product.uom_id.id
qty_in_product_uom = qty
if qty_uom_id != product.uom_id.id:
try:
qty_in_product_uom = \
self.env['product.uom'].browse(
[self._context['uom']])._compute_quantity(
qty, product.uom_id)
except UserError:
pass
price = product.price_compute('list_price')[product.id]
one_dis_price = all_dis_price = 0.0
max_dis_price = []
min_dis_price = []
partner_id = partner
if isinstance(partner, int):
partner_id = partner_obj.browse(partner)
for rule in items:
if rule.min_qty and qty_in_product_uom < rule.min_qty:
continue
if rule.max_qty and qty_in_product_uom > rule.max_qty:
continue
if rule.model_id:
check = coupon_obj.check_condition(rule, partner_id)
if check:
continue
if is_product_template:
if rule.product_tmpl_id and \
product.id != rule.product_tmpl_id.id:
continue
if rule.product_id and not (
product.product_variant_count == 1 and
product.product_variant_id.id ==
rule.product_id.id):
continue
else:
if rule.product_tmpl_id and \
product.product_tmpl_id.id != \
rule.product_tmpl_id.id:
continue
if rule.product_id and product.id != rule.product_id.id:
continue
if rule.categ_id:
cat = product.categ_id
while cat:
if cat.id == rule.categ_id.id:
break
cat = cat.parent_id
if not cat:
continue
dis_price = 0.0
if price is not False:
if rule.rule_type == 'fixed_amount':
if price != price_unit:
price = price_unit
if price < rule.discount_amount:
price = 0
suitable_rule = rule
break
else:
dis_price = price - rule.discount_amount
elif rule.rule_type == 'percent':
dis_price = (price - (price * (
rule.discount_amount / 100))) or 0.0
suitable_rule = rule
if self.apply_method == 'first_matched_rule':
one_dis_price = dis_price
break
elif self.apply_method == 'all_matched_rules':
all_dis_price += price - dis_price
elif self.apply_method == 'smallest_discount':
min_dis_price.append(price - dis_price)
else:
max_dis_price.append(price - dis_price)
if one_dis_price > 0.0:
price = one_dis_price
elif all_dis_price > 0.0:
price = price - all_dis_price
elif min_dis_price:
price = price - min(min_dis_price)
elif max_dis_price:
price = price - max(max_dis_price)
price = product.currency_id.compute(
price, self.currency_id, round=False)
results[product.id] = (price,
suitable_rule and suitable_rule.id or False)
return results

View File

@ -0,0 +1,610 @@
# -*- coding: utf-8 -*-
# Part of flectra. See LICENSE file for full copyright and licensing details.
import json
import flectra.addons.decimal_precision as dp
from flectra import api, fields, models, _
from flectra.exceptions import Warning, UserError
from flectra.tools.misc import formatLang
class SaleOrder(models.Model):
_inherit = "sale.order"
@api.depends('amount_total', 'currency_id')
def _get_amount_word(self):
for order in self:
if not order.currency_id:
return
order.amount_words = order.currency_id.amount_to_text(
order.discount)
@api.depends('order_line', 'partner_id', 'coupon_flag')
def _check_cart_rules(self):
for order in self:
if order.pricelist_id.pricelist_type == 'advance':
order._update_all()
cart_discount = 0.0
cart_discount_per = \
order.get_cart_rules_discount(order.get_values())
if order.pricelist_id.discount_policy == 'without_discount':
for line in order.order_line:
if line.get_line_percentage(cart_discount_per) < 100:
cart_discount += \
((line.price_unit * line.product_uom_qty
) * cart_discount_per) / 100
order.cart_discount = cart_discount
else:
for line in order.order_line:
line.set_line_amount(cart_discount_per)
@api.multi
def get_cart_discount(self, cart_rule_id, values):
cart_discount = cart_rule_id._get_cart_discount_amt(
self.pricelist_id, total=values.get('amount_untaxed'),
item_count=values.get('item_count'),
item_sum_count=values.get('item_sum_count'),
product_ids=values.get('product_ids'),
categ_ids=values.get('categ_ids'), order=self)
return cart_discount
@api.multi
def get_cart_rules_discount(self, values):
if not self.pricelist_id:
return 0.0
date = fields.Date.context_today(self)
self._cr.execute(
'SELECT rule.id '
'FROM cart_rule AS rule '
'WHERE (rule.pricelist_id = %s) '
'AND (rule.start_date IS NULL OR rule.start_date<=%s) '
'AND (rule.end_date IS NULL OR rule.end_date>=%s)'
'ORDER BY rule.sequence',
(self.pricelist_id.id, date, date))
item_ids = [x[0] for x in self._cr.fetchall()]
cart_rule_ids = self.env['cart.rule'].browse(item_ids)
if not cart_rule_ids:
return 0.0
final_dis_price = 0.0
one_dis_price = all_dis_price = 0.0
max_dis_price = []
min_dis_price = []
cart_discount = 0.0
for cart_rule_id in cart_rule_ids:
cart_discount = self.get_cart_discount(cart_rule_id, values)
if cart_rule_id.pricelist_id.apply_method == \
'first_matched_rule' and \
cart_discount > 0.0:
one_dis_price = cart_discount
break
elif cart_rule_id.pricelist_id.apply_method == 'all_matched_rules':
all_dis_price += cart_discount
elif cart_rule_id.pricelist_id.apply_method == \
'smallest_discount' and cart_discount:
min_dis_price.append(cart_discount)
else:
max_dis_price.append(cart_discount)
if one_dis_price > 0.0:
final_dis_price = one_dis_price
elif all_dis_price > 0.0:
final_dis_price = all_dis_price
elif min_dis_price:
final_dis_price = min(min_dis_price)
elif max_dis_price:
final_dis_price = max(max_dis_price)
return final_dis_price
@api.model
def _get_discount_vals(self):
payment_vals = []
price_list_discount = price_rule_discount = coupon_code_discount = 0.0
coupon_code_obj = self.env['coupon.code']
partner_id = self.partner_id
pricelist_id = self.pricelist_id
for line in self.order_line:
if not (line.product_id and line.product_uom and
partner_id and pricelist_id and
pricelist_id.discount_policy == 'without_discount' and
self.env.user.has_group(
'sale.group_discount_per_so_line')):
return
if pricelist_id.pricelist_type == 'basic':
price_list_discount = self.discount
else:
if line.product_uom_qty < 0 and line.coupon_code_id:
continue
if line.order_id.have_coupon_code and line.coupon_code_id:
coupon_code_discount += \
coupon_code_obj.get_coupon_discount(line, True)
if line.coupon_code_id and line.price_unit == 0:
continue
if pricelist_id.pricelist_type != 'basic':
price_rule_discount = (self.discount - coupon_code_discount
) - self.cart_discount
untaxed_amount = self.gross_amount - self.discount
payment_vals.append({
'gross_amount': formatLang(self.env, self.gross_amount, digits=2),
'price_list_discount':
formatLang(self.env, price_list_discount, digits=2),
'price_rule_discount':
formatLang(self.env, price_rule_discount, digits=2),
'cart_rule_discount':
formatLang(self.env, self.cart_discount, digits=2),
'coupon_code_discount':
formatLang(self.env, coupon_code_discount, digits=2),
'currency': self.pricelist_id.currency_id.symbol,
'untaxed_amount': formatLang(self.env, untaxed_amount, digits=2),
'position': self.pricelist_id.currency_id.position,
'amount_words': self.amount_words,
'discount': formatLang(self.env, self.discount, digits=2),
})
return payment_vals
@api.depends('discount')
def _get_discount_info_JSON(self):
for record in self:
info = {'title': _('Discount'), 'outstanding': False,
'content': record._get_discount_vals()}
record.discount_widget = json.dumps(info)
def _update_all(self):
for order in self:
amount_untaxed = amount_tax = item_count = item_sum_count = 0.0
product_ids = categ_ids = []
check_dup_product = []
for line in order.order_line:
amount_untaxed += line.price_subtotal
amount_tax += line.price_tax
item_sum_count += line.product_uom_qty
if line.product_id.id not in check_dup_product:
item_count += 1
check_dup_product.append(line.product_id.id)
product_ids.append(line.product_id.id)
categ_ids.append(line.product_id.categ_id.id)
return {
'amount_untaxed': amount_untaxed,
'amount_tax': amount_tax,
'item_sum_count': item_sum_count,
'item_count': item_count,
'product_ids': product_ids,
'categ_ids': categ_ids,
}
@api.multi
def get_values(self):
return self._update_all()
have_coupon_code = fields.Char('Have Coupon Code')
cart_discount = fields.Float(
compute='_check_cart_rules', string='Cart Discount')
coupon_flag = fields.Boolean('Check Coupon Apply')
amount_words = fields.Char(string="Discount Amount Words",
compute='_get_amount_word', store=True)
discount_widget = fields.Text(compute='_get_discount_info_JSON')
coupon_code_id = fields.Many2one('coupon.code', 'Coupon Ref')
@api.multi
def _get_percentage_coupon_discount(self, line, coupon_code_id,
onchange_context, cal_coupon,
discount_per, remove):
coupon_discount_amount = 0.0
total_price = (line.product_uom_qty * line.price_unit)
if self.coupon_flag and not onchange_context and line.coupon_code_id:
line.write({'check_coupon': False,
'discount': line.discount - discount_per,
'coupon_code_id': False,
'check_coupon': False})
elif not cal_coupon and not remove:
coupon_discount_amount = (total_price * discount_per) / 100
line.discount = line.discount + discount_per
line.coupon_code_id = coupon_code_id.id
line.check_coupon = True
else:
coupon_discount_amount = (total_price * discount_per) / 100
return coupon_discount_amount
@api.multi
def _get_fixed_coupon_discount(self, line, coupon_code_id,
onchange_context, cal_coupon, remove):
line_discount = 0.0
if not line.price_unit:
return 0.0
discount_amount = 0.0
if line.price_unit < coupon_code_id.discount_amount:
discount_amount = line.price_unit
if self.coupon_flag and not onchange_context and line.coupon_code_id:
if discount_amount:
line_discount = (line.price_unit * line.dummy_discount / 100
) - line.price_unit
line.write({'check_coupon': False,
'discount': line_discount / line.price_unit * 100,
'coupon_code_id': False})
else:
if line.dummy_discount:
line_discount = \
(line.price_unit * line.dummy_discount / 100
) - coupon_code_id.discount_amount
else:
line_discount = (line.price_unit * line.discount / 100
) - coupon_code_id.discount_amount
line.write({'check_coupon': False,
'discount': line_discount / line.price_unit * 100,
'coupon_code_id': False})
elif not cal_coupon and not remove:
if discount_amount:
line_discount = (line.price_unit * line.discount / 100
) + discount_amount
else:
line_discount = (line.price_unit * line.discount / 100
) + coupon_code_id.discount_amount
percent = line_discount / line.price_unit * 100
if percent > 100:
line.dummy_discount = percent
line.discount = 100
else:
line.discount = percent
line.coupon_code_id = coupon_code_id.id
line.check_coupon = True
return line.product_uom_qty * coupon_code_id.discount_amount
@api.multi
def _get_same_product_coupon_discount(self, line, coupon_code_id, remove):
qty = int((line.product_uom_qty / coupon_code_id.number_of_x_product)
) * coupon_code_id.number_of_y_product
if line.coupon_code_id and line.check_coupon:
line.write({'check_coupon': False, 'coupon_code_id': False})
elif self.coupon_flag and line.coupon_code_id and \
not line.check_coupon:
line.unlink()
elif line.product_uom_qty == coupon_code_id.number_of_x_product and \
not remove:
line.write({'check_coupon': True,
'coupon_code_id': coupon_code_id.id})
self.env['sale.order.line'].create(
{
'product_id': line.product_id.id,
'product_uom_qty': coupon_code_id.number_of_y_product,
'order_id': self.id,
'discount': 0.0,
'coupon_code_id': coupon_code_id.id,
'price_unit': 0.0
})
elif not self.coupon_flag and qty >= 1:
line.write({'check_coupon': True,
'coupon_code_id': coupon_code_id.id})
self.env['sale.order.line'].create(
{
'product_id': line.product_id.id,
'product_uom_qty': int(qty),
'order_id': self.id,
'discount': 0.0,
'coupon_code_id': coupon_code_id.id,
'price_unit': 0.0
})
@api.multi
def _get_other_product_coupon_discount(self, line, coupon_code_id):
qty = int((line.product_uom_qty / coupon_code_id.number_of_x_product)
) * coupon_code_id.number_of_y_product
if line.coupon_code_id and line.check_coupon:
line.write({'check_coupon': False, 'coupon_code_id': False})
return 0.0
elif self.coupon_flag and line.coupon_code_id \
and not line.check_coupon:
line.unlink()
return 0.0
elif not self.coupon_flag and qty >= 1:
line.write({'check_coupon': True,
'coupon_code_id': coupon_code_id.id})
return qty
return 0.0
@api.multi
def buy_x_get_percentage_coupon_discount(
self, line, coupon_code_id, onchange_context, cal_coupon, remove):
coupon_discount_amount = 0.0
total_price = (line.product_uom_qty * line.price_unit)
if self.coupon_flag and not onchange_context and line.coupon_code_id \
and line.product_uom_qty > coupon_code_id.number_of_x_product:
line.write({'check_coupon': False,
'discount':
line.discount - coupon_code_id.discount_amount,
'coupon_code_id': False,
'check_coupon': False})
elif not cal_coupon and not remove and line.product_uom_qty >= \
coupon_code_id.number_of_x_product:
coupon_discount_amount = \
(total_price * coupon_code_id.discount_amount) / 100
line.discount = line.discount + coupon_code_id.discount_amount
line.coupon_code_id = coupon_code_id.id
line.check_coupon = True
else:
coupon_discount_amount = \
(total_price * coupon_code_id.discount_amount) / 100
return coupon_discount_amount
@api.multi
def _check_Constraints(self):
self.get_values()
order_line = self.order_line
if not self.have_coupon_code:
raise UserError(_("Please enter the Coupon code!"))
if not order_line:
raise UserError(_("There is no sale order line!"))
if self.pricelist_id.pricelist_type != 'advance' or not \
self.pricelist_id.apply_coupon_code:
raise UserError(_("Coupon code does not apply to "
"sale order pricelist!"))
coupon_obj = self.env['coupon.code']
coupon_code_id = coupon_obj.get_coupon_records(
self.have_coupon_code, self.pricelist_id)
if not coupon_code_id:
raise UserError(_("Coupon code (%s) not found!"
) % (self.have_coupon_code))
if coupon_code_id.usage_limit > 0 \
and coupon_code_id.remaining_limit <= 0:
raise UserError(_("Coupon code (%s) Remaining Limit exceeds!"
) % (self.have_coupon_code))
if coupon_code_id.min_order_amount \
and self.amount_untaxed < coupon_code_id.min_order_amount \
and not self.env.context.get('remove', False):
raise UserError(_("Untaxed Amount (%s) must be greater than "
"Min Order Amount (%s) which required for "
"the apply coupon code!") % (
formatLang(self.env, self.amount_untaxed, digits=2),
formatLang(self.env, coupon_code_id.min_order_amount,
digits=2)))
if coupon_code_id.model_id:
check_coupon = coupon_obj.check_condition(
coupon_code_id, self.partner_id)
if check_coupon:
raise Warning(_("Coupon code (%s) condition criteria not "
"match!") % (self.have_coupon_code))
return coupon_code_id
@api.multi
def apply_coupon_code(self):
coupon_id = self._check_Constraints()
order_line = self.order_line
coupon_discount_amount = 0.0
have_coupon_code = self.have_coupon_code
coupon_flag = True
onchange_context = True
coupon_ref_id = coupon_id.id
remove = False
cal_coupon = False
if self.coupon_flag:
have_coupon_code = ''
coupon_flag = False
onchange_context = False
coupon_ref_id = False
remove = True
check_coupon = True
qty = 0.0
for line in order_line:
if coupon_id.apply_on == 'category' and not \
line.product_id.categ_id == coupon_id.categ_id:
continue
elif coupon_id.apply_on == 'product_template' and not \
line.product_id.product_tmpl_id == \
coupon_id.product_tmpl_id:
continue
elif coupon_id.apply_on == 'product' and not \
line.product_id == coupon_id.product_id:
continue
else:
if coupon_id.coupon_type == 'percent' or \
coupon_id.coupon_type == 'clubbed':
discount_per = coupon_id.discount_amount
if coupon_id.coupon_type == 'clubbed':
discount_per = coupon_id.flat_discount + \
coupon_id.extra_discount_percentage
coupon_discount_amount += \
self._get_percentage_coupon_discount(
line, coupon_id, onchange_context,
cal_coupon, discount_per, remove)
check_coupon = False
elif coupon_id.coupon_type == 'fixed_amount':
coupon_discount_amount += self._get_fixed_coupon_discount(
line, coupon_id, onchange_context, cal_coupon, remove)
check_coupon = False
elif coupon_id.coupon_type == 'buy_x_get_y' and \
coupon_id.number_of_x_product and \
coupon_id.number_of_y_product:
if line.product_uom_qty < \
coupon_id.number_of_x_product and not \
line.coupon_code_id and check_coupon:
check_coupon = True
continue
self._get_same_product_coupon_discount(
line, coupon_id, remove)
check_coupon = False
elif coupon_id.coupon_type == 'buy_x_get_y_other':
if line.product_uom_qty < \
coupon_id.number_of_x_product and not \
line.coupon_code_id and check_coupon:
check_coupon = True
continue
qty += self._get_other_product_coupon_discount(
line, coupon_id)
check_coupon = False
elif coupon_id.coupon_type == 'buy_x_get_percent':
if line.product_uom_qty < \
coupon_id.number_of_x_product and not \
line.coupon_code_id and check_coupon:
check_coupon = True
continue
coupon_discount_amount += \
self.buy_x_get_percentage_coupon_discount(
line, coupon_id, onchange_context,
cal_coupon, remove)
check_coupon = False
if check_coupon:
raise Warning(_("Coupon code (%s) condition criteria not match!"
) % (self.have_coupon_code))
if qty:
self.env['sale.order.line'].create({
'product_id': coupon_id.other_product_id.id,
'product_uom_qty': int(qty), 'order_id': self.id,
'coupon_code_id': coupon_id.id, 'price_unit': 0.0})
self.write({'have_coupon_code': have_coupon_code,
'coupon_flag': coupon_flag,
'coupon_code_id': coupon_ref_id})
class SaleOrderLine(models.Model):
_inherit = "sale.order.line"
coupon_code_id = fields.Many2one('coupon.code', 'Coupon Ref')
check_coupon = fields.Boolean('Apply Coupon')
dummy_discount = fields.Float(
string='Discount (%)',
digits=dp.get_precision('Discount'), default=0.0)
@api.multi
def get_line_percentage(self, percent):
self._onchange_discount()
discount = self.discount + percent
if discount > 100:
self.dummy_discount = discount
discount = 100
self.discount = discount
return discount
@api.multi
def set_line_amount(self, percent):
discount, product_price = self.get_rule_discount()
if product_price:
discount = product_price * (discount + percent) / 100
self.price_unit = product_price - discount
@api.multi
def get_total_coupon_code(self):
return self.env['coupon.code'].get_coupon_discount(self, False)
def _get_real_price_currency_flectra(self, product, uom,
pricelist_id, price_unit):
currency_id = pricelist_id.currency_id
product_currency = \
(product.company_id and product.company_id.currency_id
) or self.env.user.company_id.currency_id
if currency_id.id == product_currency.id:
cur_factor = 1.0
else:
cur_factor = currency_id._get_conversion_rate(
product_currency, currency_id)
product_uom = self.env.context.get('uom') or product.uom_id.id
if uom and uom.id != product_uom:
uom_factor = uom._compute_price(1.0, product.uom_id)
else:
uom_factor = 1.0
return price_unit * uom_factor * cur_factor, currency_id.id
@api.multi
def get_rule_discount(self):
date = fields.Date.context_today(self)
rules = self.env['price.rule'].get_rules(
self.order_id.pricelist_id, date)
max_dis_price = []
min_dis_price = []
discount_per = 0.0
apply_method = self.order_id.pricelist_id.apply_method
discount = 0.0
context_partner = dict(self.env.context,
partner_id=self.order_id.partner_id.id,
date=self.order_id.date_order)
pricelist_context = dict(context_partner, uom=self.product_uom.id)
product_price = 0.0
for rule in rules:
adv_price, adv_rule_id = \
self.order_id.pricelist_id.with_context(
pricelist_context).get_product_price_rule_flectra(
self.product_id, self.product_uom_qty,
self.order_id.partner_id, rule, self.price_unit)
rule_line_id = self.env['rule.line'].browse(adv_rule_id)
if not rule_line_id:
return discount, product_price
adv_new_price = 0.0
currency_id = False
if rule_line_id.rule_type == 'percent':
adv_new_price, currency_id = self.with_context(
context_partner)._get_real_price_currency(
self.product_id, False,
self.product_uom_qty,
self.product_uom,
self.order_id.pricelist_id.id)
else:
adv_new_price, currency_id = self.with_context(
context_partner)._get_real_price_currency_flectra(
self.product_id,
self.product_uom,
self.order_id.pricelist_id, self.price_unit)
if adv_new_price != 0:
if self.order_id.pricelist_id.currency_id.id != currency_id:
adv_new_price = self.env['res.currency'].browse(
currency_id).with_context(context_partner).compute(
adv_new_price, rule.pricelist_id.currency_id)
if not product_price:
product_price = adv_new_price
discount_per =\
(adv_new_price - adv_price) / adv_new_price * 100
if apply_method == 'first_matched_rule':
discount += discount_per
break
elif apply_method == 'all_matched_rules':
discount += discount_per
elif apply_method == 'smallest_discount' and adv_rule_id:
min_dis_price.append(discount_per)
else:
max_dis_price.append(discount_per)
if min_dis_price:
discount += min(min_dis_price)
if max_dis_price:
discount += max(max_dis_price)
return discount, product_price
# Overrides Function
@api.onchange('product_id', 'price_unit', 'product_uom',
'product_uom_qty', 'tax_id')
def _onchange_discount(self):
self.discount = 0.0
if not (self.product_id and self.product_uom and
self.order_id.partner_id and self.order_id.pricelist_id and
self.order_id.pricelist_id.discount_policy ==
'without_discount' and
self.env.user.has_group('sale.group_discount_per_so_line')):
return
discount = 0.0
context_partner = dict(self.env.context,
partner_id=self.order_id.partner_id.id,
date=self.order_id.date_order)
pricelist_context = dict(context_partner, uom=self.product_uom.id)
if self.order_id.pricelist_id.pricelist_type == 'basic':
price, rule_id = self.order_id.pricelist_id.with_context(
pricelist_context).get_product_price_rule(
self.product_id, self.product_uom_qty or 1.0,
self.order_id.partner_id)
new_list_price, currency_id = self.with_context(
context_partner)._get_real_price_currency(
self.product_id, rule_id, self.product_uom_qty,
self.product_uom, self.order_id.pricelist_id.id)
if new_list_price != 0:
if self.order_id.pricelist_id.currency_id.id != currency_id:
new_list_price = self.env['res.currency'].browse(
currency_id).with_context(context_partner).compute(
new_list_price, self.order_id.pricelist_id.currency_id)
discount = (new_list_price - price) / new_list_price * 100
if discount > 0:
self.discount = discount
else:
if self.coupon_code_id and (self._context.get(
'quantity', False) or self._context.get(
'price_unit', False) or self._context.get('tax', False)):
raise Warning(_('You can not change order line. '
'Please remove coupon code first!'))
discount, product_price = self.get_rule_discount()
if discount > 0:
self.discount = discount
if self.order_id.have_coupon_code and self.coupon_code_id:
self.get_total_coupon_code()

View File

@ -0,0 +1,9 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_rule_line_user,access_rule_line_user,model_rule_line,base.group_user,1,0,0,0
access_price_rule_user,access_price_rule_user,model_price_rule,base.group_user,1,0,0,0
access_cart_rule_user,access_cart_rule_user,model_cart_rule,base.group_user,1,0,0,0
access_coupon_code_user,access_coupon_code_user,model_coupon_code,base.group_user,1,0,0,0
access_rule_line_manager,access_rule_line_manager,model_rule_line,base.group_partner_manager,1,0,0,0
access_price_rule_manager,access_price_rule_manager,model_price_rule,base.group_partner_manager,1,0,0,0
access_cart_rule_manager,access_cart_rule_manager,model_cart_rule,base.group_partner_manager,1,0,0,0
access_coupon_code_manager,access_coupon_code_manager,model_coupon_code,base.group_partner_manager,1,0,0,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_rule_line_user access_rule_line_user model_rule_line base.group_user 1 0 0 0
3 access_price_rule_user access_price_rule_user model_price_rule base.group_user 1 0 0 0
4 access_cart_rule_user access_cart_rule_user model_cart_rule base.group_user 1 0 0 0
5 access_coupon_code_user access_coupon_code_user model_coupon_code base.group_user 1 0 0 0
6 access_rule_line_manager access_rule_line_manager model_rule_line base.group_partner_manager 1 0 0 0
7 access_price_rule_manager access_price_rule_manager model_price_rule base.group_partner_manager 1 0 0 0
8 access_cart_rule_manager access_cart_rule_manager model_cart_rule base.group_partner_manager 1 0 0 0
9 access_coupon_code_manager access_coupon_code_manager model_coupon_code base.group_partner_manager 1 0 0 0

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 937 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

View File

@ -0,0 +1,237 @@
<section class="container">
<div class="row oe_spaced">
<h2 class="oe_slogan" style="">Advance Pricelist</h2>
<h3 class="oe_slogan">Apply Price Rules on Sale Orders</h3>
<div class="oe_demo oe_picture oe_screenshot">
<img class="oe_picture oe_screenshot" src="pricelist_pricerule_preview.gif">
</div>
</div>
</section>
<section class="container">
<div class="row oe_spaced">
<div class="oe_demo oe_picture oe_screenshot">
<p class="mt32 text-justify">
<h4>- Add new option Pricelist Type (Basic, Advanced).</h4></br>
<h4>- Apply Method :-</h4></br>
<UL>
<li> <b>Apply First Matched Rules</b> (Calculate discount of first match condition of Price Rules and Cart Rules)</li>
<li> <b>Apply All Matched Rules</b> (Calculate discount of all match condition of Price Rules and Cart Rules)</li>
<li> <b>Apply Smallest Matched Discount</b> (Append minimum discount of every match condition of Price Rules and Cart Rules and get minimum values from the list of Price Rules and Cart Rules)</li>
<li> <b>Apply Biggest Matched Discount</b> (Append maximum discount of every match condition of Price Rules and Cart Rules and get maximum values from the list of Price Rules and Cart Rules)</li>
</UL>
<h4> Price Rules applicable on the selected option:-</h4>
<ul>
<li><b>Global: </b> Apply for all Product.</li>
<li><b>Category: </b> Apply only for selected category.</li>
<li><b>Product Template: </b>Apply only for selected Product Template variants.</li>
<li><b>Product Variant:</b>Apply only for selected Product variants.</li>
</ul>
<h4>- Product Rules Line:-</h4></br>
<ul> <li>Discount applicable based on match condition which defines in Product Rules Line.</li></ul>
</p>
</div>
</div>
</section>
<section class="container">
<div class="row oe_spaced">
<h2 class="oe_slogan" style="">Cart Rules</h2>
<h3 class="oe_slogan">Apply Cart Rules on Sale Orders.</h3>
<div class="oe_demo oe_picture oe_screenshot">
<img class="oe_picture oe_screenshot" src="cart_rules_preview.gif">
</div>
</div>
</section>
<section class="container">
<div class="row oe_spaced">
<div class="oe_demo oe_picture oe_screenshot">
<p class="mt32 text-justify">
<h4>- Apply On :-</h4></br>
<UL>
<li> <b>Subtotal At Least :-</b> Cart Rules not apply if Untaxed Amount is less than define amount in cart line.</li>
<li> <b>Subtotal less than :-</b> Cart Rules apply if Untaxed Amount is less than define amount in cart line.</li>
<li> <b>Lines Count at least :-</b> Cart Rules not apply if line count of sale order(duplicate product exclude) is less than define amount in cart line.</li>
<li> <b>Lines less than :-</b> Cart Rules apply if line count of sale order(duplicate product exclude) is less than define amount in cart line.</li>
<li> <b>Sum of Item Qty at least :-</b> Cart Rules is not apply if total quantity of product in sale order is less than define amount in cart line.</li>
<li> <b>Sum of Item Qty less than :-</b> Cart Rules apply if the total quantity of product in sale order is less than define amount in cart line.</li>
<li> <b>At least one product in order :-</b> Cart Rules apply if product match in sale order which defines in cart line.</li>
<li> <b>None of selected Products :-</b> Cart Rules do not apply if product match in sale order which defines in cart line.</li>
<li> <b>At least one category in order :-</b> Cart Rules apply if product category match in sale order which defines in cart line.</li>
<li> <b>None of selected Categories :-</b> Cart Rules do not apply if product category match in sale order which defines in cart line.</li>
</UL>
</p>
</div>
</div>
</section>
<section class="container">
<div class="row oe_spaced">
<h2 class="oe_slogan" style="">Coupon Rules</h2>
<h3 class="oe_slogan">Apply Coupon Rules on Sale Orders based on type and define conditions.</h3>
<div class="oe_demo oe_picture oe_screenshot">
<img class="oe_picture oe_screenshot" src="coupon_code_preview.gif">
</div>
</div>
</section>
<section class="container">
<div class="row oe_spaced">
<div class="oe_demo oe_picture oe_screenshot">
<p class="mt32 text-justify">
<h4>- Apply Coupon Code:</h4> Select apply coupon code option in pricelist for apply coupon code.</br>
<h4>- Coupon Type:</h4>
<UL>
<li> <b>Percent :-</b> Add Percentage in sale order line which defines in Discount Amount.</li>
<li> <b>Fixed Amount :-</b> Convert fixed amount values in percentage based on the unit price of sale order line.</li>
<li> <b>Buy X Product Get Y Product Free :-</b> Get Y same product unit free when buying X product.</li>
<li> <b>Buy X Product Get Y Other Product Free :-</b> Get Y other product(which define in coupon code) unit free when buying X product.</li>
<li> <b>Range Based Discount(Buy X Product Get Percent Free) :-</b> Get percent free(which define in coupon code) when buying X product.</li>
<li> <b>Clubbed Discount :-</b> Add Discount and Extra Discount on Sale order line.</li>
</UL>
</p>
</div>
</div>
</section>
<section class="container">
<div class="row oe_spaced">
<h2 class="oe_slogan" style="">Price Rule line</h2>
<h3 class="oe_slogan">Match first product rule line for first sale order</h3>
<div class="col-md-12">
<img class="oe_picture oe_screenshot" src="pricelist_rule_line1.png">
</div>
</div>
</section>
<section class="container">
<div class="row oe_spaced">
<h2 class="oe_slogan" style="">Cart Rule line</h2>
<h3 class="oe_slogan">Match first Cart rule line for first sale order</h3>
<div class="col-md-12">
<img class="oe_picture oe_screenshot" src="pricelist_cart_rule.png">
</div>
</div>
</section>
<section class="container">
<div class="row oe_spaced">
<h2 class="oe_slogan" style="">Discount Calculation</h2>
<h3 class="oe_slogan">Sale Order line discount calculation.</h3>
<div class="oe_demo oe_picture oe_screenshot">
<img class="oe_picture oe_screenshot" src="sale_order.png">
</div>
</div>
</section>
<section class="container">
<div class="row oe_spaced">
<div class="col-md-6">
<p class="mt32 mb32 text-justify">
<h4>First order line discount caculation:</h4> </br>
<p style="margin-left: 20px;">First order line quantity 5 is between 1 to 5 in Product Rule Line.</p>
<p style="margin-left: 20px;">Here define fixed amount = 50 in match Product Rule Line.</p>
<p style="margin-left: 20px;">Percentage Formule = Discount Amount * 100 / Unit Price</p>
<p style="margin-left: 20px;">50 * 100 / 885 = 5.65</p>
<p style="margin-left: 20px;">6.5 % of Match first Cart Rules beacuse Subtotal(Untaxed Amount) At Least : 2,500.00.</p>
<p style="margin-left: 20px;">Discount Formula= <b> Product Rule line + Cart Rules</b></p>
<p style="margin-left: 20px;">so discount is <b>5.65 + 6.5 = 12.15%</b></p>
</p>
</div>
<div class="col-md-6">
<p class="mt32 mb32 text-justify">
<h4> Second order line discount caculation:</h4> </br>
<p style="margin-left: 20px;">Second order line quantity 3 is between 1 to 5 in Product Rule Line.</p>
<p style="margin-left: 20px;">Discount = Discount Amount * 100 / Unit Price</p>
<p style="margin-left: 20px;">50 * 100 / 2950 = 1.69</p>
<p style="margin-left: 20px;">6.5 % of Match first Cart Rules beacuse Subtotal(Untaxed Amount) At Least : 2,500.00.</p>
<p style="margin-left: 20px;">so discount is <b> 1.69 + 6.5 = 8.19%</b></p>
<h4> Third order line discount caculation:</h4> </br>
<p style="margin-left: 20px;">Third order line quantity 3 is between 1 to 5 in Product Rule Line.</p>
<p style="margin-left: 20px;">Unit Price(25) is less than Fixed Amount(50) of Product Rule Lines.</p>
<p style="margin-left: 20px;">so, it give <b> 100% </b> discount for that line.</p>
</p>
</div>
</div>
</section>
<section class="container">
<div class="row oe_spaced">
<h2 class="oe_slogan" style="">Price Rule line</h2>
<h3 class="oe_slogan">Match first product rule line for Second Sale Order</h3>
<div class="col-md-12">
<img class="oe_picture oe_screenshot" src="pricelist2_rule_line.png">
</div>
</div>
</section>
<section class="container">
<div class="row oe_spaced">
<h2 class="oe_slogan" style="">Cart Rule line</h2>
<h3 class="oe_slogan">Match first Cart rule line for Second Sale Order </h3>
<div class="col-md-12">
<img class="oe_picture oe_screenshot" src="pricelist2_cart_rule.png">
</div>
</div>
</section>
<section class="container">
<div class="row oe_spaced">
<h2 class="oe_slogan" style="">Sale Order With Coupon Code</h2>
<h3 class="oe_slogan">Sale Order line discount calculation with Coupon Code.</h3>
<div class="oe_demo oe_picture oe_screenshot">
<img class="oe_picture oe_screenshot" src="sale_order_1.png">
</div>
</div>
</section>
<section class="container">
<div class="row oe_spaced">
<div class="oe_demo oe_picture oe_screenshot">
<p class="text-justify">
<h4>First order line discount caculation:</h4> </br>
<p style="margin-left: 20px;"><b>Product Lines Rules:</b></p>
<p style="margin-left: 20px;">4.9 % of Match first Product Rule Lines beacuse ordered Qty 5 is between 1 to 6.</p>
<p style="margin-left: 20px;"><b>Cart Rules:</b></p>
<p style="margin-left: 20px;">First cart Rules not match beacuse Subtotal is greater than : 3,000.00 so that rules skip.</p>
<p style="margin-left: 20px;">Second Cart Rules match beacuse Sum of Item Qty at least : 7.00 (here 8 = 5 + 3 ). so add 10 %.</p>
<p style="margin-left: 20px;"><b>Coupon Code: Coupon code get 10 percent free.</b>
<p style="margin-left: 20px;">Discount Formula= <b> Product Rule line + Cart Rules + Coupon Code</b></p>
<p style="margin-left: 20px;">First line discount is 24.9 %( 4.9 + 10 + 10)</p>
</p>
</div>
</div>
</section>
<section class="container">
<div class="row oe_spaced">
<h2 class="oe_slogan" style="">Discount Calculation View</h2>
<h3 class="oe_slogan">Display Price Rules, Cart Rules, Coupon Coupon discoun details.</h3>
<div class="col-md-12">
<img class="oe_picture oe_screenshot" src="calculation_view.png">
</div>
</div>
</section>
<section class="container">
<div class="row oe_spaced">
<div class="oe_demo oe_picture oe_screenshot">
<p class="text-justify">
<h4><b>Price Rule:</b></h4>
<p style="margin-left: 20px;"><b>Percent 4.9%.</b></p>
<p style="margin-left: 20px;">Sale Order Discount = sum of <b>(Unit Price * Ordered Qty)</b> * 4.9 / 100 of every line</p>
<p style="margin-left: 20px;">(885 * 5) + (2950 * 3) * 4.9 / 100 = <b>650.48</b></p>
<h4><b>Cart Rules:</b></h4>
<p style="margin-left: 20px;"><b>Percent 10%.</b></p>
<p style="margin-left: 20px;"><b>Cart Rules: (Gross Amount * 10) / 100</b></p>
<p style="margin-left: 20px;">13275 * 10 / 100 = <b>1327.50</b></p>
<h4><b>Coupon Code Rules:</b></h4>
<p style="margin-left: 20px;"><b>Percent 10%.</b></p>
<p style="margin-left: 20px;"><b>Coupon Code Rules: (Gross Amount * 10) / 100</b></p>
<p style="margin-left: 20px;">13275 * 10 / 100 = <b>1327.50</b></p>
</p>
</div>
</div>
</section>

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

View File

@ -0,0 +1,55 @@
flectra.define('sale.pricelist', function (require) {
"use strict";
var AbstractField = require('web.AbstractField');
var core = require('web.core');
var field_registry = require('web.field_registry');
var QWeb = core.qweb;
var ShowDiscountDetailsWidget = AbstractField.extend({
supportedFieldTypes: ['char'],
isSet: function() {
return true;
},
_render: function() {
var self = this;
var info = JSON.parse(this.value);
if (!info) {
this.$el.html('');
return;
}
this.$el.html(QWeb.render('ShowDiscountInfo', {
lines: info.content,
outstanding: info.outstanding,
title: info.title
}));
_.each(this.$('.js_discount_info'), function (k, v){
var content = info.content[v];
var options = {
content: function () {
var $content = $(QWeb.render('AllDiscountDetails', {
gross_amount: content.gross_amount,
price_list_discount: content.price_list_discount,
price_rule_discount: content.price_rule_discount,
cart_rule_discount: content.cart_rule_discount,
coupon_code_discount: content.coupon_code_discount,
currency: content.currency,
untaxed_amount: content.untaxed_amount,
position: content.position,
amount_words: content.amount_words,
discount: content.discount,
}));
return $content;
},
html: true,
placement: 'left',
title: 'Discount Calculation Details:',
trigger: 'focus',
delay: { "show": 0, "hide": 100 },
};
$(k).popover(options);
});
},
});
field_registry.add('discount_widget', ShowDiscountDetailsWidget);
});

View File

@ -0,0 +1,119 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates xml:space="preserve">
<t t-name="ShowDiscountInfo">
<div>
<table style="width:100%;">
<t t-if="lines">
<t t-foreach="lines" t-as="line">
<tr>
<t t-if="!outstanding">
<td>
<a role="button" tabindex="0" class="js_discount_info fa fa-info-circle" t-att-index="line.index" style="margin-right:2px;"></a>
</td>
</t>
</tr>
</t>
</t>
</table>
</div>
</t>
<t t-name="AllDiscountDetails">
<div>
<table>
<tr>
<td><strong>Discount Amount to Words: </strong></td>
<td style="text-align:right;">
<t t-if="position === 'before'">
<t t-esc="currency"/>
</t>
<t t-esc="discount"></t>
<t t-if="position === 'after'">
<t t-esc="currency"/>
</t>
</td>
</tr>
<tr>
<td colspan="2" style="text-align:center;padding-top:8px;">
<t t-esc="amount_words"></t>
</td>
</tr>
<tr >
<td style="padding-top:18px;"><strong>Gross Amount: </strong></td>
<td style="text-align:right; padding-top:18px;">
<t t-if="position === 'before'">
<t t-esc="currency"/>
</t>
<t t-esc="gross_amount"></t>
<t t-if="position === 'after'">
<t t-esc="currency"/>
</t>
</td>
</tr>
<tr>
<td><strong>Pricelist (-): </strong></td>
<td style="text-align:right;">
<t t-if="position === 'before'">
<t t-esc="currency"/>
</t>
<t t-esc="price_list_discount"></t>
<t t-if="position === 'after'">
<t t-esc="currency"/>
</t>
</td>
</tr>
<tr>
<td><strong>Price Rule (-): </strong></td>
<td style="text-align:right;">
<t t-if="position === 'before'">
<t t-esc="currency"/>
</t>
<t t-esc="price_rule_discount"></t>
<t t-if="position === 'after'">
<t t-esc="currency"/>
</t>
</td>
</tr>
<tr>
<td><strong>Cart Rule (-): </strong></td>
<td style="text-align:right;">
<t t-if="position === 'before'">
<t t-esc="currency"/>
</t>
<t t-esc="cart_rule_discount"></t>
<t t-if="position === 'after'">
<t t-esc="currency"/>
</t>
</td>
</tr>
<tr>
<td><strong>Coupon Code (-): </strong></td>
<td style="text-align:right;">
<t t-if="position === 'before'">
<t t-esc="currency"/>
</t>
<t t-esc="coupon_code_discount"></t>
<t t-if="position === 'after'">
<t t-esc="currency"/>
</t>
</td>
</tr>
<tr class="border-black" style="border-top:1px solid #dddddd;">
<td><strong>Untaxed Amount: </strong></td>
<td style="text-align:right;">
<t t-if="position === 'before'">
<t t-esc="currency"/>
</t>
<t t-esc="untaxed_amount"></t>
<t t-if="position === 'after'">
<t t-esc="currency"/>
</t>
</td>
</tr>
</table>
</div>
</t>
</templates>

View File

@ -0,0 +1,7 @@
# Part of Flectra See LICENSE file for full copyright and licensing details.
from . import sale_advance_pricelist_common
from . import test_01_first_match
from . import test_02_coupon_code
from . import test_03_all_match
from . import test_04_mix_all

View File

@ -0,0 +1,49 @@
# Part of Flectra See LICENSE file for full copyright and licensing details.
from flectra.tests.common import TransactionCase
class TestAdvSalePricelist(TransactionCase):
def setUp(self):
super(TestAdvSalePricelist, self).setUp()
self.partner_id = self.env.ref(
'sale_advance_pricelist.res_partner_advance_pricelist')
self.currency_id = self.env.ref('base.USD')
self.category_id = self.env.ref('product.product_category_5')
self.pricelist_1 = \
self.env.ref('sale_advance_pricelist.advance_pricelist')
self.pricelist_2 = self.env.ref(
'sale_advance_pricelist.advance_pricelist_with_coupon')
self.pricelist_3 = \
self.env.ref('sale_advance_pricelist.advance_pricelist_all')
self.sale_order_2 = \
self.env.ref('sale_advance_pricelist.sale_order_ap_2')
self.sale_order_3 = \
self.env.ref('sale_advance_pricelist.sale_order_ap_3')
self.sale_order_4 = \
self.env.ref('sale_advance_pricelist.sale_order_ap_4')
self.sale_order_5 = \
self.env.ref('sale_advance_pricelist.sale_order_ap_5')
self.sale_order_6 = \
self.env.ref('sale_advance_pricelist.sale_order_ap_6')
self.sale_order_7 = \
self.env.ref('sale_advance_pricelist.sale_order_ap_7')
self.sale_order_8 = \
self.env.ref('sale_advance_pricelist.sale_order_ap_all_1')
self.product_1 = self.env.ref('product.product_product_24')
self.product_2 = self.env.ref('product.product_product_25')
self.product_3 = self.env.ref('product.product_product_16')
self.SaleOrder = self.env['sale.order']
self.SaleOrderLine = self.env['sale.order.line']
self.CouponCode = self.env['coupon.code']
def check_all_coupon_code(self, order_id, coupon_code, pricelist_id):
coupon_code_id = self.CouponCode.get_coupon_records(
coupon_code, pricelist_id)
self.assertEqual(len(coupon_code_id), 1, 'Coupon code should be 1!')
order_id.have_coupon_code = coupon_code
order_id.apply_coupon_code()

View File

@ -0,0 +1,104 @@
# Part of Flectra See LICENSE file for full copyright and licensing details.
from .sale_advance_pricelist_common import TestAdvSalePricelist
from flectra.tools import float_compare
class TestFirstMatchDiscount(TestAdvSalePricelist):
def setUp(self):
super(TestFirstMatchDiscount, self).setUp()
def test_discount_rule_and_cart(self):
so = self.SaleOrder.create({
'partner_id': self.partner_id.id,
'partner_invoice_id': self.partner_id.id,
'partner_shipping_id': self.partner_id.id,
'pricelist_id': self.pricelist_1.id,
})
line_1 = self.SaleOrderLine.create({
'name': self.product_1.name,
'product_id': self.product_1.id,
'product_uom_qty': 5,
'product_uom': self.product_1.uom_id.id,
'price_unit': self.product_1.list_price,
'order_id': so.id,
})
self.SaleOrderLine.create({
'name': self.product_2.name,
'product_id': self.product_2.id,
'product_uom_qty': 3,
'product_uom': self.product_2.uom_id.id,
'price_unit': self.product_2.list_price,
'order_id': so.id,
})
self.SaleOrderLine.create({
'name': self.product_3.name,
'product_id': self.product_3.id,
'product_uom_qty': 3,
'product_uom': self.product_3.uom_id.id,
'price_unit': self.product_3.list_price,
'order_id': so.id,
})
so._check_cart_rules()
so._get_discount_info_JSON()
self.assertEqual(float_compare(
so.order_line[0].discount, 12.15,
precision_digits=2), 0, 'Discount Line: the discount of first'
'sale order line should be 12.15!')
line_1.write({'price_unit': 1200})
so._check_cart_rules()
self.assertEqual(float_compare(
so.order_line[0].discount, 10.67,
precision_digits=2), 0, 'Discount Line: the discount of first'
'sale order line should be 10.67!')
self.assertEqual(float_compare(
so.order_line[1].discount, 8.19,
precision_digits=2), 0, 'Discount Line: the discount of second'
'sale order line should be 8.19!')
line_1.write({'price_unit': 885})
so._check_cart_rules()
self.assertEqual(so.discount, 1337.45,
'Sale Discount: the discount for the '
'sale order should be 1337.45!')
# Change discount policy
so.pricelist_id.discount_policy = 'with_discount'
line_1.write({'product_uom_qty': 1})
line_1._onchange_discount()
so._check_cart_rules()
self.assertEqual(line_1.price_unit, 777.48,
"Price unit of the line should be 777.48!")
self.assertEqual(line_1.discount, 0.0,
"Price unit of the line should be 0.0!")
self.assertEqual(float_compare(
so.order_line[0].discount, 00.00,
precision_digits=2), 0, 'Discount Line: the discount of first'
'sale order line should be 00.00!')
basic_pricelist = self.env['product.pricelist'].create({
'name': 'Basic Pricelist',
'sequence': 1,
'discount_policy': 'without_discount',
'pricelist_type': 'basic',
'currency_id': self.currency_id.id,
'item_ids': [(0, 0, {'compute_price': 'percentage',
'percent_price': 10})],
})
so_1 = so.copy()
so_1.pricelist_id = basic_pricelist.id
self.assertEqual(float_compare(
so.order_line[0].discount, 00.00,
precision_digits=2), 0, 'Discount Line: the discount of first'
'sale order line should be 00.00!')
so_1.order_line[0]._onchange_discount()
so_1._get_discount_vals()
self.assertEqual(float_compare(
so_1.order_line[0].discount, 10.00,
precision_digits=2), 0, 'Discount Line: the discount of first'
'sale order line should be 10.00!')

View File

@ -0,0 +1,136 @@
# Part of Flectra See LICENSE file for full copyright and licensing details.
from .sale_advance_pricelist_common import TestAdvSalePricelist
from flectra.tools import float_compare
class TestCouponCodeMatchDiscount(TestAdvSalePricelist):
def setUp(self):
super(TestCouponCodeMatchDiscount, self).setUp()
def test_Percentage_coupon_code(self):
if not self.sale_order_2.coupon_flag:
self.check_all_coupon_code(self.sale_order_2,
'Get10Peroff', self.pricelist_2)
self.assertTrue(self.sale_order_2.have_coupon_code != '',
'Coupon Code: Please enter the coupon code!')
self.assertEqual(float_compare(
self.sale_order_2.order_line[0].discount, 24.90,
precision_digits=2), 0, 'Discount Line: the discount of first'
'sale order line should be 24.90!')
self.assertEqual(self.sale_order_2.discount, 3305.48,
'Sale Discount: the discount for the '
'sale order should be 3305.48!')
def test_Fixed_coupon_code(self):
if not self.sale_order_3.coupon_flag:
self.check_all_coupon_code(self.sale_order_3,
'Get20off', self.pricelist_2)
self.assertTrue(self.sale_order_3.have_coupon_code != '',
'Coupon Code: Please enter the coupon code!')
self.assertEqual(float_compare(
self.sale_order_3.order_line[0].discount, 17.16,
precision_digits=2), 0, 'Discount Line: the discount of first'
'sale order line should be 17.16!')
self.assertEqual(float_compare(
self.sale_order_3.order_line[1].discount, 15.58,
precision_digits=2), 0, 'Discount Line: the discount of second'
'sale order line should be 15.58!')
self.assertEqual(self.sale_order_3.discount, 2138.16,
'Sale Discount: the discount for the '
'sale order should be 2138.16!')
# Remove Coupon Code
self.sale_order_3.apply_coupon_code()
coupon_code_id = self.CouponCode.search([
('coupon_code', '=', 'Get20off')])
coupon_code_id.write({'discount_amount': 30})
self.SaleOrderLine.create({
'name': self.product_3.name,
'product_id': self.product_3.id,
'product_uom_qty': 3,
'product_uom': self.product_3.uom_id.id,
'price_unit': self.product_3.list_price,
'order_id': self.sale_order_3.id,
})
self.sale_order_3._check_cart_rules()
self.check_all_coupon_code(self.sale_order_3,
'Get20off', self.pricelist_2)
def test_Buy_X_Product_Get_Y_Product_Free_coupon_code(self):
if not self.sale_order_4.coupon_flag:
self.check_all_coupon_code(self.sale_order_4,
'BXGYFree', self.pricelist_2)
self.assertTrue(self.sale_order_4.have_coupon_code != '',
'Coupon Code: Please enter the coupon code!')
self.assertEqual(float_compare(
self.sale_order_4.order_line[0].discount, 14.90,
precision_digits=2), 0, 'Discount Line: the discount of first'
'sale order line should be 14.90!')
self.assertEqual(self.sale_order_4.discount, 1977.98,
'Sale Discount: the discount for the'
' sale order should be 1977.98!')
self.assertTrue(len(self.sale_order_4.order_line) == 4,
'Sale: Order Line is missing')
self.assertEqual(self.sale_order_4.order_line[2].price_unit, 0.0,
'Price unit of the line should be 0.0!')
self.assertEqual(self.sale_order_4.order_line[3].price_unit, 0.0,
'Price unit of the line should be 0.0!')
def test_Buy_X_Product_Get_Y_Other_Product_Free_coupon_code(self):
if not self.sale_order_5.coupon_flag:
self.check_all_coupon_code(self.sale_order_5,
'BXGYOtherFree', self.pricelist_2)
self.assertTrue(self.sale_order_5.have_coupon_code != '',
'Coupon Code: Please enter coupon code!')
self.assertEqual(float_compare(
self.sale_order_5.order_line[0].discount, 14.90,
precision_digits=2), 0, 'Discount Line: the discount of first'
'sale order line should be 14.90!')
self.assertEqual(self.sale_order_5.discount, 1977.98,
'Sale Discount: the discount for the '
'sale order should be 1977.98!')
self.assertTrue(len(self.sale_order_5.order_line) == 3,
'Sale: Order Line is missing')
self.assertEqual(self.sale_order_5.order_line[2].price_unit, 0.0,
'Price unit of the line should be 0.0!')
def test_Clubbed_Discount_coupon_code(self):
if not self.sale_order_6.coupon_flag:
self.check_all_coupon_code(self.sale_order_6,
'CD15Per', self.pricelist_2)
self.assertTrue(self.sale_order_6.have_coupon_code != '',
'Coupon Code: Please enter coupon code!')
self.assertEqual(float_compare(
self.sale_order_6.order_line[0].discount, 29.90,
precision_digits=2), 0, 'Discount Line: the discount of first'
'sale order line should be 29.90!')
self.assertEqual(self.sale_order_6.discount, 3969.23,
'Sale Discount: the discount for the '
'sale order should be 3969.23!')
self.assertEqual(float_compare(
self.sale_order_6.order_line[1].discount, 29.90,
precision_digits=2), 0, 'Discount Line: the discount of first'
'sale order line should be 29.90!')
self.assertEqual(float_compare(
self.sale_order_6.amount_total, 9305.78, precision_digits=2),
0, "Total not correct")
def test_Buy_X_Product_Get_Percent_Free_coupon_code(self):
if not self.sale_order_7.coupon_flag:
self.check_all_coupon_code(self.sale_order_7,
'BXGPercentFree', self.pricelist_2)
self.assertTrue(self.sale_order_7.have_coupon_code != '',
'Coupon Code: Please enter the coupon code!')
self.assertEqual(float_compare(
self.sale_order_7.order_line[0].discount, 22.65,
precision_digits=2), 0, 'Discount Line: the discount of first'
'sale order line should be 22.65!')
self.assertEqual(float_compare(
self.sale_order_7.order_line[1].discount, 14.90,
precision_digits=2), 0, 'Discount Line: the discount of first'
'sale order line should be 14.90!')
self.assertEqual(self.sale_order_7.discount, 1881.36,
'Sale Discount: the discount for the'
' sale order should be 1881.36!')

View File

@ -0,0 +1,32 @@
# Part of Flectra See LICENSE file for full copyright and licensing details.
from .sale_advance_pricelist_common import TestAdvSalePricelist
class TestAllMatchDiscount(TestAdvSalePricelist):
def setUp(self):
super(TestAllMatchDiscount, self).setUp()
def test_All_Match(self):
self.assertEqual(self.sale_order_8.order_line[0].discount, 12.50,
"Discount of first line should be 12.50!")
self.assertEqual(self.sale_order_8.order_line[1].discount, 10.50,
"Discount of Second line should be 10.50!")
self.assertEqual(self.sale_order_8.discount, 1482.38,
'Sale Discount: the discount for the '
'sale order should be 1482.38!')
# Change discount in rules lines
self.pricelist_3.rule_ids.rule_lines[0].discount_amount = 5
self.pricelist_3.rule_ids.rule_lines[1].discount_amount = 7
self.pricelist_3.rule_ids.rule_lines[2].discount_amount = 9
# Check again percentage and discount in Sale order
self.sale_order_8._check_cart_rules()
self.assertEqual(self.sale_order_8.order_line[0].discount, 14.50,
"Discount of first line should be 14.50!")
self.assertEqual(self.sale_order_8.order_line[1].discount, 12.50,
"Discount of second line should be 12.50!")
self.assertEqual(self.sale_order_8.discount, 1747.88,
'Sale Discount: the discount for the '
'sale order should be 1747.88!')

View File

@ -0,0 +1,199 @@
# Part of Flectra See LICENSE file for full copyright and licensing details.
from .sale_advance_pricelist_common import TestAdvSalePricelist
class TestMixAllDiscount(TestAdvSalePricelist):
def setUp(self):
super(TestMixAllDiscount, self).setUp()
def test_Mix_All_Match(self):
PriceRule = self.env['price.rule']
RuleLine = self.env['rule.line']
ProductPricelis = self.env['product.pricelist']
self.pricelist_id = ProductPricelis.create({
'name': 'Test Pricelist',
'sequence': 4,
'discount_policy': 'without_discount',
'pricelist_type': 'advance',
'currency_id': self.currency_id.id,
'apply_method': 'all_matched_rules',
'apply_coupon_code': True,
})
price_rule_id = PriceRule.create({
'sequence': 1,
'apply_on': 'category',
'categ_id': self.category_id.id,
'pricelist_id': self.pricelist_id.id,
})
price_rule_id._get_pricerule_name_price()
price_rule_id._onchange_apply_on()
rule_line_1 = RuleLine.create({
'sequence': 1,
'min_qty': 1,
'max_qty': 10,
'rule_type': 'percent',
'discount_amount': 12.5,
'price_rule_id': price_rule_id.id,
'model_id': self.env.ref('base.model_res_partner').id,
})
rule_line_1.check_percentage()
rule_line_1.check_date()
rule_line_2 = RuleLine.create({
'sequence': 1,
'min_qty': 5,
'max_qty': 20,
'rule_type': 'percent',
'discount_amount': 15,
'price_rule_id': price_rule_id.id,
})
rule_line_2._compute_model()
cart_rule_1 = self.env.ref('sale_advance_pricelist.cart_rule_1').copy()
cart_rule_1.pricelist_id = self.pricelist_id.id
cart_rule_1._get_cart_name_price()
cart_rule_1.check_percentage()
cart_rule_2 = self.env.ref('sale_advance_pricelist.cart_rule_2').copy()
cart_rule_2.pricelist_id = self.pricelist_id.id
cart_rule_2._get_cart_name_price()
self.coupon_code_id = self.CouponCode.create({
'name': 'Get 7%',
'coupon_code': 'GetDiscount',
'apply_on': 'category',
'categ_id': self.category_id.id,
'pricelist_id': self.pricelist_id.id,
'discount_amount': 7,
'coupon_type': 'percent',
'model_id': self.env.ref('base.model_res_partner').id,
})
self.coupon_code_id._onchange_apply_on()
self.coupon_code_id.check_percentage()
self.coupon_code_id.check_clubbed_percentage()
self.coupon_code_id._compute_model()
check_coupon = self.CouponCode.check_condition(
self.coupon_code_id, self.partner_id)
self.assertEqual(check_coupon, False,
"Coupon code condition criteria not match!")
# Check for All Match Discount
sale_order = self.sale_order_2.copy()
sale_order.pricelist_id = self.pricelist_id.id
first_order_line = sale_order.order_line[0]
first_order_line._onchange_discount()
second_order_line = sale_order.order_line[1]
second_order_line._onchange_discount()
sale_order._check_cart_rules()
self.assertEqual(first_order_line.discount, 34.00,
'Discount Percentage: the discount for the'
' first sale order line should be 34!')
self.assertEqual(second_order_line.discount, 19.00,
'Discount Percentage: the discount for the'
' second sale order line should be 19.00!')
# Check for Smallest Discount
self.pricelist_id.apply_method = 'smallest_discount'
tmp_id = self.product_1.product_tmpl_id.id
price_rule_id.write({'apply_on': 'product_template',
'categ_id': False,
'product_tmpl_id': tmp_id})
price_rule_id._get_pricerule_name_price()
price_rule_id._onchange_apply_on()
self.sale_order = self.sale_order_2.copy()
self.sale_order.pricelist_id = self.pricelist_id.id
first_order_line = self.sale_order.order_line[0]
first_order_line._onchange_discount()
self.assertEqual(first_order_line.discount, 12.5,
'Discount Percentage: the discount for the'
' sale order line should be 12.5!')
self.sale_order._check_cart_rules()
# Set coupon code with percent
self.check_all_condition(self.sale_order, 'percent')
# Set coupon code with fixed_amount
self.check_all_condition(self.sale_order, 'fixed_amount')
# Set coupon code with buy_x_get_y
self.check_all_condition(self.sale_order, 'buy_x_get_y')
# Set coupon code with buy_x_get_y_other
self.check_all_condition(self.sale_order, 'buy_x_get_y_other')
# Check for Biggest Discount
self.pricelist_id.apply_method = 'biggest_discount'
price_rule_id.write({'apply_on': 'product',
'categ_id': False,
'product_tmpl_id': False,
'product_id': self.product_1.id})
price_rule_id._get_pricerule_name_price()
cart_rule_3 = \
self.env.ref('sale_advance_pricelist.cart_rule_all_3').copy()
cart_rule_3.pricelist_id = self.pricelist_id.id
cart_rule_3._get_cart_name_price()
self.sale_order_1 = self.sale_order_2.copy()
self.sale_order_1.pricelist_id = self.pricelist_id.id
first_order_line = self.sale_order_1.order_line[0]
first_order_line._onchange_discount()
self.assertEqual(first_order_line.discount, 15.00,
'Discount Percentage: the discount for the'
' first sale order line should be 15!')
self.sale_order_1._check_cart_rules()
self.assertEqual(first_order_line.discount, 21.50,
'Discount Percentage: the discount for the'
' first sale order line should be 21.50!')
self.sale_order_1.coupon_flag = False
# # Set coupon code with buy_x_get_percent_free
self.check_all_condition(self.sale_order_1, 'buy_x_get_percent')
self.assertEqual(first_order_line.discount, 41.50,
'Discount Percentage: the discount for the'
' first sale order line should be 41.50!')
def check_all_condition(self, sale_order, coupon_type):
self.coupon_code_id.write({'coupon_type': coupon_type,
'apply_on': 'category',
'categ_id': self.category_id.id,
'discount_amount': 0.0,
'number_of_y_product': 0.0,
'number_of_y_product': 0.0,
'other_product_id': False})
if coupon_type in ['percent', 'fixed_amount']:
self.coupon_code_id.write({'discount_amount': 20})
elif coupon_type == 'buy_x_get_percent':
self.coupon_code_id.write({'discount_amount': 20,
'number_of_x_product': 3})
elif coupon_type == 'buy_x_get_y':
self.coupon_code_id.write({'number_of_x_product': 2,
'number_of_y_product': 1,
'discount_amount': 0.0})
else:
self.coupon_code_id.write({'number_of_x_product': 2,
'number_of_y_product': 1,
'discount_amount': 0.0,
'other_product_id': self.product_3.id})
# Category Coupon Code
self.check_all_coupon_code(sale_order,
'GetDiscount', self.pricelist_id)
# Product Coupon Code
self.coupon_code_id.write({'apply_on': 'product',
'product_id': self.product_1.id})
self.check_all_coupon_code(sale_order,
'GetDiscount', self.pricelist_id)
# Product Template Coupon Code
template_id = self.product_1.product_tmpl_id.id
self.coupon_code_id.write({'apply_on': 'product_template',
'product_tmpl_id': template_id})
self.check_all_coupon_code(sale_order,
'GetDiscount', self.pricelist_id)

View File

@ -0,0 +1,204 @@
<?xml version="1.0" encoding="utf-8"?>
<flectra>
<record id="view_price_rule_tree" model="ir.ui.view">
<field name="name">price.rule.tree</field>
<field name="model">price.rule</field>
<field name="arch" type="xml">
<tree string="Price Rules">
<field name="sequence" widget="handle"/>
<field name="name" string="Applicable On"/>
<field name="start_date" />
<field name="end_date" />
</tree>
</field>
</record>
<record id="view_price_rule_form" model="ir.ui.view">
<field name="name">price.rule.form</field>
<field name="model">price.rule</field>
<field name="arch" type="xml">
<form string="Price Rule">
<h1><field name="name"/></h1>
<group>
<group>
<field name="apply_on"/>
<field name="categ_id" attrs="{'invisible': [('apply_on','!=','category')], 'required': [('apply_on','=','category')]}"/>
<field name="product_id" attrs="{'invisible': [('apply_on','!=','product')], 'required': [('apply_on','=','product')]}"/>
<field name="product_tmpl_id" attrs="{'invisible': [('apply_on','!=','product_template')], 'required': [('apply_on','=','product_template')]}"/>
</group>
<group>
<field name="start_date"/>
<field name="end_date"/>
</group>
</group>
<notebook>
<page string="Product Rule Lines">
<field name="rule_lines" nolabel="1">
<tree string="Rule Line" >
<field name="sequence" widget="handle"/>
<field name="min_qty" />
<field name="max_qty" />
<field name="start_date" />
<field name="end_date" />
<field name="rule_type" />
<field name="discount_amount"/>
</tree>
<form string="Rule Lines">
<group>
<group>
<field name="rule_type" />
<field name="discount_amount" />
<field name="start_date" />
</group>
<group>
<field name="min_qty"/>
<field name="max_qty"/>
<field name="end_date" />
</group>
</group>
<group>
<label for="model_id" string="Condition"/>
<div>
<field name="model_id" widget="selection"/>
<field name="model_name" invisible="1"/>
<field name="model_real" invisible="1"/>
<field name="model_domain" widget="domain"
options="{'model': 'model_real'}"/>
</div>
</group>
</form>
</field>
</page>
<page string="Note">
<field name="note" nolabel="1"/>
</page>
</notebook>
</form>
</field>
</record>
<record id="view_cart_rule_tree" model="ir.ui.view">
<field name="name">cart.rule.tree</field>
<field name="model">cart.rule</field>
<field name="arch" type="xml">
<tree string="Cart Rules">
<field name="sequence" widget="handle"/>
<field name="name" string="Applicable On"/>
<field name="start_date"/>
<field name="end_date" />
<field name="discount_percentage"/>
</tree>
</field>
</record>
<record id="view_cart_rule_form" model="ir.ui.view">
<field name="name">cart.rule.form</field>
<field name="model">cart.rule</field>
<field name="arch" type="xml">
<form string="Cart Rule">
<h1><field name="name"/></h1>
<group>
<group>
<field name="start_date"/>
<field name="discount_percentage"/>
</group>
<group>
<field name="end_date"/>
</group>
</group>
<group>
<field name="apply_on"/>
<field name="amt_value" attrs="{'invisible': [('apply_on','in',('one_product_al_least','none_of_sel_products','one_categ_al_least','none_of_sel_categs'))], 'required': [('apply_on','not in',('one_product_al_least','none_of_sel_products','one_categ_al_least','none_of_sel_categs'))]}"/>
<field name="product_id" attrs="{'invisible': [('apply_on','!=','one_product_al_least')], 'required': [('apply_on','=','one_product_al_least')]}"/>
<field name="product_ids" widget="many2many_tags" attrs="{'invisible': [('apply_on','!=','none_of_sel_products')], 'required': [('apply_on','=','none_of_sel_products')]}"/>
<field name="categ_id" attrs="{'invisible': [('apply_on','!=','one_categ_al_least')], 'required': [('apply_on','=','one_categ_al_least')]}"/>
<field name="categ_ids" widget="many2many_tags" attrs="{'invisible': [('apply_on','!=','none_of_sel_categs')], 'required': [('apply_on','=','none_of_sel_categs')]}"/>
</group>
<group string="Note">
<field name="note" nolabel="1"/>
</group>
</form>
</field>
</record>
<record id="view_coupon_code_tree" model="ir.ui.view">
<field name="name">coupon.code.tree</field>
<field name="model">coupon.code</field>
<field name="arch" type="xml">
<tree string="Coupon">
<field name="name"/>
<field name="coupon_code"/>
<field name="code_valid_from" />
<field name="code_valid_to" />
<field name="apply_on" string="Applicable On"/>
<field name="coupon_type"/>
<field name="discount_amount"/>
<field name="min_order_amount"/>
</tree>
</field>
</record>
<record id="view_coupon_code_form" model="ir.ui.view">
<field name="name">coupon.code.form</field>
<field name="model">coupon.code</field>
<field name="arch" type="xml">
<form string="Coupon">
<div class="oe_button_box" name="button_box">
<button class="oe_stat_button" type="object" name="view_sale_order" icon="fa-usd" attrs="{'invisible': [('sale_order_count', '&lt;', 1)]}">
<field string="Sales" name="sale_order_count" widget="statinfo"/>
</button>
</div>
<group>
<group>
<field name="name"/>
<field name="coupon_code"/>
<field name="usage_limit"/>
</group>
<group>
<field name="code_valid_from"/>
<field name="code_valid_to"/>
<field name="remaining_limit" readonly="1"/>
</group>
<group>
<field name="coupon_type"/>
<field name="number_of_x_product" attrs="{'invisible': [('coupon_type','not in',['buy_x_get_y', 'buy_x_get_y_other', 'buy_x_get_percent'])], 'required': [('coupon_type','in', ['buy_x_get_y', 'buy_x_get_y_other', 'buy_x_get_percent'])]}"/>
<field name="number_of_y_product" attrs="{'invisible': [('coupon_type','not in',['buy_x_get_y', 'buy_x_get_y_other'])], 'required': [('coupon_type','in',['buy_x_get_y', 'buy_x_get_y_other'])]}"/>
<field name="discount_amount" attrs="{'invisible': [('coupon_type','not in',['percent', 'fixed_amount', 'buy_x_get_percent'])]}"/>
<field name="other_product_id" attrs="{'invisible': [('coupon_type','!=','buy_x_get_y_other')], 'required': [('coupon_type','=','buy_x_get_y_other')]}"/>
</group>
<group>
<field name="min_order_amount"/>
<field name="apply_on" attrs="{'required': [('coupon_type','not in',['percent', 'fixed_amount'])]}"/>
<field name="categ_id" attrs="{'invisible': [('apply_on','!=','category')], 'required': [('apply_on','=','category')]}"/>
<field name="product_id" attrs="{'invisible': [('apply_on','!=','product')], 'required': [('apply_on','=','product')]}"/>
<field name="product_tmpl_id" attrs="{'invisible': [('apply_on','!=','product_template')], 'required': [('apply_on','=','product_template')]}"/>
</group>
<group col="6" attrs="{'invisible':[('coupon_type', '!=', 'clubbed')]}">
<label string="Discount ="/>
<div class="o_row">
<field name="flat_discount"/>
<span>%%</span>
</div>
<label string=" + Extra"/>
<div class="o_row">
<field name="extra_discount_percentage" nolabel="1"/>
<span>%%</span>
</div>
</group>
</group>
<group>
<label for="model_id" string="Condition"/>
<div>
<field name="model_id" widget="selection"/>
<field name="model_name" invisible="1"/>
<field name="model_real" invisible="1"/>
<field name="model_domain" widget="domain"
options="{'model': 'model_real'}"/>
</div>
</group>
</form>
</field>
</record>
</flectra>

View File

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<flectra>
<record id="product_pricelist_view_flectra" model="ir.ui.view">
<field name="name">product.pricelist.flectra.form</field>
<field name="model">product.pricelist</field>
<field name="inherit_id" ref="product.product_pricelist_view"/>
<field name="arch" type="xml">
<field name="company_id" position="before">
<field name="pricelist_type" widget="radio"/>
<field name="apply_method" class="oe_inline" attrs="{'invisible':[('pricelist_type','=', 'basic')]}"/>
<field name="apply_coupon_code" attrs="{'invisible':[('pricelist_type','=', 'basic')]}"/>
</field>
<div groups="product.group_pricelist_item" position="replace">
<div groups="product.group_pricelist_item">
<notebook>
<page string="Pricelist Items" attrs="{'invisible':[('pricelist_type','!=', 'basic')]}">
<field name="item_ids" nolabel="1" context="{'default_base':'list_price'}">
<tree string="Pricelist Items">
<field name="name" string="Applicable On"/>
<field name="min_quantity"/>
<field name="date_start"/>
<field name="date_end"/>
<field name="price" string="Price"/>
<field name="base" invisible="1"/>
<field name="price_discount" invisible="1"/>
<field name="applied_on" invisible="1"/>
<field name="compute_price" invisible="1"/>
</tree>
</field>
</page>
<page string="Price Rules" attrs="{'invisible':[('pricelist_type','!=', 'advance')]}">
<field name="rule_ids"/>
</page>
<page string="Cart Rules" attrs="{'invisible':[('pricelist_type','!=', 'advance')]}">
<field name="cart_rule_ids"/>
</page>
<page string="Coupon Code" attrs="{'invisible':['|', ('apply_coupon_code','=',False), ('pricelist_type','=', 'basic')]}">
<field name="coupon_code_lines"/>
</page>
</notebook>
</div>
</div>
</field>
</record>
</flectra>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<flectra>
<template id="assets_backend" name="discount price rule" inherit_id="web.assets_backend">
<xpath expr="." position="inside">
<script type="text/javascript" src="/sale_advance_pricelist/static/src/js/discount_details.js"></script>
</xpath>
</template>
</flectra>

View File

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="utf-8"?>
<flectra>
<record id="view_order_form_flectra" model="ir.ui.view">
<field name="name">sale.order.flectra.form</field>
<field name="model">sale.order</field>
<field name="inherit_id" ref="sale.view_order_form"/>
<field name="arch" type="xml">
<field name="amount_total" position="after">
<field name="discount_widget" style="position: relative; bottom: 94px;margin-left: 52px; text-align: left;" colspan="2" nolabel="1" widget="discount_widget"/>
</field>
<xpath expr="//group[@name='left_panel']" position="inside">
<div>
<field name="coupon_flag" invisible="1"/>
<label for="have_coupon_code" class="oe_inline"/>
<field name="have_coupon_code" attrs="{'readonly':[('coupon_flag', '=', True)]}" class="oe_inline"/>
<button name="apply_coupon_code" type="object"
string="Apply Coupon Code" attrs="{'invisible': [('coupon_flag', '!=', False)]}" class="oe_edit_only oe_link"/>
<button name="apply_coupon_code" type="object" context="{'remove': True}"
string="Remove Coupon Code" attrs="{'invisible': [('coupon_flag', '=', False)]}" class="oe_edit_only oe_link"/>
</div>
<div>
<field name="cart_discount" invisible="1"/>
</div>
</xpath>
<xpath expr="//notebook/page/field/tree/field[@name='tax_id']" position="replace">
<field name="tax_id" widget="many2many_tags" options="{'no_create': True}" domain="[('type_tax_use','=','sale'),('company_id','=',parent.company_id)]"
attrs="{'readonly': [('qty_invoiced', '&gt;', 0)]}" context="{'tax': True}"/>
</xpath>
<xpath expr="//notebook/page/field/tree/field[@name='discount']" position="replace">
<field name="discount" groups="sale.group_discount_per_so_line" context="{'discount': True}"/>
</xpath>
<xpath expr="//notebook/page/field/tree/field[@name='price_unit']" position="replace">
<field name="price_unit" attrs="{'readonly': [('qty_invoiced', '&gt;', 0)]}" context="{'price_unit': True}"/>
</xpath>
<xpath expr="//notebook/page/field/tree/field[@name='discount']" position="after">
<field name="check_coupon" invisible="1"/>
</xpath>
<xpath expr="//notebook/page/field/form/group/group/field[@name='price_unit']" position="replace">
<field name="price_unit" context="{'price_unit': True}"/>
</xpath>
<xpath expr="//notebook/page/field/form/group/group/div[@name='discount']" position="replace">
<div name="discount" groups="sale.group_discount_per_so_line">
<field name="discount" class="oe_inline" context="{'discount': True}"/> %%
</div>
</xpath>
<xpath expr="//notebook/page/field/form/group/group/field[@name='tax_id']" position="replace">
<field name="tax_id" widget="many2many_tags" options="{'no_create': True}" domain="[('type_tax_use','=','sale'),('company_id','=',parent.company_id)]"
attrs="{'readonly': [('qty_invoiced', '&gt;', 0)]}" context="{'tax': True}"/>
</xpath>
</field>
</record>
</flectra>