Skip to Content
Odoo Меню
  • Увійти
  • Спробуйте це безкоштовно
  • Додатки
    Фінанси
    • Бухоблік
    • Виставлення рахунку
    • Витрати
    • Електронні таблиці (BI)
    • Документи
    • Підпис
    Продажі
    • CRM
    • Продажі
    • POS Магазин
    • POS Ресторан
    • Підписки
    • Оренда
    Веб-сайти
    • Конструктор веб-сайту
    • Електронна комерція
    • Блог
    • Форум
    • Живий чат
    • Електронне навчання
    Ланцюг поставок
    • Склад
    • Виробництво
    • PLM
    • Купівлі
    • Технічне обслуговування
    • Якість
    Кадри
    • Співробітники
    • Рекрутинг
    • Відпустки
    • Оцінювання
    • Рекомендації
    • Автотранспорт
    Маркетинг
    • Маркетинг соцмереж
    • Email-маркетинг
    • SMS-маркетинг
    • Події
    • Автом. маркетингу
    • Опитування
    Послуги
    • Проект
    • Табелі
    • Виїзне обслуговування
    • Служба підтримки
    • Планування
    • Призначення
    Продуктивність
    • Обговорення
    • Схвалення
    • IoT
    • IP-телефонія
    • База знань
    • WhatsApp
    Сторонні модулі Odoo Studio Платформа Odoo Cloud
  • Сфери
    Роздрібна торгівля
    • Книжковий магазин
    • Магазин одягу
    • Магазин меблів
    • Продуктовий магазин
    • Магазин будівельних матеріалів
    • Магазин іграшок
    Food & Hospitality
    • Бар та паб
    • Ресторан
    • Фастфуд
    • Guest House
    • Дистриб'ютор напоїв
    • Hotel
    Нерухомість
    • Real Estate Agency
    • Архітектурна фірма
    • Будівництво
    • Управління нерухомістю
    • Садівництво
    • Асоціація власників нерухомості
    Консалтинг
    • Бухгалтерська компанія
    • Партнер Odoo
    • Агенція маркетингу
    • Юридична фірма
    • Придбання Талантів
    • Аудит та сертифікація
    Виробництво
    • Textile
    • Metal
    • Меблі
    • Їжа
    • Brewery
    • Корпоративні подарунки
    Здоров'я & Фітнес
    • Спортивний клуб
    • Оптика
    • Фітнес-центр
    • Практики здоров'я
    • Аптека
    • Салон краси
    Trades
    • Ремонтник
    • IT-обладнання та Підтримка
    • Системи сонячної енергії
    • Shoe Maker
    • Cleaning Services
    • HVAC Services
    Інші
    • Nonprofit Organization
    • Екологічна агенція
    • Оренда білбордів
    • Фотографія
    • Лізинг велосипедів
    • Реселлер програмного забезпечення
    Browse all Industries
  • Спільнота
    Навчання
    • Навчальний посібник
    • Документація
    • Сертифікації
    • Тренування
    • Блог
    • Подкаст
    Сприяйте Освіті
    • Програма навчання
    • Бізнес гра Scale Up!
    • Відвідайте Odoo
    Отримайте програмне забезпечення
    • Завантаження
    • Порівняйте версії
    • Релізи
    Співпрацюйте
    • Github
    • Форум
    • Події
    • Переклади
    • Стати партнером
    • Services for Partners
    • Зареєструйте вашу бухгалтерську фірму
    Отримайте послуги
    • Знайдіть партнера
    • Знайдіть бухгалтера
    • Зустріньтеся з консультантом
    • Послуги з впровадження
    • Референси клієнтів
    • Підтримка
    • Оновлення
    Github Youtube Twitter Linkedin Instagram Facebook Spotify
    +1 (650) 691-3277
    Отримати демо
  • Ціни
  • Допомога

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

  • CRM
  • e-Commerce
  • Бухоблік
  • Склад
  • PoS
  • Проект
  • MRP
All apps
Вам необхідно зареєструватися, щоб взаємодіяти зі спільнотою.
All Posts Люди Значки
Мітки (View all)
odoo accounting v14 pos v15
Про цей форум
Вам необхідно зареєструватися, щоб взаємодіяти зі спільнотою.
All Posts Люди Значки
Мітки (View all)
odoo accounting v14 pos v15
Про цей форум
Допомога

inheritance of PosModel in POS models.js file

Підписатися

Отримуйте сповіщення про активність щодо цієї публікації

Це запитання позначене
posinheritancejs
5 Відповіді
34082 Переглядів
Аватар
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
Аватар
Відмінити
Аватар
Lithin T
Найкраща відповідь

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
Аватар
Відмінити
Аватар
Ivan Elizaryev
Найкраща відповідь

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
Аватар
Відмінити
Harold
Автор

Thanks for your answer

Nirav Jani

Is it working properly ?

Аватар
EasyPME
Найкраща відповідь

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
Аватар
Відмінити
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!

Реєстрація
Related Posts Відповіді Переглядів Дія
Issue Migrating bus_service Notification Handling from Odoo 17 to Odoo 18 (OWL-based POS)
pos js
Аватар
0
квіт. 25
2784
How i can modify JS method in POS? Вирішено
pos js
Аватар
1
вер. 23
8356
How to override js function in POS Orderline object? Вирішено
pos js
Аватар
Аватар
2
лют. 18
11584
inherit js file odoo 9
inheritance js
Аватар
Аватар
2
лип. 17
5324
pos error js instance.web.cordova
pos js
Аватар
0
черв. 17
4680
Спільнота
  • Навчальний посібник
  • Документація
  • Форум
Open Source
  • Завантаження
  • Github
  • Runbot
  • Переклади
Послуги
  • Хостинг Odoo.sh
  • Підтримка
  • Оновлення
  • Кастомні доробки
  • Навчання
  • Знайдіть бухгалтера
  • Знайдіть партнера
  • Стати партнером
Про нас
  • Наша компанія
  • Торгові активи
  • Зв'яжіться з нами
  • Вакансії
  • Події
  • Подкаст
  • Блог
  • Клієнти
  • Юридичні документи • Конфіденційність
  • Безпека
الْعَرَبيّة 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 - це набір програм для роботи з відкритим кодом, які охоплюють всі ваші потреби компанії: CRM, електронна комерція, бухгалтерський облік, склад, точка продажу, управління проектами тощо.

Унікальна пропозиція Odoo - це одночасно дуже проста у використанні та повністю інтегрована.

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