[ADD] Sale Advance Pricelist module
4
addons/sale_advance_pricelist/__init__.py
Normal file
@ -0,0 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Part of flectra. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from . import models
|
42
addons/sale_advance_pricelist/__manifest__.py
Normal 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
|
||||
}
|
33
addons/sale_advance_pricelist/data/pricelist_view.xml
Normal 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>
|
63
addons/sale_advance_pricelist/demo/cart_rule_view_data.xml
Normal 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>
|
87
addons/sale_advance_pricelist/demo/coupon_code_demo.xml
Normal 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>
|
125
addons/sale_advance_pricelist/demo/price_rule_demo.xml
Normal 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>
|
22
addons/sale_advance_pricelist/demo/res_partner_demo.xml
Normal 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>
|
312
addons/sale_advance_pricelist/demo/sale_order_demo.xml
Normal 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>
|
607
addons/sale_advance_pricelist/i18n/sale_advance_pricelist.pot
Normal 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"
|
||||
|
6
addons/sale_advance_pricelist/models/__init__.py
Normal 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
|
444
addons/sale_advance_pricelist/models/price_rules.py
Normal 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
|
192
addons/sale_advance_pricelist/models/pricelist.py
Normal 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
|
610
addons/sale_advance_pricelist/models/sale.py
Normal 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()
|
@ -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
|
|
After Width: | Height: | Size: 59 KiB |
After Width: | Height: | Size: 937 KiB |
After Width: | Height: | Size: 1.9 MiB |
BIN
addons/sale_advance_pricelist/static/description/icon.png
Normal file
After Width: | Height: | Size: 5.4 KiB |
237
addons/sale_advance_pricelist/static/description/index.html
Normal 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>
|
After Width: | Height: | Size: 36 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 83 KiB |
After Width: | Height: | Size: 2.4 MiB |
After Width: | Height: | Size: 63 KiB |
BIN
addons/sale_advance_pricelist/static/description/sale_order.png
Normal file
After Width: | Height: | Size: 44 KiB |
After Width: | Height: | Size: 47 KiB |
@ -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);
|
||||
|
||||
});
|
@ -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>
|
7
addons/sale_advance_pricelist/tests/__init__.py
Normal 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
|
@ -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()
|
104
addons/sale_advance_pricelist/tests/test_01_first_match.py
Normal 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!')
|
136
addons/sale_advance_pricelist/tests/test_02_coupon_code.py
Normal 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!')
|
32
addons/sale_advance_pricelist/tests/test_03_all_match.py
Normal 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!')
|
199
addons/sale_advance_pricelist/tests/test_04_mix_all.py
Normal 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)
|
204
addons/sale_advance_pricelist/views/price_rule_view.xml
Normal 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', '<', 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>
|
45
addons/sale_advance_pricelist/views/pricelist_view.xml
Normal 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>
|
8
addons/sale_advance_pricelist/views/sale_pricelist.xml
Normal 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>
|
53
addons/sale_advance_pricelist/views/sale_views.xml
Normal 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', '>', 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', '>', 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', '>', 0)]}" context="{'tax': True}"/>
|
||||
</xpath>
|
||||
</field>
|
||||
</record>
|
||||
</flectra>
|