diff --git a/product_return_pos/README.md b/product_return_pos/README.md new file mode 100644 index 000000000..549fddff8 --- /dev/null +++ b/product_return_pos/README.md @@ -0,0 +1,49 @@ +.. image:: https://img.shields.io/badge/licence-AGPL--1-blue.svg + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 + +Product Return In POS +===================== +POS Order Return. + +Configuration +============= +* No additional configurations needed + +Company +------- +* `Cybrosys Techno Solutions `__ + +Credits +------- +* Developers: Anusha P P@cybrosys + Version 13: Nimisha Murali@cybrosys + Version 14: Jibin James@cybrosys + +Contacts +-------- +* Mail Contact : odoo@cybrosys.com +* Website : https://cybrosys.com + +Bug Tracker +----------- +Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. + +Maintainer +========== +.. image:: https://cybrosys.com/images/logo.png + :target: https://cybrosys.com + +This module is maintained by Cybrosys Technologies. + +For support and more information, please visit `Our Website `__ + +Further information +=================== +HTML Description: ``__ + + + + + + diff --git a/product_return_pos/__init__.py b/product_return_pos/__init__.py new file mode 100644 index 000000000..afe5fa815 --- /dev/null +++ b/product_return_pos/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2019-TODAY Cybrosys Technologies(). +# Author: Anusha P P (odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. +# +# 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 (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +############################################################################# +from . import models diff --git a/product_return_pos/__manifest__.py b/product_return_pos/__manifest__.py new file mode 100644 index 000000000..1159f81f6 --- /dev/null +++ b/product_return_pos/__manifest__.py @@ -0,0 +1,43 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2020-TODAY Cybrosys Technologies(). +# Author: Anusha P P (odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. +# +# 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 (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +############################################################################# +{ + 'name': 'Product Return In POS', + 'version': '14.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.png'], + '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, + +} diff --git a/product_return_pos/doc/RELEASE_NOTES.md b/product_return_pos/doc/RELEASE_NOTES.md new file mode 100644 index 000000000..4d32546ff --- /dev/null +++ b/product_return_pos/doc/RELEASE_NOTES.md @@ -0,0 +1,8 @@ +## Module + +#### 20.11.2020 +#### Version 14.0.1.0.0 +##### ADD +- Initial Commit. + + diff --git a/product_return_pos/models/__init__.py b/product_return_pos/models/__init__.py new file mode 100644 index 000000000..7b5f6316d --- /dev/null +++ b/product_return_pos/models/__init__.py @@ -0,0 +1,23 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2019-TODAY Cybrosys Technologies(). +# Author: Anusha P P (odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. +# +# 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 (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +############################################################################# + +from . import pos_return diff --git a/product_return_pos/models/pos_return.py b/product_return_pos/models/pos_return.py new file mode 100644 index 000000000..8b9104008 --- /dev/null +++ b/product_return_pos/models/pos_return.py @@ -0,0 +1,88 @@ +# -*- coding: utf-8 -*- +############################################################################# +# +# Cybrosys Technologies Pvt. Ltd. +# +# Copyright (C) 2019-TODAY Cybrosys Technologies(). +# Author: Anusha P P (odoo@cybrosys.com) +# +# You can modify it under the terms of the GNU AFFERO +# GENERAL PUBLIC LICENSE (AGPL v3), Version 3. +# +# 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 (AGPL v3) for more details. +# +# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE +# (AGPL v3) along with this program. +# If not, see . +# +############################################################################# +from odoo import models, api, fields + + +class PosOrderReturn(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', + readonly=True, copy=False, 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] + + def _order_fields(self, ui_order): + order = super(PosOrderReturn, self)._order_fields(ui_order) + if 'return_ref' in ui_order.keys() and ui_order['return_ref']: + order['return_ref'] = ui_order['return_ref'] + parent_order = self.search([('pos_reference', '=', ui_order['return_ref'])], limit=1) + + updated_lines = ui_order['lines'] + ret = 0 + qty = 0 + for uptd in updated_lines: + line = self.env['pos.order.line'].search([('order_id', '=', parent_order.id), + ('id', '=', uptd[2]['line_id'])], limit=1) + if line: + line.returned_qty += -(uptd[2]['qty']) + for line in parent_order.lines: + qty += line.qty + ret += line.returned_qty + if qty-ret == 0: + if parent_order: + parent_order.return_status = 'fully_return' + print(parent_order.return_status) + elif ret: + if qty > ret: + if parent_order: + parent_order.return_status = 'partialy_return' + + return order + + +class PosOrderLineReturn(models.Model): + _inherit = 'pos.order.line' + + returned_qty = fields.Integer(string='Returned Qty', digits=0, readonly=True) diff --git a/product_return_pos/static/description/banner.png b/product_return_pos/static/description/banner.png new file mode 100644 index 000000000..e4813f34b Binary files /dev/null and b/product_return_pos/static/description/banner.png differ diff --git a/product_return_pos/static/description/icon.png b/product_return_pos/static/description/icon.png new file mode 100644 index 000000000..aecff0801 Binary files /dev/null and b/product_return_pos/static/description/icon.png differ diff --git a/product_return_pos/static/description/images/banner_lifeline_for_task.jpeg b/product_return_pos/static/description/images/banner_lifeline_for_task.jpeg new file mode 100644 index 000000000..4a467ea22 Binary files /dev/null and b/product_return_pos/static/description/images/banner_lifeline_for_task.jpeg differ diff --git a/product_return_pos/static/description/images/banner_project_report_xls_pdf.png b/product_return_pos/static/description/images/banner_project_report_xls_pdf.png new file mode 100644 index 000000000..3c430a7eb Binary files /dev/null and b/product_return_pos/static/description/images/banner_project_report_xls_pdf.png differ diff --git a/product_return_pos/static/description/images/banner_project_status_report.png b/product_return_pos/static/description/images/banner_project_status_report.png new file mode 100644 index 000000000..d1b689710 Binary files /dev/null and b/product_return_pos/static/description/images/banner_project_status_report.png differ diff --git a/product_return_pos/static/description/images/banner_subtask.jpeg b/product_return_pos/static/description/images/banner_subtask.jpeg new file mode 100644 index 000000000..f2b224110 Binary files /dev/null and b/product_return_pos/static/description/images/banner_subtask.jpeg differ diff --git a/product_return_pos/static/description/images/banner_task_deadline_reminder.jpeg b/product_return_pos/static/description/images/banner_task_deadline_reminder.jpeg new file mode 100644 index 000000000..998679818 Binary files /dev/null and b/product_return_pos/static/description/images/banner_task_deadline_reminder.jpeg differ diff --git a/product_return_pos/static/description/images/banner_task_statusbar.jpeg b/product_return_pos/static/description/images/banner_task_statusbar.jpeg new file mode 100644 index 000000000..2c57cbb7b Binary files /dev/null and b/product_return_pos/static/description/images/banner_task_statusbar.jpeg differ diff --git a/product_return_pos/static/description/images/checked.png b/product_return_pos/static/description/images/checked.png new file mode 100644 index 000000000..578cedb80 Binary files /dev/null and b/product_return_pos/static/description/images/checked.png differ diff --git a/product_return_pos/static/description/images/cybrosys.png b/product_return_pos/static/description/images/cybrosys.png new file mode 100644 index 000000000..d76b5bafb Binary files /dev/null and b/product_return_pos/static/description/images/cybrosys.png differ diff --git a/product_return_pos/static/description/images/normal order.png b/product_return_pos/static/description/images/normal order.png new file mode 100644 index 000000000..72d9e034c Binary files /dev/null and b/product_return_pos/static/description/images/normal order.png differ diff --git a/product_return_pos/static/description/images/order log to return.png b/product_return_pos/static/description/images/order log to return.png new file mode 100644 index 000000000..c9ac4215b Binary files /dev/null and b/product_return_pos/static/description/images/order log to return.png differ diff --git a/product_return_pos/static/description/images/order.png b/product_return_pos/static/description/images/order.png new file mode 100644 index 000000000..0b89ad184 Binary files /dev/null and b/product_return_pos/static/description/images/order.png differ diff --git a/product_return_pos/static/description/images/return click.png b/product_return_pos/static/description/images/return click.png new file mode 100644 index 000000000..51cceb50f Binary files /dev/null and b/product_return_pos/static/description/images/return click.png differ diff --git a/product_return_pos/static/description/images/return order.png b/product_return_pos/static/description/images/return order.png new file mode 100644 index 000000000..3cb7170d5 Binary files /dev/null and b/product_return_pos/static/description/images/return order.png differ diff --git a/product_return_pos/static/description/images/return status.png b/product_return_pos/static/description/images/return status.png new file mode 100644 index 000000000..4d01785b2 Binary files /dev/null and b/product_return_pos/static/description/images/return status.png differ diff --git a/product_return_pos/static/description/index.html b/product_return_pos/static/description/index.html new file mode 100644 index 000000000..3d540473e --- /dev/null +++ b/product_return_pos/static/description/index.html @@ -0,0 +1,313 @@ +
cybrosys-logo
+
+
+
+

Product Return In POS

+

Manages Product Return From POS Frontend

+
+

Key Highlights

+
    +
  • Manage Product Return through POS interface.
  • + +
  • Track Return Reference and Status
  • +
+
+ + + +
+ + +
+
+
+
+
+ +
+
+ +

Overview

+
+

+ This app will help you to return the products from the POS user interface.

+
+
+ +

Features

+
+
    +

    + Manage Product Return through POS interface. +

    +

    + Track Return Reference and Status. +

    +
+
+ +
+
+

Screenshots

+
+
+
+ +
+
+
+
+ + +
+
    +
+
+
+
+
+
+
+

Suggested Products

+
+ +
+
+

Our Service

+
+ +
+
+
+

Our Industries

+
+ +
+
+
+ +
+
+

Trading

+

Easily procure and sell your products.

+
+
+
+
+ +
+
+

Manufacturing

+

Plan, track and schedule your operations.

+
+
+
+
+ +
+
+

Restaurant

+

Run your bar or restaurant methodical.

+
+
+
+
+ +
+
+

POS

+

Easy configuring and convivial selling.

+
+
+
+
+ +
+
+

E-commerce & Website

+

Mobile friendly, awe-inspiring product pages.

+
+
+
+
+ +
+
+

Hotel Management

+

An all-inclusive hotel management application.

+
+
+
+
+ +
+
+

Education

+

A Collaborative platform for educational management.

+
+
+
+
+ +
+
+

Service Management

+

Keep track of services and invoice accordingly.

+
+
+
+
+
+ +
+
+
+

Need Any Help?

+
+

If you have anything to share with us based on your use of this module, please let us know. We are ready to offer our support.

+
+

Email us

+

odoo@cybrosys.com / info@cybrosys.com

+
+
+

Contact Us

+ www.cybrosys.com +
+
+
+
+
+
+
+
+
+ +
+ + + + + + + +
+
+
+ \ No newline at end of file diff --git a/product_return_pos/static/src/css/pos_return.css b/product_return_pos/static/src/css/pos_return.css new file mode 100644 index 000000000..01ffa4168 --- /dev/null +++ b/product_return_pos/static/src/css/pos_return.css @@ -0,0 +1,56 @@ +.ticket-screen .return-button { + color: #f0f0f0; + display: inline-block; + box-sizing: border-box; + -moz-box-sizing: border-box; + /* height: 20px; */ + padding: 4px 8px; + margin: 3px; + margin-bottom: 0px; + margin-right: 2px; + padding-top: 0px; + background: #8b8b8b; + border-top-left-radius: 3px; + border-top-right-radius: 3px; + vertical-align: top; + line-height: 20px; + text-align: center; + box-shadow: 0px -5px 10px -6px rgb(82,82,82) inset; + cursor: pointer; + min-width: 45px; +} +.ticket-screen .order-list tr.highlight{ + transition: all 150ms linear; + background: rgb(110,200,155) !important; + color: white; +} +.ticket-screen .order-list td tr.lowlight{ + transition: all 150ms linear; + background: rgb(216, 238, 227); +} +.ticket-screen .order-list tr.lowlight:nth-child(even){ + transition: all 150ms linear; + background: rgb(227, 246, 237); +} + +.return-screen .searchbox{ + right: auto; + margin-left: 50px; + margin-top:8px; + left: 25%; +} +.ticket-screen .refreshbutton{ + right: 10px; + margin-right: 5px; + margin-top:8px; + left: auto; +} +.reprint_order_screen .searchbox input{ + width: 120px; +} + +.ticket-screen .order-list{ + font-size: 15px; + width: 100%; + line-height: 40px; +} \ No newline at end of file diff --git a/product_return_pos/static/src/js/models.js b/product_return_pos/static/src/js/models.js new file mode 100644 index 000000000..230bf155f --- /dev/null +++ b/product_return_pos/static/src/js/models.js @@ -0,0 +1,178 @@ +odoo.define('product_return_pos.models',function(require) { + "use strict"; + + + +var models = require('point_of_sale.models'); +var gui = require('point_of_sale.Gui'); +var core = require('web.core'); +var QWeb = core.qweb; +var rpc = require('web.rpc'); +var _t = require('web.core')._t; +var session = require('web.session'); + + + +models.load_models({ + model: 'pos.order', + fields: ['name', 'partner_id','date_order','amount_total', 'amount_tax', + 'pos_reference','lines','state','session_id','company_id','return_ref','return_status'], + loaded: function(self, orders){ + + self.orders = orders; + } + }, + { + model: 'pos.order.line', + fields: ['product_id','qty','price_unit','price_subtotal_incl','order_id','discount','returned_qty'], + 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 _super_orderline = models.Orderline; +models.Orderline = models.Orderline.extend({ + + set_line_id: function(line_id){ + this.line_id = line_id; + }, + export_as_JSON: function(){ + var json = _super_orderline.prototype.export_as_JSON.apply(this,arguments); + json.line_id = this.line_id; + return json; + }, + init_from_JSON: function(json){ + _super_orderline.prototype.init_from_JSON.apply(this,arguments); + this.line_id = json.line_id; + }, +}); + +var _super = models.Order; +models.Order = models.Order.extend({ + + add_product: function (product, options) { + + + var order = this.pos.get_order(); + _super.prototype.add_product.call(this, product, options); + if (options !== undefined) { + if (options.extras !== undefined) { + for (var prop in options.extras) { + if (prop === 'return_ref') { + this.return_ref = options.extras['return_ref'] + this.trigger('change', this); + } + if (prop === 'label') { + order.selected_orderline.set_line_id(options.extras['label']); + } + + } + + } + + } + + }, + + export_as_JSON: function(){ + var json = _super.prototype.export_as_JSON.apply(this,arguments); + json.return_ref = this.return_ref; + return json; + }, + init_from_JSON: function(json){ + _super.prototype.init_from_JSON.apply(this,arguments); + this.return_ref = json.return_ref; + } + +}); + +models.PosModel.extend({ + _save_to_server: function (orders, options) { + if (!orders || !orders.length) { + var result = $.Deferred(); + result.resolve([]); + return result; + } + var fields = _.find(this.models,function(model){ return model.model === 'pos.order'; }).fields; + options = options || {}; + + var self = this; + var timeout = typeof options.timeout === 'number' ? options.timeout : 7500 * orders.length; + + // Keep the order ids that are about to be sent to the + // backend. In between create_from_ui and the success callback + // new orders may have been added to it. + var order_ids_to_sync = _.pluck(orders, 'id'); + + // we try to send the order. shadow prevents a spinner if it takes too long. (unless we are sending an invoice, + // then we want to notify the user that we are waiting on something ) + var args = [_.map(orders, function (order) { + order.to_invoice = options.to_invoice || false; + return order; + })]; + return rpc.query({ + model: 'pos.order', + method: 'create_from_ui', + args: args, + kwargs: {context: session.user_context}, + }, { + timeout: timeout, + shadow: !options.to_invoice + }) + .then(function (server_ids) { + _.each(order_ids_to_sync, function (order_id) { + self.db.remove_order(order_id); + }); + self.set('failed',false); + if (server_ids.length != 0){ + for (var item in server_ids){ + rpc.query({ + model: 'pos.order', + method: 'search_read', + args: [[['id', '=', server_ids[item]]], fields], + limit: 1, + }) + .then(function (order){ + self.orders.unshift(order[0]); + }); + } + } + self.load_server_data(); + return server_ids; + }).catch(function (type, error){ + if(error.code === 200 ){ // Business Logic Error, not a connection problem + //if warning do not need to display traceback!! + if (error.data.exception_type == 'warning') { + delete error.data.debug; + } + + // Hide error if already shown before ... + if ((!self.get('failed') || options.show_error) && !options.to_invoice) { + this.showpopup('error-traceback',{ + 'title': error.data.message, + 'body': error.data.debug + }); + } + self.set('failed',error); + } + console.error('Failed to send orders:', orders); + }); + }, +}); + + + + + +}); \ No newline at end of file diff --git a/product_return_pos/static/src/js/order_list_screen.js b/product_return_pos/static/src/js/order_list_screen.js new file mode 100644 index 000000000..379d767fd --- /dev/null +++ b/product_return_pos/static/src/js/order_list_screen.js @@ -0,0 +1,185 @@ +odoo.define('product_return_pos.order_list_screen',function(require) { + "use strict"; + + +var models = require('point_of_sale.models'); + +var gui = require('point_of_sale.Gui'); +var core = require('web.core'); +var QWeb = core.qweb; +var rpc = require('web.rpc'); +var _t = require('web.core')._t; +var session = require('web.session'); + const ControlButtonsMixin = require('point_of_sale.ControlButtonsMixin'); + const NumberBuffer = require('point_of_sale.NumberBuffer'); + const { onChangeOrder, useBarcodeReader } = require('point_of_sale.custom_hooks'); + const { useState , useRef} = owl.hooks; + const PosComponent = require('point_of_sale.PosComponent'); + const Registries = require('point_of_sale.Registries'); + const ProductScreen = require('point_of_sale.ProductScreen'); + const { useListener } = require('web.custom_hooks'); + const OrderManagementScreen = require('point_of_sale.OrderManagementScreen'); + const AbstractAwaitablePopup = require('point_of_sale.AbstractAwaitablePopup'); + const IndependentToOrderScreen = require('point_of_sale.IndependentToOrderScreen'); + const { posbus } = require('point_of_sale.utils'); + const { Gui } = require('point_of_sale.Gui'); + + + + + +class OrderListScreenWidget extends IndependentToOrderScreen { + + + constructor() { + super(...arguments); + useListener('filter-selected', this._onFilterSelected); + + useListener('search', this._onSearch); + this.searchDetails = {}; + this.filter = null; + this._initializeSearchFieldConstants(); + + + } + + mounted() { + var self = this; + this.render(); + var orders = this.env.pos.orders; + var search_timeout = null; + } + + back() { + this.close(); + } + + reload(){ + window.location.reload(); + } + + return_click(order){ + this.return_order(order); + } + + get ordersList() { + const filterCheck = (order) => { + return true; + }; + const { fieldValue, searchTerm } = this.searchDetails; + const fieldAccessor = this._searchFields[fieldValue]; + const searchCheck = (order) => { + if (!fieldAccessor) return true; + const fieldValue = fieldAccessor(order); + if (fieldValue === null) return true; + if (!searchTerm) return true; + return fieldValue && fieldValue.toString().toLowerCase().includes(searchTerm.toLowerCase()); + }; + const predicate = (order) => { + return searchCheck(order); + }; + + return this.orderList.filter(predicate); + } + + _onFilterSelected(event) { + this.filter = event.detail.filter; + this.render(); + } + + get orderList() { + return this.env.pos.orders; + } + + + get _searchFields() { + var fields = { + 'Receipt Number': (order) => order.name, + Date: (order) => order.date_order, + Customer: (order) => order.partner_id[1], + 'Return Ref': (order) => order.return_ref, + }; + return fields; + } + + _onSearch(event) { + const searchDetails = event.detail; + Object.assign(this.searchDetails, searchDetails); + this.render(); + } + + get searchBarConfig() { + return { + searchFields: this.constants.searchFieldNames, + filter: { show: true, options: this.filterOptions }, + }; + } + get filterOptions() { + return ['All Orders']; + } + + get _screenToStatusMap() { + return { + ProductScreen: 'Ongoing', + PaymentScreen: 'Payment', + ReceiptScreen: 'Receipt', + }; + } + + _initializeSearchFieldConstants() { + this.constants = {}; + Object.assign(this.constants, { + searchFieldNames: Object.keys(this._searchFields), + screenToStatusMap: this._screenToStatusMap, + }); + } + + + + render_list(orders){ + var contents = this.el.querySelector('.order-list-contents'); + contents.innerHTML = ""; + for(var i = 0, len = Math.min(orders.length,1000); i < len; i++){ + var order = orders[i]; + var orderline_html = this.env.qweb.render('OrderLine',{widget: this, order:order}); + var orderline = document.createElement('tbody'); + orderline.innerHTML = orderline_html; + orderline = orderline.childNodes[1]; + contents.appendChild(orderline); + } + } + + + return_order(order_id){ + var self = this; + var client = '' + if (order_id.partner_id){ + client = order_id.partner_id[0]; + } + if (order_id && order_id.return_status ==='fully_return'){ + Gui.showPopup('ErrorPopup',{ + 'title': "ERROR", + 'body': "This is a fully returned order",}); + } + else if (order_id && order_id.return_ref) { + + Gui.showPopup('ErrorPopup',{ + 'title': "ERROR", + 'body': "This is a returned order",}); + } + else{ + Gui.showPopup('ReturnWidget',{ref: order_id.pos_reference,client:client}); + + } + + } + + +} + OrderListScreenWidget.template = 'OrderListScreenWidget'; + + Registries.Component.add(OrderListScreenWidget); + + return OrderListScreenWidget; + +}); \ No newline at end of file diff --git a/product_return_pos/static/src/js/pos_return.js b/product_return_pos/static/src/js/pos_return.js new file mode 100644 index 000000000..38685c8db --- /dev/null +++ b/product_return_pos/static/src/js/pos_return.js @@ -0,0 +1,158 @@ +odoo.define('product_return_pos.pos_return',function(require) { + "use strict"; + + +var models = require('point_of_sale.models'); + + +var gui = require('point_of_sale.Gui'); +var core = require('web.core'); +var QWeb = core.qweb; +var rpc = require('web.rpc'); +var _t = require('web.core')._t; +var session = require('web.session'); + const ControlButtonsMixin = require('point_of_sale.ControlButtonsMixin'); + const NumberBuffer = require('point_of_sale.NumberBuffer'); + const { onChangeOrder, useBarcodeReader } = require('point_of_sale.custom_hooks'); + const { useState, useRef ,useSubEnv} = owl.hooks; + const PosComponent = require('point_of_sale.PosComponent'); + const Registries = require('point_of_sale.Registries'); + const ProductScreen = require('point_of_sale.ProductScreen'); + const { useListener } = require('web.custom_hooks'); + const OrderManagementScreen = require('point_of_sale.OrderManagementScreen'); + const AbstractAwaitablePopup = require('point_of_sale.AbstractAwaitablePopup'); + + + +class ReturnWidget extends AbstractAwaitablePopup { + constructor() { + super(...arguments); + this.state = useState({ inputValue: this.props.startingValue }); + this.inputRef = useRef('input'); + useSubEnv({ attribute_components: [] }); + + } + mounted() { + this.render_list() + } + + render_list(){ + $("#table-body").empty(); + var lines = []; + var pos_reference = this.props.ref + rpc.query({ + model: 'pos.order', + method: 'get_lines', + args: [pos_reference], + }).then(function (result) { + lines = result[0]; + 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 += "" + id + "" + price_unit +" " + name + "" + qty + "" + discount + "" + line_id + ""; + $(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); + + } + }).catch(function () { + alert("NO DATA") + }); + } + + + + click_confirm() { + + var self = this; + var myTable = document.getElementById('list').tBodies[0]; + var count = 0; + var c = 1; + + for (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{ + 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] + return_qty = document.getElementById("text"+c).value; + var product = this.env.pos.db.get_product_by_id(row.cells[0].innerHTML); + if (!product) { + return; + } + + if (return_qty > 0){ + this.env.pos.get_order().add_product(product, { + price: row.cells[1].innerHTML, + quantity: -(return_qty), + discount:row.cells[4].innerHTML, + merge: false, + extras: {return_ref: this.props.ref, + label:row.cells[5].innerHTML}, + }); + + } + c = c+1 + + } + + if (this.props.client){ + this.env.pos.get_order().set_client(this.env.pos.db.get_partner_by_id(this.props.client)); + } + + } + this.trigger('close-popup'); + this.showScreen('ProductScreen') + + } + + } + ReturnWidget.template = 'ReturnWidget'; + ReturnWidget.defaultProps = { + confirmText: 'Return', + cancelText: 'Cancel', + title: 'Confirm ?', + body: '', + }; + + Registries.Component.add(ReturnWidget); + + return ReturnWidget; + + + +}); \ No newline at end of file diff --git a/product_return_pos/static/src/js/return.js b/product_return_pos/static/src/js/return.js new file mode 100644 index 000000000..03e15480d --- /dev/null +++ b/product_return_pos/static/src/js/return.js @@ -0,0 +1,56 @@ +odoo.define('product_return_pos.return',function(require) { + "use strict"; + + +var models = require('point_of_sale.models'); +var gui = require('point_of_sale.Gui'); +var core = require('web.core'); +var QWeb = core.qweb; +var rpc = require('web.rpc'); +var _t = require('web.core')._t; +var session = require('web.session'); + const ControlButtonsMixin = require('point_of_sale.ControlButtonsMixin'); + const NumberBuffer = require('point_of_sale.NumberBuffer'); + const { onChangeOrder, useBarcodeReader } = require('point_of_sale.custom_hooks'); + const PosComponent = require('point_of_sale.PosComponent'); + const Registries = require('point_of_sale.Registries'); + const ProductScreen = require('point_of_sale.ProductScreen'); + const { useListener } = require('web.custom_hooks'); + const { useState, useRef } = owl.hooks; + const OrderManagementScreen = require('point_of_sale.OrderManagementScreen'); + const AbstractAwaitablePopup = require('point_of_sale.AbstractAwaitablePopup'); + + + +class ReturnButton extends PosComponent { + + constructor() { + super(...arguments); + useListener('click', this.button_click); + } + + button_click() { + var orders = this.env.pos.orders; + + this.showScreen('OrderListScreenWidget',{orders:orders}); + } + +} + + +ReturnButton.template = 'ReturnButton'; +ProductScreen.addControlButton({ + + component: ReturnButton, + condition: function () { + return true; + }, + position: ['before', 'SetPricelistButton'], + }); + + Registries.Component.add(ReturnButton); + return ReturnButton; + + + +}); \ No newline at end of file diff --git a/product_return_pos/static/src/xml/pos_return.xml b/product_return_pos/static/src/xml/pos_return.xml new file mode 100644 index 000000000..db2ef6651 --- /dev/null +++ b/product_return_pos/static/src/xml/pos_return.xml @@ -0,0 +1,107 @@ + + + + +
+ + Return +
+
+ + +
+ + + + + + + + Return + +
+
+ + +
+
+
+ + + Cancel + + + + + + + Refresh + + +
+
+
+
Date
+
Receipt Number
+
Customer
+
Return Ref
+
+ +
+
+ +
+
+ +
+
+ +
+
+ + + + + +
+
+
+
+
+
+
+ + + + +
\ No newline at end of file diff --git a/product_return_pos/views/pos_template.xml b/product_return_pos/views/pos_template.xml new file mode 100644 index 000000000..5869c1d9b --- /dev/null +++ b/product_return_pos/views/pos_template.xml @@ -0,0 +1,19 @@ + + + +