Skip to Content
Odoo Meniu
  • Autentificare
  • Try it free
  • Aplicații
    Finanțe
    • Contabilitate
    • Facturare
    • Cheltuieli
    • Spreadsheet (BI)
    • Documente
    • Semn
    Vânzări
    • CRM
    • Vânzări
    • POS Shop
    • POS Restaurant
    • Abonamente
    • Închiriere
    Site-uri web
    • Constructor de site-uri
    • eCommerce
    • Blog
    • Forum
    • Live Chat
    • eLearning
    Lanț Aprovizionare
    • Inventar
    • Producție
    • PLM
    • Achiziție
    • Maintenance
    • Calitate
    Resurse Umane
    • Angajați
    • Recrutare
    • Time Off
    • Evaluări
    • Referințe
    • Flotă
    Marketing
    • Social Marketing
    • Marketing prin email
    • SMS Marketing
    • Evenimente
    • Automatizare marketing
    • Sondaje
    Servicii
    • Proiect
    • Foi de pontaj
    • Servicii de teren
    • Centru de asistență
    • Planificare
    • Programări
    Productivitate
    • Discuss
    • Aprobări
    • IoT
    • VoIP
    • Knowledge
    • WhatsApp
    Aplicații Terțe Odoo Studio Platforma Odoo Cloud
  • Industrii
    Retail
    • Book Store
    • Magazin de îmbrăcăminte
    • Magazin de Mobilă
    • Magazin alimentar
    • Magazin de materiale de construcții
    • Magazin de jucării
    Food & Hospitality
    • Bar and Pub
    • Restaurant
    • Fast Food
    • Guest House
    • Distribuitor de băuturi
    • Hotel
    Proprietate imobiliara
    • Real Estate Agency
    • Firmă de Arhitectură
    • Construcție
    • Estate Managament
    • Grădinărit
    • Asociația Proprietarilor de Proprietăți
    Consultanta
    • Firma de Contabilitate
    • Partener Odoo
    • Agenție de marketing
    • Law firm
    • Atragere de talente
    • Audit & Certification
    Producție
    • Textil
    • Metal
    • Mobilier
    • Mâncare
    • Brewery
    • Cadouri corporate
    Health & Fitness
    • Club Sportiv
    • Magazin de ochelari
    • Centru de Fitness
    • Wellness Practitioners
    • Farmacie
    • Salon de coafură
    Trades
    • Handyman
    • IT Hardware and Support
    • Asigurare socială de stat
    • Cizmar
    • Servicii de curățenie
    • HVAC Services
    Altele
    • Organizație nonprofit
    • Agenție de Mediu
    • Închiriere panouri publicitare
    • Fotografie
    • Închiriere biciclete
    • Asigurare socială
    Browse all Industries
  • Comunitate
    Învăță
    • Tutorials
    • Documentație
    • Certificări
    • Instruire
    • Blog
    • Podcast
    Empower Education
    • Program Educațional
    • Scale Up! Business Game
    • Visit Odoo
    Obține Software-ul
    • Descărcare
    • Compară Edițiile
    • Lansări
    Colaborați
    • Github
    • Forum
    • Evenimente
    • Translations
    • Devino Partener
    • Services for Partners
    • Înregistrează-ți Firma de Contabilitate
    Obține Servicii
    • Găsește un Partener
    • Găsiți un contabil
    • Meet an advisor
    • Servicii de Implementare
    • Referințe ale clienților
    • Suport
    • Actualizări
    Github Youtube Twitter Linkedin Instagram Facebook Spotify
    +1 (650) 691-3277
    Obține un demo
  • Prețuri
  • Ajutor

Odoo is the world's easiest all-in-one management software.
It includes hundreds of business apps:

  • CRM
  • e-Commerce
  • Contabilitate
  • Inventar
  • PoS
  • Proiect
  • MRP
All apps
Trebuie să fiți înregistrat pentru a interacționa cu comunitatea.
All Posts Oameni Insigne
Etichete (View all)
odoo accounting v14 pos v15
Despre acest forum
Trebuie să fiți înregistrat pentru a interacționa cu comunitatea.
All Posts Oameni Insigne
Etichete (View all)
odoo accounting v14 pos v15
Despre acest forum
Suport

inheritance of PosModel in POS models.js file

Abonare

Primiți o notificare când există activitate la acestă postare

Această întrebare a fost marcată
posinheritancejs
5 Răspunsuri
34003 Vizualizări
Imagine profil
Harold

I made a template to facilitate POS inheritance, easy to use with the command scaffold. You can find it here https://github.com/haroldtamo/Odoo-Pos-Inheritance-Template

Sorry, I don't have enough karma to post it as answer, so i posted it here. The original question begin here :

Hi,

I want to override the PosModel in model.js (begin on line 17) by adding a new field in the fetch of products (product.product class) like this :

return self.fetch(
                        'product.product', 
                        ['name', 'field_to_add','list_price','price','pos_categ_id', 'taxes_id', 'ean13', 'default_code',
                         'to_weight', 'uom_id', 'uos_id', 'uos_coeff', 'mes_type', 'description_sale', 'description'],
                        [['sale_ok','=',true],['available_in_pos','=',true]],
                        {pricelist: self.get('shop').pricelist_id[0]} // context for price
                    );

Unfortunately, i think i use a wrong method for inheritance : in fact, i copy all the class PosModel and i add my field in a new addons so, when the POS session is loaded, products are loaded twice : first when odoo call the original class and second when it call mine. The consequence is that the loading of the pos session is very slow. So i want to know the right method to override or inherit that class (PosModel)

Here is my code for inheritance (sorry i don't see the [CODE] tag ) (look the part in bold) :

function openerp_pos_price_control_models(instance, module){ var module = instance.point_of_sale; var QWeb = instance.web.qweb; _t = instance.web._t; var round_di = instance.web.round_decimals; var round_pr = instance.web.round_precision; module.PosModel = Backbone.Model.extend({ initialize: function(session, attributes) { Backbone.Model.prototype.initialize.call(this, attributes); var self = this; this.session = session; this.ready = $.Deferred(); // used to notify the GUI that the PosModel has loaded all resources this.flush_mutex = new $.Mutex(); // used to make sure the orders are sent to the server once at time this.barcode_reader = new module.BarcodeReader({'pos': this}); // used to read barcodes this.proxy = new module.ProxyDevice(); // used to communicate to the hardware devices via a local proxy this.db = new module.PosLS(); // a database used to store the products and categories this.db.clear('products','categories'); this.debug = jQuery.deparam(jQuery.param.querystring()).debug !== undefined; //debug mode // default attributes values. If null, it will be loaded below. this.set({ 'nbr_pending_operations': 0, 'currency': {symbol: '$', position: 'after'}, 'shop': null, 'company': null, 'user': null, // the user that loaded the pos 'user_list': null, // list of all users 'partner_list': null, // list of all partners with an ean 'cashier': null, // the logged cashier, if different from user 'orders': new module.OrderCollection(), //this is the product list as seen by the product list widgets, it will change based on the category filters 'products': new module.ProductCollection(), 'cashRegisters': null, 'bank_statements': null, 'taxes': null, 'pos_session': null, 'pos_config': null, 'units': null, 'units_by_id': null, 'pricelist': null, 'selectedOrder': null, }); this.get('orders').bind('remove', function(){ self.on_removed_order(); }); // We fetch the backend data on the server asynchronously. this is done only when the pos user interface is launched, // Any change on this data made on the server is thus not reflected on the point of sale until it is relaunched. // when all the data has loaded, we compute some stuff, and declare the Pos ready to be used. $.when(this.load_server_data()) .done(function(){ //self.log_loaded_data(); //Uncomment if you want to log the data to the console for easier debugging self.ready.resolve(); }).fail(function(){ //we failed to load some backend data, or the backend was badly configured. //the error messages will be displayed in PosWidget self.ready.reject(); }); }, // helper function to load data from the server fetch: function(model, fields, domain, ctx){ return new instance.web.Model(model).query(fields).filter(domain).context(ctx).all() }, // loads all the needed data on the sever. returns a deferred indicating when all the data has loaded. load_server_data: function(){ var self = this; var loaded = self.fetch('res.users',['name','company_id'],[['id','=',this.session.uid]]) .then(function(users){ self.set('user',users[0]); return self.fetch('res.company', [ 'currency_id', 'email', 'website', 'company_registry', 'vat', 'name', 'phone', 'partner_id', ], [['id','=',users[0].company_id[0]]]); }).then(function(companies){ self.set('company',companies[0]); return self.fetch('res.partner',['contact_address'],[['id','=',companies[0].partner_id[0]]]); }).then(function(company_partners){ self.get('company').contact_address = company_partners[0].contact_address; return self.fetch('product.uom', null, null); }).then(function(units){ self.set('units',units); var units_by_id = {}; for(var i = 0, len = units.length; i < len; i++){ units_by_id[units[i].id] = units[i]; } self.set('units_by_id',units_by_id); return self.fetch('product.packaging', null, null); }).then(function(packagings){ self.set('product.packaging',packagings); return self.fetch('res.users', ['name','ean13'], [['ean13', '!=', false]]); }).then(function(users){ self.set('user_list',users); return self.fetch('res.partner', ['name','ean13'], [['ean13', '!=', false]]); }).then(function(partners){ self.set('partner_list',partners); return self.fetch('account.tax', ['amount', 'price_include', 'type']); }).then(function(taxes){ self.set('taxes', taxes); return self.fetch( 'pos.session', ['id', 'journal_ids','name','user_id','config_id','start_at','stop_at'], [['state', '=', 'opened'], ['user_id', '=', self.session.uid]] ); }).then(function(sessions){ self.set('pos_session', sessions[0]); return self.fetch( 'pos.config', ['name','journal_ids','shop_id','journal_id', 'iface_self_checkout', 'iface_led', 'iface_cashdrawer', 'iface_payment_terminal', 'iface_electronic_scale', 'iface_barscan', 'iface_vkeyboard', 'iface_print_via_proxy','iface_cashdrawer','state','sequence_id','session_ids'], [['id','=', self.get('pos_session').config_id[0]]] ); }).then(function(configs){ var pos_config = configs[0]; self.set('pos_config', pos_config); self.iface_electronic_scale = !!pos_config.iface_electronic_scale; self.iface_print_via_proxy = !!pos_config.iface_print_via_proxy; self.iface_vkeyboard = !!pos_config.iface_vkeyboard; self.iface_self_checkout = !!pos_config.iface_self_checkout; self.iface_cashdrawer = !!pos_config.iface_cashdrawer; return self.fetch('sale.shop',[],[['id','=',pos_config.shop_id[0]]]); }).then(function(shops){ self.set('shop',shops[0]); return self.fetch('product.pricelist',['currency_id'],[['id','=',self.get('shop').pricelist_id[0]]]); }).then(function(pricelists){ self.set('pricelist',pricelists[0]); return self.fetch('res.currency',['symbol','position','rounding','accuracy'],[['id','=',self.get('pricelist').currency_id[0]]]); }).then(function(currencies){ self.set('currency',currencies[0]); return self.fetch('product.packaging',['ean','product_id']); }).then(function(packagings){ self.db.add_packagings(packagings); return self.fetch('pos.category', ['id','name','parent_id','child_id','image']) }).then(function(categories){ self.db.add_categories(categories); return self.fetch( 'product.product', ['name', 'min_sale_price', 'list_price','price','pos_categ_id', 'taxes_id', 'ean13', 'default_code', 'to_weight', 'uom_id', 'uos_id', 'uos_coeff', 'mes_type', 'description_sale', 'description'], [['sale_ok','=',true],['available_in_pos','=',true]], {pricelist: self.get('shop').pricelist_id[0]} // context for price ); }).then(function(products){ self.db.add_products(products); return self.fetch( 'account.bank.statement', ['account_id','currency','journal_id','state','name','user_id','pos_session_id'], [['state','=','open'],['pos_session_id', '=', self.get('pos_session').id]] ); }).then(function(bank_statements){ var journals = new Array(); _.each(bank_statements,function(statement) { journals.push(statement.journal_id[0]) }); self.set('bank_statements', bank_statements); return self.fetch('account.journal', undefined, [['id','in', journals]]); }).then(function(journals){ self.set('journals',journals); // associate the bank statements with their journals. var bank_statements = self.get('bank_statements'); for(var i = 0, ilen = bank_statements.length; i < ilen; i++){ for(var j = 0, jlen = journals.length; j < jlen; j++){ if(bank_statements[i].journal_id[0] === journals[j].id){ bank_statements[i].journal = journals[j]; bank_statements[i].self_checkout_payment_method = journals[j].self_checkout_payment_method; } } } self.set({'cashRegisters' : new module.CashRegisterCollection(self.get('bank_statements'))}); }); return loaded; }, // logs the usefull posmodel data to the console for debug purposes log_loaded_data: function(){ console.log('PosModel data has been loaded:'); console.log('PosModel: units:',this.get('units')); console.log('PosModel: bank_statements:',this.get('bank_statements')); console.log('PosModel: journals:',this.get('journals')); console.log('PosModel: taxes:',this.get('taxes')); console.log('PosModel: pos_session:',this.get('pos_session')); console.log('PosModel: pos_config:',this.get('pos_config')); console.log('PosModel: cashRegisters:',this.get('cashRegisters')); console.log('PosModel: shop:',this.get('shop')); console.log('PosModel: company:',this.get('company')); console.log('PosModel: currency:',this.get('currency')); console.log('PosModel: user_list:',this.get('user_list')); console.log('PosModel: user:',this.get('user')); console.log('PosModel.session:',this.session); console.log('PosModel end of data log.'); }, // this is called when an order is removed from the order collection. It ensures that there is always an existing // order and a valid selected order on_removed_order: function(removed_order){ if( this.get('orders').isEmpty()){ this.add_new_order(); }else{ this.set({ selectedOrder: this.get('orders').last() }); } }, // saves the order locally and try to send it to the backend. 'record' is a bizzarely defined JSON version of the Order push_order: function(record) { this.db.add_order(record); this.flush(); }, //creates a new empty order and sets it as the current order add_new_order: function(){ var order = new module.Order({pos:this}); this.get('orders').add(order); this.set('selectedOrder', order); }, // attemps to send all pending orders ( stored in the pos_db ) to the server, // and remove the successfully sent ones from the db once // it has been confirmed that they have been sent correctly. flush: function() { //TODO make the mutex work //this makes sure only one _int_flush is called at the same time /* return this.flush_mutex.exec(_.bind(function() { return this._flush(0); }, this)); */ this._flush(0); }, // attempts to send an order of index 'index' in the list of order to send. The index // is used to skip orders that failed. do not call this method outside the mutex provided // by flush() _flush: function(index){ var self = this; var orders = this.db.get_orders(); self.set('nbr_pending_operations',orders.length); var order = orders[index]; if(!order){ return; } //try to push an order to the server // shadow : true is to prevent a spinner to appear in case of timeout (new instance.web.Model('pos.order')).call('create_from_ui',[[order]],undefined,{ shadow:true }) .fail(function(unused, event){ //don't show error popup if it fails event.preventDefault(); console.error('Failed to send order:',order); self._flush(index+1); }) .done(function(){ //remove from db if success self.db.remove_order(order.id); self._flush(index); }); }, scan_product: function(parsed_ean){ var self = this; var product = this.db.get_product_by_ean13(parsed_ean.base_ean); var selectedOrder = this.get('selectedOrder'); if(!product){ return false; } if(parsed_ean.type === 'price'){ selectedOrder.addProduct(new module.Product(product), {price:parsed_ean.value}); }else if(parsed_ean.type === 'weight'){ selectedOrder.addProduct(new module.Product(product), {quantity:parsed_ean.value, merge:false}); }else{ selectedOrder.addProduct(new module.Product(product)); } return true; }, }); }

thanks!

2
Imagine profil
Abandonează
Imagine profil
Lithin T
Cel mai bun răspuns

Here is the easy way to inherit PosModel to load new fields quick and fast

function pos_product_avialble(instance,module){ //where module=instance.point_of_sale
var models = module.PosModel.prototype.models;
for(var i=0; i<models.length; i++){
var model=models[i];
if(model.model === 'product.product'){
model.fields.push('new_field1','new_field2');
}
}
}

5
Imagine profil
Abandonează
Imagine profil
Ivan Elizaryev
Cel mai bun răspuns

I think, right way is extend load_server_data function and then update product list by adding new fields:

function pos_product_available(instance, module){

    var PosModelSuper = module.PosModel
    module.PosModel = module.PosModel.extend({
        load_server_data: function(){
            var self = this;
            var loaded = PosModelSuper.prototype.load_server_data.call(this);

            loaded = loaded.then(function(){
                return self.fetch(
                    'product.product',
                    ['qty_available'], //new field
                    [['sale_ok','=',true],['available_in_pos','=',true]],
                    {}
                );

            }).then(function(products){
                $.each(products, function(){
                    $.extend(self.db.get_product_by_id(this.id) || {}, this)
                });
                return $.when()
            })
            return loaded;
        },
    })
}

(function(){
    var _super = window.openerp.point_of_sale;
    window.openerp.point_of_sale = function(instance){
        _super(instance);
        var module = instance.point_of_sale;

        pos_product_available(instance, module);

    }
})()

 

From here: https://github.com/yelizariev/pos-addons/blob/8.0/pos_product_available/static/src/js/pos.js

3
Imagine profil
Abandonează
Harold
Autor

Thanks for your answer

Nirav Jani

Is it working properly ?

Imagine profil
EasyPME
Cel mai bun răspuns

Lithin T 's answer works

In Odoo v9 it is : 

odoo.define('pos_product_available', function (require) {

"use strict";

var module = require('point_of_sale.models');

var models = module.PosModel.prototype.models;

for(var i=0; i<models.length; i++){

var model=models[i];

if(model.model === 'product.product'){

model.fields.push('new_field1','new_field2');

}

}

});

0
Imagine profil
Abandonează
Peter Alabaster

This works in Odoo 10 too. Thanks

Enjoying the discussion? Don't just read, join in!

Create an account today to enjoy exclusive features and engage with our awesome community!

Înscrie-te
Related Posts Răspunsuri Vizualizări Activitate
Issue Migrating bus_service Notification Handling from Odoo 17 to Odoo 18 (OWL-based POS)
pos js
Imagine profil
0
apr. 25
2729
How i can modify JS method in POS? Rezolvat
pos js
Imagine profil
1
sept. 23
8319
How to override js function in POS Orderline object? Rezolvat
pos js
Imagine profil
Imagine profil
2
feb. 18
11552
inherit js file odoo 9
inheritance js
Imagine profil
Imagine profil
2
iul. 17
5293
pos error js instance.web.cordova
pos js
Imagine profil
0
iun. 17
4657
Comunitate
  • Tutorials
  • Documentație
  • Forum
Open Source
  • Descărcare
  • Github
  • Runbot
  • Translations
Servicii
  • Hosting Odoo.sh
  • Suport
  • Actualizare
  • Custom Developments
  • Educație
  • Găsiți un contabil
  • Găsește un Partener
  • Devino Partener
Despre Noi
  • Compania noastră
  • Active de marcă
  • Contactați-ne
  • Locuri de muncă
  • Evenimente
  • Podcast
  • Blog
  • Clienți
  • Aspecte juridice • Confidențialitate
  • Securitate
الْعَرَبيّة Català 简体中文 繁體中文 (台灣) Čeština Dansk Nederlands English Suomi Français Deutsch हिंदी Bahasa Indonesia Italiano 日本語 한국어 (KR) Lietuvių kalba Język polski Português (BR) română русский язык Slovenský jazyk slovenščina Español (América Latina) Español ภาษาไทย Türkçe українська Tiếng Việt

Odoo este o suită de aplicații de afaceri open source care acoperă toate nevoile companiei dvs.: CRM, comerț electronic, contabilitate, inventar, punct de vânzare, management de proiect etc.

Propunerea de valoare unică a Odoo este să fie în același timp foarte ușor de utilizat și complet integrat.

Website made with

Odoo Experience on YouTube

1. Use the live chat to ask your questions.
2. The operator answers within a few minutes.

Live support on Youtube
Watch now