+0.36
Рейтинг
Профессиональные вопросы по разработке модулейБаги в последних релизах Odoo (16)
Сообщение #3238
11 февраля 2019, 19:01 | Баги в последних релизах Odoo
Столкнулся с проблемой. Установил один из последних релизов Odoo11 январской сборки и перестал работать метод on_change.
Изучив базовый метод def onchange базового модуля models.py увидел принципиальную разницу в коде этого метода между ранним релизом Odoo летней и текущей сборок.
Проблема была в добавлении в Backend поля One2many, которую удалось локализировать в летней сборке собственным патчем. В январской сборке данный способ не работает :(
0
Какую версию Odoo (OpenERP) выбрать, в чем разница, как обновиться на новую версиюПереход на Odoo 12 (3)
Сообщение #3172
13 ноября 2018, 11:50 | Переход на Odoo 12
Что не понравилось с первой попытки:
1. Шрифты. Причем настройки тем по умолчанию ничего не меняют в этом смысле, русские шрифты «слепые».
2. Поведение интерфейса в Chrome и FireFox различны.
3. Что-то «перемудрили» с безопасностью, предосмотр в Chrome не работает.

Продолжение следует
0
Разработка первого модуляЗапрет изменения поля модели данных (1)
Сообщение #3137
12 сентября 2018, 21:43 | Запрет изменения поля модели данных
В процессе отображения данных периодически возникает необходимость закрыть доступ на изменение к определенным полям модели для определенной группы пользователей.
Например, необходимо закрыть доступ к полю name модели res.company произвольной группе my_user_group, позволив данной группе изменять остальные поля.
Odoo предлагает различные решения. Наиболее стандартным является переопределение моделей отображения для res.company и назначение группе my_user_group поля name атрибута readonly.
Если необходимо глобально закрыть доступ на изменение к полю name группе my_user_group предпочтительным может явится следующий способ:
1. Переопределяем в модели res.company метод fields_get:

class MyCompany(models.Model):
    _inherit = 'res.company'
    <ls user="api" />.model
    def fields_get(self, allfields=None, attributes=None):
     # определяем кортеж полей закрытых на изменение
     my_readonly=('name')
     # вызываем родительских метод модели
     ret=super(MyCompany,self).fields_get(allfields,attributes)
     # для группы my_user_group  устанавливаем полю name атрибут readonly
     if self.env.user.has_group('my_user_group'):
       for f in my_readonly:
        ret[f]['readonly']=True
     return ret


Аналогично решается проблема, когда наоборот необходимо открыть доступ на запись для группы, которой установлен запрет на данную операцию.
Например, если модель содержит реляционное поле и на связанную таблицу установлен запрет на запись, то возможна ошибка доступа на запись. Для ее решение необходимо переопределить метод def check

class MyIrModelAccess(models.Model):
    _inherit = 'ir.model.access'
    <ls user="tools" />.ormcache_context('self._uid', 'model', 'mode', 'raise_exception', keys=('lang',))
    <ls user="api" />.model
    def check(self, model, mode='read', raise_exception=True):
      if model=='my.model' and mode=='write' and self.env.user.has_group('my.group_user'):
       return True
     return super(MyIrModelAccess, self).check(model,mode,raise_exception)

Данный способ следует использовать осторожно, т.к. он влияет на безопасность доступа к данным модели.
Последний раз редактировал пользователь aladkoi - 12 сентября 2018, 22:01
0
Разработка первого модуляПереопределение базового метода (5)
Сообщение #3132
06 сентября 2018, 13:37 | Переопределение базового метода
Иногда возникает необходимость переопределить базовый метод из BasicModel
Можно пойти двумя путями, либо переопределить данный метод в модели данных, либо повесить на него HOOK.
Второй метод позволяет это сделать без привязки к конкретной модели.
Например, переопределяем базовый метод прав доступа к данным модели:

# сохраняем базовый вызов метода
my_rule = models.BaseModel._apply_ir_rules  
# делаем суперпользователя для привязанного к главной компании
class MyAccess(models.AbstractModel):
    _name='mymodel.extend'
    <ls user="api" />.model_cr
    def _register_hook(self):
     <ls user="api" />.model
     def _apply_ir_rules(self,query,mode='read'):
        if self._name in ['model.model1','model.model2']:
          # можем,например, проверить пользователя и назначить ему права SUPERUSER для моделей 'model.model1','model.model2'
            return
        # иначе вызвать базовый метод
        my_rule(self,query,mode) 
     models.BaseModel._apply_ir_rules = _apply_ir_rules
     return super(MyAccess, self)._register_hook()
0
Разработка первого модуляСоздаем действие для tree (1)
Сообщение #3122
30 августа 2018, 15:56 | Создаем действие для tree
Само по себе Действие необходимо для выполнение на стороне сервера необходимого программного кода.
Это может быть изменение или загрузка данных, отправка электронной почты и т.д.
При создании Действия в отображении tree, в него передается список выделенных записей.
Пример создания Действия для отображения Tree на базе модуля res.company
1. Описываем привязку к меню Действие формы вида tree:

 <record id="ir_actions_server_link_to_company" model="ir.actions.server">
  <field name="name">Мое действие</field>
  <field name="type">ir.actions.server</field>
  <field name="model_id" ref="model_res_company" />
  <field name="state">code</field>
  <field name="code">if records: action = records.action_my_link()</field>
  <field name="binding_model_id" ref="base.model_res_company" />
  </record>

2. Описываем само действие в модуле res.company


class MyCompany(models.Model):
    _inherit = 'res.company'
    api.model
    def action_my_link(self):
     осуществляем необходимое действие
Последний раз редактировал пользователь aladkoi - 30 августа 2018, 15:57
0
Разработка первого модуляСоздание нескольких видов отображения на модель данных (10)
Сообщение #3121
29 августа 2018, 11:54 | Создание нескольких видов отображения на модель данных
Бывает необходимо создать несколько различных отображений в Backend для модели данных, например order.sale.
Вкратце, по умолчанию при описании отображения на модель происходит переопределение текущего отображения модели. В Odoo есть возможность описать различные виды отображения данных на модель.
Как сделать, подсмотрено здесь learnopenerp.blogspot.com/2017/12/display-multiple-form-and-tree-view-for.html
Последний раз редактировал пользователь aladkoi - 29 августа 2018, 11:55
0
Разработка первого модуляPopup календарь в website (1)
Сообщение #3076
27 июля 2018, 09:57 | Popup календарь в website
За основу взят код из модуля survey

1. Определяем поле ввода, на которое будет привязан календарь

  <input type="text" name="date_of_birth" class="form-control date_of_birth"/>

2. Пишем javascript


odoo.define('model.my_form', function (require) {
"use strict";

// выполнить после загрузки страницы
require('web.dom_ready');

 // выполнять код только на указанной странице
if (self.location.pathname.indexOf('/my_page')!=-1) {
 /// загружаем необходимые модули
   var ajax = require('web.ajax');
   var time = require('web.time');
   var base = require('web_editor.base');
   var context = require('web_editor.context');

  function load_locale(){
        var url = "/web/webclient/locale/" + context.get().lang || 'en_US';
        return ajax.loadJS(url);
          }

  /// загружаем локализацию календаря от выбранного языка сайта
  var ready_with_locale = $.when(base.ready(), load_locale());

  /// привязываем к нашему элементу date_of_birth 
  ready_with_locale.then(function(){
        $('input.date_of_birth').datetimepicker({
            format : time.getLangDateFormat(),
            minDate: moment({ y: 1900 }),
            maxDate: moment().add(200, "y"),
            calendarWeeks: true,
            icons: {
                time: 'fa fa-clock-o',
                date: 'fa fa-calendar',
                next: 'fa fa-chevron-right',
                previous: 'fa fa-chevron-left',
                up: 'fa fa-chevron-up',
                down: 'fa fa-chevron-down',
            },
            locale : moment.locale(),
            allowInputToggle: true,
            keyBinds: null,
        });
    });
   

}

});
Последний раз редактировал пользователь aladkoi - 27 июля 2018, 09:58
0
Как установить Odoo (OpenERP) своими силамиПеренос сервера (7)
Сообщение #3065
29 июня 2018, 11:53 | Перенос сервера
Что нужно сделать при переносе сервера и базы Odoo на новый сервер.
1. Настроить Odoo.
2. Перенести все свои модули и приложения на новый сервер.
3. Внимательно проверить настройку путей в своих модулях, чтоб-бы не было ошибок при их загрузке в Odoo на новом сервере.
4. Сделать Backup базы на старом сервере.

5. Восстановить backup на новом сервере с указанием имени новой базы.

6. Перезапустить Odoo с параметрами /usr/bin/odoo -c /etc/odoo/odoo.conf -d имя базы -u имя вашего модуля
Если что-пошло не так и Ваша база не стартует правильно, то смотрим логи Odoo.

PS
Для лучшего переноса сервера и базы на новый сервер лучше сразу настроить на сервере Odoo хранилище сессий через Redis сервер
www.odoo.com/apps/modules/11.0/smile_redis_session_store/
apt-get install -y redis-server
pip3 install redis
В odoo.conf соответственно:
use_redis = True
redis_host= 127.0.0.1
и настроить хранение всех вложений в Odoo
www.odoo.com/apps/modules/11.0/ir_attachment_force_storage/
0
Разработка первого модуляOne2many и related поля (1)
Сообщение #3056
06 июня 2018, 17:36 | One2many и related поля
В определенных случаях есть необходимость вывести определенную запись на форму из отношения One2many.
Например имеем две модели, главную и подчиненную, где в главной имеется реляционное отношение One2many к подчиненной таблице.
Child:
fields1=fields.Char()
fields2=fields.Integer()
parent=Many2one('parent')

Parent:
fields1=fields.Integer()
fields_child1=fields.Char(related='child.fields1')
child=One2many('child','parent')

Для выборки определенной записи из подчиненной таблицы необходимо в поле child добавить domain
child=One2many('child','parent',domain=[('id','=',id_child)])

где id_child является номером записи из подчиненной таблицы
fields_child1 — показывает с возможностью редактирование запись из подчиненной таблицы

При необходимости в domain можно записать функцию примерно так:
child=One2many('child','parent',domain=_my_funct)

def _my_funct(self):
 if self.fields1==1:
  id=self.env['child'].sudo().search([('fields2,'=',self.fields1)],limit=1).id  # получаем id child по условию parent
  return [('id','=',id)] 
Последний раз редактировал пользователь aladkoi - 06 июня 2018, 17:37
0
Профессиональные вопросы по разработке модулейМодуль Sale (5)
Сообщение #2993
30 марта 2018, 12:57 | Модуль Sale
По истечению даты оплаты заказ в просмотре документов website клиента выдает статус Истекший (поле is_expired в моделе sale.order)
Расчет статуса поля идет путем сравнения полей даты окончания заказа и текущей даты. Судя по методу расчета в Odoo если дата окончания заказа и текущая дата совпадают, то статус заказа устанавливается в истекший, что не является по видимому логически правильным.
Исправляем код в модели sale.order:

class MySaleOrder(models.Model):
    _inherit = "sale.order"
    def _compute_is_expired(self):
      now = datetime.now()
      now += timedelta(1)
      for order in self:
       if order.validity_date and fields.Datetime.from_string(order.validity_date) < now:
        order.is_expired = False
       else:
        order.is_expired = True

или так

    def _compute_is_expired(self):
        now = datetime.now()
        for order in self:
         order.is_expired = True
         if order.validity_date and fields.Datetime.from_string(order.validity_date)<=now:
          order.is_expired = False
Последний раз редактировал пользователь aladkoi - 30 марта 2018, 13:05
0