Exemple #1
0
 def do_open_(self, action):
     encoder = PYSONEncoder()
     action['pyson_context'] = encoder.encode(self.get_context())
     action['pyson_search_value'] = encoder.encode(self.get_search_value())
     action['pyson_domain'] = encoder.encode(self.get_domain())
     action['name'] += '(' + self.record.rec_name + ')'
     return action, {}
Exemple #2
0
    def do_create_order(self, action):
        pool = Pool()
        Sale = pool.get('sale.sale')

        address = self._get_address()
        visit = self._get_visit()

        sale = Sale()
        sale.party = address.party
        sale.invoice_address = address
        sale.shipment_address = address
        if visit:
            sale.sale_date = visit.time.date()
            sale.origin = visit
        sale.save()

        encoder = PYSONEncoder()
        action['views'].reverse()
        action['domains'] = []
        action['pyson_domain'] = encoder.encode([
            ('id', '=', sale.id),
        ])
        return action, {
            'res_id': [sale.id],
        }
Exemple #3
0
    def test_email_template_get_pyson(self):
        "Test email template get with pyson"
        pool = Pool()
        Template = pool.get('ir.email.template')
        IrModel = pool.get('ir.model')
        IrModelField = pool.get('ir.model.field')
        User = pool.get('res.user')

        admin = User(1)
        admin.email = '*****@*****.**'
        admin.save()
        model, = IrModel.search([('model', '=', 'res.user')])
        field, = IrModelField.search([
            ('model', '=', model.id),
            ('name', '=', 'id'),
        ])

        template = Template(
            model=model,
            name="Test",
            recipients_pyson=PYSONEncoder().encode([Eval('self.email')]),
            recipients_secondary_pyson=PYSONEncoder().encode(
                If(Eval('self.email'), ['*****@*****.**'], [])),
        )
        template.save()

        values = template.get(admin)

        self.assertEqual(values, {
            'to': ['*****@*****.**'],
            'cc': ['*****@*****.**'],
        })
Exemple #4
0
    def fields_get(cls, fields_names=None, group=0, level=0):
        Model = Pool().get('ir.model')
        Data = Pool().get('lims.interface.data')
        res = super().fields_get(fields_names)

        table = cls.get_table()
        readonly = Transaction().context.get('lims_interface_readonly', False)
        encoder = PYSONEncoder()

        for field in table.grouped_fields_:
            if field.group != group:
                continue
            res[field.name] = {
                'name': field.name,
                'string': field.string,
                'type': FIELD_TYPE_TRYTON[field.type],
                'readonly': bool(readonly or field.formula or field.readonly),
                'help': field.help,
                'domain': field.domain,
                'states': '{}',
                }
            if field.type == 'many2one':
                res[field.name]['relation'] = (field.related_model.model if
                    field.related_model else None)
            if field.type == 'selection':
                selection = [tuple(v.split(':', 1))
                    for v in field.selection.splitlines() if v]
                res[field.name]['selection'] = selection
                res[field.name]['selection_change_with'] = []
                res[field.name]['sort'] = False
            if field.type == 'reference':
                selection = []
                for model in Model.search([]):
                    selection.append((model.model, model.name))
                res[field.name]['selection'] = selection
            if field.type in ['date', 'time', 'datetime', 'timestamp']:
                res[field.name]['format'] = PYSONEncoder().encode(
                    '%H:%M:%S.%f')
            if field.type in ['float', 'numeric']:
                res[field.name]['digits'] = encoder.encode((16, field.digits))
            if field.inputs:
                res[field.name]['on_change_with'] = field.inputs.split() + [
                    'data']
                cls.add_on_change_with_method(field)
                func_name = '%s_%s' % ('on_change_with', field.name)
                cls.__rpc__.setdefault(func_name, RPC(instantiate=0))

        res['data'] = {
            'name': 'data',
            'string': 'Data',
            'type': 'many2one',
            'readonly': True,
            'help': '',
            'states': '{}',
            'relation': 'lims.interface.data',
            'relation_field': 'group_%s' % group,
            'relation_fields': (Data.fields_get(level=level - 1)
                if level > 0 else []),
            }
        return res
Exemple #5
0
    def do_goto_notification(self, action):

        enctr_id, encounter = self._get_active_encounter()

        # Does the notification entry already exist?
        notification = Pool().get('gnuhealth.disease_notification').search([
            ('encounter', '=', enctr_id)
        ])
        if notification:
            rd = {'active_id': notification[0].id}
            action['res_id'] = rd['active_id']
        else:
            now = datetime.now()
            patient = encounter.patient
            facility = encounter.institution
            rd = {}
            action['pyson_domain'] = PYSONEncoder().encode([
                ('encounter', '=', enctr_id), ('patient', '=', patient.id),
                ('reporting_facility', '=', facility.id),
                ('date_notified', '=', localtime(now).strftime('%F %T'))
            ])
            action['pyson_context'] = PYSONEncoder().encode({
                'encounter':
                enctr_id,
                'patient':
                patient.id,
                'reporting_facility':
                facility.id,
                'date_notified':
                now
            })

        return action, rd
Exemple #6
0
 def definition(self, model, language):
     encoder = PYSONEncoder()
     definition = super().definition(model, language)
     definition['datetime_field'] = self.datetime_field
     definition['search_context'] = encoder.encode(self.search_context)
     definition['search_order'] = encoder.encode(self.search_order)
     return definition
Exemple #7
0
    def definition(self, model, language):
        pool = Pool()
        Translation = pool.get('ir.translation')
        encoder = PYSONEncoder()
        definition = {
            'context': encoder.encode(self.context),
            'loading': self.loading,
            'name': self.name,
            'on_change': list(self.on_change),
            'on_change_with': list(self.on_change_with),
            'readonly': self.readonly,
            'required': self.required,
            'states': encoder.encode(self.states),
            'type': self._type,
            'domain': encoder.encode(self.domain),
            'searchable': hasattr(model, 'search'),
            'sortable': hasattr(model, 'search'),
        }

        # Add id to on_change's if they are not cached
        # Not having the id increase the efficiency of the cache
        for method in ['on_change', 'on_change_with']:
            changes = definition[method]
            if changes:
                method_name = method + '_' + self.name
                if not model.__rpc__[method_name].cache:
                    changes.append('id')

        name = '%s,%s' % (model.__name__, self.name)
        for attr, ttype in [('string', 'field'), ('help', 'help')]:
            definition[attr] = ''
            for source in getattr(self, attr):
                definition[attr] += (Translation.get_source(
                    name, ttype, language, source) or source)
        return definition
Exemple #8
0
    def do_inpatient_evaluation(self, action):
      
        inpatient_registration = Transaction().context.get('active_id')

        try:
            reg_id = \
                Pool().get('gnuhealth.inpatient.registration').browse([inpatient_registration])[0]
        except:
            self.raise_user_error('no_record_selected')
            
        patient = reg_id.patient.id

        
        action['pyson_domain'] = PYSONEncoder().encode([
            ('patient', '=', patient),
            ('inpatient_registration_code', '=', reg_id.id),
            ('evaluation_type', '=', 'inpatient'),
            ])
        action['pyson_context'] = PYSONEncoder().encode({
            'patient': patient,
            'inpatient_registration_code': reg_id.id,
            'evaluation_type': 'inpatient',
            })
            
        return action, {}
    def analytic_accounts_fields_get(cls, field, fields_names=None,
            states=None, required_states=None):
        res = {}
        if fields_names is None:
            fields_names = []
        if states is None:
            states = {}

        encoder = PYSONEncoder()

        root_accounts = cls.search([
                ('parent', '=', None),
                ])
        for account in root_accounts:
            name = 'analytic_account_' + str(account.id)
            if name in fields_names or not fields_names:
                res[name] = field.copy()
                field_states = states.copy()
                if account.mandatory:
                    if required_states:
                        field_states['required'] = required_states
                    else:
                        field_states['required'] = True
                res[name]['states'] = encoder.encode(field_states)
                res[name]['string'] = account.name
                res[name]['relation'] = cls.__name__
                res[name]['domain'] = PYSONEncoder().encode([
                    ('root', '=', account.id),
                    ('type', '=', 'normal')])
        return res
Exemple #10
0
    def get_buttons(self, wizard, state_name):
        '''
        Returns button definitions translated
        '''
        Translation = Pool().get('ir.translation')

        def translation_key(button):
            return (','.join(
                (wizard.__name__, state_name, button.state)), 'wizard_button',
                    Transaction().language, button.string)

        translation_keys = [translation_key(button) for button in self.buttons]
        translations = Translation.get_sources(translation_keys)
        encoder = PYSONEncoder()
        result = []
        for button in self.buttons:
            validate = (button.validate if button.validate is not None else
                        button.state != wizard.end_state)
            result.append({
                'state':
                button.state,
                'icon':
                button.icon,
                'default':
                button.default,
                'validate':
                validate,
                'string': (translations.get(translation_key(button))
                           or button.string),
                'states':
                encoder.encode(button.states),
            })
        return result
Exemple #11
0
    def definition(self, model, language):
        pool = Pool()
        Translation = pool.get('ir.translation')
        encoder = PYSONEncoder()
        definition = {
            'context': encoder.encode(self.context),
            'loading': self.loading,
            'name': self.name,
            'depends': self.depends,
            'on_change': list(self.on_change),
            'on_change_with': list(self.on_change_with),
            'readonly': self.readonly,
            'required': self.required,
            'states': encoder.encode(self.states),
            'type': self._type,
            'domain': encoder.encode(self.domain),
            'searchable': hasattr(model, 'search'),
            'sortable': hasattr(model, 'search'),
            }

        # Add id to on_change's if they are not cached
        # Not having the id increase the efficiency of the cache
        for method in ['on_change', 'on_change_with']:
            changes = definition[method]
            if changes:
                method_name = method + '_' + self.name
                if not model.__rpc__[method_name].cache:
                    changes.append('id')

                for name in changes:
                    target = model
                    if '.' in name:
                        prefix, _ = name.rsplit('.', 1)
                        prefix += '.'
                    else:
                        prefix = ''
                    while name.startswith('_parent_'):
                        field, name = name.split('.', 1)
                        target = target._fields[field[8:]].get_target()
                    field = target._fields[name]
                    if field and field.context:
                        eval_fields = get_eval_fields(field.context)
                        for context_field_name in eval_fields:
                            prefix_ctx_field_name = (
                                prefix + context_field_name)
                            if (context_field_name in field.depends
                                    and prefix_ctx_field_name not in changes):
                                changes.append(prefix_ctx_field_name)

        name = '%s,%s' % (model.__name__, self.name)
        for attr, ttype in [('string', 'field'), ('help', 'help')]:
            definition[attr] = ''
            for source in getattr(self, attr):
                if not isinstance(source, LazyString):
                    source = (
                        Translation.get_source(name, ttype, language, source)
                        or source)
                definition[attr] += source
        return definition
Exemple #12
0
 def _ModelView__view_look_dom(
         cls, element, type, fields_width=None, _fields_attrs=None):
     result = super()._ModelView__view_look_dom(
         element, type, fields_width, _fields_attrs)
     if element.get('name') == 'update_totp_secret':
         encoder = PYSONEncoder()
         states = cls._buttons['update_totp_secret']
         element.set('states', encoder.encode(states))
     return result
Exemple #13
0
 def do_open_(self, action):
     encoder = PYSONEncoder()
     action['pyson_context'] = '{}'
     action['pyson_search_value'] = encoder.encode([('date', '>=',
                                                     self.record.date)])
     action['pyson_domain'] = encoder.encode([('product', '=',
                                               str(self.record.product))])
     action['name'] += ' (' + self.record.rec_name + ')'
     return action, {}
Exemple #14
0
 def _ModelView__view_look_dom(
         cls, element, type, fields_width=None, _fields_attrs=None):
     result = super()._ModelView__view_look_dom(
         element, type, fields_width, _fields_attrs)
     name = element.get('name')
     if name in {'clear_totp_secret', 'setup_totp_secret'}:
         encoder = PYSONEncoder()
         states = cls._buttons[name]
         element.set('states', encoder.encode(states))
     return result
Exemple #15
0
 def do_open_(self, action):
     entries_ids = self._get_entries_ready_for_invoicing()
     action['pyson_context'] = PYSONEncoder().encode({
         'ready_for_invoicing':
         True,
     })
     action['pyson_domain'] = PYSONEncoder().encode([
         ('id', 'in', entries_ids),
     ])
     return action, {}
Exemple #16
0
 def do_open_(self, action):
     Date = Pool().get('ir.date')
     action['pyson_context'] = PYSONEncoder().encode({
             'product': Transaction().context['active_id'],
             'warehouse': self.start.warehouse.id,
             })
     action['pyson_search_value'] = PYSONEncoder().encode([
             ('date', '>=', Date.today()),
             ])
     return action, {}
Exemple #17
0
 def do_create_(self, action):
     pool = Pool()
     Commission = pool.get('commission')
     commissions = Commission.search(self.get_domain(),
                                     order=[('agent', 'DESC'),
                                            ('date', 'DESC')])
     Commission.invoice(commissions)
     invoice_ids = list({c.invoice_line.invoice.id for c in commissions})
     encoder = PYSONEncoder()
     action['pyson_domain'] = encoder.encode([('id', 'in', invoice_ids)])
     action['pyson_search_value'] = encoder.encode([])
     return action, {}
Exemple #18
0
 def do_create_(self, action):
     pool = Pool()
     Commission = pool.get('commission')
     commissions = Commission.search(self.get_domain(),
         order=[('agent', 'DESC'), ('date', 'DESC')])
     Commission.invoice(commissions)
     invoice_ids = list({c.invoice_line.invoice.id for c in commissions})
     encoder = PYSONEncoder()
     action['pyson_domain'] = encoder.encode(
         [('id', 'in', invoice_ids)])
     action['pyson_search_value'] = encoder.encode([])
     return action, {}
Exemple #19
0
 def do_enter(self, action):
     date = self.start.date
     date = Date(date.year, date.month, date.day)
     action['pyson_domain'] = PYSONEncoder().encode([
             ('employee', '=', self.start.employee.id),
             ('date', '=', date),
             ])
     action['pyson_context'] = PYSONEncoder().encode({
             'employee': self.start.employee.id,
             'date': date,
             })
     action['name'] += " - " + self.start.employee.rec_name
     return action, {}
Exemple #20
0
    def do_open(self, action):
        pool = Pool()
        Product = pool.get('product.product')

        active_id = Transaction().context.get('active_id')
        if not active_id or active_id < 0:
            action['pyson_domain'] = PYSONEncoder().encode([
                ('template', '=', None),
            ])
        else:
            product = Product(active_id)
            action['pyson_domain'] = PYSONEncoder().encode([
                ('template', '=', product.template.id),
            ])
        return action, {}
Exemple #21
0
 def _get_window_domains(cls, types):
     key = tuple(sorted(types))
     domains = cls._get_window_domains_cache.get(key)
     if domains is not None:
         return domains
     encoder = PYSONEncoder()
     domains = []
     for status in cls.search([('types', 'in', types)]):
         domain = encoder.encode([('status', '=', status.id)])
         domains.append((status.name, domain, status.count))
     if domains:
         domains.append(
             (gettext('project.msg_domain_all'), '[]', False))
     cls._get_window_domains_cache.set(key, domains)
     return domains
 def do_report_customer(self, action):
     dict = {}
     try:
         self.start.location.id
         dict['location'] = self.start.location.id
     except:
         pass
     try:
         self.start.drug_type
         dict['drug_type'] = self.start.drug_type
     except:
         pass
     try:
         self.start.start_time
         dict['start_time'] = self.start.start_time
     except:
         pass
     try:
         self.start.end_time
         dict['end_time'] = self.start.end_time
     except:
         pass
     try:
         self.start.customer.id
         dict['customer'] = self.start.customer.id
     except:
         pass
     try:
         action['pyson_context'] = PYSONEncoder().encode(dict)
     except:
         pass
     action['name'] += ' - (%s) @ %s' % (u'药库出库报表', str(self.start.start_time) + '——' + str(self.start.end_time))
     return action, {}
Exemple #23
0
 def fields_get(cls, fields_names=None):
     Model = Pool().get('ir.model')
     res = super(Data, cls).fields_get(fields_names)
     table = cls.get_table()
     for field in table.fields:
         res[field.name] = {
             'name':
             field.name,
             'string':
             field.string,
             'type':
             FIELD_TYPE_TRYTON[field.type],
             'relation':
             (field.related_model.model if field.related_model else None),
             'readonly':
             bool(field.formula),
             'help':
             field.help,
         }
         if field.inputs:
             res[field.name]['on_change_with'] = field.inputs.split()
         if field.type == 'reference':
             selection = []
             for model in Model.search([]):
                 selection.append((model.model, model.name))
             res[field.name]['selection'] = selection
         if field.type == 'timestamp':
             res[field.name]['format'] = PYSONEncoder().encode(
                 '%H:%M:%S.%f')
     return res
    def do_open_(self, action):
        pool = Pool()
        Request = pool.get('gnuhealth.imaging.test.request')
        Result = pool.get('gnuhealth.imaging.test.result')

        request_data = []
        requests = Request.browse(Transaction().context.get('active_ids'))
        for request in requests:
            request_data.append({
                'patient': request.patient.id,
                'date': datetime.now(),
                'request_date': request.date,
                'requested_test': request.requested_test,
                'request': request.id,
                'doctor': request.doctor
            })
        results = Result.create(request_data)

        action['pyson_domain'] = PYSONEncoder().encode([
            ('id', 'in', [r.id for r in results])
        ])

        Request.requested(requests)
        Request.done(requests)
        return action, {}
    def do_report(self, action):
        dict = {}
        try:
            self.start.location.id
            dict['location'] = self.start.location.id
        except:
            pass
        try:
            self.start.start_time
            dict['start_time'] = self.start.start_time
        except:
            pass
        try:
            self.start.end_time
            dict['end_time'] = self.start.end_time
        except:
            pass
        try:
            self.start.drug_type
            dict['drug_type'] = self.start.drug_type
        except:
            pass

        action['pyson_context'] = PYSONEncoder().encode(dict)

        action['name'] += ' - (%s) @ %s' % (u'调价盈亏报表', self.start.start_time)
        return action, {}
Exemple #26
0
 def do_print_(self, action):
     #start_date = self.start.date
     end_date = self.start.to_date
     #fiscalyear = self.start.fiscalyear.id
     #start_date = Date(start_date.year, start_date.month, start_date.day)
     end_date = Date(end_date.year, end_date.month, end_date.day)
     data = {
         'company': self.start.company.id,
         'account': self.start.account.id,
         #'fiscalyear': self.start.fiscalyear.name,
         #'fiscalyear_id': self.start.fiscalyear.id,
         #'start_date': self.start.fiscalyear.start_date,
         'end_date': self.start.to_date,
         'omit_zero': self.start.omit_zero,
     }
     action['pyson_context'] = PYSONEncoder().encode({
         'company':
         self.start.company.id,
         #'fiscalyear': self.start.fiscalyear.id,
         #'start_date': start_date,
         'end_date':
         end_date,
     })
     #if self.start.fiscalyear:
     #    action['name'] += ' - %s' % self.start.fiscalyear.rec_name
     return action, data
Exemple #27
0
    def update_actions(cls, views):
        ActWindow = Pool().get('ir.action.act_window')

        to_write = []
        for view in views:
            action = view.action
            if not action:
                action = ActWindow()
            action.name = '%s (%s)' % (view.name, view.sheet.name)
            action.res_model = 'shine.data'
            action.usage = 'dashboard'
            action.context = PYSONEncoder().encode({
                'shine_view':
                view.id,
                'shine_sheet':
                view.sheet.id,
                'shine_table':
                view.current_table.id,
                #'shine_table_view': view.current_table_view.id,
            })
            action.save()
            if not view.action:
                to_write.append([view])
                to_write.append({
                    'action': action.id,
                })
        if to_write:
            with Transaction().set_context({
                    'shine_prevent_view_updates': True,
            }):
                cls.write(*to_write)
Exemple #28
0
    def do_open(self, action):
        pool = Pool()
        Product = pool.get('product.product')
        Lang = pool.get('ir.lang')

        context = {}
        product_id = Transaction().context['active_id']
        context['product'] = product_id
        if self.start.forecast_date:
            context['stock_date_end'] = self.start.forecast_date
        else:
            context['stock_date_end'] = datetime.date.max
        action['pyson_context'] = PYSONEncoder().encode(context)
        product = Product(product_id)

        for code in [Transaction().language, 'en_US']:
            langs = Lang.search([
                    ('code', '=', code),
                    ])
            if langs:
                break
        lang, = langs
        date = Lang.strftime(context['stock_date_end'],
            lang.code, lang.date)

        action['name'] += ' - %s (%s) @ %s' % (product.rec_name,
            product.default_uom.rec_name, date)
        return action, {}
Exemple #29
0
    def do_start(self, action):
        pool = Pool()
        ResultsReport = pool.get('lims.results_report')
        ResultsDetail = pool.get('lims.results_report.version.detail')
        ResultsSample = pool.get('lims.results_report.version.detail.sample')
        Notebook = pool.get('lims.notebook')

        active_ids = Transaction().context['active_ids']
        details = ResultsDetail.browse(active_ids)

        component_ids = []
        samples = ResultsSample.search([
            ('version_detail', 'in', active_ids),
        ])
        for s in samples:
            if s.component:
                component_ids.append(s.component.id)

        notebooks = Notebook.search([
            ('component', 'in', component_ids),
        ])
        notebook_ids = [n.id for n in notebooks]

        reports = ResultsReport.search([
            ('versions.details.samples.notebook', 'in', notebook_ids),
            ('versions.details.id', 'not in', active_ids),
        ])
        results_report_ids = [r.id for r in reports]

        action['pyson_domain'] = PYSONEncoder().encode([
            ('id', 'in', results_report_ids),
        ])
        action['name'] = '%s (%s)' % (gettext('lims_industry.lbl_precedents'),
                                      ', '.join(d.rec_name for d in details))
        return action, {}
Exemple #30
0
    def do_open(self, action):
        pool = Pool()
        Location = pool.get('stock.location')
        Lang = pool.get('ir.lang')

        context = {}
        context['locations'] = Transaction().context.get('active_ids')
        date = self.start.forecast_date or datetime.date.max
        context['stock_date_end'] = Date(date.year, date.month, date.day)
        action['pyson_context'] = PYSONEncoder().encode(context)

        locations = Location.browse(context['locations'])

        for code in [Transaction().language, 'en_US']:
            langs = Lang.search([
                ('code', '=', code),
            ])
            if langs:
                break
        lang = langs[0]
        date = Lang.strftime(date, lang.code, lang.date)

        action['name'] += ' - (%s) @ %s' % (','.join(l.name
                                                     for l in locations), date)
        return action, {}
Exemple #31
0
    def do_renumber(self, action):
        pool = Pool()
        Move = pool.get('account.move')
        Sequence = pool.get('ir.sequence')
        Warning = pool.get('res.user.warning')
        draft_moves = Move.search([
            ('period.fiscalyear', '=', self.start.fiscalyear.id),
            ('state', '=', 'draft'),
        ])
        if draft_moves:
            key = 'move_renumber_draft_moves%s' % self.start.fiscalyear.id
            if Warning.check(key):
                raise UserWarning(
                    key,
                    gettext('account_move_renumber.draft_moves_in_fiscalyear',
                            fiscalyear=self.start.fiscalyear.rec_name))

        sequences = set([self.start.fiscalyear.post_move_sequence])
        for period in self.start.fiscalyear.periods:
            if period.post_move_sequence:
                sequences.add(period.post_move_sequence)

        Sequence.write(list(sequences), {
            'number_next': self.start.first_number,
        })

        moves_to_renumber = Move.search([
            ('period.fiscalyear', '=', self.start.fiscalyear.id),
            ('post_number', '!=', None),
        ],
                                        order=[
                                            ('date', 'ASC'),
                                            ('id', 'ASC'),
                                        ])
        move_vals = []
        for move in moves_to_renumber:
            if move == self.start.first_move:
                number_next_old = move.period.post_move_sequence_used.number_next
                Sequence.write(list(sequences), {
                    'number_next': 1,
                })
                move_vals.extend(([move], {
                    'post_number':
                    Sequence.get_id(move.period.post_move_sequence_used.id),
                }))
                Sequence.write(list(sequences), {
                    'number_next': number_next_old,
                })
                continue
            move_vals.extend(([move], {
                'post_number': (move.period.post_move_sequence_used.get()),
            }))
        Move.write(*move_vals)

        action['pyson_domain'] = PYSONEncoder().encode([
            ('period.fiscalyear', '=', self.start.fiscalyear.id),
            ('post_number', '!=', None),
        ])
        return action, {}
Exemple #32
0
 def do_open_(self, action):
     action['pyson_context'] = PYSONEncoder().encode({
         'start_date':
         self.start.start_date,
         'end_date':
         self.start.end_date,
     })
     return action, {}
Exemple #33
0
 def do_open_(self, action):
     pool = Pool()
     Work = pool.get('project.work')
     works = Work.search([
             ('parent', 'child_of', Transaction().context['active_ids']),
             ])
     invoice_ids = set()
     for work in works:
         if work.invoice_line and work.invoice_line.invoice:
             invoice_ids.add(work.invoice_line.invoice.id)
         for timesheet_line in work.work.timesheet_lines:
             if (timesheet_line.invoice_line
                     and timesheet_line.invoice_line.invoice):
                 invoice_ids.add(timesheet_line.invoice_line.invoice.id)
     encoder = PYSONEncoder()
     action['pyson_domain'] = encoder.encode(
         [('id', 'in', list(invoice_ids))])
     action['pyson_search_value'] = encoder.encode([])
     return action, {}
Exemple #34
0
    def get_buttons(self, wizard, state_name):
        '''
        Returns button definitions translated
        '''
        Translation = Pool().get('ir.translation')

        def translation_key(button):
            return (','.join((wizard.__name__, state_name, button.state)),
                'wizard_button', Transaction().language, button.string)
        translation_keys = [translation_key(button) for button in self.buttons]
        translations = Translation.get_sources(translation_keys)
        encoder = PYSONEncoder()
        result = []
        for button in self.buttons:
            result.append({
                    'state': button.state,
                    'icon': button.icon,
                    'default': button.default,
                    'string': (translations.get(translation_key(button))
                        or button.string),
                    'states': encoder.encode(button.states),
                    })
        return result
    def fields_get(self, fields_names=None):
        """
        Return the definition of each field on the model.

        :param fields_names: a list of field names or None for all fields
        :return: a dictionary with field name as key and definition as value
        """
        res = {}
        pool = Pool()
        translation_obj = pool.get('ir.translation')
        model_access_obj = pool.get('ir.model.access')
        field_access_obj = pool.get('ir.model.field.access')

        for parent in self._inherits:
            res.update(pool.get(parent).fields_get(fields_names))
        write_access = model_access_obj.check(self._name, 'write',
                raise_exception=False)

        #Add translation to cache
        language = Transaction().language
        trans_args = []
        for field in (x for x in self._columns.keys()
                if ((not fields_names) or x in fields_names)):
            trans_args.append((self._name + ',' + field, 'field', language,
                None))
            trans_args.append((self._name + ',' + field, 'help', language,
                None))
            if hasattr(self._columns[field], 'selection'):
                if isinstance(self._columns[field].selection, (tuple, list)) \
                        and ((hasattr(self._columns[field],
                            'translate_selection') \
                            and self._columns[field].translate_selection) \
                            or not hasattr(self._columns[field],
                                'translate_selection')):
                    sel = self._columns[field].selection
                    for (key, val) in sel:
                        trans_args.append((self._name + ',' + field,
                            'selection', language, val))
        translation_obj.get_sources(trans_args)

        encoder = PYSONEncoder()

        fwrite_accesses = field_access_obj.check(self._name, fields_names or
                self._columns.keys(), 'write', access=True)
        for field in (x for x in self._columns.keys()
                if ((not fields_names) or x in fields_names)):
            res[field] = {
                'type': self._columns[field]._type,
                'name': field,
                }
            for arg in (
                    'string',
                    'readonly',
                    'states',
                    'size',
                    'required',
                    'translate',
                    'help',
                    'select',
                    'on_change',
                    'add_remove',
                    'on_change_with',
                    'autocomplete',
                    'sort',
                    'datetime_field',
                    'loading',
                    'filename',
                    ):
                if getattr(self._columns[field], arg, None) is not None:
                    res[field][arg] = copy.copy(getattr(self._columns[field],
                        arg))
            if not write_access or not fwrite_accesses.get(field, True):
                res[field]['readonly'] = True
                if res[field].get('states') and \
                        'readonly' in res[field]['states']:
                    del res[field]['states']['readonly']
            for arg in ('digits', 'invisible'):
                if hasattr(self._columns[field], arg) \
                        and getattr(self._columns[field], arg):
                    res[field][arg] = copy.copy(getattr(self._columns[field],
                        arg))
            if isinstance(self._columns[field],
                    (fields.Function, fields.One2Many)) \
                    and not self._columns[field].order_field:
                res[field]['sortable'] = False
            if ((isinstance(self._columns[field], fields.Function)
                    and not self._columns[field].searcher)
                    or self._columns[field]._type in ('binary', 'sha')):
                res[field]['searchable'] = False
            else:
                res[field]['searchable'] = True

            if Transaction().context.get('language'):
                # translate the field label
                res_trans = translation_obj.get_source(
                        self._name + ',' + field, 'field',
                        Transaction().context['language'])
                if res_trans:
                    res[field]['string'] = res_trans
                help_trans = translation_obj.get_source(
                        self._name + ',' + field, 'help',
                        Transaction().context['language'])
                if help_trans:
                    res[field]['help'] = help_trans

            if hasattr(self._columns[field], 'selection'):
                if isinstance(self._columns[field].selection, (tuple, list)):
                    sel = copy.copy(self._columns[field].selection)
                    if Transaction().context.get('language') and \
                            ((hasattr(self._columns[field],
                                'translate_selection') \
                                and self._columns[field].translate_selection) \
                                or not hasattr(self._columns[field],
                                    'translate_selection')):
                        # translate each selection option
                        sel2 = []
                        for (key, val) in sel:
                            val2 = translation_obj.get_source(
                                    self._name + ',' + field, 'selection',
                                    language, val)
                            sel2.append((key, val2 or val))
                        sel = sel2
                    res[field]['selection'] = sel
                else:
                    # call the 'dynamic selection' function
                    res[field]['selection'] = copy.copy(
                            self._columns[field].selection)
            if res[field]['type'] in (
                    'one2many',
                    'many2many',
                    'many2one',
                    'one2one',
                    ):
                if hasattr(self._columns[field], 'model_name'):
                    relation = copy.copy(self._columns[field].model_name)
                else:
                    relation = copy.copy(
                        self._columns[field].get_target()._name)
                res[field]['relation'] = relation
                res[field]['domain'] = copy.copy(self._columns[field].domain)
                res[field]['context'] = copy.copy(self._columns[field].context)
            if res[field]['type'] == 'one2many' \
                    and hasattr(self._columns[field], 'field'):
                res[field]['relation_field'] = copy.copy(
                        self._columns[field].field)

            # convert attributes into pyson
            for attr in ('states', 'domain', 'context', 'digits',
                    'add_remove'):
                if attr in res[field]:
                    res[field][attr] = encoder.encode(res[field][attr])

        if fields_names:
            # filter out fields which aren't in the fields_names list
            for i in res.keys():
                if i not in fields_names:
                    del res[i]
        return res
    def __view_look_dom(self, element, type, fields_width=None):
        pool = Pool()
        translation_obj = pool.get("ir.translation")
        model_data_obj = pool.get("ir.model.data")
        button_obj = pool.get("ir.model.button")
        user_obj = pool.get("res.user")

        if fields_width is None:
            fields_width = {}
        fields_attrs = {}
        childs = True

        if element.tag in ("field", "label", "separator", "group"):
            for attr in ("name", "icon"):
                if element.get(attr):
                    attrs = {}
                    try:
                        if element.get(attr) in self._columns:
                            field = self._columns[element.get(attr)]
                        else:
                            field = self._inherit_fields[element.get(attr)][2]
                        if hasattr(field, "model_name"):
                            relation = field.model_name
                        else:
                            relation = field.get_target()._name
                    except Exception:
                        relation = False
                    if relation and element.tag == "field":
                        childs = False
                        views = {}
                        mode = (element.attrib.pop("mode", None) or "tree,form").split(",")
                        view_ids = []
                        if element.get("view_ids"):
                            for view_id in element.get("view_ids").split(","):
                                try:
                                    view_ids.append(int(view_id))
                                except ValueError:
                                    view_ids.append(model_data_obj.get_id(*view_id.split(".")))
                        relation_obj = pool.get(relation)
                        if not len(element) and type == "form" and field._type in ("one2many", "many2many"):
                            # Prefetch only the first view to prevent infinite
                            # loop
                            if view_ids:
                                for view_id in view_ids:
                                    view = relation_obj.fields_view_get(view_id=view_id)
                                    views[view["type"]] = view
                                    break
                            else:
                                for view_type in mode:
                                    views[view_type] = relation_obj.fields_view_get(view_type=view_type)
                                    break
                        element.attrib["mode"] = ",".join(mode)
                        element.attrib["view_ids"] = ",".join(map(str, view_ids))
                        attrs = {"views": views}
                    fields_attrs[element.get(attr)] = attrs
            if element.get("name") in fields_width:
                element.set("width", str(fields_width[element.get("name")]))

        # convert attributes into pyson
        encoder = PYSONEncoder()
        for attr in ("states", "domain", "context", "digits", "add_remove", "spell", "colors"):
            if element.get(attr):
                element.set(attr, encoder.encode(safe_eval(element.get(attr), CONTEXT)))

        if element.tag == "button":
            if element.get("type", "object") == "object":
                assert not element.get("states")
                button_name = element.attrib["name"]
                if button_name in self._buttons:
                    states = self._buttons[button_name]
                else:
                    states = {}
                groups = set(user_obj.get_groups())
                button_groups = button_obj.get_groups(self._name, button_name)
                if button_groups and not groups & button_groups:
                    states = states.copy()
                    states["readonly"] = True
                element.set("states", encoder.encode(states))

        # translate view
        if Transaction().language != "en_US":
            for attr in ("string", "sum", "confirm", "help"):
                if element.get(attr):
                    trans = translation_obj.get_source(self._name, "view", Transaction().language, element.get(attr))
                    if trans:
                        element.set(attr, trans)

        # Set header string
        if element.tag in ("form", "tree", "graph"):
            element.set("string", self.view_header_get(element.get("string") or "", view_type=element.tag))

        if element.tag == "tree" and element.get("sequence"):
            fields_attrs.setdefault(element.get("sequence"), {})

        if childs:
            for field in element:
                fields_attrs.update(self.__view_look_dom(field, type, fields_width=fields_width))
        return fields_attrs
Exemple #37
0
    def __view_look_dom(cls, element, type, fields_width=None,
            fields_attrs=None):
        pool = Pool()
        Translation = pool.get('ir.translation')
        ModelData = pool.get('ir.model.data')
        Button = pool.get('ir.model.button')
        User = pool.get('res.user')

        if fields_width is None:
            fields_width = {}
        if not fields_attrs:
            fields_attrs = {}
        else:
            fields_attrs = copy.deepcopy(fields_attrs)

        def set_view_ids(element):
            view_ids = []
            if element.get('view_ids'):
                for view_id in element.get('view_ids').split(','):
                    try:
                        view_ids.append(int(view_id))
                    except ValueError:
                        view_ids.append(ModelData.get_id(*view_id.split('.')))
                element.attrib['view_ids'] = ','.join(map(str, view_ids))
            return view_ids

        def get_relation(field):
            if hasattr(field, 'model_name'):
                return field.model_name
            elif hasattr(field, 'get_target'):
                return field.get_target().__name__

        def get_views(relation, view_ids, mode):
            Relation = pool.get(relation)
            views = {}
            if field._type in ['one2many', 'many2many']:
                # Prefetch only the first view to prevent infinite loop
                if view_ids:
                    for view_id in view_ids:
                        view = Relation.fields_view_get(view_id=view_id)
                        views[str(view_id)] = view
                        break
                else:
                    for view_type in mode:
                        views[view_type] = (
                            Relation.fields_view_get(view_type=view_type))
                        break
            return views

        for attr in ('name', 'icon'):
            if not element.get(attr):
                continue
            fields_attrs.setdefault(element.get(attr), {})

        if element.tag == 'field' and type in ['tree', 'form']:
            for attr in ('name', 'icon'):
                fname = element.get(attr)
                if not fname:
                    continue
                view_ids = set_view_ids(element)
                if type != 'form':
                    continue
                field = cls._fields[fname]
                relation = get_relation(field)
                if not relation:
                    continue
                mode = (
                    element.attrib.pop('mode', None) or 'tree,form').split(',')
                views = get_views(relation, view_ids, mode)
                element.attrib['mode'] = ','.join(mode)
                fields_attrs[fname].setdefault('views', {}).update(views)

            if type == 'tree' and element.get('name') in fields_width:
                element.set('width', str(fields_width[element.get('name')]))

        encoder = PYSONEncoder()
        if element.tag == 'button':
            button_name = element.attrib['name']
            if button_name in cls._buttons:
                states = cls._buttons[button_name]
            else:
                states = {}
            groups = set(User.get_groups())
            button_groups = Button.get_groups(cls.__name__, button_name)
            if button_groups and not groups & button_groups:
                states = states.copy()
                states['readonly'] = True
            element.set('states', encoder.encode(states))

            change = cls.__change_buttons[button_name]
            if change:
                element.set('change', encoder.encode(list(change)))
            if not is_instance_method(cls, button_name):
                element.set('type', 'class')
            else:
                element.set('type', 'instance')

        # translate view
        if Transaction().language != 'en_US':
            for attr in ('string', 'sum', 'confirm', 'help'):
                if element.get(attr):
                    trans = Translation.get_source(cls.__name__, 'view',
                            Transaction().language, element.get(attr))
                    if trans:
                        element.set(attr, trans)

        # Set header string
        if element.tag in ('form', 'tree', 'graph'):
            element.set('string', cls.view_header_get(
                element.get('string') or '', view_type=element.tag))

        if element.tag == 'tree' and element.get('sequence'):
            fields_attrs.setdefault(element.get('sequence'), {})

        if element.tag == 'calendar':
            for attr in ('dtstart', 'dtend'):
                if element.get(attr):
                    fields_attrs.setdefault(element.get(attr), {})

        for field in element:
            fields_attrs = cls.__view_look_dom(field, type,
                fields_width=fields_width, fields_attrs=fields_attrs)
        return fields_attrs
Exemple #38
0
    def _view_look_dom_arch(cls, tree, type, field_children=None):
        pool = Pool()
        ModelAccess = pool.get('ir.model.access')
        FieldAccess = pool.get('ir.model.field.access')

        encoder = PYSONEncoder()
        for xpath, attribute, value in cls.view_attributes():
            for element in tree.xpath(xpath):
                element.set(attribute, encoder.encode(value))

        fields_width = {}
        tree_root = tree.getroottree().getroot()

        # Find field without read access
        fread_accesses = FieldAccess.check(cls.__name__,
                cls._fields.keys(), 'read', access=True)
        fields_to_remove = list(x for x, y in fread_accesses.iteritems()
                if not y)

        # Find relation field without read access
        for name, field in cls._fields.iteritems():
            if not ModelAccess.check_relation(cls.__name__, name, mode='read'):
                fields_to_remove.append(name)

        for name, field in cls._fields.iteritems():
            for field_to_remove in fields_to_remove:
                if field_to_remove in field.depends:
                    fields_to_remove.append(name)

        # Remove field without read access
        for field in fields_to_remove:
            xpath = ('//field[@name="%(field)s"] | //label[@name="%(field)s"]'
                ' | //page[@name="%(field)s"] | //group[@name="%(field)s"]'
                ' | //separator[@name="%(field)s"]') % {'field': field}
            for i, element in enumerate(tree.xpath(xpath)):
                if type == 'tree' or element.tag == 'page':
                    parent = element.getparent()
                    parent.remove(element)
                elif type == 'form':
                    element.tag = 'label'
                    element.attrib.clear()
                    element.attrib['id'] = 'hidden %s-%s' % (field, i)

        if type == 'tree':
            ViewTreeWidth = pool.get('ir.ui.view_tree_width')
            viewtreewidth_ids = ViewTreeWidth.search([
                ('model', '=', cls.__name__),
                ('user', '=', Transaction().user),
                ])
            for viewtreewidth in ViewTreeWidth.browse(viewtreewidth_ids):
                if viewtreewidth.width > 0:
                    fields_width[viewtreewidth.field] = viewtreewidth.width

        fields_def = cls.__view_look_dom(tree_root, type,
                fields_width=fields_width)

        if field_children:
            fields_def.setdefault(field_children, {'name': field_children})
            if field_children in cls._fields:
                field = cls._fields[field_children]
                if hasattr(field, 'field'):
                    fields_def.setdefault(field.field, {'name': field.field})

        for field_name in fields_def.keys():
            if field_name in cls._fields:
                field = cls._fields[field_name]
            else:
                continue
            for depend in field.depends:
                fields_def.setdefault(depend, {'name': depend})

        if 'active' in cls._fields:
            fields_def.setdefault('active', {'name': 'active'})

        arch = etree.tostring(
            tree, encoding='utf-8', pretty_print=False).decode('utf-8')
        fields2 = cls.fields_get(fields_def.keys())
        for field in fields_def:
            if field in fields2:
                fields2[field].update(fields_def[field])
        return arch, fields2
Exemple #39
0
    def __view_look_dom(cls, element, type, fields_width=None,
            fields_attrs=None):
        pool = Pool()
        Translation = pool.get('ir.translation')
        ModelData = pool.get('ir.model.data')
        Button = pool.get('ir.model.button')
        User = pool.get('res.user')

        if fields_width is None:
            fields_width = {}
        if not fields_attrs:
            fields_attrs = {}
        else:
            fields_attrs = copy.deepcopy(fields_attrs)
        childs = True

        if element.tag in ('field', 'label', 'separator', 'group', 'suffix',
                'prefix'):
            for attr in ('name', 'icon', 'geometry'):
                if element.get(attr):
                    fields_attrs.setdefault(element.get(attr), {})
                    try:
                        field = cls._fields[element.get(attr)]
                        if hasattr(field, 'model_name'):
                            relation = field.model_name
                        else:
                            relation = field.get_target().__name__
                    except Exception:
                        relation = False
                    if relation and element.tag == 'field':
                        childs = False
                        views = {}
                        mode = (element.attrib.pop('mode', None)
                            or 'tree,form').split(',')
                        view_ids = []
                        if element.get('view_ids'):
                            for view_id in element.get('view_ids').split(','):
                                try:
                                    view_ids.append(int(view_id))
                                except ValueError:
                                    view_ids.append(ModelData.get_id(
                                            *view_id.split('.')))
                        Relation = pool.get(relation)
                        if (not len(element)
                                and type == 'form'
                                and field._type in ('one2many', 'many2many')):
                            # Prefetch only the first view to prevent infinite
                            # loop
                            if view_ids:
                                for view_id in view_ids:
                                    view = Relation.fields_view_get(
                                        view_id=view_id)
                                    views[str(view_id)] = view
                                    break
                            else:
                                for view_type in mode:
                                    views[view_type] = \
                                        Relation.fields_view_get(
                                            view_type=view_type)
                                    break
                        element.attrib['mode'] = ','.join(mode)
                        element.attrib['view_ids'] = ','.join(
                            map(str, view_ids))
                        fields_attrs[element.get(attr)].setdefault('views', {}
                            ).update(views)
            if element.get('name') in fields_width:
                element.set('width', str(fields_width[element.get('name')]))

        # convert attributes into pyson
        encoder = PYSONEncoder()
        for attr in ('states', 'domain', 'spell', 'colors'):
            if element.get(attr):
                element.set(attr, encoder.encode(safe_eval(element.get(attr),
                    CONTEXT)))

        if element.tag == 'button':
            button_name = element.attrib['name']
            if button_name in cls._buttons:
                states = cls._buttons[button_name]
            else:
                states = {}
            groups = set(User.get_groups())
            button_groups = Button.get_groups(cls.__name__, button_name)
            if button_groups and not groups & button_groups:
                states = states.copy()
                states['readonly'] = True
            element.set('states', encoder.encode(states))

        # translate view
        if Transaction().language != 'en_US':
            for attr in ('string', 'sum', 'confirm', 'help'):
                if element.get(attr):
                    trans = Translation.get_source(cls.__name__, 'view',
                            Transaction().language, element.get(attr))
                    if trans:
                        element.set(attr, trans)

        # Set header string
        if element.tag in ('form', 'tree', 'graph'):
            element.set('string', cls.view_header_get(
                element.get('string') or '', view_type=element.tag))

        if element.tag == 'tree' and element.get('sequence'):
            fields_attrs.setdefault(element.get('sequence'), {})

        if childs:
            for field in element:
                fields_attrs = cls.__view_look_dom(field, type,
                    fields_width=fields_width, fields_attrs=fields_attrs)
        return fields_attrs
Exemple #40
0
    def __view_look_dom(cls, element, type, fields_width=None, fields_attrs=None):
        pool = Pool()
        Translation = pool.get("ir.translation")
        ModelData = pool.get("ir.model.data")
        Button = pool.get("ir.model.button")
        User = pool.get("res.user")

        if fields_width is None:
            fields_width = {}
        if not fields_attrs:
            fields_attrs = {}
        else:
            fields_attrs = copy.deepcopy(fields_attrs)
        childs = True

        if element.tag in ("field", "label", "separator", "group", "suffix", "prefix"):
            for attr in ("name", "icon"):
                if element.get(attr):
                    fields_attrs.setdefault(element.get(attr), {})
                    try:
                        field = cls._fields[element.get(attr)]
                        if hasattr(field, "model_name"):
                            relation = field.model_name
                        else:
                            relation = field.get_target().__name__
                    except Exception:
                        relation = False
                    if relation and element.tag == "field":
                        childs = False
                        views = {}
                        mode = (element.attrib.pop("mode", None) or "tree,form").split(",")
                        view_ids = []
                        if element.get("view_ids"):
                            for view_id in element.get("view_ids").split(","):
                                try:
                                    view_ids.append(int(view_id))
                                except ValueError:
                                    view_ids.append(ModelData.get_id(*view_id.split(".")))
                        Relation = pool.get(relation)
                        if not len(element) and type == "form" and field._type in ("one2many", "many2many"):
                            # Prefetch only the first view to prevent infinite
                            # loop
                            if view_ids:
                                for view_id in view_ids:
                                    view = Relation.fields_view_get(view_id=view_id)
                                    views[str(view_id)] = view
                                    break
                            else:
                                for view_type in mode:
                                    views[view_type] = Relation.fields_view_get(view_type=view_type)
                                    break
                        element.attrib["mode"] = ",".join(mode)
                        element.attrib["view_ids"] = ",".join(map(str, view_ids))
                        fields_attrs[element.get(attr)].setdefault("views", {}).update(views)
            if element.get("name") in fields_width:
                element.set("width", str(fields_width[element.get("name")]))

        # convert attributes into pyson
        encoder = PYSONEncoder()
        for attr in ("states", "domain", "context", "digits", "add_remove", "spell", "colors"):
            if element.get(attr):
                element.set(attr, encoder.encode(safe_eval(element.get(attr), CONTEXT)))

        if element.tag == "button":
            button_name = element.attrib["name"]
            if button_name in cls._buttons:
                states = cls._buttons[button_name]
            else:
                states = {}
            groups = set(User.get_groups())
            button_groups = Button.get_groups(cls.__name__, button_name)
            if button_groups and not groups & button_groups:
                states = states.copy()
                states["readonly"] = True
            element.set("states", encoder.encode(states))

        # translate view
        if Transaction().language != "en_US":
            for attr in ("string", "sum", "confirm", "help"):
                if element.get(attr):
                    trans = Translation.get_source(cls.__name__, "view", Transaction().language, element.get(attr))
                    if trans:
                        element.set(attr, trans)

        # Set header string
        if element.tag in ("form", "tree", "graph"):
            element.set("string", cls.view_header_get(element.get("string") or "", view_type=element.tag))

        if element.tag == "tree" and element.get("sequence"):
            fields_attrs.setdefault(element.get("sequence"), {})

        if childs:
            for field in element:
                fields_attrs = cls.__view_look_dom(field, type, fields_width=fields_width, fields_attrs=fields_attrs)
        return fields_attrs
Exemple #41
0
    def fields_get(cls, fields_names=None):
        """
        Return the definition of each field on the model.
        """
        res = {}
        pool = Pool()
        Translation = pool.get('ir.translation')
        FieldAccess = pool.get('ir.model.field.access')

        #Add translation to cache
        language = Transaction().language
        trans_args = []
        for field in (x for x in cls._fields.keys()
                if ((not fields_names) or x in fields_names)):
            trans_args.append((cls.__name__ + ',' + field, 'field', language,
                None))
            trans_args.append((cls.__name__ + ',' + field, 'help', language,
                None))
            if hasattr(cls._fields[field], 'selection'):
                if (isinstance(cls._fields[field].selection, (tuple, list))
                        and ((hasattr(cls._fields[field],
                                    'translate_selection')
                                and cls._fields[field].translate_selection)
                            or not hasattr(cls._fields[field],
                                'translate_selection'))):
                    sel = cls._fields[field].selection
                    for (key, val) in sel:
                        trans_args.append((cls.__name__ + ',' + field,
                            'selection', language, val))
        Translation.get_sources(trans_args)

        encoder = PYSONEncoder()

        accesses = FieldAccess.get_access([cls.__name__])[cls.__name__]
        for field in (x for x in cls._fields.keys()
                if ((not fields_names) or x in fields_names)):
            res[field] = {
                'type': cls._fields[field]._type,
                'name': field,
                }
            for arg in (
                    'string',
                    'readonly',
                    'states',
                    'size',
                    'required',
                    'translate',
                    'help',
                    'select',
                    'on_change',
                    'add_remove',
                    'on_change_with',
                    'autocomplete',
                    'sort',
                    'datetime_field',
                    'loading',
                    'filename',
                    'selection_change_with',
                    'srid',
                    ):
                if getattr(cls._fields[field], arg, None) is not None:
                    res[field][arg] = copy.copy(getattr(cls._fields[field],
                        arg))
            if not accesses.get(field, {}).get('write', True):
                res[field]['readonly'] = True
                if res[field].get('states') and \
                        'readonly' in res[field]['states']:
                    del res[field]['states']['readonly']
            for arg in ('digits', 'invisible'):
                if hasattr(cls._fields[field], arg) \
                        and getattr(cls._fields[field], arg):
                    res[field][arg] = copy.copy(getattr(cls._fields[field],
                        arg))
            if isinstance(cls._fields[field],
                    (fields.Function, fields.One2Many)) \
                    and not cls._fields[field].order_field:
                res[field]['sortable'] = False
            if ((isinstance(cls._fields[field], fields.Function)
                    and not cls._fields[field].searcher)
                    or cls._fields[field]._type in ('binary', 'sha')):
                res[field]['searchable'] = False
            else:
                res[field]['searchable'] = True

            if Transaction().context.get('language'):
                # translate the field label
                res_trans = Translation.get_source(
                    cls.__name__ + ',' + field, 'field',
                    Transaction().context['language'])
                if res_trans:
                    res[field]['string'] = res_trans
                help_trans = Translation.get_source(
                    cls.__name__ + ',' + field, 'help',
                    Transaction().context['language'])
                if help_trans:
                    res[field]['help'] = help_trans

            if hasattr(cls._fields[field], 'selection'):
                if isinstance(cls._fields[field].selection, (tuple, list)):
                    sel = copy.copy(cls._fields[field].selection)
                    if (Transaction().context.get('language')
                            and ((hasattr(cls._fields[field],
                                        'translate_selection')
                                    and cls._fields[field].translate_selection)
                                or not hasattr(cls._fields[field],
                                    'translate_selection'))):
                        # translate each selection option
                        sel2 = []
                        for (key, val) in sel:
                            val2 = Translation.get_source(
                                cls.__name__ + ',' + field, 'selection',
                                language, val)
                            sel2.append((key, val2 or val))
                        sel = sel2
                    res[field]['selection'] = sel
                else:
                    # call the 'dynamic selection' function
                    res[field]['selection'] = copy.copy(
                            cls._fields[field].selection)
            if res[field]['type'] in (
                    'one2many',
                    'many2many',
                    'many2one',
                    'one2one',
                    ):
                if hasattr(cls._fields[field], 'model_name'):
                    relation = copy.copy(cls._fields[field].model_name)
                else:
                    relation = copy.copy(
                        cls._fields[field].get_target().__name__)
                res[field]['relation'] = relation
                res[field]['domain'] = copy.copy(cls._fields[field].domain)
                res[field]['context'] = copy.copy(cls._fields[field].context)
                res[field]['create'] = accesses.get(field, {}).get('create',
                    True)
                res[field]['delete'] = accesses.get(field, {}).get('delete',
                    True)
            if res[field]['type'] == 'one2many' \
                    and hasattr(cls._fields[field], 'field'):
                res[field]['relation_field'] = copy.copy(
                        cls._fields[field].field)
            if res[field]['type'] in ('datetime', 'time'):
                res[field]['format'] = copy.copy(cls._fields[field].format)
            if res[field]['type'] == 'selection':
                res[field]['context'] = copy.copy(cls._fields[field].context)
            if res[field]['type'] == 'dict':
                res[field]['schema_model'] = cls._fields[field].schema_model
                res[field]['domain'] = copy.copy(cls._fields[field].domain)
                res[field]['context'] = copy.copy(cls._fields[field].context)
                res[field]['create'] = accesses.get(field, {}).get('create',
                    True)
                res[field]['delete'] = accesses.get(field, {}).get('delete',
                    True)

            # convert attributes into pyson
            for attr in ('states', 'domain', 'context', 'digits', 'size',
                    'add_remove', 'format'):
                if attr in res[field]:
                    res[field][attr] = encoder.encode(res[field][attr])

        if fields_names:
            # filter out fields which aren't in the fields_names list
            for i in res.keys():
                if i not in fields_names:
                    del res[i]
        return res