@ -0,0 +1,24 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# Copyright (C) 2017-TODAY Cybrosys Technologies(<http://www.cybrosys.com>). |
|||
# Author: Linto C T(<http://www.cybrosys.com>) |
|||
# you can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. |
|||
# |
|||
# It is forbidden to publish, distribute, sublicense, or sell copies |
|||
# of the Software or modified copies of the Software. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# GENERAL PUBLIC LICENSE (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
|
|||
import models |
@ -0,0 +1,44 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# Copyright (C) 2017-TODAY Cybrosys Technologies(<http://www.cybrosys.com>). |
|||
# Author: Linto C T(<http://www.cybrosys.com>) |
|||
# you can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. |
|||
# |
|||
# It is forbidden to publish, distribute, sublicense, or sell copies |
|||
# of the Software or modified copies of the Software. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# GENERAL PUBLIC LICENSE (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
{ |
|||
'name': 'Price Lists in Point of Sale', |
|||
'version': '10.0.1.0', |
|||
'category': 'Point of Sale', |
|||
'summary': """Set Price Lists for Customers. Products/POS Categories Can be Added to Price Lists""", |
|||
'author': 'Cybrosys Techno Solutions', |
|||
'website': "http://www.cybrosys.com", |
|||
'company': 'Cybrosys Techno Solutions', |
|||
'depends': ['point_of_sale'], |
|||
'data': [ |
|||
'views/pricelist.xml', |
|||
'views/pricelist_menu.xml', |
|||
'views/pos_template.xml', |
|||
'security/ir.model.access.csv', |
|||
], |
|||
'qweb': [ |
|||
'static/src/xml/*.xml'], |
|||
'images': ['static/description/banner.jpg'], |
|||
'license': 'AGPL-3', |
|||
'installable': True, |
|||
'auto_install': False, |
|||
} |
@ -0,0 +1,23 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# Copyright (C) 2017-TODAY Cybrosys Technologies(<http://www.cybrosys.com>). |
|||
# Author: Linto C T(<http://www.cybrosys.com>) |
|||
# you can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. |
|||
# |
|||
# It is forbidden to publish, distribute, sublicense, or sell copies |
|||
# of the Software or modified copies of the Software. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# GENERAL PUBLIC LICENSE (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
import pos_pricelist |
@ -0,0 +1,65 @@ |
|||
# -*- coding: utf-8 -*- |
|||
############################################################################## |
|||
# |
|||
# Cybrosys Technologies Pvt. Ltd. |
|||
# Copyright (C) 2017-TODAY Cybrosys Technologies(<http://www.cybrosys.com>). |
|||
# Author: Linto C T(<http://www.cybrosys.com>) |
|||
# you can modify it under the terms of the GNU LESSER |
|||
# GENERAL PUBLIC LICENSE (LGPL v3), Version 3. |
|||
# |
|||
# It is forbidden to publish, distribute, sublicense, or sell copies |
|||
# of the Software or modified copies of the Software. |
|||
# |
|||
# This program is distributed in the hope that it will be useful, |
|||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
# GNU LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details. |
|||
# |
|||
# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE |
|||
# GENERAL PUBLIC LICENSE (LGPL v3) along with this program. |
|||
# If not, see <http://www.gnu.org/licenses/>. |
|||
# |
|||
############################################################################## |
|||
|
|||
from odoo import models, fields |
|||
|
|||
|
|||
class PosPriceList(models.Model): |
|||
_name = 'pos.pricelist' |
|||
|
|||
def _get_default_currency_id(self): |
|||
return self.env.user.company_id.currency_id.id |
|||
|
|||
name = fields.Char(string="Name", required=True) |
|||
item_ids = fields.One2many('pos.pricelist.items', 'pos_pricelist_id', string="Pricelist Items") |
|||
currency_id = fields.Many2one('res.currency', 'Currency', default=_get_default_currency_id, required=True) |
|||
company_id = fields.Many2one('res.company', 'Company') |
|||
|
|||
|
|||
class PosPricelistItems(models.Model): |
|||
_name = 'pos.pricelist.items' |
|||
|
|||
name = fields.Char(string="Name", required=True) |
|||
pos_pricelist_id = fields.Many2one('pos.pricelist', string="Pricelist") |
|||
applied_on = fields.Selection([('global', "Global"), ('product_category', 'Product Category'), |
|||
('product', 'Product')], string="Applied On", default='global', required=True) |
|||
min_quantity = fields.Integer(string="Minimum Quantity") |
|||
date_start = fields.Date(string="Date Start") |
|||
date_end = fields.Date(string="Date End") |
|||
compute_price = fields.Selection([('fixed', 'Fixed'), ('percentage', 'Percentage')], |
|||
string="Compute Price", default='fixed') |
|||
fixed_price = fields.Float(string="Fixed Price") |
|||
percent_price = fields.Float(string="Percentage") |
|||
|
|||
categ_id = fields.Many2one('pos.category', string="POS Product Category") |
|||
product_tmpl_id = fields.Many2one('product.template', string="Product") |
|||
|
|||
company_id = fields.Many2one('res.company', 'Company', readonly=True, related='pos_pricelist_id.company_id', store=True) |
|||
currency_id = fields.Many2one('res.currency', 'Currency', |
|||
readonly=True, related='pos_pricelist_id.currency_id', store=True) |
|||
|
|||
|
|||
class PriceListPartner(models.Model): |
|||
_inherit = 'res.partner' |
|||
|
|||
pos_pricelist_id = fields.Many2one('pos.pricelist', string="POS Pricelist") |
|
After Width: | Height: | Size: 116 KiB |
After Width: | Height: | Size: 118 KiB |
After Width: | Height: | Size: 50 KiB |
After Width: | Height: | Size: 30 KiB |
After Width: | Height: | Size: 36 KiB |
@ -0,0 +1,131 @@ |
|||
<section class="oe_container"> |
|||
<div class="oe_row oe_spaced"> |
|||
<h2 class="oe_slogan">Pricelist in Point of Sale</h2> |
|||
<h3 class="oe_slogan">..Manage Your Pricing Based on Pricelists in Point of Sale..</h3> |
|||
<h4 class="oe_slogan" style="font-size: 23px;">Author : Cybrosys Techno Solutions , www.cybrosys.com</h4> |
|||
</div> |
|||
<div class="oe_row oe_spaced" style="padding-left:65px;"> |
|||
<h4>Features:</h4> |
|||
<div> |
|||
<span style="color:green;"> ☑ </span> Create price lists for products.<br/> |
|||
<span style="color:green;"> ☑ </span> Create price lists for point of sale category.<br/> |
|||
<span style="color:green;"> ☑ </span> Create global price lists.<br/> |
|||
<span style="color:green;"> ☑ </span> Apply price lists for customers.<br/> |
|||
<span style="color:green;"> ☑ </span> Independent from Sale Price List.<br/> |
|||
</div> |
|||
</div> |
|||
</section> |
|||
|
|||
<section class="oe_container oe_dark"> |
|||
<div class="oe_row oe_spaced"> |
|||
<div class="oe_picture"> |
|||
<h3 class="oe_slogan">Overview</h3> |
|||
<p class="oe_mt32"> |
|||
This module adds a feature to odoo's point of sale. With this module, we will be able to create, |
|||
configure and apply pricelists in point of sale. |
|||
</p> |
|||
</div> |
|||
</div> |
|||
</section> |
|||
|
|||
<section class="oe_container"> |
|||
<div class="oe_row oe_spaced"> |
|||
<h3 class="oe_slogan">Menu</h3> |
|||
<div style="text-align: center"> |
|||
<p> |
|||
<h4>Point of Sale -> Configuration -> Pricelists</h4> |
|||
<p> |
|||
</div> |
|||
<div> |
|||
<div class="oe_demo oe_picture oe_screenshot"> |
|||
<img style="border:10px solid white;height: 400px;" src="pricelist.png"> |
|||
</div> |
|||
<p>After installing this module, a new menu will be created under |
|||
point of sale configuration. This menu will open the form for creating the pricelists. |
|||
We can add pricelist items by clicking on the 'Add an item' button, which wil open a new form.</p> |
|||
</div> |
|||
<br> |
|||
<div class="" style="text-align: center"> |
|||
<div class="oe_demo oe_picture oe_screenshot"> |
|||
<img style="border:10px solid white;height: 400px;" src="global_item.png"> |
|||
</div> |
|||
<p> This is the form for creating pricelist items. We can create rules for product, point of sale category |
|||
and global rules.</p> |
|||
</div> |
|||
</div> |
|||
</section> |
|||
|
|||
<section class="oe_container oe_dark"> |
|||
<div class="oe_row oe_spaced"> |
|||
<h3 class="oe_slogan">Pricelist Selection</h3> |
|||
<div class="" style="text-align: center"> |
|||
<div class="oe_demo oe_picture oe_screenshot"> |
|||
<img style="border:10px solid white;height: 400px;" src="pricelist-selection-partner.png"> |
|||
</div> |
|||
<span>☛ Pricelist selection in customer form.</span> |
|||
</div> |
|||
<br> |
|||
<div class="" style="text-align: center"> |
|||
<div class="" style="text-align: center"> |
|||
<p> |
|||
After creating the pricelist, we can assign that pricelist to a customer from the customer |
|||
form. A new field is added for selecting the point of sale price list under the point of sale section. |
|||
<p> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</section> |
|||
|
|||
<section class="oe_container"> |
|||
<div class="oe_row oe_spaced"> |
|||
<h3 class="oe_slogan">Apply Pricelist</h3> |
|||
<div> |
|||
<div class="oe_demo oe_picture oe_screenshot"> |
|||
<img style="border:10px solid white;height: 400px;" src="customer_selected.png"> |
|||
</div> |
|||
<p> The pricelist will be automatically selected |
|||
after selecting the customer, if there is any pricelist set for this customer. |
|||
If there is no pricelist is there for the customer we selected, then there is an option |
|||
for us to manually select the pricelist. |
|||
</p> |
|||
</div> |
|||
</div> |
|||
</section> |
|||
|
|||
<section class="oe_container oe_dark"> |
|||
<div class="oe_row oe_spaced"> |
|||
<div style="text-align: center;"> |
|||
<a href="https://www.cybrosys.com/blog/odoo-pos-price-list"> |
|||
<h1 style="color:lightseagreen;font-family: initial;"><i> |
|||
Click here for more detailed description. |
|||
</i></h1> |
|||
</a> |
|||
</div> |
|||
</div> |
|||
</section> |
|||
|
|||
<section class="oe_container"> |
|||
<h2 class="oe_slogan" style="margin-top:20px;" >Need Any Help?</h2> |
|||
<div class="oe_slogan" style="margin-top:10px !important;"> |
|||
<div> |
|||
<a class="btn btn-primary btn-lg mt8" |
|||
style="color: #FFFFFF !important;border-radius: 0;" href="https://www.cybrosys.com"><i |
|||
class="fa fa-envelope"></i> Email </a> <a |
|||
class="btn btn-primary btn-lg mt8" style="color: #FFFFFF !important;border-radius: 0;" |
|||
href="https://www.cybrosys.com/contact/"><i |
|||
class="fa fa-phone"></i> Contact Us </a> <a |
|||
class="btn btn-primary btn-lg mt8" style="color: #FFFFFF !important;border-radius: 0;" |
|||
href="https://www.cybrosys.com/odoo-customization-and-installation/"><i |
|||
class="fa fa-check-square"></i> Request Customization </a> |
|||
</div> |
|||
<br> |
|||
<img src="cybro_logo.png" style="width: 190px; margin-bottom: 20px;" class="center-block"> |
|||
<div> |
|||
<a href="https://twitter.com/cybrosys" target="_blank"><i class="fa fa-2x fa-twitter" style="color:white;background: #00a0d1;width:35px;"></i></a></td> |
|||
<a href="https://www.linkedin.com/company/cybrosys-technologies-pvt-ltd" target="_blank"><i class="fa fa-2x fa-linkedin" style="color:white;background: #31a3d6;width:35px;padding-left: 3px;"></i></a></td> |
|||
<a href="https://www.facebook.com/cybrosystechnologies" target="_blank"><i class="fa fa-2x fa-facebook" style="color:white;background: #3b5998;width:35px;padding-left: 8px;"></i></a></td> |
|||
<a href="https://plus.google.com/106641282743045431892/about" target="_blank"><i class="fa fa-2x fa-google-plus" style="color:white;background: #c53c2c;width:35px;padding-left: 3px;"></i></a></td> |
|||
<a href="https://in.pinterest.com/cybrosys" target="_blank"><i class="fa fa-2x fa-pinterest" style="color:white;background: #ac0f18;width:35px;padding-left: 3px;"></i></a></td> |
|||
</div> |
|||
</div> |
|||
</section> |
After Width: | Height: | Size: 29 KiB |
After Width: | Height: | Size: 54 KiB |
@ -0,0 +1,14 @@ |
|||
.pos .order-pricelist{ |
|||
color: black; |
|||
margin-top: 2%; |
|||
width: 200px; |
|||
} |
|||
.pos .order-pricelist-label{ |
|||
color: #e9f6e4; |
|||
box-sizing: border-box; |
|||
-moz-box-sizing: border-box; |
|||
height: 85px !important; |
|||
font-size: initial; |
|||
vertical-align: middle; |
|||
text-align: center; |
|||
} |
@ -0,0 +1,277 @@ |
|||
odoo.define("pos_pricing.pricelist", function (require) { |
|||
"use strict"; |
|||
var core = require('web.core'); |
|||
var pos_model = require('point_of_sale.models'); |
|||
var pos_chrome = require('point_of_sale.chrome') |
|||
var models = pos_model.PosModel.prototype.models; |
|||
var PosModelSuper = pos_model.PosModel; |
|||
var OrderSuper = pos_model.Order; |
|||
var OrderlineSuper = pos_model.Orderline; |
|||
// get pos_pricelist_id of each customer
|
|||
for(var i=0; i<models.length; i++){ |
|||
var model=models[i]; |
|||
if(model.model === 'res.partner'){ |
|||
model.fields.push('pos_pricelist_id'); |
|||
} |
|||
} |
|||
// getting pricelists and pricelist items
|
|||
models.push( |
|||
{ |
|||
model: 'pos.pricelist', |
|||
fields: ['id', 'name'], |
|||
loaded: function (self, pricelists) { |
|||
for (var i in pricelists){ |
|||
self.pricelists.push(pricelists[i]); |
|||
} |
|||
}, |
|||
},{ |
|||
model: 'pos.pricelist.items', |
|||
fields: ['id', 'fixed_price', 'date_end', 'applied_on', 'min_quantity', |
|||
'percent_price', 'date_start', 'product_tmpl_id', 'pos_pricelist_id', 'compute_price', 'categ_id'], |
|||
loaded: function (self, pricelist_items) { |
|||
self.pricelist_items = pricelist_items; |
|||
}, |
|||
}, |
|||
{ |
|||
model: 'product.template', |
|||
fields: ['id', 'categ_id'], |
|||
loaded: function (self, category) { |
|||
self.category = category; |
|||
}, |
|||
} |
|||
); |
|||
// this function is used to get the id of selected pricelist using the name of pricelist
|
|||
function get_pricelist_id(pricelists, name){ |
|||
for(var i in pricelists){ |
|||
if(pricelists[i].name == name){ |
|||
return pricelists[i].id; |
|||
} |
|||
} |
|||
return false; |
|||
} |
|||
// PosModel is extended to store category, pricelists and pricelist items on startup
|
|||
pos_model.PosModel = pos_model.PosModel.extend({ |
|||
initialize: function(session, attributes) { |
|||
PosModelSuper.prototype.initialize.call(this, session, attributes) |
|||
this.pricelist_items = ['']; |
|||
this.pricelists = []; |
|||
this.category = []; |
|||
}, |
|||
}); |
|||
|
|||
pos_model.Order = pos_model.Order.extend({ |
|||
// case : selecting product after selecting client ----------------------------------
|
|||
// here we will get the pricelist selected, if there are any and apply the pricelist after validation
|
|||
add_product: function (product, options) { |
|||
var self = this; |
|||
var pricelist_id = get_pricelist_id(self.pos.pricelists, $("#pos_pricelist").val()); |
|||
OrderSuper.prototype.add_product.call(this, product, options); |
|||
if (!pricelist_id){ |
|||
if (this.pos.get_client()){ |
|||
self.apply_pricelist(this.pos.get_client(), pricelist_id); |
|||
} |
|||
} |
|||
}, |
|||
// this function returns the new price after checking the computation method of the pricelist item
|
|||
set_price: function (line, item) { |
|||
var new_price = 0; |
|||
switch (item.compute_price){ |
|||
case 'fixed': new_price = item.fixed_price; break; |
|||
case 'percentage': new_price = line.product.price -(line.product.price * item.percent_price / 100); break; |
|||
} |
|||
return new_price; |
|||
}, |
|||
/*this function is used to check the given id is present in the array or not, |
|||
since the 'in' operator was not working properly*/ |
|||
find_pricelist_item: function (id, item_ids) { |
|||
for (var j in item_ids){ |
|||
if(item_ids[j] == id){ |
|||
return true; |
|||
break; |
|||
} |
|||
} |
|||
return false; |
|||
}, |
|||
|
|||
// apply pricelist for this client----------------------------
|
|||
apply_pricelist: function(client, pricelist_id){ |
|||
var self = this; |
|||
// list of all pricelist items available
|
|||
var pricelist_items = self.pos.pricelist_items; |
|||
var items = []; |
|||
// getting this client's pricelist items from the complete list ---------------------------
|
|||
for (var i in pricelist_items){ |
|||
if(pricelist_items[i].pos_pricelist_id[0] == pricelist_id){ |
|||
items.push(pricelist_items[i]); |
|||
} |
|||
} |
|||
// checking the start date and end date of these items and selecting only the valid items
|
|||
pricelist_items = []; |
|||
var today = moment().format('YYYY-MM-DD'); |
|||
for (var i in items){ |
|||
if(((items[i].date_start == false) || (items[i].date_start <= today)) |
|||
&& ((items[i].date_end == false) || (items[i].date_end >= today))) |
|||
{ |
|||
pricelist_items.push(items[i]); |
|||
} |
|||
} |
|||
// grouping the pricelist items based on applicability
|
|||
// we are listing those products and categories which has a pricelist item for them
|
|||
// for making the checkings easier
|
|||
var global_items = []; |
|||
var category_items = []; |
|||
var category_ids = []; |
|||
var product_items = []; |
|||
var product_ids = []; |
|||
for(var i in pricelist_items){ |
|||
switch(pricelist_items[i].applied_on){ |
|||
case 'global': global_items.push(pricelist_items[i]); break; |
|||
case 'product_category': category_items.push(pricelist_items[i]); |
|||
category_ids.push(pricelist_items[i].categ_id[0]) ; break; |
|||
case 'product': product_items.push(pricelist_items[i]); |
|||
product_ids.push(pricelist_items[i].product_tmpl_id[0]) ;break; |
|||
} |
|||
} |
|||
|
|||
// getting current order ====================================================
|
|||
var order = self.pos.get_order(); |
|||
var lines = order ? order.get_orderlines() : null; |
|||
|
|||
//looping through each line
|
|||
for (var l in lines){ |
|||
// checking if this product has a valid pricelist rule set or not
|
|||
var product_item = self.find_pricelist_item(lines[l].product.product_tmpl_id, product_ids); |
|||
// checking if this product's category has a valid pricelist rule set or not
|
|||
var categ_item = self.find_pricelist_item(lines[l].product.pos_categ_id[0], category_ids); |
|||
var temp = -1; |
|||
var new_price = lines[l].product.price; |
|||
// checking if the product has any pricelist item set
|
|||
if(product_item){ |
|||
for(var j in product_items){ |
|||
if(product_items[j].product_tmpl_id[0] == lines[l].product.product_tmpl_id){ |
|||
if(lines[l].quantity >= product_items[j].min_quantity){ |
|||
if(temp < 0){ |
|||
temp = lines[l].quantity - product_items[j].min_quantity; |
|||
new_price = self.set_price(lines[l], product_items[j]); |
|||
} |
|||
else if(temp > (lines[l].quantity - product_items[j].min_quantity) && |
|||
(lines[l].quantity - product_items[j].min_quantity) >= 0){ |
|||
temp = lines[l].quantity - product_items[j].min_quantity; |
|||
new_price = self.set_price(lines[l], product_items[j]); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
lines[l].set_unit_price(new_price); |
|||
} |
|||
else if(categ_item){ |
|||
for(var j in category_items){ |
|||
if(category_items[j].categ_id[0] == lines[l].product.pos_categ_id[0]){ |
|||
if(lines[l].quantity >= category_items[j].min_quantity) |
|||
{ |
|||
if(temp < 0){ |
|||
temp = lines[l].quantity - category_items[j].min_quantity; |
|||
new_price = self.set_price(lines[l], category_items[j]); |
|||
} |
|||
else if(temp > (lines[l].quantity - category_items[j].min_quantity) && |
|||
(lines[l].quantity - category_items[j].min_quantity) >= 0){ |
|||
temp = lines[l].quantity - category_items[j].min_quantity; |
|||
new_price = self.set_price(lines[l], category_items[j]); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
lines[l].set_unit_price(new_price); |
|||
} |
|||
// if there are no rules set for product or category, we will check global pricelists
|
|||
else if(global_items.length > 0){ |
|||
for(var j in global_items){ |
|||
if(lines[l].quantity >= global_items[j].min_quantity) |
|||
{ |
|||
if(temp < 0){ |
|||
temp = lines[l].quantity - global_items[j].min_quantity; |
|||
new_price = self.set_price(lines[l], global_items[j]); |
|||
} |
|||
else if(temp > (lines[l].quantity - global_items[j].min_quantity) && |
|||
(lines[l].quantity - global_items[j].min_quantity) >= 0){ |
|||
temp = lines[l].quantity - global_items[j].min_quantity; |
|||
new_price = self.set_price(lines[l], global_items[j]); |
|||
} |
|||
} |
|||
} |
|||
lines[l].set_unit_price(new_price); |
|||
} |
|||
// else we set the original price
|
|||
else{ |
|||
lines[l].set_unit_price(lines[l].product.price); |
|||
} |
|||
} |
|||
}, |
|||
// this function will first set a customer for this order and then, it will apply the pricelist of this customer to
|
|||
// this order if there are any
|
|||
set_client: function(client){ |
|||
var self = this; |
|||
var current_pricelist = document.getElementById('pos_pricelist'); |
|||
if(client){ |
|||
if (current_pricelist != null){ |
|||
current_pricelist.value = client.pos_pricelist_id[1]; |
|||
} |
|||
var order = self.pos.get_order(); |
|||
if (order) { |
|||
if (order.orderlines.length) { |
|||
self.apply_pricelist(client, client.pos_pricelist_id[0]); |
|||
} |
|||
} |
|||
} |
|||
else if(current_pricelist){ |
|||
current_pricelist.value = ''; |
|||
} |
|||
OrderSuper.prototype.set_client.call(this, client); |
|||
}, |
|||
}); |
|||
|
|||
pos_model.Orderline = pos_model.Orderline.extend({ |
|||
set_quantity: function(quantity){ |
|||
OrderlineSuper.prototype.set_quantity.call(this, quantity); |
|||
var pricelist_id = get_pricelist_id(this.pos.pricelists, $("#pos_pricelist").val()); |
|||
if (this.order.get_client() && pricelist_id) { |
|||
this.order.apply_pricelist(this.order.get_client(), pricelist_id); |
|||
} |
|||
}, |
|||
|
|||
}); |
|||
|
|||
pos_chrome.OrderSelectorWidget.include({ |
|||
renderElement: function(){ |
|||
var pos_pricelist = $("#pos_pricelist"); |
|||
this.pos_pricelist = false; |
|||
if (pos_pricelist != null){ |
|||
this.pos_pricelist = pos_pricelist.val(); |
|||
} |
|||
var self = this; |
|||
this._super(); |
|||
this.$("#pos_pricelist").change(function () { |
|||
self.pos.pos_pricelist = false; |
|||
var order = self.pos.get_order(); |
|||
var client = order.get_client(); |
|||
var pricelist_id = get_pricelist_id(self.pos.pricelists, $("#pos_pricelist").val()); |
|||
if (client && pricelist_id){ |
|||
order.apply_pricelist(client, pricelist_id); |
|||
} |
|||
else if (!client){ |
|||
$("#pos_pricelist").val('') |
|||
alert("Unable to set pricelist. Please check customer...!!") |
|||
} |
|||
}); |
|||
this.$('.order-button.select-order').click(function(event){ |
|||
self.order_click_handler(event,$(this)); |
|||
}); |
|||
this.$('.neworder-button').click(function(event){ |
|||
self.neworder_click_handler(event,$(this)); |
|||
}); |
|||
this.$('.deleteorder-button').click(function(event){ |
|||
self.deleteorder_click_handler(event,$(this)); |
|||
}); |
|||
}, |
|||
}); |
|||
}); |
@ -0,0 +1,67 @@ |
|||
<?xml version="1.0" encoding="UTF-8"?> |
|||
<templates id="point_of_sale.template" xml:space="preserve"> |
|||
<t t-name="ClientLine"> |
|||
<tr class='client-line' t-att-data-id='partner.id'> |
|||
<td><t t-esc='partner.name' /></td> |
|||
<td><t t-esc='partner.address' /></td> |
|||
<td><t t-esc='partner.phone or partner.mobile or ""' /></td> |
|||
<td><t t-esc='partner.pos_pricelist_id[1] or ""' /></td> |
|||
</tr> |
|||
</t> |
|||
|
|||
<t t-extend="ClientDetails"> |
|||
<t t-jquery='.client-details-right' t-operation='append'> |
|||
<div class='client-detail'> |
|||
<span class='label'>Pricelist</span> |
|||
<t t-if='partner.pos_pricelist_id'> |
|||
<span class='detail client-id'><t t-esc='partner.pos_pricelist_id[1]'/></span> |
|||
</t> |
|||
<t t-if='!partner.barcode'> |
|||
<span class='detail client-id empty'>N/A</span> |
|||
</t> |
|||
</div> |
|||
</t> |
|||
</t> |
|||
<t t-extend="ClientListScreenWidget"> |
|||
<t t-jquery='.client-list' t-operation='replace'> |
|||
<table class='client-list'> |
|||
<thead> |
|||
<tr> |
|||
<th>Name</th> |
|||
<th>Address</th> |
|||
<th>Phone</th> |
|||
<th>POS Pricelist</th> |
|||
</tr> |
|||
</thead> |
|||
<tbody class='client-list-contents'> |
|||
</tbody> |
|||
</table> |
|||
</t> |
|||
</t> |
|||
|
|||
<t t-extend="OrderSelectorWidget"> |
|||
<t t-jquery="div.order-selector" t-operation="append"> |
|||
<div> |
|||
<span class="order-pricelist-label"> |
|||
<b> Pricelist: </b> |
|||
</span> |
|||
<select id ="pos_pricelist" class="order-pricelist" > |
|||
<t t-if="widget.pos_pricelist"> |
|||
<option> |
|||
<t t-esc='widget.pos_pricelist'/> |
|||
</option> |
|||
</t> |
|||
<option></option> |
|||
<t t-foreach="widget.pos.pricelists || []" t-as="item"> |
|||
<t t-if="widget.pos_pricelist != item.name"> |
|||
<option> |
|||
<t t-esc='item.name'/> |
|||
</option> |
|||
</t> |
|||
</t> |
|||
</select> |
|||
</div> |
|||
</t> |
|||
</t> |
|||
|
|||
</templates> |
@ -0,0 +1,11 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<odoo> |
|||
<data> |
|||
<template id="assets" inherit_id="point_of_sale.assets"> |
|||
<xpath expr="." position="inside"> |
|||
<script type="text/javascript" src="/pos_pricing/static/src/js/pricelist.js"></script> |
|||
<link rel="stylesheet" href="/pos_pricing/static/src/css/pos.css" id="pos-stylesheet"/> |
|||
</xpath> |
|||
</template> |
|||
</data> |
|||
</odoo> |
@ -0,0 +1,16 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<openerp> |
|||
<data> |
|||
<!--showing pricelist in partner form--> |
|||
<record id="pos_pricelist_customer_form" model="ir.ui.view"> |
|||
<field name="name">pos.pricelist.customer</field> |
|||
<field name="model">res.partner</field> |
|||
<field name="inherit_id" ref="point_of_sale.view_partner_property_form" /> |
|||
<field name="arch" type="xml"> |
|||
<xpath expr="//group[@name='point_of_sale']" position="inside"> |
|||
<field name="pos_pricelist_id" /> |
|||
</xpath> |
|||
</field> |
|||
</record> |
|||
</data> |
|||
</openerp> |
@ -0,0 +1,125 @@ |
|||
<?xml version="1.0" encoding="UTF-8" ?> |
|||
<odoo> |
|||
<data> |
|||
<!--pricelist item view--> |
|||
<record id="pos_pricelist_item_tree_view" model="ir.ui.view"> |
|||
<field name="name">pos.pricelist.item.tree</field> |
|||
<field name="model">pos.pricelist.items</field> |
|||
<field name="arch" type="xml"> |
|||
<tree string="Pricelist Items"> |
|||
<field colspan="4" name="name"/> |
|||
<field name="product_tmpl_id"/> |
|||
<field name="categ_id"/> |
|||
<field name="min_quantity"/> |
|||
<field name="date_start"/> |
|||
<field name="date_end"/> |
|||
</tree> |
|||
</field> |
|||
</record> |
|||
|
|||
<record id="pos_pricelist_item_form_view" model="ir.ui.view"> |
|||
<field name="name">pos.pricelist.item.form</field> |
|||
<field name="model">pos.pricelist.items</field> |
|||
<field name="arch" type="xml"> |
|||
<form string="Pricelist Items"> |
|||
<h1><field name="name"/></h1> |
|||
<group> |
|||
<group> |
|||
<field name="applied_on" widget="radio"/> |
|||
<field name="categ_id" attrs="{'invisible':[('applied_on', '!=', 'product_category')], 'required':[('applied_on', '=', 'product_category')]}"/> |
|||
<field name="product_tmpl_id" domain="[('available_in_pos', '=', True)]" |
|||
attrs="{'invisible':[('applied_on', '!=', 'product')],'required':[('applied_on', '=', 'product')]}" string="Product"/> |
|||
</group> |
|||
<group> |
|||
<field name="min_quantity"/> |
|||
<field name="date_start"/> |
|||
<field name="date_end"/> |
|||
</group> |
|||
</group> |
|||
<separator string="Price Computation"/> |
|||
<group> |
|||
<group> |
|||
<label for="compute_price" string="Compute Price"/> |
|||
<div> |
|||
<field name="compute_price" widget="radio"/> |
|||
<field name="currency_id" invisible="1"/> |
|||
<div attrs="{'invisible':[('compute_price', '!=', 'fixed')]}"> |
|||
<field name="fixed_price" nolabel= "1" widget='monetary' options="{'currency_field': 'currency_id'}"/></div> |
|||
<div attrs="{'invisible':[('compute_price', '!=', 'percentage')]}"> |
|||
<field name="percent_price" nolabel="1" class="oe_inline"/>%% |
|||
</div> |
|||
</div> |
|||
</group> |
|||
</group> |
|||
<div class="oe_grey" groups="product.group_uom"> |
|||
<p>The computed price is expressed in the default Unit of Measure of the product.</p> |
|||
</div> |
|||
</form> |
|||
</field> |
|||
</record> |
|||
|
|||
<record model="ir.ui.view" id="pos_pricelist_view_search"> |
|||
<field name="name">pos.pricelist.search</field> |
|||
<field name="model">pos.pricelist</field> |
|||
<field name="arch" type="xml"> |
|||
<search string="POS Price Search"> |
|||
<field name="name" string="Products Price"/> |
|||
<field name="currency_id" groups="base.group_multi_currency"/> |
|||
</search> |
|||
</field> |
|||
</record> |
|||
|
|||
|
|||
<record id="pos_pricelist_view_tree" model="ir.ui.view"> |
|||
<field name="name">pos.pricelist.tree</field> |
|||
<field name="model">pos.pricelist</field> |
|||
<field name="arch" type="xml"> |
|||
<tree string="POS Price List"> |
|||
<field name="name"/> |
|||
<field name="currency_id" groups="base.group_multi_currency"/> |
|||
</tree> |
|||
</field> |
|||
</record> |
|||
|
|||
<record id="pos_pricelist_view" model="ir.ui.view"> |
|||
<field name="name">pos.pricelist.form</field> |
|||
<field name="model">pos.pricelist</field> |
|||
<field name="arch" type="xml"> |
|||
<form string="POS Price List"> |
|||
<sheet> |
|||
<div class="oe_title"> |
|||
<h1><field name="name" placeholder="e.g. USD Retailers"/></h1> |
|||
</div> |
|||
<group> |
|||
<field name="currency_id" groups="base.group_multi_currency"/> |
|||
<field name="company_id" groups="base.group_multi_company" options="{'no_create': True}"/> |
|||
</group> |
|||
<div> |
|||
<separator string="Pricelist Items"/> |
|||
<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="applied_on" invisible="1"/> |
|||
<field name="compute_price" invisible="1"/> |
|||
</tree> |
|||
</field> |
|||
</div> |
|||
</sheet> |
|||
</form> |
|||
</field> |
|||
</record> |
|||
|
|||
<record id="action_pos_pricelist_menu" model="ir.actions.act_window"> |
|||
<field name="name">Pricelists</field> |
|||
<field name="res_model">pos.pricelist</field> |
|||
<field name="view_type">form</field> |
|||
<field name="view_mode">tree,form</field> |
|||
</record> |
|||
|
|||
<menuitem name="Pricelists" id="pos_pricelist_menu" action="action_pos_pricelist_menu" |
|||
parent="point_of_sale.menu_point_config_product" sequence="2" /> |
|||
</data> |
|||
</odoo> |