Перейти к содержимому
Odoo Меню
  • Войти
  • Попробовать бесплатно
  • Модули
    Финансы
    • Бухгалтерия
    • Выставление счетов
    • Расходы
    • Таблицы
    • Документооборот
    • Подпись
    Продажи
    • CRM
    • Продажи
    • POS Магазин
    • POS Ресторан
    • Подписки
    • Аренда
    Вебсайты
    • Конструктор вебсайтов
    • eCommerce
    • Блог
    • Форум
    • Онлайн-чат
    • Электронное обучение
    Логистика
    • Склад
    • Производство
    • PLM
    • Закупки
    • Обслуживание
    • Качество
    Отдел кадров
    • Сотрудники
    • Подбор персонала
    • Отпуска
    • Оценка персонала
    • Реферальная программа
    • Автопарк
    Маркетинг
    • SMM
    • E-mail рассылки
    • СМС рассылки
    • Мероприятия
    • Автоматизация маркетинга
    • Опросы
    Услуги
    • Проекты
    • Табели
    • Выездной сервис
    • Поддержка
    • Планирование
    • Встречи
    Продуктивность
    • Обсуждения
    • Согласование
    • IoT
    • VoIP-телефония
    • Knowledge
    • WhatsApp
    Сторонние приложения Модуль Студия Odoo Платформа Odoo Cloud
  • Индустрии
    Розничная торговля
    • Книжный магазин
    • Магазин одежды
    • Мебельный магазин
    • Продуктовый магазин
    • Строительный магазин
    • Магазин игрушек
    Гостинично-ресторанный бизнес
    • Бар и паб
    • Ресторан
    • Фастфуд
    • Гостевой дом
    • Дистрибьютор напитков
    • Отель
    Недвижимость
    • Агентство недвижимости
    • Архитектурное бюро
    • Строительство
    • Управление недвижимостью
    • Ландшафтный дизайн
    • Товарищество собственников жилья
    Консалтинг
    • Бухгалтерская фирма
    • Партнер Odoo
    • Маркетинговое агентство
    • Юридическая фирма
    • Подбор персонала
    • Аудиторское бюро
    Производство
    • Текстиль
    • Металл
    • Мебель
    • Продукты питания
    • Пивоварня
    • Корпоративные сувениры
    Здоровье и фитнес
    • Спортивный комплекс
    • Магазин оптики
    • Фитнес-клуб
    • Велнес-центр
    • Аптека
    • Салон красоты
    Услуги
    • Специалист по бытовым услугам
    • Продажа и обслуживание IT-оборудования
    • Солнечные энергосистемы
    • Производство обуви
    • Клининг
    • Системы ОВКВ
    Прочее
    • Некоммерческая организация
    • Консалтинг в сфере устойчивого развития
    • Аренда рекламных щитов
    • Бизнес по фотосъемке
    • Прокат велосипедов
    • Реселлер программного обеспечения
    Все индустрии
  • Community
    Обучение
    • Видео уроки
    • Документация
    • Сертификация
    • Тренинг
    • Блог
    • Подкаст
    Образование и развитие
    • Образовательная программа
    • Деловая игра Scale Up!
    • Экскурсия в офис Odoo
    ПО
    • Скачать
    • Сравнить версии
    • Релизы
    Сотрудничество
    • Github
    • Форум
    • Мероприятия
    • Перевод
    • Стать партнером
    • Услуги для партнеров
    • Зарегистрировать бухгалтерскую фирму
    Услуги
    • Найти партнера
    • Найти бухгалтера
    • Встреча с экспертом
    • Услуги по внедрению
    • Отзывы клиентов
    • Поддержка
    • Обновления
    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
Чтобы взаимодействовать с сообществом, необходимо зарегистрироваться.
Все посты Люди Значки
Теги (Смотреть все)
odoo accounting v14 pos v15
Об этом форуме
Чтобы взаимодействовать с сообществом, необходимо зарегистрироваться.
Все посты Люди Значки
Теги (Смотреть все)
odoo accounting v14 pos v15
Об этом форуме
Помощь

inheritance of PosModel in POS models.js file

Подписаться

Получайте уведомления о появлении активности в этом посте

Этот вопрос был отмечен
posinheritancejs
5 Ответы
34316 Представления
Аватар
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

Не оставайтесь в стороне – присоединяйтесь к обсуждению!

Создайте аккаунт сегодня, чтобы получить доступ к эксклюзивным функциям и стать частью нашего замечательного сообщества!

Регистрация
Похожие посты Ответы Просмотры Активность
Issue Migrating bus_service Notification Handling from Odoo 17 to Odoo 18 (OWL-based POS)
pos js
Аватар
0
апр. 25
2936
How i can modify JS method in POS? Решено
pos js
Аватар
1
сент. 23
8445
How to override js function in POS Orderline object? Решено
pos js
Аватар
Аватар
2
февр. 18
11690
inherit js file odoo 9
inheritance js
Аватар
Аватар
2
июл. 17
5367
pos error js instance.web.cordova
pos js
Аватар
0
июн. 17
4732
Сообщество
  • Видео уроки
  • Документация
  • Форум
Открытый исходный код
  • Скачать
  • Github
  • Runbot
  • Перевод
Услуги
  • Хостинг Odoo.sh
  • Поддержка
  • Обновление
  • Индивидуальные решения по доработке
  • Образование
  • Найти бухгалтера
  • Найти партнера
  • Стать партнером
О нас
  • Наша компания
  • Активы бренда
  • Cвяжитесь с нами
  • Вакансии
  • Мероприятия
  • Подкаст
  • Блог
  • Клиенты
  • Правовые документы • Конфиденциальность
  • Безопасность
الْعَرَبيّة 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, E-commerce, Бухгалтерия, Склад, POS, управление проектами и др.

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