def get_cache(self, domain, fields): if not self.cache or domain != self.get_product_domain() or fields != self.get_product_fields(): self.product_domain = str(domain) self.product_fields = str(fields) self.refresh_cache() return cPickle.loads(self.cache)
def get_cache(self, domain, fields): if not self.cache or domain != self.get_product_domain( ) or fields != self.get_product_fields(): self.product_domain = str(domain) self.product_fields = str(fields) self.refresh_cache() return cPickle.loads(self.cache)
def get_defaults(self, cr, uid, model, condition=False): """Returns any default values that are defined for the current model and user, (and match ``condition``, if specified), previously registered via :meth:`~.set_default`. Defaults are global to a model, not field-specific, but an optional ``condition`` can be provided to restrict matching default values to those that were defined for the same condition (usually based on another field's value). Default values also have priorities depending on whom they apply to: only the highest priority value will be returned for any field. See :meth:`~.set_default` for more details. :param string model: model name :param string condition: optional condition specification that can be used to restrict the applicability of the default values (e.g. based on another field's value). This is an opaque string as far as the API is concerned, but client stacks typically use single-field conditions in the form ``'key=stringified_value'``. (Currently, the condition is trimmed to 200 characters, so values that share the same first 200 characters always match) :return: list of default values tuples of the form ``(id, field_name, value)`` (``id`` is the ID of the default entry, usually irrelevant) """ # use a direct SQL query for performance reasons, # this is called very often query = """SELECT v.id, v.name, v.value FROM ir_values v LEFT JOIN res_users u ON (v.user_id = u.id) WHERE v.key = %%s AND v.model = %%s AND (v.user_id = %%s OR v.user_id IS NULL) AND (v.company_id IS NULL OR v.company_id = (SELECT company_id from res_users where id = %%s) ) %s ORDER BY v.user_id, u.company_id""" params = ('default', model, uid, uid) if condition: query %= 'AND v.key2 = %s' params += (condition[:200], ) else: query %= 'AND v.key2 is NULL' cr.execute(query, params) # keep only the highest priority default for each field defaults = {} for row in cr.dictfetchall(): defaults.setdefault(row['name'], (row['id'], row['name'], pickle.loads(row['value'].encode('utf-8')))) return defaults.values()
def _value_unpickle(self, cursor, user, ids, name, arg, context=None): res = {} for record in self.browse(cursor, user, ids, context=context): value = record[name[:-9]] if record.key == 'default' and value: # default values are pickled on the fly try: value = str(pickle.loads(value)) except Exception: pass res[record.id] = value return res
def _allow_automatic_convertion_to_saleorder (self,cr,uid): search_criteria = [ ('key', '=', 'default'), ('model', '=', 'sale.config.settings'), ('name', '=', 'convert_dispensed'), ] ir_values_obj = self.pool.get('ir.values') defaults = ir_values_obj.browse(cr, uid, ir_values_obj.search(cr, uid, search_criteria)) if defaults: default_convert_dispensed = pickle.loads(defaults[0].value.encode('utf-8')) return default_convert_dispensed return False
def get_defaults(self, cr, uid, model, condition=False): """Returns any default values that are defined for the current model and user, (and match ``condition``, if specified), previously registered via :meth:`~.set_default`. Defaults are global to a model, not field-specific, but an optional ``condition`` can be provided to restrict matching default values to those that were defined for the same condition (usually based on another field's value). Default values also have priorities depending on whom they apply to: only the highest priority value will be returned for any field. See :meth:`~.set_default` for more details. :param string model: model name :param string condition: optional condition specification that can be used to restrict the applicability of the default values (e.g. based on another field's value). This is an opaque string as far as the API is concerned, but client stacks typically use single-field conditions in the form ``'key=stringified_value'``. (Currently, the condition is trimmed to 200 characters, so values that share the same first 200 characters always match) :return: list of default values tuples of the form ``(id, field_name, value)`` (``id`` is the ID of the default entry, usually irrelevant) """ # use a direct SQL query for performance reasons, # this is called very often query = """SELECT v.id, v.name, v.value FROM ir_values v LEFT JOIN res_users u ON (v.user_id = u.id) WHERE v.key = %%s AND v.model = %%s AND (v.user_id = %%s OR v.user_id IS NULL) AND (v.company_id IS NULL OR v.company_id = (SELECT company_id from res_users where id = %%s) ) %s ORDER BY v.user_id, u.company_id""" params = ('default', model, uid, uid) if condition: query %= 'AND v.key2 = %s' params += (condition[:200],) else: query %= 'AND v.key2 is NULL' cr.execute(query, params) # keep only the highest priority default for each field defaults = {} for row in cr.dictfetchall(): defaults.setdefault(row['name'], (row['id'], row['name'], pickle.loads(row['value'].encode('utf-8')))) return defaults.values()
def _allow_automatic_convertion_to_saleorder(self, cr, uid): search_criteria = [ ('key', '=', 'default'), ('model', '=', 'sale.config.settings'), ('name', '=', 'convert_dispensed'), ] ir_values_obj = self.pool.get('ir.values') defaults = ir_values_obj.browse( cr, uid, ir_values_obj.search(cr, uid, search_criteria)) if defaults: default_convert_dispensed = pickle.loads( defaults[0].value.encode('utf-8')) return default_convert_dispensed return False
def get_default(self, cr, uid, model, field_name, for_all_users=True, company_id=False, condition=False): """ Return the default value defined for model, field_name, users, company and condition. Return ``None`` if no such default exists. """ search_criteria = [ ('key', '=', 'default'), ('key2', '=', condition and condition[:200]), ('model', '=', model), ('name', '=', field_name), ('user_id', '=', False if for_all_users else uid), ('company_id','=', company_id) ] defaults = self.browse(cr, uid, self.search(cr, uid, search_criteria)) return pickle.loads(defaults[0].value.encode('utf-8')) if defaults else None
def product_id_change(self, cr, uid, ids, pricelist, product, qty=0, uom=False, qty_uos=0, uos=False, name='', partner_id=False, lang=False, update_tax=True, date_order=False, packaging=False, fiscal_position=False, flag=False, context=None): context = context or {} lang = lang or context.get('lang', False) if not partner_id: raise osv.except_osv( _('No Customer Defined !'), _('Before choosing a product,\n select a customer in the sales form.' )) warning = {} product_uom_obj = self.pool.get('product.uom') partner_obj = self.pool.get('res.partner') product_obj = self.pool.get('product.product') if partner_id: lang = partner_obj.browse(cr, uid, partner_id).lang context_partner = {'lang': lang, 'partner_id': partner_id} if not product: return { 'value': { 'th_weight': 0, 'batch_id': None, 'price_unit': 0.0, 'product_uos_qty': qty }, 'domain': { 'product_uom': [], 'product_uos': [] } } if not date_order: date_order = time.strftime(DEFAULT_SERVER_DATE_FORMAT) result = {} warning_msgs = '' product_obj = product_obj.browse(cr, uid, product, context=context_partner) #-----------------populating batch id for sale order line item----------------------------------------------------------- stock_prod_lot = self.pool.get('stock.production.lot') sale_price = 0.0 result['batch_name'] = None result['batch_id'] = None result['expiry_date'] = None prodlot_context = self._get_prodlot_context(cr, uid, context=context) for prodlot_id in stock_prod_lot.search( cr, uid, [('product_id', '=', product_obj.id)], context=prodlot_context): prodlot = stock_prod_lot.browse(cr, uid, prodlot_id, context=prodlot_context) life_date = prodlot.life_date and datetime.strptime( prodlot.life_date, tools.DEFAULT_SERVER_DATETIME_FORMAT) if life_date and life_date < datetime.today(): continue if qty <= prodlot.future_stock_forecast: sale_price = prodlot.sale_price result['batch_name'] = prodlot.name result['batch_id'] = prodlot.id result['expiry_date'] = life_date.strftime('%d/%m/%Y') if ( type(life_date) == datetime) else None break #----------------------------------------------------------------- uom2 = False if uom: uom2 = product_uom_obj.browse(cr, uid, uom) if product_obj.uom_id.category_id.id != uom2.category_id.id: uom = False if uos: if product_obj.uos_id: uos2 = product_uom_obj.browse(cr, uid, uos) if product_obj.uos_id.category_id.id != uos2.category_id.id: uos = False else: uos = False fpos = fiscal_position and self.pool.get( 'account.fiscal.position').browse(cr, uid, fiscal_position) or False if update_tax: #The quantity only have changed tax_id = product_obj.taxes_id if not tax_id: search_criteria = [ ('key', '=', 'default'), ('model', '=', 'product.product'), ('name', '=', 'taxes_id'), ] ir_values_obj = self.pool.get('ir.values') defaults = ir_values_obj.browse( cr, uid, ir_values_obj.search(cr, uid, search_criteria)) default_tax_id = pickle.loads( defaults[0].value.encode('utf-8')) if defaults else None if default_tax_id: tax_id = self.pool.get('account.tax').browse( cr, uid, default_tax_id) result['tax_id'] = self.pool.get( 'account.fiscal.position').map_tax(cr, uid, fpos, tax_id) if not flag: result['name'] = self.pool.get('product.product').name_get( cr, uid, [product_obj.id], context=context_partner)[0][1] if product_obj.description_sale: result['name'] += '\n' + product_obj.description_sale domain = {} if (not uom) and (not uos): result['product_uom'] = product_obj.uom_id.id if product_obj.uos_id: result['product_uos'] = product_obj.uos_id.id result['product_uos_qty'] = qty * product_obj.uos_coeff uos_category_id = product_obj.uos_id.category_id.id else: result['product_uos'] = False result['product_uos_qty'] = qty uos_category_id = False result['th_weight'] = qty * product_obj.weight domain = { 'product_uom': [('category_id', '=', product_obj.uom_id.category_id.id)], 'product_uos': [('category_id', '=', uos_category_id)] } elif uos and not uom: # only happens if uom is False result[ 'product_uom'] = product_obj.uom_id and product_obj.uom_id.id result['product_uom_qty'] = qty_uos / product_obj.uos_coeff result[ 'th_weight'] = result['product_uom_qty'] * product_obj.weight elif uom: # whether uos is set or not default_uom = product_obj.uom_id and product_obj.uom_id.id q = product_uom_obj._compute_qty(cr, uid, uom, qty, default_uom) if product_obj.uos_id: result['product_uos'] = product_obj.uos_id.id result['product_uos_qty'] = qty * product_obj.uos_coeff else: result['product_uos'] = False result['product_uos_qty'] = qty result[ 'th_weight'] = q * product_obj.weight # Round the quantity up if not uom2: uom2 = product_obj.uom_id # get unit price if not pricelist: warn_msg = _( 'You have to select a pricelist or a customer in the sales form !\n' 'Please set one before choosing a product.') warning_msgs += _("No Pricelist ! : ") + warn_msg + "\n\n" else: price = self.pool.get('product.pricelist').price_get( cr, uid, [pricelist], product, qty or 1.0, partner_id, { 'uom': uom or result.get('product_uom'), 'date': date_order, })[pricelist] if price is False: warn_msg = _( "Cannot find a pricelist line matching this product and quantity.\n" "You have to change either the product, the quantity or the pricelist." ) warning_msgs += _( "No valid pricelist line found ! :") + warn_msg + "\n\n" else: result.update({'price_unit': self._price(price, sale_price)}) if warning_msgs: warning = { 'title': _('Configuration Error!'), 'message': warning_msgs } res = {'value': result, 'domain': domain, 'warning': warning} # Code extracted From sale_stock.py if not product: res['value'].update({'product_packaging': False}) return res #update of result obtained in super function res_packing = self.product_packaging_change(cr, uid, ids, pricelist, product, qty, uom, partner_id, packaging, context=context) res['value'].update(res_packing.get('value', {})) warning_msgs = res_packing.get( 'warning') and res_packing['warning']['message'] or '' res['value']['delay'] = (product_obj.sale_delay or 0.0) res['value']['type'] = product_obj.procure_method return res
def reverse_anonymize_database(self, cr, uid, ids, context=None): """Set the 'clear' state to defined fields""" ir_model_fields_anonymization_model = self.pool.get( 'ir.model.fields.anonymization') anonymization_history_model = self.pool.get( 'ir.model.fields.anonymization.history') # create a new history record: vals = { 'date': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'), 'state': 'started', 'direction': 'anonymized -> clear', } history_id = anonymization_history_model.create(cr, uid, vals) # check that all the defined fields are in the 'anonymized' state state = ir_model_fields_anonymization_model._get_global_state( cr, uid, context=context) if state == 'clear': raise UserError( _("The database is not currently anonymized, you cannot reverse the anonymization." )) elif state == 'unstable': msg = _( "The database anonymization is currently in an unstable state. Some fields are anonymized," " while some fields are not anonymized. You should try to solve this problem before trying to do anything." ) raise UserError(msg) wizards = self.browse(cr, uid, ids, context=context) for wizard in wizards: if not wizard.file_import: msg = _( "It is not possible to reverse the anonymization process without supplying the anonymization export file." ) self._raise_after_history_update(cr, uid, history_id, 'Error !', msg) # reverse the anonymization: # load the pickle file content into a data structure: data = pickle.loads(base64.decodestring(wizard.file_import)) migration_fix_obj = self.pool.get( 'ir.model.fields.anonymization.migration.fix') fix_ids = migration_fix_obj.search(cr, uid, [ ('target_version', '=', '.'.join(map(str, version_info[:2]))) ]) fixes = migration_fix_obj.read(cr, uid, fix_ids, [ 'model_name', 'field_name', 'query', 'query_type', 'sequence' ]) fixes = group(fixes, ('model_name', 'field_name')) for line in data: queries = [] table_name = self.pool[line['model_id']]._table if line[ 'model_id'] in self.pool else None # check if custom sql exists: key = (line['model_id'], line['field_id']) custom_updates = fixes.get(key) if custom_updates: custom_updates.sort(key=itemgetter('sequence')) queries = [(record['query'], record['query_type']) for record in custom_updates if record['query_type']] elif table_name: queries = [( "update \"%(table)s\" set \"%(field)s\" = %%(value)s where id = %%(id)s" % { 'table': table_name, 'field': line['field_id'], }, 'sql')] for query in queries: if query[1] == 'sql': sql = query[0] cr.execute(sql, { 'value': line['value'], 'id': line['id'] }) elif query[1] == 'python': raw_code = query[0] code = raw_code % line eval(code) else: raise Exception( "Unknown query type '%s'. Valid types are: sql, python." % (query['query_type'], )) # update the anonymization fields: ir_model_fields_anonymization_model = self.pool.get( 'ir.model.fields.anonymization') field_ids = ir_model_fields_anonymization_model.search( cr, uid, [('state', '<>', 'not_existing')], context=context) values = { 'state': 'clear', } ir_model_fields_anonymization_model.write(cr, uid, field_ids, values, context=context) # add a result message in the wizard: msg = '\n'.join([ "Successfully reversed the anonymization.", "", ]) self.write(cr, uid, ids, {'msg': msg}) # update the history record: anonymization_history_model.write( cr, uid, history_id, { 'field_ids': [[6, 0, field_ids]], 'msg': msg, 'filepath': False, 'state': 'done', }) # handle the view: view_id = self.pool['ir.model.data'].xmlid_to_res_id( cr, uid, 'anonymization.view_ir_model_fields_anonymize_wizard_form') return { 'res_id': ids[0], 'view_id': [view_id], 'view_type': 'form', "view_mode": 'form', 'res_model': 'ir.model.fields.anonymize.wizard', 'type': 'ir.actions.act_window', 'context': { 'step': 'just_desanonymized' }, 'target': 'new', }
def product_id_change(self, cr, uid, ids, pricelist, product, qty=0, uom=False, qty_uos=0, uos=False, name='', partner_id=False, lang=False, update_tax=True, date_order=False, packaging=False, fiscal_position=False, flag=False, context=None): context = context or {} lang = lang or context.get('lang',False) if not partner_id: raise osv.except_osv(_('No Customer Defined !'), _('Before choosing a product,\n select a customer in the sales form.')) warning = {} product_uom_obj = self.pool.get('product.uom') partner_obj = self.pool.get('res.partner') product_obj = self.pool.get('product.product') if partner_id: lang = partner_obj.browse(cr, uid, partner_id).lang context_partner = {'lang': lang, 'partner_id': partner_id} if not product: return {'value': {'th_weight': 0, 'batch_id': None, 'price_unit': 0.0, 'product_uos_qty': qty}, 'domain': {'product_uom': [], 'product_uos': []}} if not date_order: date_order = time.strftime(DEFAULT_SERVER_DATE_FORMAT) result = {} warning_msgs = '' product_obj = product_obj.browse(cr, uid, product, context=context_partner) #-----------------populating batch id for sale order line item----------------------------------------------------------- stock_prod_lot = self.pool.get('stock.production.lot') sale_price = 0.0 result['batch_name'] = None result['batch_id'] = None result['expiry_date'] = None prodlot_context = self._get_prodlot_context(cr, uid, context=context) for prodlot_id in stock_prod_lot.search(cr, uid,[('product_id','=',product_obj.id)],context=prodlot_context): prodlot = stock_prod_lot.browse(cr, uid, prodlot_id, context=prodlot_context) life_date = prodlot.life_date and datetime.strptime(prodlot.life_date, tools.DEFAULT_SERVER_DATETIME_FORMAT) if life_date and life_date < datetime.today(): continue if qty <= prodlot.future_stock_forecast: sale_price = prodlot.sale_price result['batch_name'] = prodlot.name result['batch_id'] = prodlot.id result['expiry_date'] = life_date.strftime('%d/%m/%Y') if (type(life_date) == 'datetime.datetime') else None break #----------------------------------------------------------------- uom2 = False if uom: uom2 = product_uom_obj.browse(cr, uid, uom) if product_obj.uom_id.category_id.id != uom2.category_id.id: uom = False if uos: if product_obj.uos_id: uos2 = product_uom_obj.browse(cr, uid, uos) if product_obj.uos_id.category_id.id != uos2.category_id.id: uos = False else: uos = False fpos = fiscal_position and self.pool.get('account.fiscal.position').browse(cr, uid, fiscal_position) or False if update_tax: #The quantity only have changed tax_id = product_obj.taxes_id if not tax_id: search_criteria = [ ('key', '=', 'default'), ('model', '=', 'product.product'), ('name', '=', 'taxes_id'), ] ir_values_obj = self.pool.get('ir.values') defaults = ir_values_obj.browse(cr, uid, ir_values_obj.search(cr, uid, search_criteria)) default_tax_id = pickle.loads(defaults[0].value.encode('utf-8')) if defaults else None if default_tax_id: tax_id = self.pool.get('account.tax').browse(cr, uid, default_tax_id) result['tax_id'] = self.pool.get('account.fiscal.position').map_tax(cr, uid, fpos, tax_id) if not flag: result['name'] = self.pool.get('product.product').name_get(cr, uid, [product_obj.id], context=context_partner)[0][1] if product_obj.description_sale: result['name'] += '\n'+product_obj.description_sale domain = {} if (not uom) and (not uos): result['product_uom'] = product_obj.uom_id.id if product_obj.uos_id: result['product_uos'] = product_obj.uos_id.id result['product_uos_qty'] = qty * product_obj.uos_coeff uos_category_id = product_obj.uos_id.category_id.id else: result['product_uos'] = False result['product_uos_qty'] = qty uos_category_id = False result['th_weight'] = qty * product_obj.weight domain = {'product_uom': [('category_id', '=', product_obj.uom_id.category_id.id)], 'product_uos': [('category_id', '=', uos_category_id)]} elif uos and not uom: # only happens if uom is False result['product_uom'] = product_obj.uom_id and product_obj.uom_id.id result['product_uom_qty'] = qty_uos / product_obj.uos_coeff result['th_weight'] = result['product_uom_qty'] * product_obj.weight elif uom: # whether uos is set or not default_uom = product_obj.uom_id and product_obj.uom_id.id q = product_uom_obj._compute_qty(cr, uid, uom, qty, default_uom) if product_obj.uos_id: result['product_uos'] = product_obj.uos_id.id result['product_uos_qty'] = qty * product_obj.uos_coeff else: result['product_uos'] = False result['product_uos_qty'] = qty result['th_weight'] = q * product_obj.weight # Round the quantity up if not uom2: uom2 = product_obj.uom_id # get unit price if not pricelist: warn_msg = _('You have to select a pricelist or a customer in the sales form !\n' 'Please set one before choosing a product.') warning_msgs += _("No Pricelist ! : ") + warn_msg +"\n\n" else: price = self.pool.get('product.pricelist').price_get(cr, uid, [pricelist], product, qty or 1.0, partner_id, { 'uom': uom or result.get('product_uom'), 'date': date_order, })[pricelist] if price is False: warn_msg = _("Cannot find a pricelist line matching this product and quantity.\n" "You have to change either the product, the quantity or the pricelist.") warning_msgs += _("No valid pricelist line found ! :") + warn_msg +"\n\n" else: result.update({'price_unit': self._price(price,sale_price)}) if warning_msgs: warning = { 'title': _('Configuration Error!'), 'message' : warning_msgs } res = {'value': result, 'domain': domain, 'warning': warning} # Code extracted From sale_stock.py if not product: res['value'].update({'product_packaging': False}) return res #update of result obtained in super function res_packing = self.product_packaging_change(cr, uid, ids, pricelist, product, qty, uom, partner_id, packaging, context=context) res['value'].update(res_packing.get('value', {})) warning_msgs = res_packing.get('warning') and res_packing['warning']['message'] or '' res['value']['delay'] = (product_obj.sale_delay or 0.0) res['value']['type'] = product_obj.procure_method return res