@ -0,0 +1,37 @@ |
|||||
|
POS Return v10 |
||||
|
============== |
||||
|
|
||||
|
Helps You To Manage Product Return From Frontend. |
||||
|
|
||||
|
Depends |
||||
|
======= |
||||
|
[point_of_sale] addon Odoo |
||||
|
|
||||
|
Installation |
||||
|
============ |
||||
|
|
||||
|
- www.odoo.com/documentation/10.0/setup/install.html |
||||
|
- Install our custom addon |
||||
|
|
||||
|
License |
||||
|
======= |
||||
|
GNU LESSER GENERAL PUBLIC LICENSE, Version 3 (LGPLv3) |
||||
|
(http://www.gnu.org/licenses/agpl.html) |
||||
|
|
||||
|
Bug Tracker |
||||
|
=========== |
||||
|
|
||||
|
Contact odoo@cybrosys.com |
||||
|
|
||||
|
Credits |
||||
|
======= |
||||
|
Anusha P P @ cybrosys, anusha@cybrosys.in |
||||
|
Linto CT @ cybrosys, linto@cybrosys.in |
||||
|
|
||||
|
|
||||
|
Maintainer |
||||
|
---------- |
||||
|
|
||||
|
This module is maintained by Cybrosys Technologies. |
||||
|
|
||||
|
For support and more information, please visit https://www.cybrosys.com. |
@ -0,0 +1,3 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
|
||||
|
from . import models |
@ -0,0 +1,43 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
################################################################################### |
||||
|
# |
||||
|
# Cybrosys Technologies Pvt. Ltd. |
||||
|
# Copyright (C) 2017-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). |
||||
|
# Author: Anusha (<https://www.cybrosys.com>) |
||||
|
# |
||||
|
# This program is free software: you can modify |
||||
|
# it under the terms of the GNU Affero General Public License (AGPL) as |
||||
|
# published by the Free Software Foundation, either version 3 of the |
||||
|
# License, or (at your option) any later version. |
||||
|
# |
||||
|
# 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 Affero General Public License for more details. |
||||
|
# |
||||
|
# You should have received a copy of the GNU Affero General Public License |
||||
|
# along with this program. If not, see <https://www.gnu.org/licenses/>. |
||||
|
# |
||||
|
################################################################################### |
||||
|
{ |
||||
|
'name': 'Product Return In POS', |
||||
|
'version': '10.0.1.0.0', |
||||
|
'category': 'Point of Sale', |
||||
|
'summary': 'POS Order Return', |
||||
|
'author': 'Cybrosys Techno Solutions', |
||||
|
'company': 'Cybrosys Techno Solutions', |
||||
|
'maintainer': 'Cybrosys Techno Solutions', |
||||
|
'images': ['static/description/banner.jpg'], |
||||
|
'website': 'https://www.cybrosys.com', |
||||
|
'depends': ['point_of_sale'], |
||||
|
'data': [ |
||||
|
'views/return.xml', |
||||
|
'views/pos_template.xml', |
||||
|
], |
||||
|
'qweb': ['static/src/xml/pos_return.xml'], |
||||
|
'license': 'AGPL-3', |
||||
|
'installable': True, |
||||
|
'auto_install': False, |
||||
|
'application': False, |
||||
|
|
||||
|
} |
@ -0,0 +1,3 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
|
||||
|
from . import pos_return |
@ -0,0 +1,83 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
from odoo import models, api, fields |
||||
|
|
||||
|
|
||||
|
class PosReturn(models.Model): |
||||
|
_inherit = 'pos.order' |
||||
|
|
||||
|
return_ref = fields.Char(string='Return Ref', readonly=True, copy=False) |
||||
|
return_status = fields.Selection([ |
||||
|
('nothing_return', 'Nothing Returned'), |
||||
|
('partialy_return', 'Partialy Returned'), |
||||
|
('fully_return', 'Fully Returned') |
||||
|
], string="Return Status", default='nothing_return', |
||||
|
help="Return status of Order") |
||||
|
|
||||
|
@api.model |
||||
|
def get_lines(self, ref): |
||||
|
result = [] |
||||
|
order_id = self.search([('pos_reference', '=', ref)], limit=1) |
||||
|
if order_id: |
||||
|
lines = self.env['pos.order.line'].search([('order_id', '=', order_id.id)]) |
||||
|
for line in lines: |
||||
|
if line.qty - line.returned_qty > 0: |
||||
|
new_vals = { |
||||
|
'product_id': line.product_id.id, |
||||
|
'product': line.product_id.name, |
||||
|
'qty': line.qty - line.returned_qty, |
||||
|
'price_unit': line.price_unit, |
||||
|
'discount': line.discount, |
||||
|
'line_id': line.id, |
||||
|
} |
||||
|
result.append(new_vals) |
||||
|
|
||||
|
return [result] |
||||
|
|
||||
|
@api.model |
||||
|
def get_client(self, ref): |
||||
|
order_id = self.search([('pos_reference', '=', ref)], limit=1) |
||||
|
client = '' |
||||
|
if order_id: |
||||
|
client = order_id.partner_id.id |
||||
|
return client |
||||
|
|
||||
|
def _order_fields(self, ui_order): |
||||
|
order = super(PosReturn, self)._order_fields(ui_order) |
||||
|
if ui_order['lines']: |
||||
|
for data in ui_order['lines']: |
||||
|
if data[2]['line_id']: |
||||
|
line = self.env['pos.order.line'].search([('id', '=', data[2]['line_id'])]) |
||||
|
if line: |
||||
|
qty = -(data[2]['qty']) |
||||
|
line.returned_qty += qty |
||||
|
if ui_order['return_ref']: |
||||
|
order['return_ref'] = ui_order['return_ref'] |
||||
|
parent_order = self.search([('pos_reference', '=', ui_order['return_ref'])], limit=1) |
||||
|
lines = self.env['pos.order.line'].search([('order_id', '=', parent_order.id)]) |
||||
|
ret = 0 |
||||
|
qty = 0 |
||||
|
for line in lines: |
||||
|
qty += line.qty |
||||
|
if line.returned_qty: |
||||
|
ret += 1 |
||||
|
if qty-ret == 0: |
||||
|
parent_order.return_status = 'fully_return' |
||||
|
elif ret: |
||||
|
if qty > ret: |
||||
|
parent_order.return_status = 'partialy_return' |
||||
|
|
||||
|
return order |
||||
|
|
||||
|
@api.model |
||||
|
def get_status(self, ref): |
||||
|
order_id = self.search([('pos_reference', '=', ref)], limit=1) |
||||
|
if order_id.return_status == 'fully_return': |
||||
|
return False |
||||
|
else: |
||||
|
return True |
||||
|
|
||||
|
|
||||
|
class NewPosLines(models.Model): |
||||
|
_inherit = "pos.order.line" |
||||
|
|
||||
|
returned_qty = fields.Integer(string='Returned', digits=0) |
After Width: | Height: | Size: 95 KiB |
After Width: | Height: | Size: 110 KiB |
After Width: | Height: | Size: 228 KiB |
After Width: | Height: | Size: 8.5 KiB |
After Width: | Height: | Size: 37 KiB |
@ -0,0 +1,139 @@ |
|||||
|
<section class="oe_container"> |
||||
|
<div class="oe_row oe_spaced"> |
||||
|
<h2 class="oe_slogan">Product Return In POS</h2> |
||||
|
<h3 class="oe_slogan">Manages Product Return From POS Frontend</h3> |
||||
|
<h4 class="oe_slogan"><a href="https://www.cybrosys.com">Cybrosys Technologies</a> </h4> |
||||
|
</div> |
||||
|
<div class="oe_row oe_spaced" style="padding-left:65px;"> |
||||
|
<h4>Features:</h4> |
||||
|
<div> |
||||
|
<span style="color:green;"> ☑ </span> Manage Product Return From Frontend.<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 text-justify" style="text-align: center;"> |
||||
|
This app will help you to return the products in pos from the user interface. |
||||
|
</p> |
||||
|
</div> |
||||
|
</div> |
||||
|
</section> |
||||
|
|
||||
|
<section class="oe_container"> |
||||
|
<div class="oe_row oe_spaced"> |
||||
|
<div style="text-align: center"> |
||||
|
<span class="oe_mt32 text-justify" style="text-align: center;">Create a normal order.</span> |
||||
|
<div class="oe_demo oe_picture oe_screenshot"> |
||||
|
<img style="border:10px solid white;" src="order_1.png"> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</section> |
||||
|
|
||||
|
<section class="oe_container oe_dark"> |
||||
|
<div class="oe_row oe_spaced"> |
||||
|
<div class="" style="text-align: center"> |
||||
|
<div class="oe_demo oe_picture oe_screenshot"> |
||||
|
<img style="border:10px solid white;" src="button.png"> |
||||
|
</div> |
||||
|
<span class="oe_mt32 text-justify" style="text-align: center;">Click on Return button In order to return orders</span> |
||||
|
</div> |
||||
|
</div> |
||||
|
</section> |
||||
|
|
||||
|
<section class="oe_container"> |
||||
|
<div class="oe_row oe_spaced"> |
||||
|
<div class="" style="text-align: center"> |
||||
|
<div class="oe_demo oe_picture oe_screenshot"> |
||||
|
<img style="border:10px solid white;" src="ret_order.png"> |
||||
|
</div> |
||||
|
<span class="oe_mt32 text-justify" style="text-align: center;">Select the order and click on Return.</span> |
||||
|
</div> |
||||
|
</div> |
||||
|
</section> |
||||
|
|
||||
|
<section class="oe_container oe_dark"> |
||||
|
<div class="oe_row oe_spaced"> |
||||
|
<div class="" style="text-align: center"> |
||||
|
<div class="oe_demo oe_picture oe_screenshot"> |
||||
|
<img style="border:10px solid white;height: 400px;" src="line.png"> |
||||
|
</div> |
||||
|
<span class="oe_mt32 text-justify" style="text-align: center;">Return some of the products.</span> |
||||
|
</div> |
||||
|
</div> |
||||
|
</section> |
||||
|
|
||||
|
<section class="oe_container"> |
||||
|
<div class="oe_row oe_spaced"> |
||||
|
<div class="" style="text-align: center"> |
||||
|
<div class="oe_demo oe_picture oe_screenshot"> |
||||
|
<img style="border:10px solid white;height: 400px;" src="rest.png"> |
||||
|
</div> |
||||
|
</div> |
||||
|
<span class="oe_mt32 text-justify" style="text-align: center;">When we create the return for the same order we get the rest of the products to return.</span> |
||||
|
</div> |
||||
|
</section> |
||||
|
|
||||
|
<section class="oe_container oe_dark"> |
||||
|
<div class="oe_row oe_spaced"> |
||||
|
<div class="" style="text-align: center"> |
||||
|
<div class="oe_demo oe_picture oe_screenshot"> |
||||
|
<img style="border:10px solid white;" src="fully.png"> |
||||
|
</div> |
||||
|
</div> |
||||
|
<span class="oe_mt32 text-justify" style="text-align: center;">We select a order that fully returned a warning will come.</span> |
||||
|
</div> |
||||
|
</section> |
||||
|
|
||||
|
<section class="oe_container"> |
||||
|
<div class="oe_row oe_spaced"> |
||||
|
<div class="" style="text-align: center"> |
||||
|
<div class="oe_demo oe_picture oe_screenshot"> |
||||
|
<img style="border:10px solid white;" src="ref.png"> |
||||
|
</div> |
||||
|
<span class="oe_mt32 text-justify" style="text-align: center;">We get the return reference very easily.</span> |
||||
|
</div> |
||||
|
</div> |
||||
|
</section> |
||||
|
|
||||
|
<section class="oe_container oe_dark"> |
||||
|
<div class="oe_row oe_spaced"> |
||||
|
<div class="" style="text-align: center"> |
||||
|
<div class="oe_demo oe_picture oe_screenshot"> |
||||
|
<img style="border:10px solid white;height: 400px;" src="backend.png"> |
||||
|
</div> |
||||
|
<span>We get the return reference and status of the return from backend also.</span> |
||||
|
</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: 18 KiB |
After Width: | Height: | Size: 240 KiB |
After Width: | Height: | Size: 40 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 29 KiB |
@ -0,0 +1,549 @@ |
|||||
|
odoo.define('pos_return',function(require){ |
||||
|
"use strict"; |
||||
|
|
||||
|
var gui = require('point_of_sale.gui'); |
||||
|
var chrome = require('point_of_sale.chrome'); |
||||
|
var popups = require('point_of_sale.popups'); |
||||
|
var core = require('web.core'); |
||||
|
var PosBaseWidget = require('point_of_sale.BaseWidget'); |
||||
|
var models = require('point_of_sale.models'); |
||||
|
var PosModelSuper = models.PosModel; |
||||
|
var pos_screens = require('point_of_sale.screens'); |
||||
|
var Model = require('web.DataModel'); |
||||
|
var QWeb = core.qweb; |
||||
|
var _t = core._t; |
||||
|
var exports = {}; |
||||
|
|
||||
|
models.load_models({ |
||||
|
model: 'pos.order', |
||||
|
fields: ['id', 'name', 'session_id', 'pos_reference', 'partner_id', 'amount_total','lines', 'amount_tax','return_ref'], |
||||
|
loaded: function (self, pos_orders) { |
||||
|
var orders = []; |
||||
|
for (var i in pos_orders){ |
||||
|
orders[pos_orders[i].id] = pos_orders[i]; |
||||
|
} |
||||
|
self.pos_orders = orders; |
||||
|
self.order = []; |
||||
|
for (var i in pos_orders){ |
||||
|
self.order[i] = pos_orders[i]; |
||||
|
} |
||||
|
}, |
||||
|
}); |
||||
|
var _super_posmodel = models.PosModel.prototype; |
||||
|
models.PosModel = models.PosModel.extend({ |
||||
|
initialize: function (session, attributes) { |
||||
|
var posorder_model = _.find(this.models, function(model){ |
||||
|
return model.model === 'pos.order'; |
||||
|
}); |
||||
|
posorder_model.fields.push('return_status'); |
||||
|
return _super_posmodel.initialize.call(this, session, attributes); |
||||
|
}, |
||||
|
}); |
||||
|
|
||||
|
models.load_models({ |
||||
|
model: 'pos.order.line', |
||||
|
fields: ['product_id','qty','price_unit','price_subtotal_incl','order_id','discount'], |
||||
|
loaded: function(self,order_lines){ |
||||
|
self.order_line = []; |
||||
|
for (var i = 0; i < order_lines.length; i++) { |
||||
|
self.order_line[i] = order_lines[i]; |
||||
|
} |
||||
|
}, |
||||
|
}); |
||||
|
|
||||
|
var DomCache = core.Class.extend({ |
||||
|
init: function(options){ |
||||
|
options = options || {}; |
||||
|
this.max_size = options.max_size || 2000; |
||||
|
|
||||
|
this.cache = {}; |
||||
|
this.access_time = {}; |
||||
|
this.size = 0; |
||||
|
}, |
||||
|
cache_node: function(key,node){ |
||||
|
var cached = this.cache[key]; |
||||
|
this.cache[key] = node; |
||||
|
this.access_time[key] = new Date().getTime(); |
||||
|
if(!cached){ |
||||
|
this.size++; |
||||
|
while(this.size >= this.max_size){ |
||||
|
var oldest_key = null; |
||||
|
var oldest_time = new Date().getTime(); |
||||
|
for(key in this.cache){ |
||||
|
var time = this.access_time[key]; |
||||
|
if(time <= oldest_time){ |
||||
|
oldest_time = time; |
||||
|
oldest_key = key; |
||||
|
} |
||||
|
} |
||||
|
if(oldest_key){ |
||||
|
delete this.cache[oldest_key]; |
||||
|
delete this.access_time[oldest_key]; |
||||
|
} |
||||
|
this.size--; |
||||
|
} |
||||
|
} |
||||
|
return node; |
||||
|
}, |
||||
|
clear_node: function(key) { |
||||
|
var cached = this.cache[key]; |
||||
|
if (cached) { |
||||
|
delete this.cache[key]; |
||||
|
delete this.access_time[key]; |
||||
|
this.size --; |
||||
|
} |
||||
|
}, |
||||
|
get_node: function(key){ |
||||
|
var cached = this.cache[key]; |
||||
|
if(cached){ |
||||
|
this.access_time[key] = new Date().getTime(); |
||||
|
} |
||||
|
return cached; |
||||
|
}, |
||||
|
}); |
||||
|
|
||||
|
var ReturnButton = pos_screens.ActionButtonWidget.extend({ |
||||
|
template: 'ReturnButton', |
||||
|
button_click: function(){ |
||||
|
if (this.pos.get_order().get_orderlines().length === 0){ |
||||
|
this.gui.show_screen('ReturnOrdersWidget'); |
||||
|
} |
||||
|
else{ |
||||
|
this.gui.show_popup('error',{ |
||||
|
title :_t('Process Only one operation at a time'), |
||||
|
body :_t('Process the current order first'), |
||||
|
}); |
||||
|
} |
||||
|
}, |
||||
|
}); |
||||
|
|
||||
|
pos_screens.define_action_button({ |
||||
|
'name': 'Return', |
||||
|
'widget': ReturnButton, |
||||
|
'condition': function(){ |
||||
|
return this.pos; |
||||
|
}, |
||||
|
}); |
||||
|
|
||||
|
models.PosModel = models.PosModel.extend({ |
||||
|
_save_to_server: function (orders, options) { |
||||
|
var result_new = PosModelSuper.prototype._save_to_server.call(this, orders, options); |
||||
|
var self = this; |
||||
|
var new_order = {}; |
||||
|
var orders_list = self.pos_orders; |
||||
|
for (var i in orders) { |
||||
|
var partners = self.partners; |
||||
|
var partner = ""; |
||||
|
for(var j in partners){ |
||||
|
if(partners[j].id == orders[i].data.partner_id){ |
||||
|
partner = partners[j].name; |
||||
|
} |
||||
|
} |
||||
|
new_order = { |
||||
|
'amount_tax': orders[i].data.amount_tax, |
||||
|
'amount_total': orders[i].data.amount_total, |
||||
|
'pos_reference': orders[i].data.name, |
||||
|
'return_ref': orders[i].data.return_ref, |
||||
|
'partner_id': [orders[i].data.partner_id, partner], |
||||
|
'return_status':orders[i].data.return_status, |
||||
|
'session_id': [ |
||||
|
self.pos_session.id, self.pos_session.name |
||||
|
] |
||||
|
}; |
||||
|
orders_list.push(new_order); |
||||
|
self.pos_orders = orders_list; |
||||
|
self.gui.screen_instances.ReturnOrdersWidget.render_list(orders_list); |
||||
|
} |
||||
|
return result_new; |
||||
|
}, |
||||
|
}); |
||||
|
|
||||
|
var ReturnOrdersWidget = pos_screens.ScreenWidget.extend({ |
||||
|
template: 'ReturnOrdersWidget', |
||||
|
|
||||
|
init: function(parent, options){ |
||||
|
this._super(parent, options); |
||||
|
this.order_cache = new DomCache(); |
||||
|
this.order_string = ""; |
||||
|
this.pos_reference = ""; |
||||
|
}, |
||||
|
|
||||
|
auto_back: true, |
||||
|
renderElement: function () { |
||||
|
this._super(this); |
||||
|
var self = this; |
||||
|
|
||||
|
}, |
||||
|
|
||||
|
show: function(){ |
||||
|
var self = this; |
||||
|
this._super(); |
||||
|
|
||||
|
this.renderElement(); |
||||
|
this.details_visible = false; |
||||
|
|
||||
|
this.$('.back').click(function(){ |
||||
|
self.gui.back(); |
||||
|
}); |
||||
|
var pos_orders = this.pos.pos_orders; |
||||
|
this.render_list(pos_orders); |
||||
|
|
||||
|
|
||||
|
var search_timeout = null; |
||||
|
|
||||
|
if(this.pos.config.iface_vkeyboard && this.chrome.widget.keyboard){ |
||||
|
this.chrome.widget.keyboard.connect(this.$('.searchbox input')); |
||||
|
} |
||||
|
|
||||
|
this.$('.searchbox input').on('keypress',function(event){ |
||||
|
clearTimeout(search_timeout); |
||||
|
|
||||
|
var query = this.value; |
||||
|
search_timeout = setTimeout(function(){ |
||||
|
self.perform_search(query,event.which === 13); |
||||
|
},70); |
||||
|
}); |
||||
|
|
||||
|
this.$('.searchbox .search-clear').click(function(){ |
||||
|
self.clear_search(); |
||||
|
}); |
||||
|
}, |
||||
|
hide: function () { |
||||
|
this._super(); |
||||
|
this.new_client = null; |
||||
|
}, |
||||
|
perform_search: function(query, associate_result){ |
||||
|
var new_orders; |
||||
|
if(query){ |
||||
|
new_orders = this.search_order(query); |
||||
|
|
||||
|
this.render_list(new_orders); |
||||
|
}else{ |
||||
|
var orders = this.pos.pos_orders; |
||||
|
this.render_list(orders); |
||||
|
} |
||||
|
}, |
||||
|
search_order: function(query){ |
||||
|
var self = this; |
||||
|
try { |
||||
|
query = query.replace(/[\[\]\(\)\+\*\?\.\-\!\&\^\$\|\~\_\{\}\:\,\\\/]/g,'.'); |
||||
|
query = query.replace(' ','.+'); |
||||
|
var re = RegExp("([0-9]+):.*?"+query,"gi"); |
||||
|
}catch(e){ |
||||
|
return []; |
||||
|
} |
||||
|
var results = []; |
||||
|
for(var i = 0; i < Math.min(self.pos.pos_orders.length,1000); i++){ |
||||
|
var r = re.exec(this.order_string); |
||||
|
if(r){ |
||||
|
var id = Number(r[1]); |
||||
|
results.push(this.get_order_by_id(id)); |
||||
|
}else{ |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
return results; |
||||
|
}, |
||||
|
// returns the order with the id provided
|
||||
|
get_order_by_id: function (id) { |
||||
|
return this.pos.pos_orders[id]; |
||||
|
}, |
||||
|
clear_search: function(){ |
||||
|
var orders = this.pos.pos_orders; |
||||
|
this.render_list(orders); |
||||
|
this.$('.searchbox input')[0].value = ''; |
||||
|
this.$('.searchbox input').focus(); |
||||
|
}, |
||||
|
render_list: function(orders){ |
||||
|
var self = this; |
||||
|
for(var i = 0, len = Math.min(orders.length,1000); i < len; i++) { |
||||
|
if (orders[i]) { |
||||
|
var order = orders[i]; |
||||
|
self.order_string += i + ':' + order.pos_reference + '\n'; |
||||
|
} |
||||
|
} |
||||
|
this.$('.order-list-lines').delegate('.return-button','click',function(event){ |
||||
|
|
||||
|
var pos_ref = $(this).data('id'); |
||||
|
var order_new = null; |
||||
|
for(var i = 0, len = Math.min(orders.length,1000); i < len; i++) { |
||||
|
if (orders[i] && orders[i].pos_reference == pos_ref) { |
||||
|
order_new = orders[i]; |
||||
|
} |
||||
|
} |
||||
|
$('span.searchbox').css('display', 'none'); |
||||
|
$('.button.return').css('display', 'block') |
||||
|
self.pos_reference = order_new.pos_reference; |
||||
|
if (order_new.return_ref){ |
||||
|
self.gui.show_popup('error',_t('This is a returned order')); |
||||
|
self.gui.show_popup('error',{ |
||||
|
title :_t('Cannot Return'), |
||||
|
body :_t('This order is a returned order'), |
||||
|
}); |
||||
|
} |
||||
|
else{ |
||||
|
new Model('pos.order').call('get_status',[order_new.pos_reference]).then(function(result){ |
||||
|
if (result){ |
||||
|
self.gui.show_popup('OrderReturnWidget',{ |
||||
|
ref: pos_ref |
||||
|
}); |
||||
|
} |
||||
|
else{ |
||||
|
self.gui.show_popup('error',{ |
||||
|
title :_t('Fully Returned Order'), |
||||
|
body :_t('This order is fully returned'), |
||||
|
}); |
||||
|
|
||||
|
|
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
var contents = this.$el[0].querySelector('.order-list-lines'); |
||||
|
if (contents){ |
||||
|
contents.innerHTML = ""; |
||||
|
for(var i = 0, len = Math.min(orders.length,1000); i < len; i++) { |
||||
|
if (orders[i]) { |
||||
|
var order = orders[i]; |
||||
|
var orderline = this.order_cache.get_node(order.id); |
||||
|
if (!orderline) { |
||||
|
var clientline_html = QWeb.render('OrderLines', {widget: this, order: order}); |
||||
|
var orderline = document.createElement('tbody'); |
||||
|
orderline.innerHTML = clientline_html; |
||||
|
orderline = orderline.childNodes[1]; |
||||
|
if (order.id){ |
||||
|
this.order_cache.cache_node(order.id, orderline); |
||||
|
} |
||||
|
else{ |
||||
|
this.order_cache.cache_node(i, orderline); |
||||
|
} |
||||
|
} |
||||
|
contents.appendChild(orderline); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
|
||||
|
close: function(){ |
||||
|
this._super(); |
||||
|
}, |
||||
|
}); |
||||
|
var OrderReturnWidget = PosBaseWidget.extend({ |
||||
|
template: 'OrderReturnWidget', |
||||
|
|
||||
|
init: function(parent, options){ |
||||
|
this._super(parent, options); |
||||
|
this.order_cache = new DomCache(); |
||||
|
this.ordernes = ""; |
||||
|
this.pos_reference = ""; |
||||
|
this.client =""; |
||||
|
}, |
||||
|
show: function (options) { |
||||
|
var self = this; |
||||
|
this._super(options); |
||||
|
var pos_orders = this.pos.pos_orders; |
||||
|
this.render_list(options); |
||||
|
|
||||
|
}, |
||||
|
close: function(){ |
||||
|
if (this.pos.barcode_reader) { |
||||
|
this.pos.barcode_reader.restore_callbacks(); |
||||
|
} |
||||
|
}, |
||||
|
events: { |
||||
|
'click .button.cancel': 'click_cancel', |
||||
|
'click .button.confirm': 'click_confirm', |
||||
|
}, |
||||
|
|
||||
|
render_list:function(options){ |
||||
|
var order_new = null; |
||||
|
$("#table-body").empty(); |
||||
|
var lines = []; |
||||
|
this.pos_reference = options.ref |
||||
|
new Model('pos.order').call('get_lines',[options.ref]).then(function(result){ |
||||
|
lines = result[0]; |
||||
|
this.client = result[1]; |
||||
|
for(var j=0;j < lines.length; j++){ |
||||
|
var product_line = lines[j]; |
||||
|
var rows = ""; |
||||
|
var id = product_line.product_id |
||||
|
var price_unit = product_line.price_unit; |
||||
|
var name =product_line.product; |
||||
|
var qty = product_line.qty; |
||||
|
var line_id = product_line.line_id; |
||||
|
var discount = product_line.discount; |
||||
|
rows += "<tr><td>" + id + "</td><td>" + price_unit +" </td><td>" + name + "</td><td>" + qty + "</td><td>" + discount + "</td><td>" + line_id + "</td></tr>"; |
||||
|
$(rows).appendTo("#list tbody"); |
||||
|
var rows = document.getElementById('list').rows; |
||||
|
for (var row = 0; row < rows.length; row++) { |
||||
|
var cols = rows[row].cells; |
||||
|
cols[0].style.display = 'none'; |
||||
|
cols[1].style.display = 'none'; |
||||
|
cols[5].style.display = 'none'; |
||||
|
|
||||
|
} |
||||
|
|
||||
|
} |
||||
|
var table = document.getElementById('list'); |
||||
|
var tr = table.getElementsByTagName("tr"); |
||||
|
for (var i = 1; i < tr.length; i++) { |
||||
|
var td = document.createElement('td'); |
||||
|
var input = document.createElement('input'); |
||||
|
input.setAttribute("type", "text"); |
||||
|
input.setAttribute("value", 0); |
||||
|
input.setAttribute("id", "text"+i); |
||||
|
td.appendChild(input); |
||||
|
tr[i].appendChild(td); |
||||
|
|
||||
|
} |
||||
|
|
||||
|
}); |
||||
|
|
||||
|
}, |
||||
|
click_confirm: function(){ |
||||
|
var self = this; |
||||
|
var myTable = document.getElementById('list').tBodies[0]; |
||||
|
var count = 0 |
||||
|
var c = 1 |
||||
|
for (var r=0, n = myTable.rows.length; r < n; r++) { |
||||
|
var row = myTable.rows[r] |
||||
|
var return_qty = document.getElementById("text"+c).value |
||||
|
if (row.cells[3].innerHTML < return_qty){ |
||||
|
count +=1 |
||||
|
} |
||||
|
c = c+1 |
||||
|
} |
||||
|
if (count > 0){ |
||||
|
alert('Please check the Returned Quantity,it is higher than purchased') |
||||
|
} |
||||
|
else{ |
||||
|
var c = 1 |
||||
|
// OrderSuper.prototype.set_client.call(this, this.client);
|
||||
|
for (var r=0, n = myTable.rows.length; r < n; r++) { |
||||
|
row = myTable.rows[r] |
||||
|
var return_qty = document.getElementById("text"+c).value |
||||
|
var product = this.pos.db.get_product_by_id(row.cells[0].innerHTML); |
||||
|
if (!product) { |
||||
|
return; |
||||
|
} |
||||
|
if (return_qty > 0){ |
||||
|
this.pos.get_order().add_product(product, { |
||||
|
price: row.cells[1].innerHTML, |
||||
|
quantity: -(return_qty), |
||||
|
discount:row.cells[4].innerHTML, |
||||
|
merge: false, |
||||
|
extras: {pos_ref: this.pos_reference, |
||||
|
label:row.cells[5].innerHTML}, |
||||
|
}); |
||||
|
|
||||
|
} |
||||
|
c = c+1 |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
this.gui.close_popup(); |
||||
|
|
||||
|
self.gui.show_screen('products'); |
||||
|
|
||||
|
}, |
||||
|
click_cancel: function(){ |
||||
|
this.gui.close_popup(); |
||||
|
|
||||
|
}, |
||||
|
|
||||
|
}); |
||||
|
|
||||
|
var OrderSuper = models.Order; |
||||
|
models.Order = models.Order.extend({ |
||||
|
initialize: function(attributes,options){ |
||||
|
var order = OrderSuper.prototype.initialize.call(this, attributes,options); |
||||
|
order.return_ref = ''; |
||||
|
return order; |
||||
|
}, |
||||
|
init_from_JSON: function(json) { |
||||
|
OrderSuper.prototype.init_from_JSON.call(this, json); |
||||
|
this.return_ref = json.return_ref; |
||||
|
|
||||
|
|
||||
|
}, |
||||
|
export_as_JSON: function() { |
||||
|
var json_new = OrderSuper.prototype.export_as_JSON.call(this); |
||||
|
json_new.return_ref = this.get_return_ref(); |
||||
|
return json_new; |
||||
|
}, |
||||
|
|
||||
|
get_return_ref: function(){ |
||||
|
return this.return_ref; |
||||
|
}, |
||||
|
|
||||
|
add_product: function (product, options) { |
||||
|
OrderSuper.prototype.add_product.call(this, product, options); |
||||
|
var order = this.pos.get_order(); |
||||
|
var last_orderline = this.get_last_orderline(); |
||||
|
if (options !== undefined){ |
||||
|
if(options.extras !== undefined){ |
||||
|
for (var prop in options.extras) { |
||||
|
if (prop ==='pos_ref'){ |
||||
|
this.return_ref = options.extras['pos_ref'] |
||||
|
this.trigger('change',this); |
||||
|
var self = this; |
||||
|
var curr_client = order.get_client(); |
||||
|
if (!curr_client) { |
||||
|
new Model('pos.order').call('get_client',[options.extras['pos_ref']]).then(function(result){ |
||||
|
if (result){ |
||||
|
var partner = self.pos.db.get_partner_by_id(result); |
||||
|
order.set_client(partner); |
||||
|
|
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
else if(prop ==='label'){ |
||||
|
order.selected_orderline.set_order_line_id(options.extras['label']); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
}, |
||||
|
|
||||
|
}); |
||||
|
var OrderlineSuper = models.Orderline; |
||||
|
models.Orderline = models.Orderline.extend({ |
||||
|
initialize: function(attr,options){ |
||||
|
OrderlineSuper.prototype.initialize.call(this, attr,options); |
||||
|
this.line_id = ''; |
||||
|
|
||||
|
}, |
||||
|
init_from_JSON: function(json) { |
||||
|
OrderlineSuper.prototype.init_from_JSON.call(this, json); |
||||
|
this.line_id = json.line_id |
||||
|
}, |
||||
|
clone: function(){ |
||||
|
var orderline = OrderlineSuper.prototype.clone.call(this); |
||||
|
orderline.line_id = this.line_id; |
||||
|
return orderline; |
||||
|
}, |
||||
|
get_line_id: function(){ |
||||
|
return this.line_id; |
||||
|
}, |
||||
|
set_order_line_id:function(id){ |
||||
|
this.line_id = id; |
||||
|
this.trigger('change',this); |
||||
|
}, |
||||
|
export_as_JSON: function(){ |
||||
|
var json = OrderlineSuper.prototype.export_as_JSON.apply(this,arguments); |
||||
|
json.line_id = this.get_line_id(); |
||||
|
return json; |
||||
|
}, |
||||
|
}); |
||||
|
|
||||
|
gui.define_screen({name:'ReturnOrdersWidget', widget: ReturnOrdersWidget}); |
||||
|
gui.define_popup({name:'OrderReturnWidget', widget: OrderReturnWidget}); |
||||
|
|
||||
|
}); |
@ -0,0 +1,103 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<templates id="template" xml:space="preserve"> |
||||
|
|
||||
|
<t t-name="ReturnButton"> |
||||
|
<div class='control-button'> |
||||
|
<i class="fa fa-shopping-cart" />Return |
||||
|
</div> |
||||
|
</t> |
||||
|
|
||||
|
<t t-name="OrderLines"> |
||||
|
<tr class='order-line' t-att-data-id='order.id'> |
||||
|
<td><t t-esc='order.pos_reference' /></td> |
||||
|
<td> |
||||
|
<t t-if="order.return_ref"> |
||||
|
<t t-esc='order.return_ref' /> |
||||
|
</t> |
||||
|
</td> |
||||
|
<td><t t-esc='order.partner_id[1]' /></td> |
||||
|
<td><t t-esc='order.session_id[1]'/></td> |
||||
|
<td><t t-esc='order.amount_total'/></td> |
||||
|
<td class="return-button" t-att-data-id='order.pos_reference'><span class="order-button square orders" >Return</span></td> |
||||
|
</tr> |
||||
|
</t> |
||||
|
|
||||
|
<t t-name="ReturnOrdersWidget"> |
||||
|
<div class="clientlist-screen screen"> |
||||
|
<div class="screen-content"> |
||||
|
<section class="top-content"> |
||||
|
<span class='button back'> |
||||
|
<i class='fa fa-angle-double-left'></i> |
||||
|
Cancel |
||||
|
</span> |
||||
|
<span class='searchbox' style="margin-left:217px !important;"> |
||||
|
<input placeholder='Search Orders by ref' /> |
||||
|
<span class='search-clear'></span> |
||||
|
</span> |
||||
|
</section> |
||||
|
<section class="full-content"> |
||||
|
<div class='window'> |
||||
|
<section class='subwindow collapsed'> |
||||
|
<div class='subwindow-container collapsed'> |
||||
|
<div class='subwindow-container-fix order-details-contents'> |
||||
|
</div> |
||||
|
</div> |
||||
|
</section> |
||||
|
<section class='subwindow'> |
||||
|
<div class='subwindow-container'> |
||||
|
<div class='subwindow-container-fix touch-scrollable scrollable-y'> |
||||
|
<table class='client-list'> |
||||
|
<thead> |
||||
|
<tr> |
||||
|
<th>Reciept Ref.</th> |
||||
|
<th>Return Ref.</th> |
||||
|
<th>Partner</th> |
||||
|
<th>Session</th> |
||||
|
<th>Amount Total</th> |
||||
|
</tr> |
||||
|
</thead> |
||||
|
<tbody class='order-list-lines'> |
||||
|
</tbody> |
||||
|
</table> |
||||
|
</div> |
||||
|
</div> |
||||
|
</section> |
||||
|
</div> |
||||
|
</section> |
||||
|
</div> |
||||
|
</div> |
||||
|
</t> |
||||
|
|
||||
|
<t t-name="OrderReturnWidget"> |
||||
|
<div class="modal-dialog"> |
||||
|
<div class="popup popup-selection product_return_pos"> |
||||
|
<p class="title">Return Product</p> |
||||
|
<div class='selection scrollable-y touch-scrollable'> |
||||
|
<table id = "list" cellspacing = "1px" cellpadding = "10px" text-align = "center" width="100%" style="border:1px;padding-left:1.16cm;"> |
||||
|
<thead> |
||||
|
<tr> |
||||
|
<td>ID</td> |
||||
|
<td>Price</td> |
||||
|
<td>Name</td> |
||||
|
<td>Qty</td> |
||||
|
<td>Dis</td> |
||||
|
<td>Line ID</td> |
||||
|
<td>Returned Quantity</td> |
||||
|
</tr> |
||||
|
</thead> |
||||
|
<tbody id="table-body"> |
||||
|
</tbody> |
||||
|
</table> |
||||
|
</div> |
||||
|
<div class="footer"> |
||||
|
<div class="button confirm"> |
||||
|
Return |
||||
|
</div> |
||||
|
<div class="button cancel"> |
||||
|
Cancel |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</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_return/static/src/js/pos_return.js"></script> |
||||
|
</xpath> |
||||
|
</template> |
||||
|
|
||||
|
</data> |
||||
|
</odoo> |
@ -0,0 +1,31 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<odoo> |
||||
|
<data> |
||||
|
<record model="ir.ui.view" id="view_pos_new_form_extended"> |
||||
|
<field name="name">pos.order.form.extend</field> |
||||
|
<field name="model">pos.order</field> |
||||
|
<field name="inherit_id" ref="point_of_sale.view_pos_pos_form"/> |
||||
|
<field name="arch" type="xml"> |
||||
|
<xpath expr="//field[@name='pos_reference']" position="after"> |
||||
|
<field name="return_ref"/> |
||||
|
<field name="return_status"/> |
||||
|
</xpath> |
||||
|
<xpath expr="//field[@name='qty']" position="after"> |
||||
|
<field name="returned_qty" invisible="1"/> |
||||
|
</xpath> |
||||
|
</field> |
||||
|
</record> |
||||
|
|
||||
|
<record model="ir.ui.view" id="view_pos_new_tree_extended"> |
||||
|
<field name="name">pos.order.tree.extend</field> |
||||
|
<field name="model">pos.order</field> |
||||
|
<field name="inherit_id" ref="point_of_sale.view_pos_order_tree"/> |
||||
|
<field name="arch" type="xml"> |
||||
|
<xpath expr="//field[@name='pos_reference']" position="after"> |
||||
|
<field name="return_ref"/> |
||||
|
</xpath> |
||||
|
</field> |
||||
|
</record> |
||||
|
|
||||
|
</data> |
||||
|
</odoo> |