class product_template(Model): _inherit = "product.template" _columns = { 'attribute_custom_tmpl': fields.serialized('Custom Template Attributes'), }
class IrActionsServerExecution(orm.Model): _name = 'ir.actions.server.execution' _description = "Server Action Execution" _table = 'ir_act_server_execution' _rec_name = 'action_id' _columns = { 'action_id': fields.many2one('ir.actions.server', "Server Action", readonly=True, required=True, ondelete="restrict"), 'locked': fields.boolean('Locked', readonly=True), 'create_date': fields.datetime('Create Date', readonly=True), 'state': fields.selection([('draft', 'To Do'), ('done', 'Done')], "State", readonly=True), 'launch': fields.selection([('manual', 'manually'), ('trigger', 'by trigger')], "Launched", readonly=True), 'args': fields.serialized("Arguments", help="", readonly=True), } _defaults = { 'state': 'draft', 'launch': 'manual', } def _check_locked_action(self, cr, uid, ids, context=None): if isinstance(ids, (int, long)): ids = [ids] executions = self.browse(cr, uid, ids, context=None) action_ids = [execution.action_id.id for execution in executions] locked_execution_ids = self.search(cr, uid, [ ('id', 'not in', ids), ('state', '=', 'draft'), ('action_id', 'in', action_ids), ('locked', '=', True), ], context=context) if locked_execution_ids: return False return True _constraints = [ (_check_locked_action, 'This action is under execution!', ['action_id']) ] def auto_execute(self, cr, uid, context=None): action_obj = self.pool.get('ir.actions.server') ids = self.search(cr, uid, [('state', '=', 'draft'), ('locked', '=', False)], context=context) for execution in self.browse(cr, uid, ids, context): action_obj.run(cr, **execution.args) return True
class trobz_api_log(osv.osv): _name = "trobz.api.log" _description = "Trobz API Log" _columns = { 'name': fields.datetime('Date Time', required=True), 'uid': fields.many2one('res.users', string='User'), 'model': fields.char('Model'), 'action': fields.char('Action'), 'vals': fields.serialized('Vals'), 'domain': fields.char('Domain'), 'message': fields.char('Return Message'), 'resource_id': fields.integer('Resource'), 'status': fields.selection([('pass', 'Pass'), ('fail', 'Fail')], 'Status'), } _order = "name desc" _defaults = { 'name': lambda *a: fields.datetime.now(), }
class report_print_actions(orm.TransientModel): _name = 'aeroo.print_actions' _description = 'Aeroo reports print wizard' def check_report(self, report_name): if 'report.%s' % report_name not in netsvc.Service._services: # check if report exist in register of reports raise orm.except_orm( _('System Error !'), _('Report was not registered in system or deactivated !')) return True def _reopen(self, res_id, model): return { 'type': 'ir.actions.act_window', 'view_mode': 'form', 'view_type': 'form', 'res_id': res_id, 'res_model': self._name, 'target': 'new', } def check_if_deferred(self, report_xml, print_ids): extras = report_xml.extras.split(',') if 'deferred_processing' in extras and report_xml.deferred != 'off' and len( print_ids) >= report_xml.deferred_limit: return True return False def start_deferred(self, cr, uid, ids, context=None): this = self.browse(cr, uid, ids[0], context=context) report_xml = self.pool.get('ir.actions.report.xml').browse( cr, uid, context['report_action_id']) deferred_proc_obj = self.pool.get('deferred_processing.task') process_id = deferred_proc_obj.create(cr, uid, {'name': report_xml.name}, context=context) deferred_proc_obj.new_process(cr, uid, process_id, context=context) deferred_proc_obj.start_process_report(cr, uid, process_id, this.print_ids, context['report_action_id'], context=context) mod_obj = self.pool.get('ir.model.data') act_obj = self.pool.get('ir.actions.act_window') mod_id = mod_obj.search( cr, uid, [('name', '=', 'action_deferred_processing_task_deferred_processing')])[0] res_id = mod_obj.read(cr, uid, mod_id, ['res_id'])['res_id'] act_win = act_obj.read(cr, uid, res_id, ['name','type','view_id','res_model','view_type', \ 'search_view_id','view_mode','target','context']) act_win['res_id'] = process_id act_win['view_type'] = 'form' act_win['view_mode'] = 'form,tree' return act_win def simple_print(self, cr, uid, ids, context): this = self.browse(cr, uid, ids[0], context=context) report_xml = self.pool.get('ir.actions.report.xml').browse( cr, uid, context['report_action_id']) data = { 'model': report_xml.model, 'ids': this.print_ids, 'id': context['active_id'], 'report_type': 'aeroo' } if str(report_xml.out_format.id) != this.out_format: report_xml.write({'out_format': this.out_format}, context=context) return { 'type': 'ir.actions.report.xml', 'report_name': report_xml.report_name, 'datas': data, 'context': context } def to_print(self, cr, uid, ids, context=None): if context is None: context = {} this = self.browse(cr, uid, ids[0], context=context) report_xml = self.pool.get('ir.actions.report.xml').browse( cr, uid, context['report_action_id']) self.check_report(report_xml.report_name) print_ids = [] if this.copies <= 0: print_ids = this.print_ids else: while (this.copies): print_ids.extend(this.print_ids) this.copies -= 1 if str(report_xml.out_format.id) != this.out_format: report_xml.write({'out_format': this.out_format}, context=context) if self.check_if_deferred(report_xml, print_ids): this.write( { 'state': 'confirm', 'message': _("This process may take too long for interactive processing. \ It is advisable to defer the process in background. \ Do you want to start a deferred process?"), 'print_ids': print_ids }, context=context) return self._reopen(this.id, this._model) ##### Simple print ##### data = { 'model': report_xml.model, 'ids': print_ids, 'id': context['active_id'], 'report_type': 'aeroo' } return { 'type': 'ir.actions.report.xml', 'report_name': report_xml.report_name, 'datas': data, 'context': context } def _out_format_get(self, cr, uid, context=None): if context is None: context = {} obj = self.pool.get('report.mimetypes') report_action_id = context.get('report_action_id', False) if report_action_id: in_format = self.pool.get('ir.actions.report.xml').read( cr, uid, report_action_id, ['in_format'])['in_format'] ids = obj.search(cr, uid, [('compatible_types', '=', in_format)], context=context) res = obj.read(cr, uid, ids, ['name'], context) return [(str(r['id']), r['name']) for r in res] else: return [] _columns = { 'out_format': fields.selection(_out_format_get, 'Output format', required=True), 'out_format_code': fields.char('Output format code', size=16, required=False, readonly=True), 'copies': fields.integer('Number of copies', required=True), 'message': fields.text('Message'), 'state': fields.selection([ ('draft', 'Draft'), ('confirm', 'Confirm'), ('done', 'Done'), ], 'State', select=True, readonly=True), 'print_ids': fields.serialized(), } def onchange_out_format(self, cr, uid, ids, out_format_id): if not out_format_id: return {} out_format = self.pool.get('report.mimetypes').read( cr, uid, int(out_format_id), ['code']) return {'value': {'out_format_code': out_format['code']}} def _get_default_outformat(field): def get_default_outformat(self, cr, uid, context): report_action_id = context.get('report_action_id', False) if report_action_id: report_xml = self.pool.get('ir.actions.report.xml').browse( cr, uid, report_action_id) return str(getattr(report_xml.out_format, field)) else: return False return get_default_outformat def _get_default_number_of_copies(self, cr, uid, context): report_action_id = context.get('report_action_id', False) if not report_action_id: return False report_xml = self.pool.get('ir.actions.report.xml').browse( cr, uid, context['report_action_id']) return report_xml.copies _defaults = { 'out_format': _get_default_outformat('id'), 'out_format_code': _get_default_outformat('code'), 'copies': _get_default_number_of_copies, 'state': 'draft', 'print_ids': lambda self, cr, uid, ctx: ctx.get('active_ids') }
class AccountStatementLine(orm.Model): """ Add sparse field on the statement line to allow to store all the bank infos that are given by a bank/office. You can then add you own in your module. The idea here is to store all bank/office infos in the additionnal_bank_fields serialized field when importing the file. If many values, add a tab in the bank statement line to store your specific one. Have a look in account_statement_base_import module to see how we've done it. """ _inherit = "account.bank.statement.line" _order = "already_completed desc, date asc" _columns = { 'additionnal_bank_fields': fields.serialized( 'Additionnal infos from bank', help="Used by completion and import system. Adds every field that " "is present in your bank/office statement file"), 'label': fields.sparse(type='char', string='Label', serialization_field='additionnal_bank_fields', help="Generic field to store a label given from the " "bank/office on which we can base the default/standard " "providen rule."), 'already_completed': fields.boolean( "Auto-Completed", help="When this checkbox is ticked, the auto-completion " "process/button will ignore this line."), # Set account_id field as optional by removing required option. 'account_id': fields.many2one('account.account', 'Account'), } _defaults = { 'already_completed': False, } def _get_line_values_from_rules(self, cr, uid, line, rules, context=None): """We'll try to find out the values related to the line based on rules setted on the profile.. We will ignore line for which already_completed is ticked. :return: A dict of dict value that can be passed directly to the write method of the statement line or {}. The first dict has statement line ID as a key: {117009: {'partner_id': 100997, 'account_id': 489L}} """ profile_obj = self.pool['account.statement.profile'] if line.get('already_completed'): return {} # Ask the rule vals = profile_obj._find_values_from_rules(cr, uid, rules, line, context) if vals: vals['id'] = line['id'] return vals return {} def _get_available_columns(self, statement_store, include_serializable=False): """Return writeable by SQL columns""" statement_line_obj = self.pool['account.bank.statement.line'] model_cols = statement_line_obj._columns avail = [ k for k, col in model_cols.iteritems() if not hasattr(col, '_fnct') ] keys = [k for k in statement_store[0].keys() if k in avail] # add sparse fields.. if include_serializable: for k, col in model_cols.iteritems(): if k in statement_store[0].keys() and \ isinstance(col, fields.sparse) and \ col.serialization_field not in keys and \ col._type == 'char': keys.append(col.serialization_field) keys.sort() return keys def _prepare_insert(self, statement, cols): """ Apply column formating to prepare data for SQL inserting Return a copy of statement """ st_copy = statement for k, col in st_copy.iteritems(): if k in cols: st_copy[k] = self._columns[k]._symbol_set[1](col) return st_copy def _prepare_manyinsert(self, statement_store, cols): """ Apply column formating to prepare multiple SQL inserts Return a copy of statement_store """ values = [] for statement in statement_store: values.append(self._prepare_insert(statement, cols)) return values def _serialize_sparse_fields(self, cols, statement_store): """ Serialize sparse fields values in the target serialized field Return a copy of statement_store """ statement_line_obj = self.pool['account.bank.statement.line'] model_cols = statement_line_obj._columns sparse_fields = dict([ (k, col) for k, col in model_cols.iteritems() if isinstance(col, fields.sparse) and col._type == 'char' ]) values = [] for statement in statement_store: to_json_k = set() st_copy = statement.copy() for k, col in sparse_fields.iteritems(): if k in st_copy: to_json_k.add(col.serialization_field) serialized = st_copy.setdefault(col.serialization_field, {}) serialized[k] = st_copy[k] for k in to_json_k: st_copy[k] = simplejson.dumps(st_copy[k]) values.append(st_copy) return values def _insert_lines(self, cr, uid, statement_store, context=None): """ Do raw insert into database because ORM is awfully slow when doing batch write. It is a shame that batch function does not exist""" statement_line_obj = self.pool['account.bank.statement.line'] statement_line_obj.check_access_rule(cr, uid, [], 'create') statement_line_obj.check_access_rights(cr, uid, 'create', raise_exception=True) cols = self._get_available_columns(statement_store, include_serializable=True) statement_store = self._prepare_manyinsert(statement_store, cols) tmp_vals = (', '.join(cols), ', '.join(['%%(%s)s' % i for i in cols])) sql = "INSERT INTO account_bank_statement_line (%s) " \ "VALUES (%s);" % tmp_vals try: cr.executemany( sql, tuple(self._serialize_sparse_fields(cols, statement_store))) except psycopg2.Error as sql_err: cr.rollback() raise orm.except_orm(_("ORM bypass error"), sql_err.pgerror) def _update_line(self, cr, uid, vals, context=None): """ Do raw update into database because ORM is awfully slow when cheking security. TODO / WARM: sparse fields are skipped by the method. IOW, if your completion rule update an sparse field, the updated value will never be stored in the database. It would be safer to call the update method from the ORM for records updating this kind of fields. """ cols = self._get_available_columns([vals]) vals = self._prepare_insert(vals, cols) tmp_vals = (', '.join(['%s = %%(%s)s' % (i, i) for i in cols])) sql = "UPDATE account_bank_statement_line " \ "SET %s where id = %%(id)s;" % tmp_vals try: cr.execute(sql, vals) except psycopg2.Error as sql_err: cr.rollback() raise orm.except_orm(_("ORM bypass error"), sql_err.pgerror)
class dashboard_board(osv.osv): _name = "dashboard.board" _description = "Dashboard" def extra_fields(self, cr, uid, ids, field_names, arg, context=None): result = {} for board in self.browse(cr, uid, ids, context=context): widgets = [] for widget in board.widget_ids: sequence = 0 width = 10 for rel in board.widget_rel: if rel.widget_id == widget.id: sequence = rel.sequence width = rel.width widgets.append({ 'id': widget.id, 'name': widget.name, 'identifier': widget.identifier, 'type': widget.type, 'method': widget.method, 'limit': widget.limit, 'sequence': sequence, 'width': width, 'metrics': widget.metrics, }) result[board.id] = {'widgets': widgets} return result _columns = { 'name': fields.char('Name'), 'global_field_refs': fields.serialized(string='Global Field References'), 'widget_ids': fields.many2many('dashboard.widget', 'dashboard_board_to_widget_rel', id1='board_id', id2='widget_id', string='Widgets', ondelete='cascade'), 'widget_rel': fields.one2many('dashboard.board_to_widget_rel', 'board_id', 'widget relation'), 'period_name': fields.selection((('day', 'Day'), ('week', 'Week'), ('month', 'Month'), ('quarter', 'Quarter'), ('semester', 'Semester'), ('year', 'Year')), 'Period Name'), 'period_type': fields.selection((('rolling', 'Rolling'), ('calendar', 'Calendar')), 'Period Type'), 'period_start_at': fields.date('Period Start', help="override Period Name and Period Type if defined"), 'period_end_at': fields.date('Period End', help="override Period Name and Period Type if defined"), # get widget details directly by JSON-RPC (no need to query dashboard.widget on web side) 'widgets': fields.function(extra_fields, method=True, multi=True, type='serialized', string='Metrics Data', readonly=True), } _defaults = { 'period_name': 'month', 'period_type': 'calendar', 'global_field_refs': [] }
class product_product(Model): _inherit = "product.product" _columns = { 'attribute_set_id': fields.many2one('attribute.set', 'Attribute Set'), 'attribute_custom_variant': fields.serialized('Custom Variant Attributes'), } def open_attributes(self, cr, uid, ids, context=None): ir_model_data_obj = self.pool.get('ir.model.data') ir_model_data_id = ir_model_data_obj.search( cr, uid, [['model', '=', 'ir.ui.view'], ['name', '=', 'product_attributes_form_view']], context=context) if ir_model_data_id: res_id = ir_model_data_obj.read(cr, uid, ir_model_data_id, fields=['res_id'])[0]['res_id'] set_id = self.read(cr, uid, ids, fields=['attribute_set_id'], context=context)[0]['attribute_set_id'] if not set_id: raise except_osv( _('User Error'), _('Please choose an attribute set before opening the product attributes' )) return { 'name': 'Product Attributes', 'view_type': 'form', 'view_mode': 'form', 'view_id': [res_id], 'res_model': self._name, 'context': "{'set_id': %s, 'open_attributes': %s}" % (set_id[0], True), 'type': 'ir.actions.act_window', 'nodestroy': True, 'target': 'new', 'res_id': ids and ids[0] or False, } def save_and_close_product_attributes(self, cr, uid, ids, context=None): return {'type': 'ir.actions.act_window_close'} def _build_attribute_field(self, cr, uid, page, attribute, context=None): parent = page kwargs = {'name': "%s" % attribute.name} parent = etree.SubElement(page, 'group', colspan="2", col="4") if attribute.ttype == 'many2many': sep = etree.SubElement(parent, 'separator', string="%s" % attribute.field_description, colspan="4") kwargs['nolabel'] = "1" #if attribute.ttype in ['many2one', 'many2many']: if attribute.attribute_type in ['select', 'multiselect']: kwargs[ 'domain'] = "[('attribute_id', '=', %s)]" % attribute.attribute_id.id field = etree.SubElement(parent, 'field', **kwargs) return parent def _build_attributes_notebook(self, cr, uid, set_id, context=None): attribute_set = self.pool.get('attribute.set').browse(cr, uid, set_id, context=context) notebook = etree.Element('notebook', name="attributes_notebook", colspan="4") toupdate_fields = [] for group in attribute_set.attribute_group_ids: page = etree.SubElement(notebook, 'page', string=group.name.capitalize()) for attribute in group.attribute_ids: toupdate_fields.append(attribute.name) self._build_attribute_field(cr, uid, page, attribute, context=context) return notebook, toupdate_fields def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False): result = super(product_product, self).fields_view_get(cr, uid, view_id, view_type, context, toolbar=toolbar, submenu=submenu) if not context: context = {} attr_set_obj = self.pool.get('attribute.set') if view_type == 'form': eview = etree.fromstring(result['arch']) #hide button under the name button = eview.xpath("//button[@name='open_attributes']") if button: button = button[0] button.getparent().remove(button) set_ids = attr_set_obj.search(cr, uid, []) for set_id in set_ids: attributes_notebook, toupdate_fields = self._build_attributes_notebook( cr, uid, set_id, context=context) result['fields'].update( self.fields_get(cr, uid, toupdate_fields, context)) main_page = etree.Element( 'page', string=_('Custom Attributes'), modifiers='{"invisible": [["attribute_set_id", "!=", ' + str(set_id) + ']]}') main_page.append(attributes_notebook) #info_page = eview.xpath("//page[@string='Information']")[0] info_page = eview.xpath("//page")[0] info_page.addnext(main_page) result['arch'] = etree.tostring(eview, pretty_print=True) return result
class IrModelExport(Model): _name = 'ir.model.export' _description = 'Export' _rec_name = 'create_date' _order = 'create_date desc' def __init__(self, pool, cr): super(IrModelExport, self).__init__(pool, cr) setattr(Registry, 'load', state_cleaner(getattr(Registry, 'load'))) def _get_line_count(self, cr, uid, ids, name, arg, context=None): res = {} for export in self.browse(cr, uid, ids, context): if export.export_tmpl_id.link_resources: res[export.id] = len(export.line_ids) else: res[export.id] = len(export.resource_ids) return res _columns = { 'export_tmpl_id': fields.many2one('ir.model.export.template', 'Template', required=True, ondelete='cascade'), 'model_id': fields.related('export_tmpl_id', 'model_id', type='many2one', relation='ir.model', string='Object', readonly=True), 'model': fields.related('model_id', 'model', type='char', string='Model', readonly=True), 'domain': fields.related('export_tmpl_id', 'domain', type='char', string='Domain', readonly=True), 'limit': fields.related('export_tmpl_id', 'limit', type='integer', string='Limit', readonly=True), 'offset': fields.integer('Offset'), 'order': fields.related('export_tmpl_id', 'order', type='char', string='Order by', readonly=True), 'unique': fields.related('export_tmpl_id', 'unique', type='boolean', string='Unique', readonly=True), 'method': fields.related('export_tmpl_id', 'method', type='char', string='Method', readonly=True), 'action_id': fields.related('export_tmpl_id', 'action_id', type='many2one', relation='ir.actions.server', string='Action', readonly=True), 'create_date': fields.datetime('Creation Date', readonly=True), 'create_uid': fields.many2one('res.users', 'Creation User', readonly=True), 'to_date': fields.datetime('End Date', readonly=True), 'line_ids': fields.one2many('ir.model.export.line', 'export_id', 'Lines'), 'line_count': fields.function(_get_line_count, method=True, type='integer', string='Lines'), 'resource_ids': fields.serialized('Resource Ids', readonly=True), 'log_ids': fields.one2many('smile.log', 'res_id', 'Logs', domain=[('model_name', '=', 'ir.model.export')], readonly=True), 'state': fields.selection(STATES, "State", readonly=True, required=True), 'exception': fields.text('Exception'), } _defaults = { 'resource_ids': [], } def create_new_cr(self, dbname, uid, vals, context): db = pooler.get_db(dbname) cr = db.cursor() try: export_id = self.pool.get('ir.model.export').create( cr, uid, vals, context) cr.commit() except Exception, e: _logger.error("Could not create export %s: %s" % (export_id, _get_exception_message(e))) raise e finally: