17 changed files with 559 additions and 0 deletions
			
			
		| @ -0,0 +1,39 @@ | |||||
|  | ======================== | ||||
|  | POS Product Multiple UOM | ||||
|  | ======================== | ||||
|  | 
 | ||||
|  | Added option to update the uom of products in pos. | ||||
|  | 
 | ||||
|  | Installation | ||||
|  | ============ | ||||
|  | 
 | ||||
|  | Just select it from available modules to install it, there is no need to extra installations. | ||||
|  | 
 | ||||
|  | Usage | ||||
|  | ===== | ||||
|  | 
 | ||||
|  | After installation, go to Inventory -> Settings | ||||
|  |  and enable the multiple uom option under the 'Products' section. | ||||
|  | 
 | ||||
|  | Known issues / Roadmap | ||||
|  | ====================== | ||||
|  | 
 | ||||
|  | * ... | ||||
|  | 
 | ||||
|  | Bug Tracker | ||||
|  | =========== | ||||
|  | 
 | ||||
|  | Contact odoo@cybrosys.com | ||||
|  | 
 | ||||
|  | Contributors | ||||
|  | ------------ | ||||
|  | 
 | ||||
|  | * Linto CT  <linto@cybrosys.in> | ||||
|  | * Shereef PT <shereef@cybrosys.in> | ||||
|  | 
 | ||||
|  | Maintainer | ||||
|  | ---------- | ||||
|  | 
 | ||||
|  | This module is maintained by Cybrosys Technologies. | ||||
|  | 
 | ||||
|  | For support and more information, please visit https://www.cybrosys.com. | ||||
| @ -0,0 +1,25 @@ | |||||
|  | # -*- coding: utf-8 -*- | ||||
|  | 
 | ||||
|  | ############################################################################## | ||||
|  | # | ||||
|  | #    Cybrosys Technologies Pvt. Ltd. | ||||
|  | #    Copyright (C) 2017-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). | ||||
|  | #    Author: LINTO C T(<https://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 <https://www.gnu.org/licenses/>. | ||||
|  | # | ||||
|  | ############################################################################## | ||||
|  | 
 | ||||
|  | import models | ||||
| @ -0,0 +1,45 @@ | |||||
|  | # -*- coding: utf-8 -*- | ||||
|  | 
 | ||||
|  | ############################################################################## | ||||
|  | # | ||||
|  | #    Cybrosys Technologies Pvt. Ltd. | ||||
|  | #    Copyright (C) 2018-TODAY Cybrosys Technologies(<https://www.cybrosys.com>). | ||||
|  | #    Author: LINTO C T(<https://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 <https://www.gnu.org/licenses/>. | ||||
|  | # | ||||
|  | ############################################################################## | ||||
|  | { | ||||
|  |     'name': 'POS Product Multiple UOM', | ||||
|  |     'version': '10.0.1.0.0', | ||||
|  |     'category': 'Point of Sale', | ||||
|  |     'summary': 'Multiple UOM for Products', | ||||
|  |     'author': 'Cybrosys Techno Solutions', | ||||
|  |     'company': 'Cybrosys Techno Solutions', | ||||
|  |     'maintainer': 'Cybrosys Techno Solutions', | ||||
|  |     'website': 'https://www.cybrosys.com', | ||||
|  |     'depends': ['point_of_sale', 'stock'], | ||||
|  |     'data': [ | ||||
|  |              'views/pos_template.xml', | ||||
|  |              'views/pos_view_extended.xml', | ||||
|  |             ], | ||||
|  |     'demo': [], | ||||
|  |     'qweb': ['static/src/xml/pos.xml'], | ||||
|  |     'images': ['static/description/banner.jpg'], | ||||
|  |     'license': 'LGPL-3', | ||||
|  |     'installable': True, | ||||
|  |     'application': False, | ||||
|  |     'auto_install': False, | ||||
|  | } | ||||
| @ -0,0 +1,3 @@ | |||||
|  | # -*- coding: utf-8 -*- | ||||
|  | 
 | ||||
|  | import pos_orderline | ||||
| @ -0,0 +1,112 @@ | |||||
|  | # -*- coding: utf-8 -*- | ||||
|  | 
 | ||||
|  | from odoo import _ | ||||
|  | from odoo.tools import float_is_zero | ||||
|  | from odoo import models, fields, api | ||||
|  | 
 | ||||
|  | 
 | ||||
|  | class PosOrderLinesExtended(models.Model): | ||||
|  |     _inherit = 'pos.order.line' | ||||
|  | 
 | ||||
|  |     uom_id = fields.Many2one('product.uom', string="UOM") | ||||
|  | 
 | ||||
|  |     @api.model | ||||
|  |     def create(self, values): | ||||
|  |         """updating uom to orderlines""" | ||||
|  |         try: | ||||
|  |             if values.get('uom_id'): | ||||
|  |                 values['uom_id'] = values['uom_id'][0] | ||||
|  |         except Exception: | ||||
|  |             values['uom_id'] = None | ||||
|  |             pass | ||||
|  |         res = super(PosOrderLinesExtended, self).create(values) | ||||
|  |         return res | ||||
|  | 
 | ||||
|  | 
 | ||||
|  | class PosOrderExtended(models.Model): | ||||
|  |     _inherit = 'pos.order' | ||||
|  | 
 | ||||
|  |     # overwriting this function because, we need to set the uom id based on the unit | ||||
|  |     # in the orderline instead of product uom, at the time of creating the stock moves | ||||
|  |     def create_picking(self): | ||||
|  |         """Create a picking for each order and validate it.""" | ||||
|  |         Picking = self.env['stock.picking'] | ||||
|  |         Move = self.env['stock.move'] | ||||
|  |         StockWarehouse = self.env['stock.warehouse'] | ||||
|  |         for order in self: | ||||
|  |             if not order.lines.filtered(lambda l: l.product_id.type in ['product', 'consu']): | ||||
|  |                 continue | ||||
|  |             address = order.partner_id.address_get(['delivery']) or {} | ||||
|  |             picking_type = order.picking_type_id | ||||
|  |             return_pick_type = order.picking_type_id.return_picking_type_id or order.picking_type_id | ||||
|  |             order_picking = Picking | ||||
|  |             return_picking = Picking | ||||
|  |             moves = Move | ||||
|  |             location_id = order.location_id.id | ||||
|  |             if order.partner_id: | ||||
|  |                 destination_id = order.partner_id.property_stock_customer.id | ||||
|  |             else: | ||||
|  |                 if (not picking_type) or (not picking_type.default_location_dest_id): | ||||
|  |                     customerloc, supplierloc = StockWarehouse._get_partner_locations() | ||||
|  |                     destination_id = customerloc.id | ||||
|  |                 else: | ||||
|  |                     destination_id = picking_type.default_location_dest_id.id | ||||
|  | 
 | ||||
|  |             if picking_type: | ||||
|  |                 message = _("This transfer has been created from the point of sale session: <a href=# data-oe-model=pos.order data-oe-id=%d>%s</a>") % (order.id, order.name) | ||||
|  |                 picking_vals = { | ||||
|  |                     'origin': order.name, | ||||
|  |                     'partner_id': address.get('delivery', False), | ||||
|  |                     'date_done': order.date_order, | ||||
|  |                     'picking_type_id': picking_type.id, | ||||
|  |                     'company_id': order.company_id.id, | ||||
|  |                     'move_type': 'direct', | ||||
|  |                     'note': order.note or "", | ||||
|  |                     'location_id': location_id, | ||||
|  |                     'location_dest_id': destination_id, | ||||
|  |                 } | ||||
|  |                 pos_qty = any([x.qty > 0 for x in order.lines if x.product_id.type in ['product', 'consu']]) | ||||
|  |                 if pos_qty: | ||||
|  |                     order_picking = Picking.create(picking_vals.copy()) | ||||
|  |                     order_picking.message_post(body=message) | ||||
|  |                 neg_qty = any([x.qty < 0 for x in order.lines if x.product_id.type in ['product', 'consu']]) | ||||
|  |                 if neg_qty: | ||||
|  |                     return_vals = picking_vals.copy() | ||||
|  |                     return_vals.update({ | ||||
|  |                         'location_id': destination_id, | ||||
|  |                         'location_dest_id': return_pick_type != picking_type and return_pick_type.default_location_dest_id.id or location_id, | ||||
|  |                         'picking_type_id': return_pick_type.id | ||||
|  |                     }) | ||||
|  |                     return_picking = Picking.create(return_vals) | ||||
|  |                     return_picking.message_post(body=message) | ||||
|  | 
 | ||||
|  |             for line in order.lines.filtered(lambda l: l.product_id.type in ['product', 'consu'] and not float_is_zero(l.qty, precision_rounding=l.product_id.uom_id.rounding)): | ||||
|  |                 moves |= Move.create({ | ||||
|  |                     'name': line.name, | ||||
|  |                     'product_uom': line.uom_id.id, | ||||
|  |                     'picking_id': order_picking.id if line.qty >= 0 else return_picking.id, | ||||
|  |                     'picking_type_id': picking_type.id if line.qty >= 0 else return_pick_type.id, | ||||
|  |                     'product_id': line.product_id.id, | ||||
|  |                     'product_uom_qty': abs(line.qty), | ||||
|  |                     'state': 'draft', | ||||
|  |                     'location_id': location_id if line.qty >= 0 else destination_id, | ||||
|  |                     'location_dest_id': destination_id if line.qty >= 0 else return_pick_type != picking_type and return_pick_type.default_location_dest_id.id or location_id, | ||||
|  |                 }) | ||||
|  |             # prefer associating the regular order picking, not the return | ||||
|  |             order.write({'picking_id': order_picking.id or return_picking.id}) | ||||
|  | 
 | ||||
|  |             if return_picking: | ||||
|  |                 order._force_picking_done(return_picking) | ||||
|  |             if order_picking: | ||||
|  |                 order._force_picking_done(order_picking) | ||||
|  | 
 | ||||
|  |             # when the pos.config has no picking_type_id set only the moves will be created | ||||
|  |             if moves and not return_picking and not order_picking: | ||||
|  |                 tracked_moves = moves.filtered(lambda move: move.product_id.tracking != 'none') | ||||
|  |                 untracked_moves = moves - tracked_moves | ||||
|  |                 tracked_moves.action_confirm() | ||||
|  |                 untracked_moves.action_assign() | ||||
|  |                 moves.filtered(lambda m: m.state in ['confirmed', 'waiting']).force_assign() | ||||
|  |                 moves.filtered(lambda m: m.product_id.tracking == 'none').action_done() | ||||
|  | 
 | ||||
|  |         return True | ||||
| After Width: | Height: | Size: 124 KiB | 
| After Width: | Height: | Size: 50 KiB | 
| @ -0,0 +1,92 @@ | |||||
|  | <section class="oe_container"> | ||||
|  |     <div class="oe_row oe_spaced"> | ||||
|  |         <h2 class="oe_slogan">POS Product Multiple UOM</h2> | ||||
|  |         <h3 class="oe_slogan"></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;"> | ||||
|  | 	<h3><p style="margin-left: 42px;"><b>Features:</b></p></h3> | ||||
|  |         <div> | ||||
|  |             <span style="color:green;"> ☑ </span> Multiple UOM for products in POS.<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;"> | ||||
|  |                By default, Odoo does not provide the option to update the unit of measure | ||||
|  |                     of the products we select in the point of sale. We can sell products only in its | ||||
|  |                     default unit. This module provides an option to update the UOM of the products | ||||
|  |                 in point of sale. The stock will also be updated in the new UOM. | ||||
|  |             </p> | ||||
|  |         </div> | ||||
|  |     </div> | ||||
|  | </section> | ||||
|  | 
 | ||||
|  | <section class="oe_container"> | ||||
|  |     <div class="oe_row oe_spaced"> | ||||
|  |         <h5 class="oe_slogan"><b>New button added for opening the wizard.</b></h5> | ||||
|  |         <div style="text-align:center;"> | ||||
|  |             <div class="oe_demo oe_picture  oe_screenshot"> | ||||
|  |                 <img src="modify_uom_button.png"> | ||||
|  |             </div> | ||||
|  |         </div> | ||||
|  |         <br /> | ||||
|  |         <div class="oe_row oe_spaced"> | ||||
|  |              <h5 class="oe_slogan"><b>This button will open a wizard which will show all the UOMs | ||||
|  |                  associated with the selected product. | ||||
|  |              </b></h5> | ||||
|  |          </div> | ||||
|  |         <div class="col-md-12"> | ||||
|  |             <div class="oe_row_img oe_demo oe_picture oe_screenshot"> | ||||
|  |                 <img src="multi_uom_wiz.png"> | ||||
|  |             </div> | ||||
|  |         </div> | ||||
|  |         <div class="oe_row oe_spaced"> | ||||
|  |              <p class="oe_slogan"> | ||||
|  |                 We can select the UOMs available for this product and update it. | ||||
|  |              </p> | ||||
|  |         </div> | ||||
|  | 
 | ||||
|  |     </div> | ||||
|  | </section> | ||||
|  | 
 | ||||
|  | <section class="oe_container oe_dark"> | ||||
|  |    	<div class="col-md-12"> | ||||
|  | 	    <div class=" oe_demo oe_picture  oe_screenshot"> | ||||
|  |              <img src="orderlines.png" /> | ||||
|  |              <div class="oe_demo_footer oe_centeralign" style="background-color:rgba(162, 70, 137, 0.7);"> | ||||
|  |                 Updated orderline | ||||
|  |              </div> | ||||
|  | 	    </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: 136 KiB | 
| After Width: | Height: | Size: 108 KiB | 
| After Width: | Height: | Size: 130 KiB | 
| @ -0,0 +1,22 @@ | |||||
|  | .button-multi-uom{ | ||||
|  |     width: 100%; | ||||
|  |     height: 32px; | ||||
|  |     font-size: 16px; | ||||
|  |     text-align: center; | ||||
|  |     border-radius: 5px; | ||||
|  | } | ||||
|  | .multi-uom-span { | ||||
|  |     width: 50%; | ||||
|  |     border: 1px solid; | ||||
|  |     /* vertical-align: middle; */ | ||||
|  |     align-self: center; | ||||
|  |     padding: 5px 10px; | ||||
|  |     background-color: #6EC89B; | ||||
|  |     color: #fff; | ||||
|  |     LINE-HEIGHT: 2.5; | ||||
|  |     transition: all 150ms linear; | ||||
|  | } | ||||
|  | 
 | ||||
|  | .popup-product-creation{ | ||||
|  |     height: 50% !important; | ||||
|  | } | ||||
| After Width: | Height: | Size: 36 KiB | 
| @ -0,0 +1,152 @@ | |||||
|  | odoo.define('product_multi_uom_pos.multi_uom',function(require) { | ||||
|  | "use strict"; | ||||
|  | 
 | ||||
|  | var gui = require('point_of_sale.gui'); | ||||
|  | var PosBaseWidget = require('point_of_sale.BaseWidget'); | ||||
|  | var core = require('web.core'); | ||||
|  | var models = require('point_of_sale.models'); | ||||
|  | var OrderlineSuper = models.Orderline; | ||||
|  | var pos_screens = require('point_of_sale.screens'); | ||||
|  | 
 | ||||
|  | var MultiUomWidget = PosBaseWidget.extend({ | ||||
|  |     template: 'MultiUomWidget', | ||||
|  |     init: function(parent, args) { | ||||
|  |         this._super(parent, args); | ||||
|  |         this.options = {}; | ||||
|  |         this.uom_list = []; | ||||
|  |     }, | ||||
|  |     events: { | ||||
|  |         'click .button.cancel':  'click_cancel', | ||||
|  |         'click .button.confirm': 'click_confirm', | ||||
|  |     }, | ||||
|  |     /*function returns all the uom s in the specified category*/ | ||||
|  |     get_units_by_category: function(uom_list, categ_id){ | ||||
|  |         var uom_by_categ = [] | ||||
|  |         for (var uom in uom_list){ | ||||
|  |             if(uom_list[uom].category_id[0] == categ_id[0]){ | ||||
|  |                 uom_by_categ.push(uom_list[uom]); | ||||
|  |             } | ||||
|  |         } | ||||
|  |         return uom_by_categ; | ||||
|  |     }, | ||||
|  |     /*Find the base price(price of the product for reference unit)*/ | ||||
|  |     find_reference_unit_price: function(product, product_uom){ | ||||
|  |         if(product_uom.uom_type == 'reference'){ | ||||
|  |             return product.price; | ||||
|  |         } | ||||
|  |         else if(product_uom.uom_type == 'smaller'){ | ||||
|  |            return (product.price * product_uom.factor); | ||||
|  |         } | ||||
|  |         else if(product_uom.uom_type == 'bigger'){ | ||||
|  |            return (product.price / product_uom.factor_inv); | ||||
|  |         } | ||||
|  |     }, | ||||
|  |     /*finds the latest price for the product based on the new uom selected*/ | ||||
|  |     get_latest_price: function(uom, product){ | ||||
|  |         var uom_by_category = this.get_units_by_category(this.pos.units_by_id, uom.category_id); | ||||
|  |         var product_uom = this.pos.units_by_id[product.uom_id[0]]; | ||||
|  |         var ref_price = this.find_reference_unit_price(product, product_uom); | ||||
|  |         var ref_unit = null; | ||||
|  |         for (var i in uom_by_category){ | ||||
|  |             if(uom_by_category[i].uom_type == 'reference'){ | ||||
|  |                 ref_unit = uom_by_category[i]; | ||||
|  |                 break; | ||||
|  |             } | ||||
|  |         } | ||||
|  |         if(ref_unit){ | ||||
|  |             if(uom.uom_type == 'bigger'){ | ||||
|  |                 return (ref_price * uom.factor_inv); | ||||
|  |             } | ||||
|  |             else if(uom.uom_type == 'smaller'){ | ||||
|  |                 return (ref_price / uom.factor); | ||||
|  |             } | ||||
|  |             else if(uom.uom_type == 'reference'){ | ||||
|  |                 return ref_price; | ||||
|  |             } | ||||
|  |         } | ||||
|  |         return product.price; | ||||
|  |     }, | ||||
|  |     /*Rendering the wizard*/ | ||||
|  |     show: function(options){ | ||||
|  |         options = options || {}; | ||||
|  |         var current_uom = this.pos.units_by_id[options.uom_list[0]]; | ||||
|  |         var uom_list = this.pos.units_by_id; | ||||
|  |         var uom_by_category = this.get_units_by_category(uom_list, current_uom.category_id); | ||||
|  |         this.uom_list = uom_by_category; | ||||
|  |         this.current_uom = options.uom_list[0]; | ||||
|  |         this.renderElement(); | ||||
|  |     }, | ||||
|  |     close: function(){ | ||||
|  |         if (this.pos.barcode_reader) { | ||||
|  |             this.pos.barcode_reader.restore_callbacks(); | ||||
|  |         } | ||||
|  |     }, | ||||
|  |     click_confirm: function(){ | ||||
|  |         var self = this; | ||||
|  |         var uom = parseInt(this.$('.uom').val()); | ||||
|  |         var order = self.pos.get_order(); | ||||
|  |         var orderline = order.get_selected_orderline(); | ||||
|  |         var selected_uom = this.pos.units_by_id[uom]; | ||||
|  |         orderline.uom_id = []; | ||||
|  |         orderline.uom_id[0] = uom; | ||||
|  |         orderline.uom_id[1] = selected_uom.display_name; | ||||
|  | 
 | ||||
|  |         /*Updating the orderlines*/ | ||||
|  |         order.remove_orderline(orderline); | ||||
|  |         order.add_orderline(orderline); | ||||
|  |         var latest_price = this.get_latest_price(selected_uom, orderline.product); | ||||
|  |         order.get_selected_orderline().set_unit_price(latest_price); | ||||
|  |         this.gui.close_popup(); | ||||
|  |         return; | ||||
|  | 
 | ||||
|  |     }, | ||||
|  |     click_cancel: function(){ | ||||
|  |         this.gui.close_popup(); | ||||
|  |     }, | ||||
|  | }); | ||||
|  | gui.define_popup({name:'multi_uom_screen', widget: MultiUomWidget}); | ||||
|  | 
 | ||||
|  | models.Orderline = models.Orderline.extend({ | ||||
|  |     /*Adding uom_id to orderline*/ | ||||
|  |     initialize: function(attr,options){ | ||||
|  |         OrderlineSuper.prototype.initialize.call(this, attr, options); | ||||
|  |         this.uom_id = this ? this.product.uom_id: []; | ||||
|  |     }, | ||||
|  |     export_as_JSON: function() { | ||||
|  |         var result = OrderlineSuper.prototype.export_as_JSON.call(this); | ||||
|  |         result.uom_id = this.uom_id; | ||||
|  |         return result; | ||||
|  |     }, | ||||
|  |     /*this function now will return the uom_id of the orderline , | ||||
|  |     instead of the default uom_id of the product*/ | ||||
|  |     get_unit: function(){ | ||||
|  |         var res = OrderlineSuper.prototype.get_unit.call(this); | ||||
|  | 
 | ||||
|  |         var unit_id = this.uom_id; | ||||
|  |         if(!unit_id){ | ||||
|  |             return res; | ||||
|  |         } | ||||
|  |         unit_id = unit_id[0]; | ||||
|  |         if(!this.pos){ | ||||
|  |             return undefined; | ||||
|  |         } | ||||
|  |         return this.pos.units_by_id[unit_id]; | ||||
|  |     } | ||||
|  | }); | ||||
|  | 
 | ||||
|  | pos_screens.ActionpadWidget.include({ | ||||
|  |     /*opening the wizard on button click*/ | ||||
|  |     renderElement: function() { | ||||
|  |         this._super(); | ||||
|  |         var self = this; | ||||
|  |         this.$('.multi-uom-span').click(function(){ | ||||
|  |             var orderline = self.pos.get_order().get_selected_orderline(); | ||||
|  |             var options = { | ||||
|  |                 'uom_list': orderline.product.uom_id | ||||
|  |             }; | ||||
|  |             self.gui.show_popup('multi_uom_screen', options); | ||||
|  |         }); | ||||
|  |     } | ||||
|  | }); | ||||
|  | 
 | ||||
|  | }); | ||||
| @ -0,0 +1,39 @@ | |||||
|  | <?xml version="1.0" encoding="UTF-8"?> | ||||
|  | <templates id="template" xml:space="preserve"> | ||||
|  |     <t t-extend="ActionpadWidget"> | ||||
|  |         <t t-jquery="div.actionpad" t-operation="before"> | ||||
|  |             <div class="button-multi-uom"> | ||||
|  |                 <span class="multi-uom-span"> | ||||
|  |                     Modify Unit of Measure | ||||
|  |                 </span> | ||||
|  |             </div> | ||||
|  |         </t> | ||||
|  |     </t> | ||||
|  | 
 | ||||
|  |     <t t-name="MultiUomWidget"> | ||||
|  |         <div class="modal-dialog multi-uom"> | ||||
|  |             <div class="popup popup-product-creation"> | ||||
|  |                 <p class="title">Select Unit of Measure</p> | ||||
|  |                 <div> | ||||
|  |                     <select class="uom" style="width:35%;height:30px;border-radius:5px;"> | ||||
|  |                         <t t-foreach='widget.uom_list' t-as='uom'> | ||||
|  |                             <option t-att-value='uom.id' | ||||
|  |                                     t-att-selected="((uom.id == widget.current_uom) ? true:undefined)" > | ||||
|  |                             <t t-esc='uom.display_name'/> | ||||
|  |                             </option> | ||||
|  |                         </t> | ||||
|  |                     </select> | ||||
|  |                 </div> | ||||
|  |                 <div class="footer"> | ||||
|  |                     <div class="button confirm"> | ||||
|  |                         Ok | ||||
|  |                     </div> | ||||
|  |                     <div class="button cancel"> | ||||
|  |                         Cancel | ||||
|  |                     </div> | ||||
|  |                 </div> | ||||
|  |             </div> | ||||
|  |         </div> | ||||
|  |     </t> | ||||
|  | 
 | ||||
|  | </templates> | ||||
| @ -0,0 +1,14 @@ | |||||
|  | <?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="/product_multi_uom_pos/static/src/js/multi_uom.js"></script> | ||||
|  |             </xpath> | ||||
|  |             <xpath expr="//link[@id='pos-stylesheet']" position="after"> | ||||
|  |               <link rel="stylesheet" href="/product_multi_uom_pos/static/src/css/style.css"/> | ||||
|  |             </xpath> | ||||
|  |         </template> | ||||
|  | 
 | ||||
|  |     </data> | ||||
|  | </odoo> | ||||
| @ -0,0 +1,16 @@ | |||||
|  | <?xml version="1.0" encoding="UTF-8" ?> | ||||
|  | <odoo> | ||||
|  |     <data> | ||||
|  |         <!--Adding uom id to lines--> | ||||
|  |         <record id="pos_order_line_uom" model="ir.ui.view"> | ||||
|  |             <field name="name">UOM for Order-line</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='lines']/tree/field[@name='qty']" position="after"> | ||||
|  |                     <field name="uom_id"/> | ||||
|  |                 </xpath> | ||||
|  |             </field> | ||||
|  |         </record> | ||||
|  |     </data> | ||||
|  | </odoo> | ||||
					Loading…
					
					
				
		Reference in new issue