def __init__(self, pool, cr): """ Dynamically add columns """ super(report_prompt_class, self).__init__(pool, cr) for counter in range(0, MAX_PARAMS): field_name = PARAM_XXX_STRING_VALUE % counter self._columns[field_name] = fields.char('String Value', size=64) field_name = PARAM_XXX_BOOLEAN_VALUE % counter self._columns[field_name] = fields.boolean('Boolean Value') field_name = PARAM_XXX_INTEGER_VALUE % counter self._columns[field_name] = fields.integer('Integer Value') field_name = PARAM_XXX_NUMBER_VALUE % counter self._columns[field_name] = fields.float('Number Value') field_name = PARAM_XXX_DATE_VALUE % counter self._columns[field_name] = fields.date('Date Value') field_name = PARAM_XXX_TIME_VALUE % counter self._columns[field_name] = fields.datetime('Time Value') self.paramfile = False
class users(osv.osv): __admin_ids = {} _uid_cache = {} _name = "res.users" _order = 'name' WELCOME_MAIL_SUBJECT = u"Welcome to OpenERP" WELCOME_MAIL_BODY = u"An OpenERP account has been created for you, "\ "\"%(name)s\".\n\nYour login is %(login)s, "\ "you should ask your supervisor or system administrator if you "\ "haven't been given your password yet.\n\n"\ "If you aren't %(name)s, this email reached you errorneously, "\ "please delete it." def get_welcome_mail_subject(self, cr, uid, context=None): """ Returns the subject of the mail new users receive (when created via the res.config.users wizard), default implementation is to return config_users.WELCOME_MAIL_SUBJECT """ return self.WELCOME_MAIL_SUBJECT def get_welcome_mail_body(self, cr, uid, context=None): """ Returns the subject of the mail new users receive (when created via the res.config.users wizard), default implementation is to return config_users.WELCOME_MAIL_BODY """ return self.WELCOME_MAIL_BODY def get_current_company(self, cr, uid): cr.execute( 'select company_id, res_company.name from res_users left join res_company on res_company.id = company_id where res_users.id=%s' % uid) return cr.fetchall() def send_welcome_email(self, cr, uid, id, context=None): if isinstance(id, list): id = id[0] user = self.read(cr, uid, id, ['email', 'login', 'name', 'user_email'], context=context) email = user['email'] or user['user_email'] ir_mail_server = self.pool.get('ir.mail_server') msg = ir_mail_server.build_email( email_from=None, # take config default email_to=[email], subject=self.get_welcome_mail_subject(cr, uid, context=context), body=(self.get_welcome_mail_body(cr, uid, context=context) % user)) return ir_mail_server.send_email(cr, uid, msg, context=context) def _set_interface_type(self, cr, uid, ids, name, value, arg, context=None): """Implementation of 'view' function field setter, sets the type of interface of the users. @param name: Name of the field @param arg: User defined argument @param value: new value returned @return: True/False """ if not value or value not in ['simple', 'extended']: return False group_obj = self.pool.get('res.groups') extended_group_id = group_obj.get_extended_interface_group( cr, uid, context=context) # First always remove the users from the group (avoids duplication if called twice) self.write(cr, uid, ids, {'groups_id': [(3, extended_group_id)]}, context=context) # Then add them back if requested if value == 'extended': self.write(cr, uid, ids, {'groups_id': [(4, extended_group_id)]}, context=context) return True def _get_interface_type(self, cr, uid, ids, name, args, context=None): """Implementation of 'view' function field getter, returns the type of interface of the users. @param field_name: Name of the field @param arg: User defined argument @return: Dictionary of values """ group_obj = self.pool.get('res.groups') extended_group_id = group_obj.get_extended_interface_group( cr, uid, context=context) extended_users = group_obj.read(cr, uid, extended_group_id, ['users'], context=context)['users'] return dict( zip(ids, [ 'extended' if user in extended_users else 'simple' for user in ids ])) def _set_new_password(self, cr, uid, id, name, value, args, context=None): if value is False: # Do not update the password if no value is provided, ignore silently. # For example web client submits False values for all empty fields. return if uid == id: # To change their own password users must use the client-specific change password wizard, # so that the new password is immediately used for further RPC requests, otherwise the user # will face unexpected 'Access Denied' exceptions. raise osv.except_osv( _('Operation Canceled'), _('Please use the change password wizard (in User Preferences or User menu) to change your own password.' )) self.write(cr, uid, id, {'password': value}) def _get_password(self, cr, uid, ids, arg, karg, context=None): return dict.fromkeys(ids, '') _columns = { 'id': fields.integer('ID'), 'name': fields.char('User Name', size=64, required=True, select=True, help="The new user's real name, used for searching" " and most listings"), 'login': fields.char('Login', size=64, required=True, help="Used to log into the system"), 'password': fields.char( 'Password', size=64, invisible=True, help= "Keep empty if you don't want the user to be able to connect on the system." ), 'new_password': fields.function( _get_password, type='char', size=64, fnct_inv=_set_new_password, string='Set password', help= "Specify a value only when creating a user or if you're changing the user's password, " "otherwise leave empty. After a change of password, the user has to login again." ), 'user_email': fields.char('Email', size=64), 'signature': fields.text('Signature'), 'active': fields.boolean('Active'), 'action_id': fields.many2one( 'ir.actions.actions', 'Home Action', help= "If specified, this action will be opened at logon for this user, in addition to the standard menu." ), 'menu_id': fields.many2one( 'ir.actions.actions', 'Menu Action', help= "If specified, the action will replace the standard menu for this user." ), 'groups_id': fields.many2many('res.groups', 'res_groups_users_rel', 'uid', 'gid', 'Groups'), # Special behavior for this field: res.company.search() will only return the companies # available to the current user (should be the user's companies?), when the user_preference # context is set. 'company_id': fields.many2one('res.company', 'Company', required=True, help="The company this user is currently working for.", context={'user_preference': True}), 'company_ids': fields.many2many('res.company', 'res_company_users_rel', 'user_id', 'cid', 'Companies'), 'context_lang': fields.selection( _lang_get, 'Language', required=True, help= "The default language used in the graphical user interface, when translations are available. To add a new language, you can use the 'Load an Official Translation' wizard available from the 'Administration' menu." ), 'context_tz': fields.selection( _tz_get, 'Timezone', size=64, help= "The user's timezone, used to output proper date and time values inside printed reports. " "It is important to set a value for this field. You should use the same timezone " "that is otherwise used to pick and render date and time values: your computer's timezone." ), 'view': fields.function( _get_interface_type, type='selection', fnct_inv=_set_interface_type, selection=[('simple', 'Simplified'), ('extended', 'Extended')], string='Interface', help= "OpenERP offers a simplified and an extended user interface. If you use OpenERP for the first time we strongly advise you to select the simplified interface, which has less features but is easier to use. You can switch to the other interface from the User/Preferences menu at any time." ), 'menu_tips': fields.boolean( 'Menu Tips', help= "Check out this box if you want to always display tips on each menu action" ), 'date': fields.datetime('Latest Connection', readonly=True), 'avatar': fields.binary('Image', help='', readonly=False), } def on_change_company_id(self, cr, uid, ids, company_id): return { 'warning': { 'title': _("Company Switch Warning"), 'message': _("Please keep in mind that documents currently displayed may not be relevant after switching to another company. If you have unsaved changes, please make sure to save and close all forms before switching to a different company. (You can click on Cancel in the User Preferences now)" ), } } def read(self, cr, uid, ids, fields=None, context=None, load='_classic_read'): def override_password(o): if 'password' in o and ('id' not in o or o['id'] != uid): o['password'] = '******' return o result = super(users, self).read(cr, uid, ids, fields, context, load) canwrite = self.pool.get('ir.model.access').check( cr, uid, 'res.users', 'write', False) if not canwrite: if isinstance(ids, (int, float)): result = override_password(result) else: result = map(override_password, result) return result def _check_company(self, cr, uid, ids, context=None): return all( ((this.company_id in this.company_ids) or not this.company_ids) for this in self.browse(cr, uid, ids, context)) _constraints = [ (_check_company, 'The chosen company is not in the allowed companies for this user', ['company_id', 'company_ids']), ] _sql_constraints = [('login_key', 'UNIQUE (login)', 'You can not have two users with the same login !')] def _get_email_from(self, cr, uid, ids, context=None): if not isinstance(ids, list): ids = [ids] res = dict.fromkeys(ids, False) for user in self.browse(cr, uid, ids, context=context): if user.user_email: res[user.id] = "%s <%s>" % (user.name, user.user_email) return res def _get_admin_id(self, cr): if self.__admin_ids.get(cr.dbname) is None: ir_model_data_obj = self.pool.get('ir.model.data') mdid = ir_model_data_obj._get_id(cr, 1, 'base', 'user_root') self.__admin_ids[cr.dbname] = ir_model_data_obj.read( cr, 1, [mdid], ['res_id'])[0]['res_id'] return self.__admin_ids[cr.dbname] def _get_company(self, cr, uid, context=None, uid2=False): if not uid2: uid2 = uid user = self.pool.get('res.users').read(cr, uid, uid2, ['company_id'], context) company_id = user.get('company_id', False) return company_id and company_id[0] or False def _get_companies(self, cr, uid, context=None): c = self._get_company(cr, uid, context) if c: return [c] return False def _get_menu(self, cr, uid, context=None): dataobj = self.pool.get('ir.model.data') try: model, res_id = dataobj.get_object_reference( cr, uid, 'base', 'action_menu_admin') if model != 'ir.actions.act_window': return False return res_id except ValueError: return False def _get_group(self, cr, uid, context=None): dataobj = self.pool.get('ir.model.data') result = [] try: dummy, group_id = dataobj.get_object_reference( cr, 1, 'base', 'group_user') result.append(group_id) dummy, group_id = dataobj.get_object_reference( cr, 1, 'base', 'group_partner_manager') result.append(group_id) except ValueError: # If these groups does not exists anymore pass return result _defaults = { 'password': '', 'context_lang': 'en_US', 'active': True, 'menu_id': _get_menu, 'company_id': _get_company, 'company_ids': _get_companies, 'groups_id': _get_group, 'menu_tips': False } # User can write to a few of her own fields (but not her groups for example) SELF_WRITEABLE_FIELDS = [ 'menu_tips', 'view', 'password', 'signature', 'action_id', 'company_id', 'user_email', 'name' ] def write(self, cr, uid, ids, values, context=None): if not hasattr(ids, '__iter__'): ids = [ids] if ids == [uid]: for key in values.keys(): if not (key in self.SELF_WRITEABLE_FIELDS or key.startswith('context_')): break else: if 'company_id' in values: if not (values['company_id'] in self.read( cr, 1, uid, ['company_ids'], context=context)['company_ids']): del values['company_id'] uid = 1 # safe fields only, so we write as super-user to bypass access rights if 'avatar' in values and values.get('avatar') is not False: logo = cStringIO.StringIO() img = Image.open( cStringIO.StringIO(base64.decodestring(values.get('avatar')))) img.thumbnail((64, 64), Image.ANTIALIAS) img.save(logo, format='PNG') img = base64.encodestring(logo.getvalue()) values['avatar'] = img res = super(users, self).write(cr, uid, ids, values, context=context) # clear caches linked to the users self.pool.get('ir.model.access').call_cache_clearing_methods(cr) clear = partial(self.pool.get('ir.rule').clear_cache, cr) map(clear, ids) db = cr.dbname if db in self._uid_cache: for id in ids: if id in self._uid_cache[db]: del self._uid_cache[db][id] return res def unlink(self, cr, uid, ids, context=None): if 1 in ids: raise osv.except_osv( _('Can not remove root user!'), _('You can not remove the admin user as it is used internally for resources created by OpenERP (updates, module installation, ...)' )) db = cr.dbname if db in self._uid_cache: for id in ids: if id in self._uid_cache[db]: del self._uid_cache[db][id] return super(users, self).unlink(cr, uid, ids, context=context) def name_search(self, cr, user, name='', args=None, operator='ilike', context=None, limit=100): if not args: args = [] if not context: context = {} ids = [] if name: ids = self.search(cr, user, [('login', '=', name)] + args, limit=limit, context=context) if not ids: ids = self.search(cr, user, [('name', operator, name)] + args, limit=limit, context=context) return self.name_get(cr, user, ids, context=context) def copy(self, cr, uid, id, default=None, context=None): user2copy = self.read(cr, uid, [id], ['login', 'name'])[0] if default is None: default = {} copy_pattern = _("%s (copy)") copydef = dict( login=(copy_pattern % user2copy['login']), name=(copy_pattern % user2copy['name']), ) copydef.update(default) return super(users, self).copy(cr, uid, id, copydef, context) def context_get(self, cr, uid, context=None): user = self.browse(cr, uid, uid, context) result = {} for k in self._columns.keys(): if k.startswith('context_'): res = getattr(user, k) or False if isinstance(res, browse_record): res = res.id result[k[8:]] = res or False return result def action_get(self, cr, uid, context=None): dataobj = self.pool.get('ir.model.data') data_id = dataobj._get_id(cr, 1, 'base', 'action_res_users_my') return dataobj.browse(cr, uid, data_id, context=context).res_id def authenticate(self, db, login, password, user_agent_env): """Verifies and returns the user ID corresponding to the given ``login`` and ``password`` combination, or False if there was no matching user. :param str db: the database on which user is trying to authenticate :param str login: username :param str password: user password :param dict user_agent_env: environment dictionary describing any relevant environment attributes """ uid = self.login(db, login, password) if uid == openerp.SUPERUSER_ID: # Successfully logged in as admin! # Attempt to guess the web base url... if user_agent_env and user_agent_env.get('base_location'): cr = pooler.get_db(db).cursor() try: self.pool.get('ir.config_parameter').set_param( cr, uid, 'web.base.url', user_agent_env['base_location']) cr.commit() except Exception: _logger.exception( "Failed to update web.base.url configuration parameter" ) finally: cr.close() return uid def get_groups_names(self, db, uid): if not uid: return [] cr = pooler.get_db(db).cursor() user = self.browse( cr, uid, uid, ) cr.execute( ''' SELECT module, name FROM ir_model_data WHERE res_id IN %s AND model = 'res.groups' ''', (tuple(group.id for group in user.groups_id) or tuple([]), )) groups = cr.fetchall() groups = groups and ["%s.%s" % group for group in groups] return groups def login(self, db, login, password): if not password: return False cr = pooler.get_db(db).cursor() try: # autocommit: our single request will be performed atomically. # (In this way, there is no opportunity to have two transactions # interleaving their cr.execute()..cr.commit() calls and have one # of them rolled back due to a concurrent access.) # We effectively unconditionally write the res_users line. cr.autocommit(True) # Even w/ autocommit there's a chance the user row will be locked, # in which case we can't delay the login just for the purpose of # update the last login date - hence we use FOR UPDATE NOWAIT to # try to get the lock - fail-fast cr.execute("""SELECT id from res_users WHERE login=%s AND password=%s AND active FOR UPDATE NOWAIT""", (tools.ustr(login), tools.ustr(password)), log_exceptions=False) cr.execute( """UPDATE res_users SET date = now() AT TIME ZONE 'UTC' WHERE login=%s AND password=%s AND active RETURNING id""", (tools.ustr(login), tools.ustr(password))) except Exception: # Failing to acquire the lock on the res_users row probably means # another request is holding it - no big deal, we skip the update # for this time, and let the user login anyway. cr.rollback() cr.execute( """SELECT id from res_users WHERE login=%s AND password=%s AND active""", (tools.ustr(login), tools.ustr(password))) finally: res = cr.fetchone() cr.close() if res: return res[0] return False def check_super(self, passwd): if passwd == tools.config['admin_passwd']: return True else: raise openerp.exceptions.AccessDenied() def check(self, db, uid, passwd): """Verifies that the given (uid, password) pair is authorized for the database ``db`` and raise an exception if it is not.""" if not passwd: # empty passwords disallowed for obvious security reasons raise openerp.exceptions.AccessDenied() if self._uid_cache.get(db, {}).get(uid) == passwd: return cr = pooler.get_db(db).cursor() try: cr.execute( 'SELECT COUNT(1) FROM res_users WHERE id=%s AND password=%s AND active=%s', (int(uid), passwd, True)) res = cr.fetchone()[0] if not res: raise openerp.exceptions.AccessDenied() if self._uid_cache.has_key(db): ulist = self._uid_cache[db] ulist[uid] = passwd else: self._uid_cache[db] = {uid: passwd} finally: cr.close() def access(self, db, uid, passwd, sec_level, ids): if not passwd: return False cr = pooler.get_db(db).cursor() try: cr.execute('SELECT id FROM res_users WHERE id=%s AND password=%s', (uid, passwd)) res = cr.fetchone() if not res: raise openerp.exceptions.AccessDenied() return res[0] finally: cr.close() def change_password(self, cr, uid, old_passwd, new_passwd, context=None): """Change current user password. Old password must be provided explicitly to prevent hijacking an existing user session, or for cases where the cleartext password is not used to authenticate requests. :return: True :raise: openerp.exceptions.AccessDenied when old password is wrong :raise: except_osv when new password is not set or empty """ self.check(cr.dbname, uid, old_passwd) if new_passwd: return self.write(cr, uid, uid, {'password': new_passwd}) raise osv.except_osv( _('Warning!'), _("Setting empty passwords is not allowed for security reasons!"))
class pos_order_line(osv.osv): _name = "pos.order.line" _description = "Lines of Point of Sale" _rec_name = "product_id" def _amount_line_all(self, cr, uid, ids, field_names, arg, context=None): print "file: point_of_sale class: pos_order_line fun: _amount_line_all" res = dict([(i, {}) for i in ids]) account_tax_obj = self.pool.get('account.tax') cur_obj = self.pool.get('res.currency') for line in self.browse(cr, uid, ids, context=context): taxes = line.product_id.taxes_id price = line.price_unit * (1 - (line.discount or 0.0) / 100.0) taxes = account_tax_obj.compute_all( cr, uid, line.product_id.taxes_id, price, line.qty, product=line.product_id, partner=line.order_id.partner_id or False) cur = line.order_id.pricelist_id.currency_id res[line.id]['price_subtotal'] = cur_obj.round( cr, uid, cur, taxes['total']) res[line.id]['price_subtotal_incl'] = cur_obj.round( cr, uid, cur, taxes['total_included']) return res def onchange_product_id(self, cr, uid, ids, pricelist, product_id, qty=0, partner_id=False, context=None): print "file: point_of_sale class: pos_order_line fun: onchange_product_id" context = context or {} if not product_id: return {} if not pricelist: raise osv.except_osv(_('No Pricelist !'), _('You have to select a pricelist in the sale form !\n' \ 'Please set one before choosing a product.')) price = self.pool.get('product.pricelist').price_get( cr, uid, [pricelist], product_id, qty or 1.0, partner_id)[pricelist] result = self.onchange_qty(cr, uid, ids, product_id, 0.0, qty, price, context=context) result['value']['price_unit'] = price return result def onchange_qty(self, cr, uid, ids, product, discount, qty, price_unit, context=None): print "file: point_of_sale class: pos_order_line fun: onchange_qty" result = {} if not product: return result account_tax_obj = self.pool.get('account.tax') cur_obj = self.pool.get('res.currency') prod = self.pool.get('product.product').browse(cr, uid, product, context=context) taxes = prod.taxes_id price = price_unit * (1 - (discount or 0.0) / 100.0) taxes = account_tax_obj.compute_all(cr, uid, prod.taxes_id, price, qty, product=prod, partner=False) result['price_subtotal'] = taxes['total'] result['price_subtotal_incl'] = taxes['total_included'] return {'value': result} _columns = { 'company_id': fields.many2one('res.company', 'Company', required=True), 'name': fields.char('Line No', size=32, required=True), 'notice': fields.char('Discount Notice', size=128), 'product_id': fields.many2one('product.product', 'Product', domain=[('sale_ok', '=', True)], required=True, change_default=True), 'price_unit': fields.float(string='Unit Price', digits=(16, 2)), 'qty': fields.float('Quantity', digits=(16, 2)), 'price_subtotal': fields.function(_amount_line_all, multi='pos_order_line_amount', string='Subtotal w/o Tax', store=True), 'price_subtotal_incl': fields.function(_amount_line_all, multi='pos_order_line_amount', string='Subtotal', store=True), 'discount': fields.float('Discount (%)', digits=(16, 2)), 'order_id': fields.many2one('pos.order', 'Order Ref', ondelete='cascade'), 'create_date': fields.datetime('Creation Date', readonly=True), } _defaults = { 'name': lambda obj, cr, uid, context: obj.pool.get('ir.sequence').get( cr, uid, 'pos.order.line'), 'qty': lambda *a: 1, 'discount': lambda *a: 0.0, 'company_id': lambda self, cr, uid, c: self.pool.get('res.users').browse( cr, uid, uid, c).company_id.id, } def copy_data(self, cr, uid, id, default=None, context=None): print "file: point_of_sale class: pos_order_line fun: copy_data" if not default: default = {} default.update({ 'name': self.pool.get('ir.sequence').get(cr, uid, 'pos.order.line') }) return super(pos_order_line, self).copy_data(cr, uid, id, default, context=context)
class ir_model_data(osv.osv): _name = 'ir.model.data' __logger = logging.getLogger('addons.base.' + _name) _columns = { 'name': fields.char('XML Identifier', required=True, size=128, select=1), 'model': fields.char('Object', required=True, size=64, select=1), 'module': fields.char('Module', required=True, size=64, select=1), 'res_id': fields.integer('Resource ID', select=1), 'noupdate': fields.boolean('Non Updatable'), 'date_update': fields.datetime('Update Date'), 'date_init': fields.datetime('Init Date') } _defaults = { 'date_init': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'), 'date_update': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'), 'noupdate': lambda *a: False, 'module': lambda *a: '' } _sql_constraints = [ ('module_name_uniq', 'unique(name, module)', 'You cannot have multiple records with the same id for the same module' ), ] def __init__(self, pool, cr): osv.osv.__init__(self, pool, cr) self.loads = {} self.doinit = True self.unlink_mark = {} @tools.cache() def _get_id(self, cr, uid, module, xml_id): """Returns the id of the ir.model.data record corresponding to a given module and xml_id (cached) or raise a ValueError if not found""" ids = self.search(cr, uid, [('module', '=', module), ('name', '=', xml_id)]) if not ids: raise ValueError('No references to %s.%s' % (module, xml_id)) # the sql constraints ensure us we have only one result return ids[0] @tools.cache() def get_object_reference(self, cr, uid, module, xml_id): """Returns (model, res_id) corresponding to a given module and xml_id (cached) or raise ValueError if not found""" data_id = self._get_id(cr, uid, module, xml_id) res = self.read(cr, uid, data_id, ['model', 'res_id']) return (res['model'], res['res_id']) def get_object(self, cr, uid, module, xml_id, context=None): """Returns a browsable record for the given module name and xml_id or raise ValueError if not found""" res_model, res_id = self.get_object_reference(cr, uid, module, xml_id) return self.pool.get(res_model).browse(cr, uid, res_id, context=context) def _update_dummy(self, cr, uid, model, module, xml_id=False, store=True): if not xml_id: return False try: id = self.read(cr, uid, [self._get_id(cr, uid, module, xml_id)], ['res_id'])[0]['res_id'] self.loads[(module, xml_id)] = (model, id) except: id = False return id def _update(self, cr, uid, model, module, values, xml_id=False, store=True, noupdate=False, mode='init', res_id=False, context=None): warning = True model_obj = self.pool.get(model) if not context: context = {} if xml_id and ('.' in xml_id): assert len(xml_id.split('.')) == 2, _( '"%s" contains too many dots. XML ids should not contain dots ! These are used to refer to other modules data, as in module.reference_id' ) % (xml_id) warning = False module, xml_id = xml_id.split('.') if (not xml_id) and (not self.doinit): return False action_id = False if xml_id: cr.execute( 'select id,res_id from ir_model_data where module=%s and name=%s', (module, xml_id)) results = cr.fetchall() for action_id2, res_id2 in results: cr.execute( 'select id from ' + model_obj._table + ' where id=%s', (res_id2, )) result3 = cr.fetchone() if not result3: self._get_id.clear_cache(cr.dbname, uid, module, xml_id) self.get_object_reference.clear_cache( cr.dbname, uid, module, xml_id) cr.execute('delete from ir_model_data where id=%s', (action_id2, )) res_id = False else: res_id, action_id = res_id2, action_id2 if action_id and res_id: model_obj.write(cr, uid, [res_id], values, context=context) self.write(cr, uid, [action_id], { 'date_update': time.strftime('%Y-%m-%d %H:%M:%S'), }, context=context) elif res_id: model_obj.write(cr, uid, [res_id], values, context=context) if xml_id: self.create(cr, uid, { 'name': xml_id, 'model': model, 'module': module, 'res_id': res_id, 'noupdate': noupdate, }, context=context) if model_obj._inherits: for table in model_obj._inherits: inherit_id = model_obj.browse( cr, uid, res_id, context=context)[model_obj._inherits[table]] self.create( cr, uid, { 'name': xml_id + '_' + table.replace('.', '_'), 'model': table, 'module': module, 'res_id': inherit_id, 'noupdate': noupdate, }, context=context) else: if mode == 'init' or (mode == 'update' and xml_id): res_id = model_obj.create(cr, uid, values, context=context) if xml_id: self.create(cr, uid, { 'name': xml_id, 'model': model, 'module': module, 'res_id': res_id, 'noupdate': noupdate }, context=context) if model_obj._inherits: for table in model_obj._inherits: inherit_id = model_obj.browse( cr, uid, res_id, context=context)[model_obj._inherits[table]] self.create( cr, uid, { 'name': xml_id + '_' + table.replace('.', '_'), 'model': table, 'module': module, 'res_id': inherit_id, 'noupdate': noupdate, }, context=context) if xml_id: if res_id: self.loads[(module, xml_id)] = (model, res_id) if model_obj._inherits: for table in model_obj._inherits: inherit_field = model_obj._inherits[table] inherit_id = model_obj.read( cr, uid, res_id, [inherit_field])[inherit_field] self.loads[(module, xml_id + '_' + \ table.replace('.', '_'))] = (table, inherit_id) return res_id def _unlink(self, cr, uid, model, res_ids): for res_id in res_ids: self.unlink_mark[(model, res_id)] = False cr.execute( 'delete from ir_model_data where res_id=%s and model=%s', (res_id, model)) return True def ir_set(self, cr, uid, key, key2, name, models, value, replace=True, isobject=False, meta=None, xml_id=False): obj = self.pool.get('ir.values') if type(models[0]) == type([]) or type(models[0]) == type(()): model, res_id = models[0] else: res_id = None model = models[0] if res_id: where = ' and res_id=%s' % (res_id, ) else: where = ' and (res_id is null)' if key2: where += ' and key2=\'%s\'' % (key2, ) else: where += ' and (key2 is null)' cr.execute( 'select * from ir_values where model=%s and key=%s and name=%s' + where, (model, key, name)) res = cr.fetchone() if not res: res = ir.ir_set(cr, uid, key, key2, name, models, value, replace, isobject, meta) elif xml_id: cr.execute( 'UPDATE ir_values set value=%s WHERE model=%s and key=%s and name=%s' + where, (value, model, key, name)) return True def _process_end(self, cr, uid, modules): if not modules: return True modules = list(modules) module_in = ",".join(["%s"] * len(modules)) cr.execute( 'select id,name,model,res_id,module from ir_model_data where module IN (' + module_in + ') and noupdate=%s', modules + [False]) wkf_todo = [] for (id, name, model, res_id, module) in cr.fetchall(): if (module, name) not in self.loads: self.unlink_mark[(model, res_id)] = id if model == 'workflow.activity': cr.execute( 'select res_type,res_id from wkf_instance where id IN (select inst_id from wkf_workitem where act_id=%s)', (res_id, )) wkf_todo.extend(cr.fetchall()) cr.execute( "update wkf_transition set condition='True', role_id=NULL, signal=NULL,act_to=act_from,act_from=%s where act_to=%s", (res_id, res_id)) cr.execute("delete from wkf_transition where act_to=%s", (res_id, )) for model, id in wkf_todo: wf_service = netsvc.LocalService("workflow") wf_service.trg_write(uid, model, id, cr) cr.commit() if not config.get('import_partial'): for (model, res_id) in self.unlink_mark.keys(): if self.pool.get(model): self.__logger.info('Deleting %s@%s', res_id, model) try: self.pool.get(model).unlink(cr, uid, [res_id]) if id: ids = self.search(cr, uid, [('res_id', '=', res_id), ('model', '=', model)]) self.__logger.debug('=> Deleting %s: %s', self._name, ids) if len(ids) > 1 and \ self.__logger.isEnabledFor(logging.WARNING): self.__logger.warn( 'Got %d %s for (%s, %d): %s', len(ids), self._name, model, res_id, map( itemgetter('module', 'name'), self.read(cr, uid, ids, ['name', 'module']))) self.unlink(cr, uid, ids) cr.execute('DELETE FROM ir_values WHERE value=%s', ('%s,%s' % (model, res_id), )) cr.commit() except Exception: cr.rollback() self.__logger.exception( 'Could not delete id: %d of model %s\nThere ' 'should be some relation that points to this ' 'resource\nYou should manually fix this and ' 'restart with --update=module', res_id, model) return True
class document_directory(osv.osv): _name = 'document.directory' _description = 'Document directory' _columns = { 'name': fields.char('Name', size=64, required=True, select=1), 'write_date': fields.datetime('Date Modified', readonly=True), 'write_uid': fields.many2one('res.users', 'Last Modification User', readonly=True), 'create_date': fields.datetime('Date Created', readonly=True), 'create_uid': fields.many2one('res.users', 'Creator', readonly=True), 'file_type': fields.char('Content Type', size=32), 'domain': fields.char('Domain', size=128), 'user_id': fields.many2one('res.users', 'Owner'), 'group_ids': fields.many2many('res.groups', 'document_directory_group_rel', 'item_id', 'group_id', 'Groups'), 'parent_id': fields.many2one('document.directory', 'Parent Item'), 'child_ids': fields.one2many('document.directory', 'parent_id', 'Children'), 'file_ids': fields.one2many('ir.attachment', 'parent_id', 'Files'), 'content_ids': fields.one2many('document.directory.content', 'directory_id', 'Virtual Files'), 'type': fields.selection([('directory', 'Static Directory'), ('ressource', 'Other Ressources')], 'Type', required=True), 'ressource_type_id': fields.many2one('ir.model', 'Ressource Model'), 'ressource_id': fields.integer('Ressource ID'), 'ressource_tree': fields.boolean('Tree Structure'), } _defaults = { 'user_id': lambda self, cr, uid, ctx: uid, 'domain': lambda self, cr, uid, ctx: '[]', 'type': lambda *args: 'directory', } _sql_constraints = [ ('filename_uniq', 'unique (name,parent_id,ressource_id)', 'The directory name must be unique !') ] def _check_recursion(self, cr, uid, ids): level = 100 while len(ids): cr.execute( 'select distinct parent_id from document_directory where id in (' + ','.join(map(str, ids)) + ')') ids = filter(None, map(lambda x: x[0], cr.fetchall())) if not level: return False level -= 1 return True _constraints = [ (_check_recursion, 'Error! You can not create recursive Directories.', ['parent_id']) ] def __init__(self, *args, **kwargs): res = super(document_directory, self).__init__(*args, **kwargs) self._cache = {} return res def onchange_content_id(self, cr, uid, ids, ressource_type_id): return {} def _get_childs(self, cr, uid, node, nodename=False, context={}): where = [] if nodename: where.append(('name', '=', nodename)) if object: where.append(('parent_id', '=', object.id)) ids = self.search(cr, uid, where, context) return self.browse(cr, uid, ids, context), False """ PRE: uri: of the form "Sales Order/SO001" PORT: uri object: the object.directory or object.directory.content object2: the other object linked (if object.directory.content) """ def get_object(self, cr, uid, uri, context={}): if not uri: return None turi = tuple(uri) if (turi in self._cache): print '*' * 50 (path, oo, oo2, content, type, root) = self._cache[turi] if oo: object = self.pool.get(oo[0]).browse(cr, uid, oo[1], context) else: object = False if oo2: object2 = self.pool.get(oo2[0]).browse(cr, uid, oo2[1], context) else: object2 = False node = node_class(cr, uid, path, object, object2, context, content, type, root) return node node = node_class(cr, uid, uri[0], False, type='database') for path in uri[1:]: if path: node = node.child(path) oo = node.object and (node.object._name, node.object.id) or False oo2 = node.object2 and (node.object2._name, node.object2.id) or False self._cache[turi] = (node.path, oo, oo2, node.content, node.type, node.root) return node def get_childs(self, cr, uid, uri, context={}): node = self.get_object(cr, uid, uri, context) if uri: children = node.children() else: children = [node] result = map(lambda node: node.path_get(), children) #childs,object2 = self._get_childs(cr, uid, object, False, context) #result = map(lambda x: urlparse.urljoin(path+'/',x.name), childs) return result def create(self, cr, uid, vals, context=None): if vals.get('name', False) and (vals.get('name').find('/') + 1 or vals.get('name').find('@') + 1 or vals.get('name').find('$') + 1 or vals.get('name').find('#') + 1): raise webdav.DAV.errors.DAV_NotFound( 'Directory name must not contain special character...') return super(document_directory, self).create(cr, uid, vals, context)
class hr_interview(osv.osv): _name = "hr.interview" _description = "Interview Evaluation" def eval_performance(self, cr, uid, ids, *args): tech_obj = self.pool.get("technical.skill") tot_marks = obt_marks = 0 tech_id = tech_obj.search(cr, uid, [('candidate_id', '=', ids[0])]) if tech_id: for rec in tech_obj.browse(cr, uid, tech_id): tot_marks += rec.tot_marks obt_marks += rec.obt_marks self.write(cr, uid, ids, {'performance': (obt_marks * 100) / tot_marks}) return True def _constraint_obt_marks(self, cr, uid, ids): tech_skill_obj = self.pool.get("technical.skill") tech_skill_ids = tech_skill_obj.search(cr, uid, [('candidate_id', '=', ids[0])]) for rec in tech_skill_obj.browse(cr, uid, tech_skill_ids): if rec['obt_marks'] > rec['tot_marks'] or rec['tot_marks'] <= 0: return False return True def _constraint_evaluator(self, cr, uid, ids): rec = self.read(cr, uid, ids[0]) if rec['reference_id']: if rec['reference_id'][0] in rec['evaluator_ids']: return False return True _columns = { 'hr_id': fields.char("Interview ID", size=64), 'name': fields.char("Candidate Name", size=64, required=True, select=True), 'crm_case_id': fields.many2one('crm.case', "Case"), 'email': fields.char("E-mail", size=64, required=True), 'mobile_no': fields.char("Mobile", size=64), 'date': fields.datetime('Scheduled Date'), 'exam_date': fields.datetime('Exam On'), 'education': fields.selection([("be_ce", "BE Computers"), ("be_it", "BE IT"), ("bsc_it", "BSc IT"), ("bca", "BCA"), ("btech_ce", "BTech Computers"), ("btech_it", "BTech IT"), ("mca", "MCA"), ("msc_it", "MSc IT"), ("mtech_ce", "MTech Computers"), ("other", "Other")], "Education"), 'category_id': fields.many2one("candidate.category", "Category"), 'experience_id': fields.many2one("candidate.experience", "Experience"), 'remarks': fields.text("Remarks"), 'evaluator_ids': fields.many2many("hr.employee", 'hr_empl_rel', 'hr_cand_id', 'emp_id', "Evaluator"), 'reference_id': fields.many2one("hr.employee", "Reference"), 'tech_skills_ids': fields.one2many("technical.skill", "candidate_id", "Technology Skills"), 'performance': fields.float("Performance (%)", readonly=True), 'state': fields.selection([("draft", "Draft"), ('scheduled', 'Scheduled'), ('re-scheduled', 'Re-Scheduled'), ('start-interview', 'Start-Interview'), ('end-interview', 'End-Interview'), ("selected", "Selected"), ('rejected', 'Rejected'), ("cancel", "Cancel")], "State", readonly=True, select=1), 'history_log_ids': fields.one2many("hr.interview.log", "history_id", "Interview Logs", readonly=True), } _defaults = { 'state': lambda *a: "draft", 'hr_id': lambda obj, cr, uid, context: obj.pool.get('ir.sequence').get( cr, uid, 'hr.interview'), } _constraints = [ (_constraint_obt_marks, _('Obtained marks cannot be greater than Total marks!'), ['obt_marks']), (_constraint_evaluator, "Reference Person cannot be among Evaluators!", ['reference_id']) ] def state_scheduled(self, cr, uid, ids, *arg): self.write(cr, uid, ids, {'state': 'scheduled'}) self._log(cr, uid, ids, 'scheduled') return True def state_cancel(self, cr, uid, ids, *arg): self.write(cr, uid, ids, {'state': 'cancel'}) self._log(cr, uid, ids, 'cancel') return True def state_re_scheduled(self, cr, uid, ids, *arg): self.write(cr, uid, ids, {'state': 're-scheduled'}) self._log(cr, uid, ids, 're-scheduled') return True def state_start_interview(self, cr, uid, ids, *arg): self.write(cr, uid, ids, {'state': 'start-interview'}) self._log(cr, uid, ids, 'start-interview') return True def state_end_interview(self, cr, uid, ids, *arg): self.write(cr, uid, ids, {'state': 'end-interview'}) self._log(cr, uid, ids, 'end-interview') return True def state_selected(self, cr, uid, ids, *arg): self.write(cr, uid, ids, {'state': 'selected'}) self._log(cr, uid, ids, 'selected') return True def state_rejected(self, cr, uid, ids, *arg): self.write(cr, uid, ids, {'state': 'rejected'}) self._log(cr, uid, ids, 'rejected') return True def _log(self, cr, uid, ids, action): his_obj = self.pool.get("hr.interview.log") his_obj.create( cr, uid, { 'state': action, 'date': strftime("%Y-%m-%d %H:%M:%S"), "user_id": uid, 'history_id': ids[0] }) return True def copy(self, cr, uid, id, default=None, context=None): raise osv.except_osv(_('Error !'), _('You cannot duplicate the resource!')) return False def create(self, cr, uid, vals, context=None): que_obj = self.pool.get("category.question") tech_skill_obj = self.pool.get("technical.skill") hr_id = super(hr_interview, self).create(cr, uid, vals, context=context) if vals.get('category_id', False): cate_id = vals.get('category_id') que_ids = que_obj.search(cr, uid, [('category_id', '=', int(cate_id))], context=context) for rec in que_obj.browse(cr, uid, que_ids, context=context): tech_skill_obj.create( cr, uid, { 'name': rec.name, 'tot_marks': rec.tot_marks, 'candidate_id': hr_id }) self._log(cr, uid, [hr_id], 'draft') return hr_id def write(self, cr, uid, ids, vals, context=None): que_obj = self.pool.get("category.question") tech_skill_obj = self.pool.get("technical.skill") if 'category_id' in vals: cate_id = vals['category_id'] que_ids = que_obj.search(cr, uid, [('category_id', '=', int(cate_id))]) tech_skill_ids = tech_skill_obj.search( cr, uid, [('candidate_id', '=', ids[0])]) if tech_skill_ids: tech_skill_obj.unlink(cr, uid, tech_skill_ids) for rec in que_obj.browse(cr, uid, que_ids): tech_skill_obj.create( cr, uid, { 'name': rec.name, 'tot_marks': rec.tot_marks, 'candidate_id': ids[0] }) return super(hr_interview, self).write(cr, uid, ids, vals, context=context)
class hr_holidays(osv.osv): _name = "hr.holidays" _description = "Leave" _order = "type desc, date_from asc" def _employee_get(obj, cr, uid, context=None): ids = obj.pool.get('hr.employee').search(cr, uid, [('user_id', '=', uid)], context=context) if ids: return ids[0] return False def _compute_number_of_days(self, cr, uid, ids, name, args, context=None): result = {} for hol in self.browse(cr, uid, ids, context=context): if hol.type == 'remove': result[hol.id] = -hol.number_of_days_temp else: result[hol.id] = hol.number_of_days_temp return result _columns = { 'name': fields.char('Description', required=True, size=64), 'state': fields.selection( [('draft', 'Draft'), ('confirm', 'Waiting Approval'), ('refuse', 'Refused'), ('validate1', 'Waiting Second Approval'), ('validate', 'Approved'), ('cancel', 'Cancelled')], 'State', readonly=True, help= 'When the holiday request is created the state is \'Draft\'.\n It is confirmed by the user and request is sent to admin, the state is \'Waiting Approval\'.\ If the admin accepts it, the state is \'Approved\'. If it is refused, the state is \'Refused\'.' ), 'user_id': fields.related('employee_id', 'user_id', type='many2one', relation='res.users', string='User', store=True), 'date_from': fields.datetime('Start Date', readonly=True, states={'draft': [('readonly', False)]}), 'date_to': fields.datetime('End Date', readonly=True, states={'draft': [('readonly', False)]}), 'holiday_status_id': fields.many2one("hr.holidays.status", "Leave Type", required=True, readonly=True, states={'draft': [('readonly', False)]}), 'employee_id': fields.many2one( 'hr.employee', "Employee", select=True, invisible=False, readonly=True, states={'draft': [('readonly', False)] }, help= 'Leave Manager can let this field empty if this leave request/allocation is for every employee' ), #'manager_id': fields.many2one('hr.employee', 'Leave Manager', invisible=False, readonly=True, help='This area is automaticly filled by the user who validate the leave'), #'notes': fields.text('Notes',readonly=True, states={'draft':[('readonly',False)]}), 'manager_id': fields.many2one( 'hr.employee', 'First Approval', invisible=False, readonly=True, help= 'This area is automaticly filled by the user who validate the leave' ), 'notes': fields.text('Reasons', readonly=True, states={'draft': [('readonly', False)]}), 'number_of_days_temp': fields.float('Number of Days', readonly=True, states={'draft': [('readonly', False)]}), 'number_of_days': fields.function(_compute_number_of_days, method=True, string='Number of Days', store=True), 'case_id': fields.many2one('crm.meeting', 'Meeting'), 'type': fields.selection( [('remove', 'Leave Request'), ('add', 'Allocation Request')], 'Request Type', required=True, readonly=True, states={'draft': [('readonly', False)]}, help= "Choose 'Leave Request' if someone wants to take an off-day. \nChoose 'Allocation Request' if you want to increase the number of leaves available for someone" ), 'parent_id': fields.many2one('hr.holidays', 'Parent'), 'linked_request_ids': fields.one2many( 'hr.holidays', 'parent_id', 'Linked Requests', ), 'department_id': fields.related('employee_id', 'department_id', string='Department', type='many2one', relation='hr.department', readonly=True, store=True), 'category_id': fields.many2one('hr.employee.category', "Category", help='Category of Employee'), 'holiday_type': fields.selection( [('employee', 'By Employee'), ('category', 'By Employee Category')], 'Allocation Type', help= 'By Employee: Allocation/Request for individual Employee, By Employee Category: Allocation/Request for group of employees in category', required=True), 'manager_id2': fields.many2one( 'hr.employee', 'Second Approval', readonly=True, help= 'This area is automaticly filled by the user who validate the leave with second level (If Leave type need second validation)' ) } _defaults = { 'employee_id': _employee_get, 'state': 'draft', 'type': 'remove', 'user_id': lambda obj, cr, uid, context: uid, 'holiday_type': 'employee' } _sql_constraints = [( 'type_value', "CHECK( (holiday_type='employee' AND employee_id IS NOT NULL) or (holiday_type='category' AND category_id IS NOT NULL))", "You have to select an employee or a category"), ('date_check', "CHECK ( number_of_days_temp > 0 )", "The number of days must be greater than 0 !"), ('date_check2', "CHECK ( (type='add') OR (date_from < date_to))", "The start date must be before the end date !")] def _create_resource_leave(self, cr, uid, vals, context=None): '''This method will create entry in resource calendar leave object at the time of holidays validated ''' obj_res_leave = self.pool.get('resource.calendar.leaves') return obj_res_leave.create(cr, uid, vals, context=context) def _remove_resouce_leave(self, cr, uid, ids, context=None): '''This method will create entry in resource calendar leave object at the time of holidays cancel/removed''' obj_res_leave = self.pool.get('resource.calendar.leaves') leave_ids = obj_res_leave.search(cr, uid, [('holiday_id', 'in', ids)], context=context) return obj_res_leave.unlink(cr, uid, leave_ids) def onchange_type(self, cr, uid, ids, holiday_type): result = {} if holiday_type == 'employee': ids_employee = self.pool.get('hr.employee').search( cr, uid, [('user_id', '=', uid)]) if ids_employee: result['value'] = {'employee_id': ids_employee[0]} return result # TODO: can be improved using resource calendar method def _get_number_of_days(self, date_from, date_to): """Returns a float equals to the timedelta between two dates given as string.""" DATETIME_FORMAT = "%Y-%m-%d %H:%M:%S" from_dt = datetime.datetime.strptime(date_from, DATETIME_FORMAT) to_dt = datetime.datetime.strptime(date_to, DATETIME_FORMAT) timedelta = to_dt - from_dt diff_day = timedelta.days + float(timedelta.seconds) / 86400 return diff_day def unlink(self, cr, uid, ids, context=None): for rec in self.browse(cr, uid, ids, context=context): if rec.state <> 'draft': raise osv.except_osv( _('Warning!'), _('You cannot delete a leave which is not in draft state !' )) return super(hr_holidays, self).unlink(cr, uid, ids, context) def onchange_date_from(self, cr, uid, ids, date_to, date_from): result = {} if date_to and date_from: diff_day = self._get_number_of_days(date_from, date_to) result['value'] = {'number_of_days_temp': round(diff_day) + 1} return result result['value'] = { 'number_of_days_temp': 0, } return result def onchange_sec_id(self, cr, uid, ids, status, context=None): warning = {} if status: brows_obj = self.pool.get('hr.holidays.status').browse( cr, uid, status, context=context) if brows_obj.categ_id and brows_obj.categ_id.section_id and not brows_obj.categ_id.section_id.allow_unlink: warning = { 'title': "Warning for ", 'message': "You won\'t be able to cancel this leave request because the CRM Sales Team of the leave type disallows." } return {'warning': warning} def set_to_draft(self, cr, uid, ids, *args): self.write(cr, uid, ids, { 'state': 'draft', 'manager_id': False, }) wf_service = netsvc.LocalService("workflow") for id in ids: wf_service.trg_create(uid, 'hr.holidays', id, cr) return True def holidays_validate(self, cr, uid, ids, *args): self.check_holidays(cr, uid, ids) obj_emp = self.pool.get('hr.employee') ids2 = obj_emp.search(cr, uid, [('user_id', '=', uid)]) manager = ids2 and ids2[0] or False return self.write(cr, uid, ids, { 'state': 'validate1', 'manager_id': manager }) def holidays_validate2(self, cr, uid, ids, *args): self.check_holidays(cr, uid, ids) obj_emp = self.pool.get('hr.employee') ids2 = obj_emp.search(cr, uid, [('user_id', '=', uid)]) manager = ids2 and ids2[0] or False self.write(cr, uid, ids, {'state': 'validate', 'manager_id2': manager}) data_holiday = self.browse(cr, uid, ids) for record in data_holiday: if record.holiday_type == 'employee' and record.type == 'remove': meeting_obj = self.pool.get('crm.meeting') vals = { 'name': record.name, 'categ_id': record.holiday_status_id.categ_id.id, 'duration': record.number_of_days_temp * 8, 'note': record.notes, 'user_id': record.user_id.id, 'date': record.date_from, 'end_date': record.date_to, 'date_deadline': record.date_to, } case_id = meeting_obj.create(cr, uid, vals) self.write(cr, uid, ids, {'case_id': case_id}) elif record.holiday_type == 'category': emp_ids = obj_emp.search( cr, uid, [('category_ids', 'child_of', [record.category_id.id])]) leave_ids = [] for emp in obj_emp.browse(cr, uid, emp_ids): vals = { 'name': record.name, 'type': record.type, 'holiday_type': 'employee', 'holiday_status_id': record.holiday_status_id.id, 'date_from': record.date_from, 'date_to': record.date_to, 'notes': record.notes, 'number_of_days_temp': record.number_of_days_temp, 'parent_id': record.id, 'employee_id': emp.id } leave_ids.append(self.create(cr, uid, vals, context=None)) wf_service = netsvc.LocalService("workflow") for leave_id in leave_ids: wf_service.trg_validate(uid, 'hr.holidays', leave_id, 'confirm', cr) wf_service.trg_validate(uid, 'hr.holidays', leave_id, 'validate', cr) wf_service.trg_validate(uid, 'hr.holidays', leave_id, 'second_validate', cr) return True def holidays_confirm(self, cr, uid, ids, *args): self.check_holidays(cr, uid, ids) return self.write(cr, uid, ids, {'state': 'confirm'}) def holidays_refuse(self, cr, uid, ids, *args): obj_emp = self.pool.get('hr.employee') ids2 = obj_emp.search(cr, uid, [('user_id', '=', uid)]) manager = ids2 and ids2[0] or False self.write(cr, uid, ids, {'state': 'refuse', 'manager_id2': manager}) self.holidays_cancel(cr, uid, ids) return True def holidays_cancel(self, cr, uid, ids, *args): obj_crm_meeting = self.pool.get('crm.meeting') for record in self.browse(cr, uid, ids): # Delete the meeting if record.case_id: obj_crm_meeting.unlink(cr, uid, [record.case_id.id]) # If a category that created several holidays, cancel all related wf_service = netsvc.LocalService("workflow") for res in record.linked_request_ids: wf_service.trg_validate(uid, 'hr.holidays', res.id, 'cancel', cr) return True def check_holidays(self, cr, uid, ids): holi_status_obj = self.pool.get('hr.holidays.status') for record in self.browse(cr, uid, ids): if record.holiday_type == 'employee' and record.type == 'remove': if record.employee_id and not record.holiday_status_id.limit: leaves_rest = holi_status_obj.get_days( cr, uid, [record.holiday_status_id.id], record.employee_id.id, False)[record.holiday_status_id.id]['remaining_leaves'] if leaves_rest < record.number_of_days_temp: raise osv.except_osv( _('Warning!'), _('You cannot validate leaves for employee %s: too few remaining days (%s).' ) % (record.employee_id.name, leaves_rest)) return True
#Lets plan it for 0.9 'folder':fields.selection([ ('inbox', 'Inbox'), ('drafts', 'Drafts'), ('outbox', 'Outbox'), ('trash', 'Trash'), ('followup', 'Follow Up'), ('sent', 'Sent Items'), ], 'Folder', required=True), 'state':fields.selection([ ('read', 'Read'), ('unread', 'Un-Read'), ('na', 'Not Applicable'), ('sending', 'Sending'), ], 'Status', required=True), 'date_mail':fields.datetime( 'Rec/Sent Date'), 'history':fields.text( 'History', readonly=True, store=True) } _defaults = { 'state': lambda * a: 'na', 'folder': lambda * a: 'outbox', } def search(self, cr, uid, args, offset=0, limit=None, order=None, context=None, count=False): if context is None: context = {} if context.get('company', False):
class stock_location_product(osv.osv_memory): _inherit = "stock.location.product" _logger = logging.getLogger(__name__) _columns = { 'from_date2': fields.datetime('From'), 'to_date2': fields.datetime('To'), 'adjust_time': fields.boolean('Adjust Time', help="Adjusts From to '00:00:00' and To to '23:59:59'") } _defaults = {'adjust_time': lambda *a: '1'} def action_open(self, cr, uid, ids, context=None): self._logger.debug('FGF stock_location_product ids %s' % ids) self._logger.debug('FGF stock_location_product context %s' % context) if context is None: context = {} res = super(stock_location_product, self).action_open_window(cr, uid, ids, context) if context.get('open') == 'report': mod_obj = self.pool.get('ir.model.data') rep_obj = self.pool.get('ir.actions.report.xml') res1 = mod_obj.get_object_reference( cr, uid, 'c2c_stock_accounting', 'report_print_computed_product') id = res1 and res1[1] or False res.update(rep_obj.read(cr, uid, [id], context=context)[0]) self._logger.debug('FGF stock_location_product res %s' % res) location_products = self.read( cr, uid, ids, ['from_date', 'to_date', 'from_date2', 'to_date2', 'adjust_time'], context) self._logger.debug('FGF stock_location_products %s' % location_products) from_date1 = location_products[0]['from_date'] to_date1 = location_products[0]['to_date'] from_date2 = location_products[0]['from_date2'] to_date2 = location_products[0]['to_date2'] format = tools.DEFAULT_SERVER_DATETIME_FORMAT tz = context['tz'] date_local = tools.server_to_local_timestamp(date, format, format, tz) res['context']['local_from_date1'] = '' res['context']['local_to_date1'] = '' res['context']['local_from_date2'] = '' res['context']['local_to_date2'] = '' if from_date1: res['context'][ 'local_from_date1'] = tools.server_to_local_timestamp( from_date1, format, format, tz) if to_date1: res['context']['local_to_date1'] = tools.server_to_local_timestamp( to_date1, format, format, tz) if from_date2: res['context'][ 'local_from_date2'] = tools.server_to_local_timestamp( from_date2, format, format, tz) if to_date2: res['context']['local_to_date2'] = tools.server_to_local_timestamp( to_date2, format, format, tz) res['context']['from_date'] = from_date1 res['context']['to_date'] = to_date1 res['context']['from_date1'] = from_date1 res['context']['to_date1'] = to_date1 res['context']['from_date2'] = from_date2 res['context']['to_date2'] = to_date2 res['context']['location_name'] = self.pool.get('stock.location').read( cr, uid, res['context']['location'], ['name'])['name'] #res['context']['cr1'] = cr self._logger.debug('FGF stock_location_product res neu %s' % res) return res def action_open_window(self, cr, uid, ids, context=None): if context is None: context = {} context.update({'open': 'view'}) return self.action_open(cr, uid, ids, context) def action_open_report(self, cr, uid, ids, context=None): if not context: context = {} data = self.read(cr, uid, ids, [], context=context)[0] context.update({'open': 'report'}) res = self.action_open(cr, uid, ids, context) context = res['context'] self._logger.debug('FGF report context %s' % context) self._logger.debug('FGF report data %s' % data) product_obj = self.pool.get('product.product') product_ids = product_obj.search(cr, uid, []) datas = {'ids': product_ids, 'model': 'ir.ui.menu', 'form': data} self._logger.debug('FGF context %s' % context) return { 'type': 'ir.actions.report.xml', 'report_name': 'report.print.computed.product', 'datas': datas, 'context': context } def onchange_date(self, cr, uid, ids, field_name, adjust_time, time, date, context=None): if adjust_time: format = tools.DEFAULT_SERVER_DATETIME_FORMAT tz = context['tz'] date_local = tools.server_to_local_timestamp( date, format, format, tz) date_local_new = date_local[0:10] + ' ' + time server_tz = tools.get_server_timezone() if server_tz != 'UTC': raise osv.except_osv( _('Error'), _('Only UTC server time is currently supported')) # convet to UTC utc = pytz.utc local_tz = pytz.timezone(tz) fmt = '%Y-%m-%d %H:%M:%S' dt = datetime.strptime(date_local_new, fmt) local_dt = local_tz.localize(dt) date_r = utc.normalize(local_dt.astimezone(utc)).strftime(fmt) else: date_r = date result = {'value': {field_name: date_r}} return result
class payment_line(osv.osv): _name = 'payment.line' _description = 'Payment Line' def translate(self, orig): return { "due_date": "date_maturity", "reference": "ref" }.get(orig, orig) def info_owner(self, cr, uid, ids, name=None, args=None, context=None): if not ids: return {} partner_zip_obj = self.pool.get('res.partner.zip') result = {} info = '' for line in self.browse(cr, uid, ids, context=context): owner = line.order_id.mode.bank_id.partner_id result[line.id] = False if owner.address: for ads in owner.address: if ads.type == 'default': st = ads.street and ads.street or '' st1 = ads.street2 and ads.street2 or '' if 'zip_id' in ads: zip_city = ads.zip_id and partner_zip_obj.name_get( cr, uid, [ads.zip_id.id])[0][1] or '' else: zip = ads.zip and ads.zip or '' city = ads.city and ads.city or '' zip_city = zip + ' ' + city cntry = ads.country_id and ads.country_id.name or '' info = owner.name + "\n" + st + " " + st1 + "\n" + zip_city + "\n" + cntry result[line.id] = info break return result def info_partner(self, cr, uid, ids, name=None, args=None, context=None): if not ids: return {} partner_zip_obj = self.pool.get('res.partner.zip') result = {} info = '' for line in self.browse(cr, uid, ids, context=context): result[line.id] = False if not line.partner_id: break partner = line.partner_id.name or '' if line.partner_id.address: for ads in line.partner_id.address: if ads.type == 'default': st = ads.street and ads.street or '' st1 = ads.street2 and ads.street2 or '' if 'zip_id' in ads: zip_city = ads.zip_id and partner_zip_obj.name_get( cr, uid, [ads.zip_id.id])[0][1] or '' else: zip = ads.zip and ads.zip or '' city = ads.city and ads.city or '' zip_city = zip + ' ' + city cntry = ads.country_id and ads.country_id.name or '' info = partner + "\n" + st + " " + st1 + "\n" + zip_city + "\n" + cntry result[line.id] = info break return result def select_by_name(self, cr, uid, ids, name, args, context=None): if not ids: return {} partner_obj = self.pool.get('res.partner') cr.execute( """SELECT pl.id, ml.%s FROM account_move_line ml INNER JOIN payment_line pl ON (ml.id = pl.move_line_id) WHERE pl.id IN %%s""" % self.translate(name), (tuple(ids), )) res = dict(cr.fetchall()) if name == 'partner_id': partner_name = {} for p_id, p_name in partner_obj.name_get( cr, uid, filter(lambda x: x and x != 0, res.values()), context=context): partner_name[p_id] = p_name for id in ids: if id in res and partner_name: res[id] = (res[id], partner_name[res[id]]) else: res[id] = (False, False) else: for id in ids: res.setdefault(id, (False, "")) return res def _amount(self, cursor, user, ids, name, args, context=None): if not ids: return {} currency_obj = self.pool.get('res.currency') if context is None: context = {} res = {} for line in self.browse(cursor, user, ids, context=context): ctx = context.copy() ctx['date'] = line.order_id.date_done or time.strftime('%Y-%m-%d') res[line.id] = currency_obj.compute(cursor, user, line.currency.id, line.company_currency.id, line.amount_currency, context=ctx) return res def _get_currency(self, cr, uid, context=None): user_obj = self.pool.get('res.users') currency_obj = self.pool.get('res.currency') user = user_obj.browse(cr, uid, uid, context=context) if user.company_id: return user.company_id.currency_id.id else: return currency_obj.search(cr, uid, [('rate', '=', 1.0)])[0] def _get_date(self, cr, uid, context=None): if context is None: context = {} payment_order_obj = self.pool.get('payment.order') date = False if context.get('order_id') and context['order_id']: order = payment_order_obj.browse(cr, uid, context['order_id'], context=context) if order.date_prefered == 'fixed': date = order.date_scheduled else: date = time.strftime('%Y-%m-%d') return date def _get_ml_inv_ref(self, cr, uid, ids, *a): res = {} for id in self.browse(cr, uid, ids): res[id.id] = False if id.move_line_id: if id.move_line_id.invoice: res[id.id] = id.move_line_id.invoice.id return res def _get_ml_maturity_date(self, cr, uid, ids, *a): res = {} for id in self.browse(cr, uid, ids): if id.move_line_id: res[id.id] = id.move_line_id.date_maturity else: res[id.id] = False return res def _get_ml_created_date(self, cr, uid, ids, *a): res = {} for id in self.browse(cr, uid, ids): if id.move_line_id: res[id.id] = id.move_line_id.date_created else: res[id.id] = False return res _columns = { 'name': fields.char('Your Reference', size=64, required=True), 'communication': fields.char( 'Communication', size=64, required=True, help= "Used as the message between ordering customer and current company. Depicts 'What do you want to say to the recipient about this order ?'" ), 'communication2': fields.char('Communication 2', size=64, help='The successor message of Communication.'), 'move_line_id': fields.many2one( 'account.move.line', 'Entry line', domain=[('reconcile_id', '=', False), ('account_id.type', '=', 'payable')], help= 'This Entry Line will be referred for the information of the ordering customer.' ), 'amount_currency': fields.float('Amount in Partner Currency', digits=(16, 2), required=True, help='Payment amount in the partner currency'), 'currency': fields.many2one('res.currency', 'Partner Currency', required=True), 'company_currency': fields.many2one('res.currency', 'Company Currency', readonly=True), 'bank_id': fields.many2one('res.partner.bank', 'Destination Bank account'), 'order_id': fields.many2one('payment.order', 'Order', required=True, ondelete='cascade', select=True), 'partner_id': fields.many2one('res.partner', string="Partner", required=True, help='The Ordering Customer'), 'amount': fields.function(_amount, string='Amount in Company Currency', method=True, type='float', help='Payment amount in the company currency'), 'ml_date_created': fields.function(_get_ml_created_date, string="Effective Date", method=True, type='date', help="Invoice Effective Date"), 'ml_maturity_date': fields.function(_get_ml_maturity_date, method=True, type='date', string='Due Date'), 'ml_inv_ref': fields.function(_get_ml_inv_ref, method=True, type='many2one', relation='account.invoice', string='Invoice Ref.'), 'info_owner': fields.function(info_owner, string="Owner Account", method=True, type="text", help='Address of the Main Partner'), 'info_partner': fields.function(info_partner, string="Destination Account", method=True, type="text", help='Address of the Ordering Customer.'), 'date': fields.date( 'Payment Date', help= "If no payment date is specified, the bank will treat this payment line directly" ), 'create_date': fields.datetime('Created', readonly=True), 'state': fields.selection([('normal', 'Free'), ('structured', 'Structured')], 'Communication Type', required=True), 'bank_statement_line_id': fields.many2one('account.bank.statement.line', 'Bank statement line') } _defaults = { 'name': lambda obj, cursor, user, context: obj.pool.get('ir.sequence').get( cursor, user, 'payment.line'), 'state': 'normal', 'currency': _get_currency, 'company_currency': _get_currency, 'date': _get_date, } _sql_constraints = [ ('name_uniq', 'UNIQUE(name)', 'The payment line name must be unique!'), ] def onchange_move_line(self, cr, uid, ids, move_line_id, payment_type, date_prefered, date_scheduled, currency=False, company_currency=False, context=None): data = {} move_line_obj = self.pool.get('account.move.line') data['amount_currency'] = data['communication'] = data[ 'partner_id'] = data['reference'] = data['date_created'] = data[ 'bank_id'] = data['amount'] = False if move_line_id: line = move_line_obj.browse(cr, uid, move_line_id, context=context) data['amount_currency'] = line.amount_to_pay res = self.onchange_amount(cr, uid, ids, data['amount_currency'], currency, company_currency, context) if res: data['amount'] = res['value']['amount'] data['partner_id'] = line.partner_id.id temp = line.currency_id and line.currency_id.id or False if not temp: if line.invoice: data['currency'] = line.invoice.currency_id.id else: data['currency'] = temp # calling onchange of partner and updating data dictionary temp_dict = self.onchange_partner(cr, uid, ids, line.partner_id.id, payment_type) data.update(temp_dict['value']) data['reference'] = line.ref data['date_created'] = line.date_created data['communication'] = line.ref if date_prefered == 'now': #no payment date => immediate payment data['date'] = False elif date_prefered == 'due': data['date'] = line.date_maturity elif date_prefered == 'fixed': data['date'] = date_scheduled return {'value': data} def onchange_amount(self, cr, uid, ids, amount, currency, cmpny_currency, context=None): if (not amount) or (not cmpny_currency): return {'value': {'amount': False}} res = {} currency_obj = self.pool.get('res.currency') company_amount = currency_obj.compute(cr, uid, currency, cmpny_currency, amount) res['amount'] = company_amount return {'value': res} def onchange_partner(self, cr, uid, ids, partner_id, payment_type, context=None): data = {} partner_zip_obj = self.pool.get('res.partner.zip') partner_obj = self.pool.get('res.partner') payment_mode_obj = self.pool.get('payment.mode') data['info_partner'] = data['bank_id'] = False if partner_id: part_obj = partner_obj.browse(cr, uid, partner_id, context=context) partner = part_obj.name or '' if part_obj.address: for ads in part_obj.address: if ads.type == 'default': st = ads.street and ads.street or '' st1 = ads.street2 and ads.street2 or '' if 'zip_id' in ads: zip_city = ads.zip_id and partner_zip_obj.name_get( cr, uid, [ads.zip_id.id])[0][1] or '' else: zip = ads.zip and ads.zip or '' city = ads.city and ads.city or '' zip_city = zip + ' ' + city cntry = ads.country_id and ads.country_id.name or '' info = partner + "\n" + st + " " + st1 + "\n" + zip_city + "\n" + cntry data['info_partner'] = info if part_obj.bank_ids and payment_type: bank_type = payment_mode_obj.suitable_bank_types( cr, uid, payment_type, context=context) for bank in part_obj.bank_ids: if bank.state in bank_type: data['bank_id'] = bank.id break return {'value': data} def fields_get(self, cr, uid, fields=None, context=None): res = super(payment_line, self).fields_get(cr, uid, fields, context) if 'communication2' in res: res['communication2'].setdefault('states', {}) res['communication2']['states']['structured'] = [('readonly', True) ] res['communication2']['states']['normal'] = [('readonly', False)] return res
class member_charge(osv.osv): '''会员充值信息''' _name = "member_management.member_charge" _descripton = "会员充值设置" _columns = { "member_id": fields.many2one("member_management.member", "member_id", select=True, required=True, help="会员卡号"), "bill_datetime": fields.datetime('bill_date', required=True, help="充值时间"), "charge_fee": fields.float("charge_fee", digits_compute=dp.get_precision('member_management_fee'), help="本次充值金额"), "before_charge_balance": fields.float("before_charge_banalce", readonly=True, digits_compute=dp.get_precision('member_management_fee'), help="充值前卡余额"), "after_charge_balance": fields.float("after_charge_banalce", readonly=True, digits_compute=dp.get_precision('member_management_fee'), help="充值后卡余额"), "charge_points": fields.integer("charge_points", help="本次充值积分"), "before_charge_points": fields.integer("before_charge_points", help="充值前卡积分"), "after_charge_points": fields.integer('after_charge_points', help="充值后卡积分"), "pay_type_id": fields.many2one('member_management.pay_type', 'pay_type_id', required=True, help="付款方式"), "present_charge_fee": fields.float("present_charge_fee", readonly=True, digits_compute=dp.get_precision('member_management_fee'), help="本次赠送金额"), "printed": fields.boolean("printed", readonly=True, help="是否已打印"), "active": fields.boolean("active"), } _defaults = { "bill_datetime": fields.datetime.now, "charge_fee": 0.0, "before_charge_balance": 0.0, "after_charge_balance": 0.0, "charge_points": 0, "before_charge_points": 0, "after_charge_points": 0, "present_charge_fee": 0.0, "pay_type_id": lambda obj, cr, uid, context: obj.pool.get( 'member_management.pay_type').get_pay_type_id( cr, uid, pay_type.PAY_TYPE_CASH), "printed": False, "active": True, } def onchange_member_id_or_charge_fee(self, cr, uid, ids, member_id, charge_fee): ''' member_id发生变化时,需要处理赠送金额 ''' if not member_id: return {} present_fee = 0.0 pool = self.pool member = pool.get('member_management.member').browse( cr, uid, member_id) #获取会员充值优惠设置 if charge_fee > 0: member_class_id = member.member_class_id.id pref_ids = pool.get( 'member_management.member_recharge_pref').search( cr, uid, [('member_class_id', '=', member_class_id)]) active_prefs = [ pref for pref in pool.get('member_management.member_recharge_pref'). browse(cr, uid, pref_ids) if charge_fee >= pref.start_fee and charge_fee <= pref.end_fee ] if active_prefs: present_fee = active_prefs[0].pref_fee vals = { 'present_charge_fee': present_fee, 'before_charge_balance': member.balance, 'after_charge_balance': member.balance + charge_fee + present_fee, } return {"value": vals} def print_info(self, cr, uid, id, context): ''' 获取打印信息 ''' #判断是否已打印 vals = self.read(cr, uid, id, context) if not vals['printed']: self.write(cr, uid, id, {'printed': True}) member = self.pool.get('member_management.member').read( cr, uid, vals['member_id'][0]) vals['member_id'] = member return vals
class ir_property(osv.osv): _name = 'ir.property' def _models_field_get(self, cr, uid, field_key, field_value, context=None): get = attrgetter(field_key, field_value) obj = self.pool.get('ir.model.fields') ids = obj.search(cr, uid, [('view_load', '=', 1)], context=context) res = set() for o in obj.browse(cr, uid, ids, context=context): res.add(get(o)) return list(res) def _models_get(self, cr, uid, context=None): return self._models_field_get(cr, uid, 'model', 'model_id.name', context) def _models_get2(self, cr, uid, context=None): return self._models_field_get(cr, uid, 'relation', 'relation', context) _columns = { 'name': fields.char('Name', size=128, select=1), 'res_id': fields.reference( 'Resource', selection=_models_get, size=128, help="If not set, acts as a default value for new resources", select=1), 'company_id': fields.many2one('res.company', 'Company', select=1), 'fields_id': fields.many2one('ir.model.fields', 'Field', ondelete='cascade', required=True, select=1), 'value_float': fields.float('Value'), 'value_integer': fields.integer_big('Value'), # will contain (int, bigint) 'value_text': fields.text('Value'), # will contain (char, text) 'value_binary': fields.binary('Value'), 'value_reference': fields.reference('Value', selection=_models_get2, size=128), 'value_datetime': fields.datetime('Value'), 'type': fields.selection([ ('char', 'Char'), ('float', 'Float'), ('boolean', 'Boolean'), ('integer', 'Integer'), ('integer_big', 'Integer Big'), ('text', 'Text'), ('binary', 'Binary'), ('many2one', 'Many2One'), ('date', 'Date'), ('datetime', 'DateTime'), ], 'Type', required=True, select=1), } _defaults = { 'type': 'many2one', } def _update_values(self, cr, uid, ids, values): value = values.pop('value', None) if not value: return values prop = None type_ = values.get('type') if not type_: if ids: prop = self.browse(cr, uid, ids[0]) type_ = prop.type else: type_ = self._defaults['type'] type2field = { 'char': 'value_text', 'float': 'value_float', 'boolean': 'value_integer', 'integer': 'value_integer', 'integer_big': 'value_integer', 'text': 'value_text', 'binary': 'value_binary', 'many2one': 'value_reference', 'date': 'value_datetime', 'datetime': 'value_datetime', } field = type2field.get(type_) if not field: raise osv.except_osv('Error', 'Invalid type') if field == 'value_reference': if isinstance(value, osv.orm.browse_record): value = '%s,%d' % (value._name, value.id) elif isinstance(value, (int, long)): field_id = values.get('fields_id') if not field_id: if not prop: raise ValueError() field_id = prop.fields_id else: field_id = self.pool.get('ir.model.fields').browse( cr, uid, field_id) value = '%s,%d' % (field_id.relation, value) values[field] = value return values def write(self, cr, uid, ids, values, context=None): return super(ir_property, self).write(cr, uid, ids, self._update_values(cr, uid, ids, values), context=context) def create(self, cr, uid, values, context=None): return super(ir_property, self).create(cr, uid, self._update_values(cr, uid, None, values), context=context) def get_by_record(self, cr, uid, record, context=None): if record.type in ('char', 'text'): return record.value_text elif record.type == 'float': return record.value_float elif record.type == 'boolean': return bool(record.value_integer) elif record.type in ('integer', 'integer_big'): return record.value_integer elif record.type == 'binary': return record.value_binary elif record.type == 'many2one': return record.value_reference elif record.type == 'datetime': return record.value_datetime elif record.type == 'date': if not record.value_datetime: return False return time.strftime( '%Y-%m-%d', time.strptime(record.value_datetime, '%Y-%m-%d %H:%M:%S')) return False def get(self, cr, uid, name, model, res_id=False, context={}): domain = self._get_domain(cr, uid, name, model, context=context) if domain is not None: domain = [('res_id', '=', res_id)] + domain nid = self.search(cr, uid, domain, context=context) if not nid: return False record = self.browse(cr, uid, nid[0], context=context) return self.get_by_record(cr, uid, record, context=context) return False def _get_domain_default(self, cr, uid, prop_name, model, context=None): domain = self._get_domain(cr, uid, prop_name, model, context=context) if domain is None: return None return ['&', ('res_id', '=', False)] + domain def _get_domain(self, cr, uid, prop_name, model, context=None): context = context or {} cr.execute('select id from ir_model_fields where name=%s and model=%s', (prop_name, model)) res = cr.fetchone() if not res: return None if 'force_company' in context and context['force_company']: cid = context['force_company'] else: company = self.pool.get('res.company') cid = company._company_default_get(cr, uid, model, res[0], context=context) domain = [ '&', ('fields_id', '=', res[0]), '|', ('company_id', '=', cid), ('company_id', '=', False) ] return domain
class product_images(magerp_osv.magerp_osv): _inherit = "product.images" _columns = { 'base_image': fields.boolean('Base Image'), 'small_image': fields.boolean('Small Image'), 'thumbnail': fields.boolean('Thumbnail'), 'exclude': fields.boolean('Exclude'), 'position': fields.integer('Position'), 'sync_status': fields.boolean('Sync Status', readonly=True), 'create_date': fields.datetime('Created date', readonly=True), 'write_date': fields.datetime('Updated date', readonly=True), } _defaults = { 'sync_status': lambda *a: False, 'base_image': lambda *a: True, 'small_image': lambda *a: True, 'thumbnail': lambda *a: True, 'exclude': lambda *a: False } _logger = logging.getLogger(__name__) def get_changed_ids(self, cr, uid, start_date=False): proxy = self.pool.get('product.images') domain = start_date and [ '|', ('create_date', '>', start_date), ('write_date', '>', start_date) ] or [] return proxy.search(cr, uid, domain) def del_image_name(self, cr, uid, id, context=None): if context is None: context = {} image_ext_name_obj = self.pool.get('product.images.external.name') name_id = image_ext_name_obj.search( cr, uid, [('image_id', '=', id), ('external_referential_id', '=', context['external_referential_id'])], context=context) if name_id: return image_ext_name_obj.unlink(cr, uid, name_id, context=context) return False def update_remote_images(self, cr, uid, ids, context=None): if context is None: context = {} conn = context.get('conn_obj', False) if not conn: return False ir_model_data_obj = self.pool.get('ir.model.data') def detect_types(image): types = [] if image.small_image: types.append('small_image') if image.base_image: types.append('image') if image.thumbnail: types.append('thumbnail') return types #TODO update the image file def update_image(image_name, image): result = conn.call('catalog_product_attribute_media.update', [ image.product_id.magento_sku, image_name, { 'label': image.name, 'exclude': image.exclude, 'types': detect_types(image), } ]) return result list_image = [] list_image = self.read(cr, uid, ids, ['write_date', 'create_date'], context=context) date_2_image = {} image_2_date = {} for image in list_image: if date_2_image.get(image['write_date'] or image['create_date'], False): done = False count = 0 while not done: count += 1 if not date_2_image.get( (image['write_date'] or image['create_date']) + '-' + str(count), False): date_2_image[ (image['write_date'] or image['create_date']) + '-' + str(count)] = image['id'] done = True else: date_2_image[image['write_date'] or image['create_date']] = image['id'] image_2_date[ image['id']] = image['write_date'] or image['create_date'] list_date = date_2_image.keys() list_date.sort() ids = [date_2_image[date] for date in list_date] while ids: product_images = self.browse_w_order(cr, uid, ids[:1000], context=context) for each in product_images: need_to_be_created = True ext_file_name = each.oeid_to_extid( context['external_referential_id']) if ext_file_name: #If update try: self._logger.info( "Updating %s's image: %s" % (each.product_id.magento_sku, each.name)) result = update_image(ext_file_name, each) self._logger.info( "%s's image updated with sucess: %s" % (each.product_id.magento_sku, each.name)) need_to_be_created = False except Exception, e: self._logger.error(_("Error in connecting:%s") % (e)) if not "Fault 103" in str(e): self._logger.error(_("Unknow error stop export")) raise else: #If the image was deleded in magento, the external name is automatically deleded before trying to re-create the image in magento model_data_ids = ir_model_data_obj.search( cr, uid, [('model', '=', self._name), ('res_id', '=', each.id), ('external_referential_id', '=', context['external_referential_id'])]) if model_data_ids and len(model_data_ids) > 0: ir_model_data_obj.unlink(cr, uid, model_data_ids, context=context) self._logger.error( _("The image don't exist in magento, try to create it" )) if need_to_be_created: if each.product_id.magento_sku: self._logger.info( "Sending %s's image: %s" % (each.product_id.magento_sku, each.name)) result = conn.call( 'catalog_product_attribute_media.create', [ each.product_id.magento_sku, { 'file': { 'name': each.name, 'content': each.file, 'mime': each.link and each.url and mimetypes.guess_type(each.url)[0] or each.extention and mimetypes.guess_type(each.extention)[0] or 'image/jpeg', } } ]) self.create_external_id_vals( cr, uid, each.id, result, context['external_referential_id'], context=context) result = update_image(result, each) self._logger.info( "%s's image send with sucess: %s" % (each.product_id.magento_sku, each.name)) if image_2_date[each.id] > context[ 'last_images_export_date']: #indeed if a product was created a long time ago and checked as exportable recently, the write date of the image can be far away in the past self.pool.get('sale.shop').write( cr, uid, context['shop_id'], {'last_images_export_date': image_2_date[each.id]}) cr.commit() ids = ids[1000:] self._logger.info("still %s image to export" % len(ids)) return True
class mrp_production_workcenter_line(osv.osv): def _get_date_date(self, cr, uid, ids, field_name, arg, context=None): """ Finds starting date. @return: Dictionary of values. """ res = {} for op in self.browse(cr, uid, ids, context=context): if op.date_start: res[op.id] = op.date_start[:10] else: res[op.id] = False return res def _get_date_end(self, cr, uid, ids, field_name, arg, context=None): """ Finds ending date. @return: Dictionary of values. """ ops = self.browse(cr, uid, ids, context=context) date_and_hours_by_cal = [(op.date_planned, op.hour, op.workcenter_id.calendar_id.id) for op in ops if op.date_planned] intervals = self.pool.get('resource.calendar').interval_get_multi( cr, uid, date_and_hours_by_cal) res = {} for op in ops: res[op.id] = False if op.date_planned: i = intervals.get((op.date_planned, op.hour, op.workcenter_id.calendar_id.id)) if i: res[op.id] = i[-1][1].strftime('%Y-%m-%d %H:%M:%S') else: res[op.id] = op.date_planned return res def onchange_production_id(self, cr, uid, ids, production_id, context=None): if not production_id: return {} production = self.pool.get('mrp.production').browse(cr, uid, production_id, context=None) result = { 'product': production.product_id.id, 'qty': production.product_qty, 'uom': production.product_uom.id, } return {'value': result} _inherit = 'mrp.production.workcenter.line' _order = "sequence, date_planned" _columns = { 'state': fields.selection([('draft','Draft'),('startworking', 'In Progress'),('pause','Pending'),('cancel','Cancelled'),('done','Finished')],'State', readonly=True, help="* When a work order is created it is set in 'Draft' state.\n" \ "* When user sets work order in start mode that time it will be set in 'In Progress' state.\n" \ "* When work order is in running mode, during that time if user wants to stop or to make changes in order then can set in 'Pending' state.\n" \ "* When the user cancels the work order it will be set in 'Canceled' state.\n" \ "* When order is completely processed that time it is set in 'Finished' state."), 'date_start_date': fields.function(_get_date_date, string='Start Date', type='date'), 'date_planned': fields.datetime('Scheduled Date', select=True), 'date_planned_end': fields.function(_get_date_end, string='End Date', type='datetime'), 'date_start': fields.datetime('Start Date'), 'date_finished': fields.datetime('End Date'), 'delay': fields.float('Working Hours',help="The elapsed time between operation start and stop in this Work Center",readonly=True), 'production_state':fields.related('production_id','state', type='selection', selection=[('draft','Draft'),('picking_except', 'Picking Exception'),('confirmed','Waiting Goods'),('ready','Ready to Produce'),('in_production','In Production'),('cancel','Canceled'),('done','Done')], string='Production State', readonly=True), 'product':fields.related('production_id','product_id',type='many2one',relation='product.product',string='Product', readonly=True), 'qty':fields.related('production_id','product_qty',type='float',string='Qty',readonly=True, store=True), 'uom':fields.related('production_id','product_uom',type='many2one',relation='product.uom',string='UOM',readonly=True), } _defaults = {'state': lambda *a: 'draft', 'delay': lambda *a: 0.0} def modify_production_order_state(self, cr, uid, ids, action): """ Modifies production order state if work order state is changed. @param action: Action to perform. @return: Nothing """ wf_service = netsvc.LocalService("workflow") prod_obj_pool = self.pool.get('mrp.production') oper_obj = self.browse(cr, uid, ids)[0] prod_obj = oper_obj.production_id if action == 'start': if prod_obj.state == 'confirmed': prod_obj_pool.force_production(cr, uid, [prod_obj.id]) wf_service.trg_validate(uid, 'mrp.production', prod_obj.id, 'button_produce', cr) elif prod_obj.state == 'ready': wf_service.trg_validate(uid, 'mrp.production', prod_obj.id, 'button_produce', cr) elif prod_obj.state == 'in_production': return else: raise osv.except_osv( _('Error!'), _('Manufacturing order cannot start in state "%s"!') % (prod_obj.state, )) else: oper_ids = self.search(cr, uid, [('production_id', '=', prod_obj.id)]) obj = self.browse(cr, uid, oper_ids) flag = True for line in obj: if line.state != 'done': flag = False if flag: for production in prod_obj_pool.browse(cr, uid, [prod_obj.id], context=None): if production.move_lines or production.move_created_ids: prod_obj_pool.action_produce(cr, uid, production.id, production.product_qty, 'consume_produce', context=None) wf_service.trg_validate(uid, 'mrp.production', oper_obj.production_id.id, 'button_produce_done', cr) return def write(self, cr, uid, ids, vals, context=None, update=True): result = super(mrp_production_workcenter_line, self).write(cr, uid, ids, vals, context=context) prod_obj = self.pool.get('mrp.production') if vals.get('date_planned', False) and update: for prod in self.browse(cr, uid, ids, context=context): if prod.production_id.workcenter_lines: dstart = min( vals['date_planned'], prod.production_id.workcenter_lines[0]['date_planned']) prod_obj.write(cr, uid, [prod.production_id.id], {'date_start': dstart}, context=context, mini=False) return result def action_draft(self, cr, uid, ids, context=None): """ Sets state to draft. @return: True """ return self.write(cr, uid, ids, {'state': 'draft'}, context=context) def action_start_working(self, cr, uid, ids, context=None): """ Sets state to start working and writes starting date. @return: True """ self.modify_production_order_state(cr, uid, ids, 'start') self.write(cr, uid, ids, { 'state': 'startworking', 'date_start': time.strftime('%Y-%m-%d %H:%M:%S') }, context=context) return True def action_done(self, cr, uid, ids, context=None): """ Sets state to done, writes finish date and calculates delay. @return: True """ delay = 0.0 date_now = time.strftime('%Y-%m-%d %H:%M:%S') obj_line = self.browse(cr, uid, ids[0]) date_start = datetime.strptime(obj_line.date_start, '%Y-%m-%d %H:%M:%S') date_finished = datetime.strptime(date_now, '%Y-%m-%d %H:%M:%S') delay += (date_finished - date_start).days * 24 delay += (date_finished - date_start).seconds / float(60 * 60) self.write(cr, uid, ids, { 'state': 'done', 'date_finished': date_now, 'delay': delay }, context=context) self.modify_production_order_state(cr, uid, ids, 'done') return True def action_cancel(self, cr, uid, ids, context=None): """ Sets state to cancel. @return: True """ return self.write(cr, uid, ids, {'state': 'cancel'}, context=context) def action_pause(self, cr, uid, ids, context=None): """ Sets state to pause. @return: True """ return self.write(cr, uid, ids, {'state': 'pause'}, context=context) def action_resume(self, cr, uid, ids, context=None): """ Sets state to startworking. @return: True """ return self.write(cr, uid, ids, {'state': 'startworking'}, context=context)
list_message = _("%s product relisted successfully on ebay") % product_name self.log(cr, uid,increment, list_message) return def onchange_listing_type(self,cr,uid,ids,type): result = {} if type: search_duration = self.pool.get('duration.time').search(cr,uid,[('type','=',type)]) if search_duration: result['list_durtn'] = search_duration[0] return{'value':result} _rec_name = 'shop_id' _columns = { # 'name' :fields.char('Name',size=64), 'shop_id' : fields.many2one('sale.shop','Ebay Shop',required=True,help="Shop on which products to be relisted"), 'rel_prod' : fields.many2many('product.product','shop_prod_rel','shop_id','prod_id','List of Expired Products'), 'schedule_time':fields.datetime('Schedule Time'), 'list_durtn' : fields.many2one('duration.time','Duration',required=True,help="Duration Of the Product on Ebay"), 'template_id': fields.many2one('ebayerp.template','Template',required=True,help="Selected Template Configuration will be applied to the Listing Products"), 'ebay_current_time':fields.datetime('Ebay Current Time'), 'type': fields.selection([('Chinese','Auction'),('FixedPriceItem','Fixed Price'),('LeadGeneration','Classified Ad')],'Type',required=True,help="Type in which Products to be listed"), 'start_price':fields.many2one('product.pricelist','Start Price',help="Selected Pricelist will be applied to the Listing Products"), 'reserve_price':fields.many2one('product.pricelist','Reserve Price',help="Selected Pricelist will be applied to the Listing Products"), 'buy_it_nw':fields.many2one('product.pricelist','Buy It Now Price',help="Selected Pricelist will be applied to the Listing Products"), 'condtn':fields.selection([('1000','New'),('1500','New other (see details)'),('2000','Manufacturer refurbished'),('2500','Seller refurbished'),('3000','Used'),('7000','For parts or not working')],'Condition'), 'inst_list_chk' : fields.boolean('Start listing immediately',help="Will Active Product Immediately on Ebay"), } _defaults = { 'type': 'Chinese', 'inst_list_chk':True, 'start_price':1, 'reserve_price':1,
v = base64.decodestring(value) fp.write(v) filesize = os.stat(fname).st_size cr.execute('update ir_attachment set store_fname=%s,store_method=%s,file_size=%s where id=%s', (os.path.join(flag,filename),'fs',len(v),id)) return True except Exception,e : raise except_orm(_('Error!'), str(e)) _columns = { 'user_id': fields.many2one('res.users', 'Owner', select=1), 'group_ids': fields.many2many('res.groups', 'document_directory_group_rel', 'item_id', 'group_id', 'Groups'), 'parent_id': fields.many2one('document.directory', 'Directory', select=1), 'file_size': fields.integer('File Size', required=True), 'file_type': fields.char('Content Type', size=32), 'index_content': fields.text('Indexed Content'), 'write_date': fields.datetime('Date Modified', readonly=True), 'write_uid': fields.many2one('res.users', 'Last Modification User', readonly=True), 'create_date': fields.datetime('Date Created', readonly=True), 'create_uid': fields.many2one('res.users', 'Creator', readonly=True), 'store_method': fields.selection([('db','Database'),('fs','Filesystem'),('link','Link')], "Storing Method"), 'datas': fields.function(_data_get,method=True,fnct_inv=_data_set,string='File Content',type="binary"), 'store_fname': fields.char('Stored Filename', size=200), 'res_model': fields.char('Attached Model', size=64), #res_model 'res_id': fields.integer('Attached ID'), #res_id 'partner_id':fields.many2one('res.partner', 'Partner', select=1), 'title': fields.char('Resource Title',size=64), } _defaults = { 'user_id': lambda self,cr,uid,ctx:uid, 'file_size': lambda self,cr,uid,ctx:0,
class res_letter(osv.osv): """A register class to log all movements regarding letters""" _name = 'res.letter' _description = "A Register class to log all movements regarding letters" def _get_number(self, cr, uid, context): if context is None: context = {} move = context.get('move', 'in') if move == 'in': res = self.pool.get('ir.sequence').get(cr, uid, 'in.letter') else: res = self.pool.get('ir.sequence').get(cr, uid, 'out.letter') return res _columns = { 'name': fields.char('Subject', size=128, help="Subject of letter"), 'number': fields.char('Number', size=32, help="Autogenerated Number of letter", required=True), 'move': fields.selection([('in', 'IN'), ('out', 'OUT')], 'Move', readonly=True, help="Incoming or Outgoing Letter"), 'type': fields.many2one('letter.type', 'Type', help="Type of Letter, Depeding upon size", required=True), 'class': fields.many2one('letter.class', 'Class', help="Classification of Document", required=True), 'date': fields.datetime('Sent / Received Date', required=True), 'partner_id': fields.many2one('res.partner', 'Partner'), 'address_id': fields.many2one('res.partner.address', 'Address'), 'int_ref': fields.reference('Reference', selection=_links_get, size=128), 'int_ref2': fields.reference('Reference 2', selection=_links_get, size=128), 'user_id': fields.many2one('res.users', "Dispatcher", required=True), 'snd_rec_id': fields.many2one('res.users', "Sender / Receiver"), 'note': fields.text('Note'), 'state': fields.selection([('draft', 'Draft'), ('rec', 'Received'), ('sent', 'Sent'), ('rec_bad', 'Received Damage'), ('rec_ret', 'Received But Returned'), ('cancel', 'Cancelled')], 'State', readonly=True), 'parent_id': fields.many2one('res.letter', 'Parent'), 'child_line': fields.one2many('res.letter', 'parent_id', 'Letter Lines'), 'active': fields.boolean('Active'), 'channel_id': fields.many2one('letter.channel', 'Sent / Receive Source'), 'company_id': fields.many2one('res.company', 'Company', required=True), 'history_line': fields.one2many('letter.history', 'register_id', 'History'), 'ref_data': fields.char('Reference Number', size=32, help="Reference Number Provided by postal provider."), 'weight': fields.float('Weight (in KG)'), 'size': fields.char('Size', size=64), } _defaults = { 'number': _get_number, 'date': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'), 'user_id': lambda self, cr, uid, context: uid, 'move': lambda self, cr, uid, context: context.get('move', 'in'), 'state': lambda *a: 'draft', 'active': lambda *a: 1, 'company_id': lambda self, cr, uid, c: self.pool.get('res.company'). _company_default_get(cr, uid, 'res.letter', context=c), } def history(self, cr, uid, ids, context={}, keyword=False): lh_pool = self.pool.get('letter.history') for id in ids: lh_pool.create(cr, uid, { 'name': keyword, 'user_id': uid, 'register_id': id }) return True def action_received(self, cr, uid, ids, context={}): self.write(cr, uid, ids, {'state': 'rec'}) self.history(cr, uid, ids, context={'translated_keyword': _('Received')}, keyword=_('Received')) return True def action_cancel(self, cr, uid, ids, context={}): self.write(cr, uid, ids, {'state': 'cancel'}) self.history(cr, uid, ids, context={'translated_keyword': _('Cancel')}, keyword=_('Cancel')) return True def action_sent(self, cr, uid, ids, context={}): self.write(cr, uid, ids, {'state': 'sent'}) self.history(cr, uid, ids, context={'translated_keyword': _('Sent')}, keyword=_('Sent')) return True def action_rec_ret(self, cr, uid, ids, context={}): self.write(cr, uid, ids, {'state': 'rec_ret'}) self.history( cr, uid, ids, context={'translated_keyword': _('Received But Returned')}, keyword=_('Received But Returned')) return True def action_rec_bad(self, cr, uid, ids, context={}): self.write(cr, uid, ids, {'state': 'rec_bad'}) self.history(cr, uid, ids, context={'translated_keyword': _('Received Damage')}, keyword=_('Received Damage')) return True def action_set_draft(self, cr, uid, ids, context={}): self.write(cr, uid, ids, {'state': 'draft'}) self.history(cr, uid, ids, context={'translated_keyword': _('Set To Draft')}, keyword=_('Set To Draft')) return True
class mrp_operations_operation(osv.osv): _name = "mrp_operations.operation" def _order_date_search_production(self, cr, uid, ids, context=None): """ Finds operations for a production order. @return: List of ids """ operation_ids = self.pool.get('mrp_operations.operation').search( cr, uid, [('production_id', '=', ids[0])], context=context) return operation_ids def _get_order_date(self, cr, uid, ids, field_name, arg, context=None): """ Calculates planned date for an operation. @return: Dictionary of values """ res = {} operation_obj = self.browse(cr, uid, ids, context=context) for operation in operation_obj: res[operation.id] = operation.production_id.date_planned return res def calc_delay(self, cr, uid, vals): """ Calculates delay of work order. @return: Delay """ code_lst = [] time_lst = [] code_ids = self.pool.get('mrp_operations.operation.code').search( cr, uid, [('id', '=', vals['code_id'])]) code = self.pool.get('mrp_operations.operation.code').browse( cr, uid, code_ids)[0] oper_ids = self.search(cr, uid, [('production_id', '=', vals['production_id']), ('workcenter_id', '=', vals['workcenter_id'])]) oper_objs = self.browse(cr, uid, oper_ids) for oper in oper_objs: code_lst.append(oper.code_id.start_stop) time_lst.append(oper.date_start) code_lst.append(code.start_stop) time_lst.append(vals['date_start']) diff = 0 for i in range(0, len(code_lst)): if code_lst[i] == 'pause' or code_lst[i] == 'done' or code_lst[ i] == 'cancel': if not i: continue if code_lst[i - 1] not in ('resume', 'start'): continue a = datetime.strptime(time_lst[i - 1], '%Y-%m-%d %H:%M:%S') b = datetime.strptime(time_lst[i], '%Y-%m-%d %H:%M:%S') diff += (b - a).days * 24 diff += (b - a).seconds / float(60 * 60) return diff def check_operation(self, cr, uid, vals): """ Finds which operation is called ie. start, pause, done, cancel. @param vals: Dictionary of values. @return: True or False """ code_ids = self.pool.get('mrp_operations.operation.code').search( cr, uid, [('id', '=', vals['code_id'])]) code = self.pool.get('mrp_operations.operation.code').browse( cr, uid, code_ids)[0] code_lst = [] oper_ids = self.search(cr, uid, [('production_id', '=', vals['production_id']), ('workcenter_id', '=', vals['workcenter_id'])]) oper_objs = self.browse(cr, uid, oper_ids) if not oper_objs: if code.start_stop != 'start': raise osv.except_osv(_('Sorry!'), _('Operation is not started yet !')) return False else: for oper in oper_objs: code_lst.append(oper.code_id.start_stop) if code.start_stop == 'start': if 'start' in code_lst: raise osv.except_osv( _('Sorry!'), _('Operation has already started !' 'Youcan either Pause/Finish/Cancel the operation')) return False if code.start_stop == 'pause': if code_lst[len(code_lst) - 1] != 'resume' and code_lst[ len(code_lst) - 1] != 'start': raise osv.except_osv( _('Error!'), _('In order to Pause the operation, it must be in the Start or Resume state!' )) return False if code.start_stop == 'resume': if code_lst[len(code_lst) - 1] != 'pause': raise osv.except_osv( _('Error!'), _('In order to Resume the operation, it must be in the Pause state!' )) return False if code.start_stop == 'done': if code_lst[len(code_lst) - 1] != 'start' and code_lst[ len(code_lst) - 1] != 'resume': raise osv.except_osv( _('Sorry!'), _('In order to Finish the operation, it must be in the Start or Resume state!' )) return False if 'cancel' in code_lst: raise osv.except_osv(_('Sorry!'), _('Operation is Already Cancelled!')) return False if code.start_stop == 'cancel': if not 'start' in code_lst: raise osv.except_osv( _('Error!'), _('There is no Operation to be cancelled!')) return False if 'done' in code_lst: raise osv.except_osv(_('Error!'), _('Operation is already finished!')) return False return True def write(self, cr, uid, ids, vals, context=None): oper_objs = self.browse(cr, uid, ids, context=context)[0] vals['production_id'] = oper_objs.production_id.id vals['workcenter_id'] = oper_objs.workcenter_id.id if 'code_id' in vals: self.check_operation(cr, uid, vals) if 'date_start' in vals: vals['date_start'] = vals['date_start'] vals['code_id'] = oper_objs.code_id.id delay = self.calc_delay(cr, uid, vals) wc_op_id = self.pool.get('mrp.production.workcenter.line').search( cr, uid, [('workcenter_id', '=', vals['workcenter_id']), ('production_id', '=', vals['production_id'])]) self.pool.get('mrp.production.workcenter.line').write( cr, uid, wc_op_id, {'delay': delay}) return super(mrp_operations_operation, self).write(cr, uid, ids, vals, context=context) def create(self, cr, uid, vals, context=None): wf_service = netsvc.LocalService('workflow') code_ids = self.pool.get('mrp_operations.operation.code').search( cr, uid, [('id', '=', vals['code_id'])]) code = self.pool.get('mrp_operations.operation.code').browse( cr, uid, code_ids, context=context)[0] wc_op_id = self.pool.get('mrp.production.workcenter.line').search( cr, uid, [('workcenter_id', '=', vals['workcenter_id']), ('production_id', '=', vals['production_id'])]) if code.start_stop in ('start', 'done', 'pause', 'cancel', 'resume'): if not wc_op_id: production_obj = self.pool.get('mrp.production').browse( cr, uid, vals['production_id'], context=context) wc_op_id.append( self.pool.get('mrp.production.workcenter.line').create( cr, uid, { 'production_id': vals['production_id'], 'name': production_obj.product_id.name, 'workcenter_id': vals['workcenter_id'] })) if code.start_stop == 'start': self.pool.get( 'mrp.production.workcenter.line').action_start_working( cr, uid, wc_op_id) wf_service.trg_validate(uid, 'mrp.production.workcenter.line', wc_op_id[0], 'button_start_working', cr) if code.start_stop == 'done': self.pool.get('mrp.production.workcenter.line').action_done( cr, uid, wc_op_id) wf_service.trg_validate(uid, 'mrp.production.workcenter.line', wc_op_id[0], 'button_done', cr) self.pool.get('mrp.production').write( cr, uid, vals['production_id'], { 'date_finished': datetime.now().strftime('%Y-%m-%d %H:%M:%S') }) if code.start_stop == 'pause': self.pool.get('mrp.production.workcenter.line').action_pause( cr, uid, wc_op_id) wf_service.trg_validate(uid, 'mrp.production.workcenter.line', wc_op_id[0], 'button_pause', cr) if code.start_stop == 'resume': self.pool.get('mrp.production.workcenter.line').action_resume( cr, uid, wc_op_id) wf_service.trg_validate(uid, 'mrp.production.workcenter.line', wc_op_id[0], 'button_resume', cr) if code.start_stop == 'cancel': self.pool.get('mrp.production.workcenter.line').action_cancel( cr, uid, wc_op_id) wf_service.trg_validate(uid, 'mrp.production.workcenter.line', wc_op_id[0], 'button_cancel', cr) if not self.check_operation(cr, uid, vals): return delay = self.calc_delay(cr, uid, vals) line_vals = {} line_vals['delay'] = delay if vals.get('date_start', False): if code.start_stop == 'done': line_vals['date_finished'] = vals['date_start'] elif code.start_stop == 'start': line_vals['date_start'] = vals['date_start'] self.pool.get('mrp.production.workcenter.line').write(cr, uid, wc_op_id, line_vals, context=context) return super(mrp_operations_operation, self).create(cr, uid, vals, context=context) def initialize_workflow_instance(self, cr, uid, context=None): wf_service = netsvc.LocalService("workflow") line_ids = self.pool.get('mrp.production.workcenter.line').search( cr, uid, [], context=context) for line_id in line_ids: wf_service.trg_create(uid, 'mrp.production.workcenter.line', line_id, cr) return True _columns = { 'production_id': fields.many2one('mrp.production', 'Production', required=True), 'workcenter_id': fields.many2one('mrp.workcenter', 'Work Center', required=True), 'code_id': fields.many2one('mrp_operations.operation.code', 'Code', required=True), 'date_start': fields.datetime('Start Date'), 'date_finished': fields.datetime('End Date'), 'order_date': fields.function(_get_order_date, string='Order Date', type='date', store={ 'mrp.production': (_order_date_search_production, ['date_planned'], 10) }), } _defaults = { 'date_start': lambda *a: datetime.now().strftime('%Y-%m-%d %H:%M:%S') }
class tcv_mrp_gangsaw_order(osv.osv): _name = 'tcv.mrp.gangsaw.order' _description = '' _order = 'ref desc' ##------------------------------------------------------------------------- def name_get(self, cr, uid, ids, context): ids = isinstance(ids, (int, long)) and [ids] or ids res = [] for item in self.browse(cr, uid, ids, context={}): res.append( (item.id, '[%s] %s' % (item.ref, item.template_id.name))) return res ##------------------------------------------------------- _internal methods def _get_supplies_yield(self, cr, uid, template_id, product_id, supplie_id): if not (template_id and product_id and supplie_id): return 0 sql = ''' select supplie_id, product_id, round(avg(yield), 3) as avg_yield from ( select product_id, supplie_id, round((quantity*round(vol/total_vol, 3))/area,3) as yield from ( select b.product_id, p.name, round((b.net_length*b.net_heigth*b.slab_qty),4) as area, round((length*heigth*width),4) as vol, tb.total_vol, p2.id as supplie_id, s.quantity from tcv_mrp_gangsaw g left join tcv_mrp_gangsaw_blocks b on b.gangsaw_id = g.id left join tcv_mrp_subprocess sp on g.parent_id = sp.id left join tcv_mrp_template t on sp.template_id = t.id left join stock_production_lot l on b.prod_lot_id = l.id left join product_template p on b.product_id = p.id left join tcv_mrp_gangsaw_supplies s on g.id = s.task_id left join product_template p2 on s.product_id = p2.id left join ( select gangsaw_id, round(sum(length*heigth*width),4) as total_vol from tcv_mrp_gangsaw_blocks left join stock_production_lot spl on prod_lot_id = spl.id where gangsaw_id=tcv_mrp_gangsaw_blocks.gangsaw_id group by gangsaw_id) tb on tb.gangsaw_id = b.gangsaw_id where g.date_end > '2015-01-01 00:00:00' and t.id = %s ) as q1 ) as q2 where supplie_id = %s and product_id = %s group by supplie_id, product_id order by supplie_id, product_id ''' cr.execute(sql % (template_id, supplie_id, product_id)) res = cr.dictfetchall() return res and res[0].get('avg_yield', 0) or 0 def _compute_cut_down_feed(self, cr, uid, item, context): ''' item: browse object -> tcv.mrp.gangsaw.order.lines return cut_down_feed ''' obj_gbl = self.pool.get('tcv.mrp.gangsaw.blocks') gbl_ids = obj_gbl.search(cr, uid, [ ('date_end', '>=', '2015-01-01 00:00:00'), ('product_id', '=', item.product_id.id), ('template_id', '=', item.gangsaw_order_id.template_id.id), ]) total_cdf = 0.0 qty = 0.0 for item in obj_gbl.browse(cr, uid, gbl_ids, context={}): total_cdf += item.cut_down_feed qty += 1 return total_cdf / qty if qty else 0 def _create_process(self, cr, uid, item, context): obj_prc = self.pool.get('tcv.mrp.process') data = {'date': time.strftime('%Y-%m-%d'), 'name': item.name} return obj_prc.create(cr, uid, data, context) def _create_subprocess(self, cr, uid, item, process_id, context): obj_prc = self.pool.get('tcv.mrp.subprocess') data = { 'template_id': item.template_id.id, 'process_id': process_id, 'name': item.template_id.name } return obj_prc.create(cr, uid, data, context) def _create_gangsaw(self, cr, uid, item, process_id, subprocess_id, context): obj_prc = self.pool.get('tcv.mrp.gangsaw') obj_tmp = self.pool.get('tcv.mrp.template') new_blade_heigth = obj_tmp.get_var_value(cr, uid, item.template_id.id, 'new_blade_heigth') or 0 supplies = [(0, 0, { 'product_id': x.product_id.id, 'quantity': x.product_qty or 100 }) for x in item.supplies_ids] blocks = [(0, 0, { 'prod_lot_id': x.prod_lot_id.id, 'block_ref': x.block_ref, 'net_length': x.length, 'net_heigth': x.heigth, 'thickness': x.thickness, 'blade_id': item.blade_id.id, 'blade_qty': x.blade_qty, 'slab_qty': x.blade_qty - 1, 'blade_start': new_blade_heigth, 'blade_end': new_blade_heigth - x.blade_heigth_used, }) for x in item.line_ids] date_end = ( datetime.strptime(item.date_start, '%Y-%m-%d %H:%M:%S') + timedelta(hours=item.run_time or 96)).strftime('%Y-%m-%d %H:%M:%S') data = { 'parent_id': subprocess_id, 'narration': _('Gangsaw order: %s') % item.ref, 'date_start': item.date_start, 'date_end': date_end, 'supplies_ids': supplies, 'gangsaw_ids': blocks, } return obj_prc.create(cr, uid, data, context) def _notify_users(self, cr, uid, ids, context=None): request = self.pool.get('res.request') obj_cfg = self.pool.get('tcv.mrp.config') company_id = self.pool.get('res.users').browse( cr, uid, uid, context=context).company_id.id cfg_id = obj_cfg.search(cr, uid, [('company_id', '=', company_id)]) if cfg_id: mrp_cfg = obj_cfg.browse(cr, uid, cfg_id[0], context=context) for item in self.browse(cr, uid, ids, context=context): if mrp_cfg.block_check_user_id and mrp_cfg.block_check_user_id.id: block_lines = [] for block in item.line_ids: block_lines.append( _('Block: %s - %s') % (block.prod_lot_id.name, block.product_id.name)) rq_id = request.create( cr, uid, { 'name': _("Check block cost (%s)") % item.ref, 'act_from': uid, 'act_to': mrp_cfg.block_check_user_id.id, 'body': '\n'.join(block_lines), 'trigger_date': time.strftime('%Y-%m-%d %H:%M:%S') }, context) request.request_send(cr, uid, [rq_id]) return True ##--------------------------------------------------------- function fields def _compute_all(self, cr, uid, ids, field_name, arg, context=None): res = {} for item in self.browse(cr, uid, ids, context=context): if item.date_start and item.run_time: date_end = ( datetime.strptime(item.date_start, '%Y-%m-%d %H:%M:%S') + timedelta(hours=item.run_time or 96) ).strftime('%Y-%m-%d %H:%M:%S') res[item.id] = {'date_end': date_end} else: res[item.id] = {'date_end': item.date_start} throwput = 0 for l in item.line_ids: throwput += l.throwput res[item.id].update({'throwput': throwput}) return res ##------------------------------------------------------------------------- _columns = { 'ref': fields.char('Reference', size=64, required=False, readonly=True), 'name': fields.char('Info', size=128, required=False, readonly=False), 'template_id': fields.many2one('tcv.mrp.template', 'Task template', required=True, ondelete='restrict', readonly=True, states={'draft': [('readonly', False)]}, domain=[('res_model', '=', 'tcv.mrp.gangsaw')]), 'blade_id': fields.many2one('product.product', 'Blade / Product', ondelete='restrict', required=False, help="The product (blade) used, using the factor " + "of the template: default_blade_product"), 'date': fields.date('Date', required=True, readonly=True, states={'draft': [('readonly', False)]}, select=True, help="Gangsaw order\s date"), 'date_start': fields.datetime('Date started', required=False, readonly=False, states={'done': [('readonly', True)]}, select=True, help="Date when the process in planned to start."), 'date_end': fields.function(_compute_all, method=True, type='datetime', string='Date finished', multi='all', help="Estimated date end"), 'run_time': fields.float( 'Production runtime', readonly=True, digits_compute=dp.get_precision('Account'), help="Estimated production time in hours (the decimal part " + "represents the hour's fraction 0.50 = 30 min) (minus downtime)."), 'employee_id': fields.many2one('hr.employee', "Operator", required=False, ondelete='restrict', readonly=False, states={'done': [('readonly', True)]}), 'state': fields.selection( [('draft', 'Draft'), ('to_produce', 'To produce'), ('in_progress', 'In progress'), ('done', 'Done'), ('cancel', 'Cancelled')], string='State', required=True, readonly=True, help="'Draft': User\'s state (data transcription) no process " + "started\n" + "'To produce': Blocks ready to be loaded (in load\'s car)\n" + "'In progress': Blocks in cutting process (gangsaw)\n" + "'Done': Blocks gangsaw done."), 'line_ids': fields.one2many('tcv.mrp.gangsaw.order.lines', 'gangsaw_order_id', 'Blocks', readonly=True, states={'draft': [('readonly', False)]}), 'supplies_ids': fields.one2many('tcv.mrp.gangsaw.order.supplies', 'gangsaw_order_id', 'Supplies', readonly=True), 'narration': fields.text('Notes', readonly=False), 'company_id': fields.many2one('res.company', 'Company', required=True, readonly=True, ondelete='restrict'), 'params_id': fields.many2one('tcv.mrp.gangsaw.params', 'Params', required=True, readonly=True, ondelete='restrict'), 'process_id': fields.many2one('tcv.mrp.process', 'Process', readonly=True, ondelete='restrict'), 'subprocess_id': fields.many2one('tcv.mrp.subprocess', 'Subprocess', readonly=True, ondelete='set null'), 'gangsaw_id': fields.many2one('tcv.mrp.gangsaw', 'Gangsaw', readonly=True, ondelete='set null'), 'throwput': fields.function(_compute_all, method=True, store=False, type='float', string='Throwput (E)', digits_compute=dp.get_precision('Product UoM'), multi='all'), } _defaults = { 'ref': lambda *a: '/', 'date': lambda *a: time.strftime('%Y-%m-%d'), 'state': lambda *a: 'draft', 'company_id': lambda self, cr, uid, c: self.pool.get('res.company'). _company_default_get(cr, uid, self._name, context=c), } _sql_constraints = [] ##------------------------------------------------------------------------- ##---------------------------------------------------------- public methods def clear_supplies_lines(self, cr, uid, item, context): unlink_ids = [] for l in item.supplies_ids: unlink_ids.append(l.id) obj_lin = self.pool.get('tcv.mrp.gangsaw.order.supplies') if unlink_ids: obj_lin.unlink(cr, uid, unlink_ids, context=context) return unlink_ids ##-------------------------------------------------------- buttons (object) def button_compute(self, cr, uid, ids, context=None): ''' Compute supplies qty and run_time ''' obj_tmp = self.pool.get('tcv.mrp.template') obj_lin = self.pool.get('tcv.mrp.gangsaw.order.lines') obj_uom = self.pool.get('product.uom') for item in self.browse(cr, uid, ids, context={}): steel_grit_prd = obj_tmp.get_var_value( cr, uid, item.template_id.id, 'default_steel_grit_product') steel_grit_id = self.pool.get('product.product').search( cr, uid, [('default_code', '=', steel_grit_prd)])[0] steel_grit_qty = 0 lime_prd = obj_tmp.get_var_value(cr, uid, item.template_id.id, 'default_lime_product') lime_id = self.pool.get('product.product').search( cr, uid, [('default_code', '=', lime_prd)])[0] lime_qty = 0 run_time = 0 for line in item.line_ids: #~ Compute and update blade_qty blade_qty = obj_lin._compute_blade_qty(cr, uid, line.width, line.thickness, item.template_id.id) #~ compute throwput throwput = obj_uom._calc_area(blade_qty - 1, line.length, line.heigth) #~ compute runtime line_cdf = self._compute_cut_down_feed(cr, uid, line, context) or 999 line_run_time = round(line.heigth * 1000 / line_cdf, 2) if line_run_time > run_time: run_time = line_run_time #~ Compute supplies steel_grit_qty += round( self._get_supplies_yield(cr, uid, item.template_id.id, line.product_id.id, steel_grit_id) * throwput / 10, 0) * 10 lime_qty += round( self._get_supplies_yield(cr, uid, item.template_id.id, line.product_id.id, lime_id) * throwput / 10, 0) * 10 obj_lin.write(cr, uid, [line.id], {'blade_qty': blade_qty}, context=context) values = [{ 'product_id': steel_grit_id, 'product_qty': steel_grit_qty }, { 'product_id': lime_id, 'product_qty': lime_qty }] data = [(0, 0, x) for x in values] self.clear_supplies_lines(cr, uid, item, context) self.write(cr, uid, [item.id], { 'supplies_ids': data, 'run_time': run_time }, context=context) return True ##------------------------------------------------------------ on_change... def on_change_template_id(self, cr, uid, ids, template_id): res = {} if template_id: obj_tmp = self.pool.get('tcv.mrp.template') blade_prd = obj_tmp.get_var_value(cr, uid, template_id, 'default_blade_product') blade_id = self.pool.get('product.product').search( cr, uid, [('default_code', '=', blade_prd)]) obj_prm = self.pool.get('tcv.mrp.gangsaw.params') params_id = obj_prm.search(cr, uid, [('template_id', '=', template_id)]) res.update({ 'blade_id': blade_id and blade_id[0], 'params_id': params_id and params_id[0] }) return {'value': res} ##----------------------------------------------------- create write unlink def create(self, cr, uid, vals, context=None): if not vals.get('ref') or vals.get('ref') == '/': vals.update({ 'ref': self.pool.get('ir.sequence').get(cr, uid, 'tcv.mrp.gangsaw.order') }) if not vals.get('blade_id'): obj_tmp = self.pool.get('tcv.mrp.template') blade_prd = obj_tmp.get_var_value(cr, uid, vals.get('template_id'), 'default_blade_product') blade_id = self.pool.get('product.product').search( cr, uid, [('default_code', '=', blade_prd)]) vals.update({'blade_id': blade_id and blade_id[0]}) if not vals.get('params_id'): obj_prm = self.pool.get('tcv.mrp.gangsaw.params') params_id = obj_prm.search( cr, uid, [('template_id', '=', vals.get('template_id'))]) vals.update({'params_id': params_id and params_id[0]}) res = super(tcv_mrp_gangsaw_order, self).create(cr, uid, vals, context) return res def write(self, cr, uid, ids, vals, context=None): if vals.get('template_id'): obj_tmp = self.pool.get('tcv.mrp.template') blade_prd = obj_tmp.get_var_value(cr, uid, vals.get('template_id'), 'default_blade_product') blade_id = self.pool.get('product.product').search( cr, uid, [('default_code', '=', blade_prd)]) vals.update({'blade_id': blade_id and blade_id[0]}) obj_prm = self.pool.get('tcv.mrp.gangsaw.params') params_id = obj_prm.search( cr, uid, [('template_id', '=', vals.get('template_id'))]) vals.update({'params_id': params_id and params_id[0]}) res = super(tcv_mrp_gangsaw_order, self).write(cr, uid, ids, vals, context) return res ##---------------------------------------------------------------- Workflow def button_draft(self, cr, uid, ids, context=None): vals = {'state': 'draft'} return self.write(cr, uid, ids, vals, context) def button_to_produce(self, cr, uid, ids, context=None): ''' Assign block letter secuence. see: http://stackoverflow.com/questions/14381940/ python-pair-alphabets-after-loop-is-completed ''' def multiletters(seq): for n in count(1): for s in product(seq, repeat=n): yield ''.join(s) vals = {'state': 'to_produce'} res = self.write(cr, uid, ids, vals, context) obj_blk = self.pool.get('tcv.mrp.gangsaw.order.lines') obj_tmp = self.pool.get('tcv.mrp.template') for item in self.browse(cr, uid, ids, context={}): block_list = [] for block in item.line_ids: if not block.block_ref: block_num = int( self.pool.get('ir.sequence').get( cr, uid, 'tcv.mrp.gangsaw.order.lines')) block_ref = list( islice(multiletters(ascii_uppercase), block_num))[-1] obj_blk.write(cr, uid, [block.id], {'block_ref': block_ref}, context=context) else: block_ref = block.block_ref block_list.append('[%s] %s (%s)' % (block.product_id.default_code, block.prod_lot_id.name, block_ref)) ref_name = obj_tmp.get_var_value(cr, uid, item.template_id.id, 'ref_name') or '' name = '%s - %s' % (ref_name, ', '.join(block_list)) self.write(cr, uid, ids, {'name': name}, context) self._notify_users(cr, uid, ids, context) return res def button_in_progress(self, cr, uid, ids, context=None): vals = {'state': 'in_progress'} return self.write(cr, uid, ids, vals, context) def button_done(self, cr, uid, ids, context=None): for item in self.browse(cr, uid, ids, context={}): data = {} #~ process if not item.process_id: process_id = self._create_process(cr, uid, item, context) data.update({'process_id': process_id}) else: process_id = item.process_id.id #~ subprocess if not item.subprocess_id: subprocess_id = self._create_subprocess( cr, uid, item, process_id, context) data.update({'subprocess_id': subprocess_id}) else: subprocess_id = item.subprocess_id.id #~ gangsaw if not item.gangsaw_id: gangsaw_id = self._create_gangsaw(cr, uid, item, process_id, subprocess_id, context) data.update({'gangsaw_id': gangsaw_id}) if data: self.write(cr, uid, [item.id], data, context) vals = {'state': 'done'} return self.write(cr, uid, ids, vals, context) def button_cancel(self, cr, uid, ids, context=None): vals = {'state': 'cancel'} return self.write(cr, uid, ids, vals, context) def test_draft(self, cr, uid, ids, *args): return True def test_done(self, cr, uid, ids, *args): for item in self.browse(cr, uid, ids, context={}): if not item.date_start: raise osv.except_osv(_('Error!'), _('Must indicate date started')) return True def test_in_progress(self, cr, uid, ids, *args): for item in self.browse(cr, uid, ids, context={}): if not item.date_start: raise osv.except_osv(_('Error!'), _('Must indicate date started')) if item.gangsaw_id or item.subprocess_id: raise osv.except_osv( _('Error!'), _('Can\'t reset an order with related gangsaw data. ' + 'Must delete gangsaw data manually first')) return True def test_to_produce(self, cr, uid, ids, *args): for item in self.browse(cr, uid, ids, context={}): if not item.supplies_ids: raise osv.except_osv(_('Error!'), _('Must compute supplies first')) return True def test_cancel(self, cr, uid, ids, *args): return True
class sale_order(osv.osv): _inherit = 'sale.order' _prestashop = True _prestashop_name = 'orders' _columns = { 'invoice_number': fields.char('Invoice Number', size=64), 'delivery_number': fields.char('Delivery Number', size=64), 'secure_key': fields.char('Secure_key', size=132, help="Write your prestashop secure key"), 'payment': fields.char('Payment', size=64), 'gift_message': fields.char('Gift Message', size=64, help="Specify Gift Message if any"), 'shipping_number': fields.char('Shipping Number', size=64, help="Specify the shipping number"), 'invoice_date': fields.datetime('Invoice Date'), 'delivery_date': fields.datetime('Delivery Date'), 'conversion_rate': fields.float('Conversion Rate', help="Specify the current conversion rate"), 'recyclable': fields.boolean('Recyclable', help="Check if it is recyclable"), 'gift': fields.boolean('Gift', help="Check if it's a Gift"), 'current_state_id': fields.many2one('sale.order.state', 'Current State', help="Select a current order state"), 'total_discounts': fields.float('Total Discounts'), 'total_paid': fields.float('Total Paid'), 'total_paid_real': fields.float('Total Real Paid '), 'total_products': fields.float('Total Products'), 'total_products_wt': fields.float('Total Weight'), 'total_shipping': fields.float('Total Shipping'), 'carrier_tax_rate': fields.float('Carrier Tax Rate'), 'total_wrapping': fields.float('Total Wrapping'), 'presta_exported': fields.boolean('Exported', help="Export to prestashop"), } def set_ext_ref(self, cr, uid, external_reference_id, openerp_id, presta_id, context={}): ref_pool = self.pool.get('external.reference') ref_ids = ref_pool.search(cr, uid, [ ('res_model', '=', self._name), ('res_id', '=', openerp_id), ('external_reference_id', '=', external_reference_id), ]) if ref_ids: ref_pool.write(cr, uid, ref_ids, {'ext_id': presta_id}) else: ref_pool.create( cr, uid, { 'res_model': self._name, 'res_id': openerp_id, 'external_reference_id': external_reference_id, 'ext_id': presta_id, }) return True def _get_price_list(self, cr, uid, shop_id, context): pricelist_id = self.pool.get('sale.shop').read(cr, uid, shop_id, ['pricelist_id'], context) if pricelist_id.get('pricelist_id', False): return pricelist_id['pricelist_id'][0] return False def update_status(self, cr, uid, ids, context={}): self._update_status(cr, uid, 1, ids, context) return True def _update_status(self, cr, uid, shop_id, ids, context={}): state_mapping = self.get_state_mapping(cr, uid, shop_id, context) wf_service = netsvc.LocalService("workflow") for self_obj in self.browse(cr, uid, ids, context=context): if self_obj.current_state_id.name in state_mapping: if self_obj.state \ in state_mapping[self_obj.current_state_id.name]: wf_service.trg_validate( uid, 'sale.order', self_obj.id, state_mapping[self_obj.current_state_id.name][ self_obj.state][-1], cr) def get_state_mapping(self, cr, uid, shop_id, context=None): result = {} if not context: context = {} shop_pool = self.pool.get('sale.shop') shop_data = shop_pool.read(cr, uid, shop_id, ['prestashop_config_path']) if not shop_data['prestashop_config_path'] or \ not shop_data['prestashop_config_path'].endswith(".conf") or\ not self._prestashop: return result, False config = ConfigParser() config.read(shop_data['prestashop_config_path']) if not self._name in config.sections(): return result, False mapping = dict(config.items(self._name)) return eval(mapping['state_mapping']) def _set_associations(self, cr, uid, shop_id, associations, context={}): partner_id = self.pool.get('res.partner').get_int_ref( cr, uid, shop_id, associations['id_customer'].get('_text', False), context=context) or False, lang_id = self.pool.get('res.lang').get_int_ref( cr, uid, shop_id, associations['id_lang'].get('_text', False), context=context) or False, asscociat = associations['associations']['order_rows'] final_list = [] if not asscociat or not asscociat.get('order_row', False): return False order_ext_id = self.pool.get('sale.order').get_int_ref( cr, uid, shop_id, associations['id'], context=context) order_rows = asscociat['order_row'] if isinstance(order_rows, (list, tuple)): order_rows = order_rows else: order_rows = [order_rows] product_pool = self.pool.get('product.product') saleorder_line_pool = self.pool.get('sale.order.line') pricelist_id = self._get_price_list(cr, uid, shop_id, context) order_detail_ids = [] for order_row in order_rows: order_detail_ids.append(order_row['id']) order_shipping = {} if associations['total_shipping'] > 0.0: order_shipping.update({ 'name': 'shipping charge', 'price_unit': associations['total_shipping'], 'product_id': False, 'product_uom_qty': 1, 'product_uom': 1 }) line_ids = (0, 0, order_shipping) if order_ext_id: line_ids = self.pool.get('sale.order.line').search( cr, uid, [ ('order_id', '=', order_ext_id), ('name', '=', 'shipping charge'), ], context=context) line_ids = line_ids and (1, line_ids[0], order_shipping) or ( 0, 0, order_shipping) final_list.append(line_ids) line_datas = self.pool.get( 'sale.order.line').get_sale_order_data_prestashop( cr, uid, shop_id, order_detail_ids, context=context) for line_data in line_datas: if order_ext_id: line_ids = self.pool.get('sale.order.line').search( cr, uid, [('order_id', '=', order_ext_id), ('product_id', '=', line_data[-1]['product_id'])], context=context) if line_ids: line_data[0] = 1 line_data[1] = line_ids[0] final_list.append(line_data) result = final_list return result
class google_contact_account(osv.osv): _name = "google.contact_account" _description = "Google Contact Account" _columns = { 'name': fields.char('User', size=255, required=True, select=1), 'password': fields.char( 'Password', size=255, required=True, ), 'active': fields.boolean('Active'), 'last_sync_time': fields.datetime("Last Updated on "), } _order = 'name asc' _defaults = { 'active': lambda *a: True, } def check_login(self, cr, uid, ids, context=None): account = self.browse(cr, uid, ids[0]) test = gdata.contacts.service.ContactsService() test.email = account.name test.password = account.password try: test.ProgrammaticLogin() raise osv.except_osv(_("Connection OK"), _("Your login information is correct.")) except gdata.service.CaptchaRequired: raise osv.except_osv(_("Error"), _("Required Captcha.")) except gdata.service.BadAuthentication: raise osv.except_osv(_("Error"), _("Bad Authentication.")) except gdata.service.Error: raise osv.except_osv(_("Error"), _("Login Error.")) return self.write(cr, uid, ids[0], {'active': True}) def create_google_contact(self, cr, uid, gc, contact, context=None): if not gc or not contact: return False if contact.last_name and contact.first_name: name = " ".join([contact.last_name, contact.first_name]) elif contact.last_name: name = contact.last_name else: name = contact.first_name primary_email = contact.email and contact.email or '' primary_email = primary_email.replace(' ', '').replace("'", "").decode('utf-8') _logger.info(u"Contact %s going to create with email = %s" % (name, primary_email)) if not primary_email: return False #-- #--Check Any google contact exist with same email ? #-- query = gdata.contacts.client.ContactsQuery(text_query=primary_email) feed = gc.GetContacts(q=query) if feed and len(feed.entry): _logger.info(u"Contact with email = %s exist" % (primary_email)) _logger.info(u"FEED: total feed matched = %s" % (str(len(feed.entry)))) feed_entry = None for entry in feed.entry: _e = None for _email in entry.email: if _email.address and _email.address == primary_email: _e = True break if _e: feed_entry = entry break if feed_entry: if feed_entry.name: _logger.info(u"FEED:\nName : %s" % (feed_entry.name.full_name.text)) if not feed_entry.name: feed_entry.name = gdata.data.Name() if contact.last_name and contact.first_name: new_name = " ".join( [contact.last_name, contact.first_name]) elif contact.last_name: new_name = contact.last_name else: new_name = contact.first_name feed_entry.name.full_name = gdata.data.FullName(text=new_name) phone = None for _phone in feed_entry.phone_number: if _phone.primary == 'true': phone = _phone if not phone and feed_entry.phone_number: phone = feed_entry.phone_number[0] if phone: phone.text = contact.mobile phone.rel = 'http://schemas.google.com/g/2005#mobile' else: if contact.mobile: feed_entry.phone_number.append( gdata.data.PhoneNumber( text=contact.mobile, rel='http://schemas.google.com/g/2005#mobile', primary="true")) try: gc.Update(feed_entry) self.pool.get('res.partner.address.contact').write( cr, uid, [contact.id], { 'google_updated': feed_entry.updated.text, 'google_id': feed_entry.id.text }) except: _logger.info( u"UnknownError: Google Contact (%s) does not updated" % (contact.email)) return False return True new_contact = gdata.contacts.data.ContactEntry(name=gdata.data.Name( full_name=gdata.data.FullName(text=name))) new_contact.email.append( gdata.data.Email(address=primary_email, primary='true', rel=gdata.data.WORK_REL)) feed = gc.GetGroups() group = filter(lambda g: g.title.text == 'System Group: My Contacts', feed.entry)[0] gmeminfo = gdata.contacts.data.GroupMembershipInfo(href=group.get_id()) new_contact.group_membership_info.append(gmeminfo) if contact.mobile: new_contact.phone_number.append((gdata.data.PhoneNumber( text=contact.mobile, rel='http://schemas.google.com/g/2005#mobile', primary="true"))) try: entry = gc.CreateContact(new_contact) if entry: self.pool.get('res.partner.address.contact').write( cr, uid, [contact.id], { 'google_updated': entry.updated.text, 'google_id': entry.id.text }) if contact.photo: try: tmp_image_file = tempfile.mktemp('%s_photo.jpg' % (str(contact.id))) fp = open(tmp_image_file, 'wb+') fp.write(contact.photo.decode('base64')) gc.ChangePhoto(tmp_image_file, entry, content_type='image/jpeg') finally: fp.close() except: _logger.info( u"UnknownError: Google Contact (%s <%s>) does not created" % (name, contact.email)) return False return True def _google_sync_contractor_updates(self, cr, uid, ids=False, context=None): if context is None: context = {} google_accounts = self.search(cr, uid, [('active', '=', True)]) for gac in google_accounts: self.openerp_google_sync(cr, uid, gac, context=context) return True def openerp_google_sync(self, cr, uid, account_id, context=None): if not account_id: return False g_account = self.pool.get('google.contact_account').browse( cr, uid, account_id, context=context) gc_client = gdata.contacts.client.ContactsClient( source='openerp-sync-google-1') gc_client.ClientLogin(g_account.name, g_account.password, gc_client.source) _logger.info(u"Login successfully to Google Contact: %s" % g_account.name) success_cb_ids = [] search_filter = [('google_account_id', '=', g_account.id)] if g_account.last_sync_time: search_filter.append( ('create_date', '>=', g_account.last_sync_time)) #-- #--create contacts to Google #-- create_buffers = self.pool.get('google.contact_buffer').search( cr, uid, search_filter + [('action', '=', 'create')]) for cb in self.pool.get('google.contact_buffer').browse( cr, uid, create_buffers, context=context): if self.create_google_contact(cr, uid, gc_client, cb.contact_id, context=context): self.pool.get('google.contact_buffer').unlink(cr, uid, [cb.id], context=context) #success_cb_ids.append(cb.id) #-- #--update contacts to google #-- update_buffer = self.pool.get('google.contact_buffer').search( cr, uid, search_filter + [('action', '=', 'update')]) for cb in self.pool.get('google.contact_buffer').browse( cr, uid, update_buffer, context=context): if not cb.contact_id.google_id: self.create_google_contact(cr, uid, gc_client, cb.contact_id, context=context) continue try: feed_entry = gc_client.GetContact(cb.contact_id.google_id) except: _logger.info( u"UnknownError: Google contact does not exist with key = %s\nSo new google contact is created" % cb.contact_id.google_id) self.create_google_contact(cr, uid, gc_client, cb.contact_id, context=context) continue #feed_entry = feed_hash.get(cb.contact_id.google_id, False) if feed_entry: contact = cb.contact_id if not feed_entry.name: feed_entry.name = gdata.data.Name() if contact.last_name and contact.first_name: new_name = " ".join( [contact.last_name, contact.first_name]) elif contact.last_name: new_name = contact.last_name else: new_name = contact.first_name feed_entry.name.full_name = gdata.data.FullName(text=new_name) email = None for _email in feed_entry.email: if _email.primary == 'true': email = _email if not email and feed_entry.email: email = feed_entry.email[0] if email: email.address = contact.email phone = None for _phone in feed_entry.phone_number: if _phone.primary == 'true': phone = _phone if not phone and feed_entry.phone_number: phone = feed_entry.phone_number[0] if phone: phone.text = contact.mobile phone.rel = 'http://schemas.google.com/g/2005#mobile' else: if contact.mobile: feed_entry.phone_number.append( gdata.data.PhoneNumber( text=contact.mobile, rel='http://schemas.google.com/g/2005#mobile', primary="true")) try: gc_client.Update(feed_entry) success_cb_ids.append(cb.id) except: _logger.info( u"UnknownError: Google Contact (%s) does not updated" % (contact.work_email)) #-- #--Delete contacts to Google #-- unlink_buffer = self.pool.get('google.contact_buffer').search( cr, uid, search_filter + [('action', '=', 'unlink')]) for cb in self.pool.get('google.contact_buffer').browse( cr, uid, unlink_buffer, context=context): if not cb.google_id: continue try: feed_entry = gc_client.GetContact(cb.google_id) if feed_entry: gc_client.Delete(feed_entry) success_cb_ids.append(cb.id) except: _logger.info( u"UnknownError : Google can not able to delete contact with key = %s" % (cb.google_id)) self.pool.get('google.contact_buffer').unlink(cr, uid, success_cb_ids, context=context) self.pool.get('google.contact_account').write( cr, uid, [account_id], {'last_sync_time': time.strftime("%Y-%m-%d %H:%M:%S")}) return True
class hr_attendance(osv.osv): def _day_compute(self, cr, uid, ids, fieldnames, args, context=None): res = super(hr_attendance, self)._day_compute(cr, uid, ids, fieldnames, args, context) return res def _get_emp(self, cr, uid, ids, fieldnames, args, context=None): res = {} emp_code = self.read(cr, uid, ids[0], ['employee_id'], context=context) emp_code = emp_code['employee_id'] emp_id = self.pool.get('hr.employee').search( cr, uid, [('emp_code', '=', emp_code)], context=context) res[ids[0]] = emp_id and emp_id[0] or 0 return res _inherit = "hr.attendance" _columns = { 'name': fields.datetime('Date', required=True, select=1, readonly=True), 'action': fields.selection([('sign_in', 'Sign In'), ('sign_out', 'Sign Out'), ('action', 'Action')], 'Action', required=True, readonly=False), 'employee_id': fields.integer("Employee's Code", required=True, readonly=True), 'day': fields.function(_day_compute, method=True, type='char', string='Day', store=True, select=1, size=32), 'emp_id': fields.many2one('hr.employee', "Employee", select=True), } def fields_view_get(self, cr, uid, view_id=None, view_type='tree', context=None, toolbar=False, submenu=False): """ Returns views and fields for current model. @param cr: A database cursor @param user: ID of the user currently logged in @param view_id: list of fields, which required to read signatures @param view_type: defines a view type. it can be one of (form, tree, graph, calender, gantt, search, mdx) @param context: context arguments, like lang, time zone @param toolbar: contains a list of reports, wizards, and links related to current model @return: Returns a dictionary that contains definition for fields, views, and toolbars """ if not context: context = {} emp_code_ids = self.search(cr, uid, [('emp_id', '=', False)], context=context) if emp_code_ids: attendance = self.browse(cr, uid, emp_code_ids, context=context) emp_obj = self.pool.get('hr.employee') emp_ids = emp_obj.search(cr, uid, [], context=context) emp_basic = emp_obj.read(cr, uid, emp_ids, ['emp_code'], context=context) emp_basic = {int(x['emp_code']): int(x['id']) for x in emp_basic} for x in attendance: new_id = x.employee_id in emp_basic and emp_basic[ x.employee_id] if new_id: x.write({'emp_id': new_id}) res = super(hr_attendance, self).fields_view_get(cr, uid, view_id=view_id, view_type=view_type, context=context, toolbar=toolbar, submenu=submenu) return res def _altern_si_so(self, cr, uid, ids, context=None): for id in ids: sql = ''' SELECT action, name FROM hr_attendance AS att WHERE emp_id = (SELECT emp_id FROM hr_attendance WHERE id=%s) AND action IN ('sign_in','sign_out') AND name <= (SELECT name FROM hr_attendance WHERE id=%s) ORDER BY name DESC LIMIT 2 ''' cr.execute(sql, (id, id)) atts = cr.fetchall() if not ((len(atts) == 1 and atts[0][0] == 'sign_in') or (len(atts) == 2 and atts[0][0] != atts[1][0] and atts[0][1] != atts[1][1])): #return False pass return True _constraints = [( _altern_si_so, 'Error ! Sign in (resp. Sign out) must follow Sign out (resp. Sign in)', ['action'])]
class product_serial_number(osv.Model): """Product Serial Number""" _name = 'product.serial.number' _description = 'Product Serial Number' def name_get(self, cr, uid, ids, context=None): res = [] for line in self.browse(cr, uid, ids, context=context): res.append((line.id, line.name)) return res def create(self, cr, uid, vals, context=None): exist_psn = self.search(cr, uid, [('name', '=', vals['name']), ('product_id', '=', vals['product_id'])]) psn_obj = self.pool.get('product.serial.number') if exist_psn: psn = [] for psn_item in psn_obj.browse(cr, uid, exist_psn): psn.append(psn_item.product_id.default_code) psn = str(psn) productid = vals.get('product_id', False) if not productid: raise osv.except_osv( _('Error!'), _('No se puede crear un numero de serie sin un producto asociado' )) return False for product in self.pool.get('product.product').browse( cr, uid, [vals['product_id']]): if product.psn_unique_ftp: raise osv.except_osv( _('Error!'), _('La serie %s ya existe para este producto: %s ') % (vals['name'], product.default_code)) return False if product.psn_unique: raise osv.except_osv( _('Error!'), _('La serie %s ya existe para el/los siguiente(s) producto(s): %s y debe ser unica.' ) % (vals['name'], psn)) return False return super(product_serial_number, self).create(cr, uid, vals, context) _columns = { 'name': fields.char('Numero de Serie', size=64, required=True), 'product_id': fields.many2one('product.product', 'Producto', required=True), 'location_id': fields.many2one('stock.location', 'Ubicacion'), 'create_uid': fields.many2one('res.users', 'Creador'), 'write_uid': fields.many2one('res.users', 'Modificador'), 'create_date': fields.datetime('Fecha creacion', readonly=True), 'write_date': fields.datetime('Fecha modificacion', readonly=True), 'move_ids': fields.many2many('stock.move', 'serialnumber_stockmove_rel', 'serialnumber_id', 'move_id', 'Movimientos de stock'), 'expiration_date': fields.date('Fecha de expiracion'), 'import_date': fields.datetime('Fecha Importacion'), 'to_import': fields.boolean('Para importar'), 'prodlot_id': fields.many2one('stock.production.lot', 'Lote'), 'pvp': fields.related('product_id', 'lst_price', type='float', string='Precio'), 'costo': fields.related('product_id', 'standard_price', type='float', string='Costo'), 'active_move_id': fields.many2one('stock.move', 'Stock Move Activo'), 'state': fields.selection([ ('draft', 'Nuevo'), ('cancel', 'Cancelado'), ('waiting', 'Esperando'), ('confirmed', 'Esperando disponibilidad'), ('assigned', 'Disponible'), ('done', 'Realizado'), ], 'Estado'), 'last_move_id': fields.many2one('stock.move', 'Ultimo Stock Move'), 'picking_id': fields.related('last_move_id', 'picking_id', type='many2one', relation='stock.picking', string='Albaran'), 'active': fields.boolean('Activo'), } _defaults = { 'to_import': False, 'active_move_id': False, 'active': True, 'state': 'draft' } def unlink(self, cr, uid, ids, context=None): if context: ctx = context.copy() else: ctx = {} for psn in self.browse(cr, uid, ids, context=ctx): if psn.move_ids: raise osv.except_osv( 'Error', 'No puede eliminar un numero de serie (%s) que este asociado a algun movimiento de stock, pero lo puede desactivar.' % psn.name) return False return super(product_serial_number, self).unlink(cr, uid, ids, context=ctx)
class document_file(osv.osv): _inherit = 'ir.attachment' def _data_get(self, cr, uid, ids, name, arg, context): result = {} cr.execute( 'select id,store_method,datas,store_fname,link from ir_attachment where id in (' + ','.join(map(str, ids)) + ')') for id, m, d, r, l in cr.fetchall(): if m == 'db': result[id] = d elif m == 'fs': path = os.path.join(os.getcwd(), 'filestore') value = file(os.path.join(path, r), 'rb').read() result[id] = base64.encodestring(value) else: result[id] = '' return result # # This code can be improved # def _data_set(self, cr, obj, id, name, value, uid=None, context={}): if not value: return True if (not context) or context.get('store_method', 'fs') == 'fs': path = os.path.join(os.getcwd(), "filestore") if not os.path.isdir(path): os.mkdir(path) flag = None for dirs in os.listdir(path): if os.path.isdir(os.path.join(path, dirs)) and len( os.listdir(os.path.join(path, dirs))) < 4000: flag = dirs break flag = flag or create_directory(path) filename = random_name() fname = os.path.join(path, flag, filename) fp = file(fname, 'wb') fp.write(base64.decodestring(value)) filesize = os.stat(fname).st_size cr.execute( 'update ir_attachment set store_fname=%s,store_method=%s,file_size=%d where id=%d', (os.path.join(flag, filename), 'fs', filesize, id)) else: cr.execute( 'update ir_attachment set datas=%s,store_method=%s where id=%d', (psycopg.Binary(value), 'db', id)) return True _columns = { 'user_id': fields.many2one('res.users', 'Owner', select=1), 'group_ids': fields.many2many('res.groups', 'document_directory_group_rel', 'item_id', 'group_id', 'Groups'), 'parent_id': fields.many2one('document.directory', 'Directory', select=1), 'file_size': fields.integer('File Size', required=True), 'file_type': fields.char('Content Type', size=32), 'index_content': fields.text('Indexed Content'), 'write_date': fields.datetime('Date Modified', readonly=True), 'write_uid': fields.many2one('res.users', 'Last Modification User', readonly=True), 'create_date': fields.datetime('Date Created', readonly=True), 'create_uid': fields.many2one('res.users', 'Creator', readonly=True), 'store_method': fields.selection([('db', 'Database'), ('fs', 'Filesystem'), ('link', 'Link')], "Storing Method"), 'datas': fields.function(_data_get, method=True, store=True, fnct_inv=_data_set, string='File Content', type="binary"), 'store_fname': fields.char('Stored Filename', size=200), 'res_model': fields.char('Attached Model', size=64), #res_model 'res_id': fields.integer('Attached ID'), #res_id 'partner_id': fields.many2one('res.partner', 'Partner', select=1), 'title': fields.char('Resource Title', size=64), } _defaults = { 'user_id': lambda self, cr, uid, ctx: uid, 'file_size': lambda self, cr, uid, ctx: 0, 'store_method': lambda *args: 'db' } def write(self, cr, uid, ids, vals, context=None): result = super(document_file, self).write(cr, uid, ids, vals, context=context) try: for f in self.browse(cr, uid, ids, context=context): if 'datas' not in vals: vals['datas'] = f.datas res = content_index(base64.decodestring(vals['datas']), f.datas_fname, f.file_type or None) super(document_file, self).write(cr, uid, ids, {'index_content': res}) except: pass return result def create(self, cr, uid, vals, context={}): vals['title'] = vals['name'] if vals.get('res_id', False) and vals.get('res_model', False): obj_model = self.pool.get(vals['res_model']) result = obj_model.browse(cr, uid, [vals['res_id']], context=context) if len(result): vals['title'] = (result[0].name or '')[:60] if obj_model._name == 'res.partner': vals['partner_id'] = result[0].id elif 'address_id' in result[0]: vals['partner_id'] = result[ 0].address_id.partner_id.id or False else: vals['partner_id'] = 'partner_id' in result[0] and result[ 0].partner_id.id or False if 'parent_id' not in vals: obj_directory = self.pool.get('document.directory') directory_ids = obj_directory.search( cr, uid, [('ressource_type_id', '=', vals['res_model'])]) dirs = obj_directory.browse(cr, uid, directory_ids) for dir in dirs: if dir.domain: object_ids = obj_model.search(cr, uid, eval(dir.domain)) if vals['res_id'] in object_ids: vals['parent_id'] = dir.id datas = None if 'datas' not in vals: import urllib datas = base64.encodestring(urllib.urlopen(vals['link']).read()) else: datas = vals['datas'] vals['file_size'] = len(datas) result = super(document_file, self).create(cr, uid, vals, context) cr.commit() try: res = content_index(base64.decodestring(datas), vals['datas_fname'], vals.get('content_type', None)) super(document_file, self).write(cr, uid, [result], { 'index_content': res, }) except: pass return result def unlink(self, cr, uid, ids, context={}): for f in self.browse(cr, uid, ids, context): if f.store_method == 'fs': path = os.path.join(os.getcwd(), 'filestore', f.store_fname) os.unlink(path) return super(document_file, self).unlink(cr, uid, ids, context)
class survey(osv.osv): _name = 'survey' _description = 'Survey' _rec_name = 'title' def default_get(self, cr, uid, fields, context=None): data = super(survey, self).default_get(cr, uid, fields, context) return data _columns = { 'title': fields.char('Survey Title', size=128, required=1), 'page_ids': fields.one2many('survey.page', 'survey_id', 'Page'), 'date_open': fields.datetime('Survey Open Date', readonly=1), 'date_close': fields.datetime('Survey Close Date', readonly=1), 'max_response_limit': fields.integer('Maximum Answer Limit', help="Set to one if survey is answerable only once"), 'response_user': fields.integer( 'Maximum Answer per User', help="Set to one if you require only one Answer per user"), 'state': fields.selection([('draft', 'Draft'), ('open', 'Open'), ('close', 'Closed'), ('cancel', 'Cancelled')], 'Status', readonly=True), 'responsible_id': fields.many2one('res.users', 'Responsible', help="User responsible for survey"), 'tot_start_survey': fields.integer("Total Started Survey", readonly=1), 'tot_comp_survey': fields.integer("Total Completed Survey", readonly=1), 'note': fields.text('Description', size=128), 'history': fields.one2many('survey.history', 'survey_id', 'History Lines', readonly=True), 'users': fields.many2many('res.users', 'survey_users_rel', 'sid', 'uid', 'Users'), 'send_response': fields.boolean('E-mail Notification on Answer'), 'type': fields.many2one('survey.type', 'Type'), 'invited_user_ids': fields.many2many('res.users', 'survey_invited_user_rel', 'sid', 'uid', 'Invited User'), } _defaults = { 'state': lambda *a: "draft", 'tot_start_survey': lambda *a: 0, 'tot_comp_survey': lambda *a: 0, 'send_response': lambda *a: 1, 'response_user': lambda *a: 1, } def survey_draft(self, cr, uid, ids, arg): self.write(cr, uid, ids, {'state': 'draft'}) return True def survey_open(self, cr, uid, ids, arg): self.write(cr, uid, ids, { 'state': 'open', 'date_open': strftime("%Y-%m-%d %H:%M:%S") }) return True def survey_close(self, cr, uid, ids, arg): self.write(cr, uid, ids, { 'state': 'close', 'date_close': strftime("%Y-%m-%d %H:%M:%S") }) return True def survey_cancel(self, cr, uid, ids, arg): self.write(cr, uid, ids, {'state': 'cancel'}) return True def copy(self, cr, uid, ids, default=None, context=None): vals = {} current_rec = self.read(cr, uid, ids, context=context) title = current_rec.get('title') + ' (Copy)' vals.update({'title': title}) return super(survey, self).copy(cr, uid, ids, vals, context=context) def action_print_survey(self, cr, uid, ids, context=None): """ If response is available then print this response otherwise print survey form(print template of the survey). @param self: The object pointer @param cr: the current row, from the database cursor, @param uid: the current user’s ID for security checks, @param ids: List of Survey IDs @param context: A standard dictionary for contextual values @return : Dictionary value for print survey form. """ if context is None: context = {} datas = {} if 'response_id' in context: response_id = context.get('response_id', 0) datas['ids'] = [context.get('survey_id', 0)] else: response_id = self.pool.get('survey.response').search( cr, uid, [('survey_id', '=', ids)], context=context) datas['ids'] = ids page_setting = { 'orientation': 'vertical', 'without_pagebreak': 0, 'paper_size': 'letter', 'page_number': 1, 'survey_title': 1 } report = {} if response_id and response_id[0]: context.update({'survey_id': datas['ids']}) datas['form'] = page_setting datas['model'] = 'survey.print.answer' report = { 'type': 'ir.actions.report.xml', 'report_name': 'survey.browse.response', 'datas': datas, 'context': context, 'nodestroy': True, } else: datas['form'] = page_setting datas['model'] = 'survey.print' report = { 'type': 'ir.actions.report.xml', 'report_name': 'survey.form', 'datas': datas, 'context': context, 'nodestroy': True, } return report
class pos_order(osv.osv): _name = "pos.order" _description = "Point of Sale" _order = "id desc" def create_from_ui(self, cr, uid, orders, context=None): print "file: point_of_sale fun: create_from_ui" #_logger.info("orders: %r", orders) list = [] for order in orders: # order :: {'name': 'Order 1329148448062', 'amount_paid': 9.42, 'lines': [[0, 0, {'discount': 0, 'price_unit': 1.46, 'product_id': 124, 'qty': 5}], [0, 0, {'discount': 0, 'price_unit': 0.53, 'product_id': 62, 'qty': 4}]], 'statement_ids': [[0, 0, {'journal_id': 7, 'amount': 9.42, 'name': '2012-02-13 15:54:12', 'account_id': 12, 'statement_id': 21}]], 'amount_tax': 0, 'amount_return': 0, 'amount_total': 9.42} order_obj = self.pool.get('pos.order') # get statements out of order because they will be generated with add_payment to ensure # the module behavior is the same when using the front-end or the back-end statement_ids = order.pop('statement_ids') order_id = self.create(cr, uid, order, context) list.append(order_id) # call add_payment; refer to wizard/pos_payment for data structure # add_payment launches the 'paid' signal to advance the workflow to the 'paid' state data = { 'journal': statement_ids[0][2]['journal_id'], 'amount': order['amount_paid'], 'payment_name': order['name'], 'payment_date': statement_ids[0][2]['name'], } order_obj.add_payment(cr, uid, order_id, data, context=context) return list def unlink(self, cr, uid, ids, context=None): print "file: point_of_sale fun: unlink" for rec in self.browse(cr, uid, ids, context=context): if rec.state not in ('draft', 'cancel'): raise osv.except_osv( _('Unable to Delete !'), _('In order to delete a sale, it must be new or cancelled.' )) return super(pos_order, self).unlink(cr, uid, ids, context=context) def onchange_partner_id(self, cr, uid, ids, part=False, context=None): print "file: point_of_sale fun: onchange_partner_id" if not part: return {'value': {}} pricelist = self.pool.get('res.partner').browse( cr, uid, part, context=context).property_product_pricelist.id return {'value': {'pricelist_id': pricelist}} def _amount_all(self, cr, uid, ids, name, args, context=None): print "file: point_of_sale fun: _amount_all" tax_obj = self.pool.get('account.tax') cur_obj = self.pool.get('res.currency') res = {} for order in self.browse(cr, uid, ids, context=context): res[order.id] = { 'amount_paid': 0.0, 'amount_return': 0.0, 'amount_tax': 0.0, } val1 = val2 = 0.0 cur = order.pricelist_id.currency_id for payment in order.statement_ids: res[order.id]['amount_paid'] += payment.amount res[order.id]['amount_return'] += (payment.amount < 0 and payment.amount or 0) for line in order.lines: val1 += line.price_subtotal_incl val2 += line.price_subtotal res[order.id]['amount_tax'] = cur_obj.round( cr, uid, cur, val1 - val2) res[order.id]['amount_total'] = cur_obj.round(cr, uid, cur, val1) return res def _default_sale_journal(self, cr, uid, context=None): print "file: point_of_sale fun: _default_sale_journal" res = self.pool.get('account.journal').search(cr, uid, [('type', '=', 'sale')], limit=1) return res and res[0] or False def _default_shop(self, cr, uid, context=None): print "file: point_of_sale fun: _default_shop" res = self.pool.get('sale.shop').search(cr, uid, []) return res and res[0] or False def copy(self, cr, uid, id, default=None, context=None): print "file: point_of_sale fun: copy" if not default: default = {} d = { 'state': 'draft', 'invoice_id': False, 'account_move': False, 'picking_id': False, 'statement_ids': [], 'nb_print': 0, 'name': self.pool.get('ir.sequence').get(cr, uid, 'pos.order'), } d.update(default) return super(pos_order, self).copy(cr, uid, id, d, context=context) _columns = { 'name': fields.char('Order Ref', size=64, required=True, states={'draft': [('readonly', False)]}, readonly=True), 'company_id': fields.many2one('res.company', 'Company', required=True, readonly=True), 'shop_id': fields.many2one('sale.shop', 'Shop', required=True, states={'draft': [('readonly', False)]}, readonly=True), 'date_order': fields.datetime('Date Ordered', readonly=True, select=True), 'user_id': fields.many2one( 'res.users', 'Connected Salesman', help= "Person who uses the the cash register. It could be a reliever, a student or an interim employee." ), 'amount_tax': fields.function(_amount_all, string='Taxes', digits_compute=dp.get_precision('Point Of Sale'), multi='all'), 'amount_total': fields.function(_amount_all, string='Total', multi='all'), 'amount_paid': fields.function(_amount_all, string='Paid', states={'draft': [('readonly', False)]}, readonly=True, digits_compute=dp.get_precision('Point Of Sale'), multi='all'), 'amount_return': fields.function(_amount_all, 'Returned', digits_compute=dp.get_precision('Point Of Sale'), multi='all'), 'lines': fields.one2many('pos.order.line', 'order_id', 'Order Lines', states={'draft': [('readonly', False)]}, readonly=True), 'statement_ids': fields.one2many('account.bank.statement.line', 'pos_statement_id', 'Payments', states={'draft': [('readonly', False)]}, readonly=True), 'pricelist_id': fields.many2one('product.pricelist', 'Pricelist', required=True, states={'draft': [('readonly', False)]}, readonly=True), 'partner_id': fields.many2one('res.partner', 'Customer', change_default=True, select=1, states={ 'draft': [('readonly', False)], 'paid': [('readonly', False)] }), 'state': fields.selection([('draft', 'New'), ('cancel', 'Cancelled'), ('paid', 'Paid'), ('done', 'Posted'), ('invoiced', 'Invoiced')], 'State', readonly=True), 'invoice_id': fields.many2one('account.invoice', 'Invoice'), 'account_move': fields.many2one('account.move', 'Journal Entry', readonly=True), 'picking_id': fields.many2one('stock.picking', 'Picking', readonly=True), 'note': fields.text('Internal Notes'), 'nb_print': fields.integer('Number of Print', readonly=True), 'sale_journal': fields.many2one('account.journal', 'Journal', required=True, states={'draft': [('readonly', False)]}, readonly=True), } def _default_pricelist(self, cr, uid, context=None): print "file: point_of_sale fun: _default_pricelist" res = self.pool.get('sale.shop').search(cr, uid, [], context=context) if res: shop = self.pool.get('sale.shop').browse(cr, uid, res[0], context=context) return shop.pricelist_id and shop.pricelist_id.id or False return False _defaults = { 'user_id': lambda self, cr, uid, context: uid, 'state': 'draft', 'name': lambda obj, cr, uid, context: obj.pool.get('ir.sequence').get( cr, uid, 'pos.order'), 'date_order': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'), 'nb_print': 0, 'company_id': lambda self, cr, uid, c: self.pool.get('res.users').browse( cr, uid, uid, c).company_id.id, 'sale_journal': _default_sale_journal, 'shop_id': _default_shop, 'pricelist_id': _default_pricelist, } def test_paid(self, cr, uid, ids, context=None): print "file: point_of_sale fun: test_paid" """A Point of Sale is paid when the sum @return: True """ for order in self.browse(cr, uid, ids, context=context): if order.lines and not order.amount_total: return True if (not order.lines) or (not order.statement_ids) or \ (abs(order.amount_total-order.amount_paid) > 0.00001): return False return True def create_picking(self, cr, uid, ids, context=None): print "file: point_of_sale fun: create_picking" """Create a picking for each order and validate it.""" picking_obj = self.pool.get('stock.picking') partner_obj = self.pool.get('res.partner') move_obj = self.pool.get('stock.move') for order in self.browse(cr, uid, ids, context=context): if not order.state == 'draft': continue addr = order.partner_id and partner_obj.address_get( cr, uid, [order.partner_id.id], ['delivery']) or {} picking_id = picking_obj.create( cr, uid, { 'origin': order.name, 'address_id': addr.get('delivery', False), 'type': 'out', 'company_id': order.company_id.id, 'move_type': 'direct', 'note': order.note or "", 'invoice_state': 'none', 'auto_picking': True, }, context=context) self.write(cr, uid, [order.id], {'picking_id': picking_id}, context=context) location_id = order.shop_id.warehouse_id.lot_stock_id.id output_id = order.shop_id.warehouse_id.lot_output_id.id for line in order.lines: if line.product_id and line.product_id.type == 'service': continue if line.qty < 0: location_id, output_id = output_id, location_id move_obj.create(cr, uid, { 'name': line.name, 'product_uom': line.product_id.uom_id.id, 'product_uos': line.product_id.uom_id.id, 'picking_id': picking_id, 'product_id': line.product_id.id, 'product_uos_qty': abs(line.qty), 'product_qty': abs(line.qty), 'tracking_id': False, 'state': 'draft', 'location_id': location_id, 'location_dest_id': output_id, }, context=context) if line.qty < 0: location_id, output_id = output_id, location_id wf_service = netsvc.LocalService("workflow") wf_service.trg_validate(uid, 'stock.picking', picking_id, 'button_confirm', cr) picking_obj.force_assign(cr, uid, [picking_id], context) return True def set_to_draft(self, cr, uid, ids, *args): print "file: point_of_sale fun: set_to_draft" if not len(ids): return False for order in self.browse(cr, uid, ids, context=context): if order.state <> 'cancel': raise osv.except_osv( _('Error!'), _('In order to set to draft a sale, it must be cancelled.') ) self.write(cr, uid, ids, {'state': 'draft'}) wf_service = netsvc.LocalService("workflow") for i in ids: wf_service.trg_create(uid, 'pos.order', i, cr) return True def cancel_order(self, cr, uid, ids, context=None): print "file: point_of_sale fun: cancel_order" """ Changes order state to cancel @return: True """ stock_picking_obj = self.pool.get('stock.picking') for order in self.browse(cr, uid, ids, context=context): wf_service.trg_validate(uid, 'stock.picking', order.picking_id.id, 'button_cancel', cr) if stock_picking_obj.browse( cr, uid, order.picking_id.id, context=context).state <> 'cancel': raise osv.except_osv(_('Error!'), _('Unable to cancel the picking.')) self.write(cr, uid, ids, {'state': 'cancel'}, context=context) return True def add_payment(self, cr, uid, order_id, data, context=None): print "file: point_of_sale fun: add_payment" """Create a new payment for the order""" statement_obj = self.pool.get('account.bank.statement') statement_line_obj = self.pool.get('account.bank.statement.line') prod_obj = self.pool.get('product.product') property_obj = self.pool.get('ir.property') curr_c = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id curr_company = curr_c.id order = self.browse(cr, uid, order_id, context=context) ids_new = [] args = { 'amount': data['amount'], } if 'payment_date' in data.keys(): args['date'] = data['payment_date'] args['name'] = order.name if data.get('payment_name', False): args['name'] = args['name'] + ': ' + data['payment_name'] account_def = property_obj.get(cr, uid, 'property_account_receivable', 'res.partner', context=context) args['account_id'] = (order.partner_id and order.partner_id.property_account_receivable \ and order.partner_id.property_account_receivable.id) or (account_def and account_def.id) or False args['partner_id'] = order.partner_id and order.partner_id.id or None if not args['account_id']: if not args['partner_id']: msg = _( 'There is no receivable account defined to make payment') else: msg = _( 'There is no receivable account defined to make payment for the partner: "%s" (id:%d)' ) % ( order.partner_id.name, order.partner_id.id, ) raise osv.except_osv(_('Configuration Error !'), msg) statement_id = statement_obj.search( cr, uid, [('journal_id', '=', int(data['journal'])), ('company_id', '=', curr_company), ('user_id', '=', uid), ('state', '=', 'open')], context=context) if len(statement_id) == 0: raise osv.except_osv(_('Error !'), _('You have to open at least one cashbox')) if statement_id: statement_id = statement_id[0] args['statement_id'] = statement_id args['pos_statement_id'] = order_id args['journal_id'] = int(data['journal']) args['type'] = 'customer' args['ref'] = order.name statement_line_obj.create(cr, uid, args, context=context) ids_new.append(statement_id) wf_service = netsvc.LocalService("workflow") wf_service.trg_validate(uid, 'pos.order', order_id, 'paid', cr) wf_service.trg_write(uid, 'pos.order', order_id, cr) return statement_id def refund(self, cr, uid, ids, context=None): print "file: point_of_sale fun: refund" """Create a copy of order for refund order""" clone_list = [] line_obj = self.pool.get('pos.order.line') for order in self.browse(cr, uid, ids, context=context): clone_id = self.copy(cr, uid, order.id, { 'name': order.name + ' REFUND', }, context=context) clone_list.append(clone_id) for clone in self.browse(cr, uid, clone_list, context=context): for order_line in clone.lines: line_obj.write(cr, uid, [order_line.id], {'qty': -order_line.qty}, context=context) new_order = ','.join(map(str, clone_list)) abs = { #'domain': "[('id', 'in', ["+new_order+"])]", 'name': _('Return Products'), 'view_type': 'form', 'view_mode': 'form', 'res_model': 'pos.order', 'res_id': clone_list[0], 'view_id': False, 'context': context, 'type': 'ir.actions.act_window', 'nodestroy': True, 'target': 'current', } return abs def action_invoice_state(self, cr, uid, ids, context=None): print "file: point_of_sale fun: action_invoice_state" return self.write(cr, uid, ids, {'state': 'invoiced'}, context=context) def action_invoice(self, cr, uid, ids, context=None): print "file: point_of_sale fun: action_invoice" wf_service = netsvc.LocalService("workflow") inv_ref = self.pool.get('account.invoice') inv_line_ref = self.pool.get('account.invoice.line') product_obj = self.pool.get('product.product') inv_ids = [] for order in self.pool.get('pos.order').browse(cr, uid, ids, context=context): if order.invoice_id: inv_ids.append(order.invoice_id.id) continue if not order.partner_id: raise osv.except_osv( _('Error'), _('Please provide a partner for the sale.')) acc = order.partner_id.property_account_receivable.id inv = { 'name': order.name, 'origin': order.name, 'account_id': acc, 'journal_id': order.sale_journal.id or None, 'type': 'out_invoice', 'reference': order.name, 'partner_id': order.partner_id.id, 'comment': order.note or '', 'currency_id': order.pricelist_id.currency_id. id, # considering partner's sale pricelist's currency } inv.update( inv_ref.onchange_partner_id(cr, uid, [], 'out_invoice', order.partner_id.id)['value']) if not inv.get('account_id', None): inv['account_id'] = acc inv_id = inv_ref.create(cr, uid, inv, context=context) self.write(cr, uid, [order.id], { 'invoice_id': inv_id, 'state': 'invoiced' }, context=context) inv_ids.append(inv_id) for line in order.lines: inv_line = { 'invoice_id': inv_id, 'product_id': line.product_id.id, 'quantity': line.qty, } inv_name = product_obj.name_get(cr, uid, [line.product_id.id], context=context)[0][1] inv_line.update( inv_line_ref.product_id_change( cr, uid, [], line.product_id.id, line.product_id.uom_id.id, line.qty, partner_id=order.partner_id.id, fposition_id=order.partner_id. property_account_position.id)['value']) if line.product_id.description_sale: inv_line['note'] = line.product_id.description_sale inv_line['price_unit'] = line.price_unit inv_line['discount'] = line.discount inv_line['name'] = inv_name inv_line['invoice_line_tax_id'] = ('invoice_line_tax_id' in inv_line)\ and [(6, 0, inv_line['invoice_line_tax_id'])] or [] inv_line_ref.create(cr, uid, inv_line, context=context) inv_ref.button_reset_taxes(cr, uid, [inv_id], context=context) wf_service.trg_validate(uid, 'pos.order', order.id, 'invoice', cr) if not inv_ids: return {} mod_obj = self.pool.get('ir.model.data') res = mod_obj.get_object_reference(cr, uid, 'account', 'invoice_form') res_id = res and res[1] or False return { 'name': _('Customer Invoice'), 'view_type': 'form', 'view_mode': 'form', 'view_id': [res_id], 'res_model': 'account.invoice', 'context': "{'type':'out_invoice'}", 'type': 'ir.actions.act_window', 'nodestroy': True, 'target': 'current', 'res_id': inv_ids and inv_ids[0] or False, } def create_account_move(self, cr, uid, ids, context=None): print "file: point_of_sale fun: create_account_move" """Create a account move line of order grouped by products or not.""" account_move_obj = self.pool.get('account.move') account_move_line_obj = self.pool.get('account.move.line') account_period_obj = self.pool.get('account.period') period = account_period_obj.find(cr, uid, context=context)[0] account_tax_obj = self.pool.get('account.tax') res_obj = self.pool.get('res.users') property_obj = self.pool.get('ir.property') for order in self.browse(cr, uid, ids, context=context): if order.state <> 'paid': continue curr_c = res_obj.browse(cr, uid, uid).company_id comp_id = res_obj.browse(cr, order.user_id.id, order.user_id.id).company_id comp_id = comp_id and comp_id.id or False to_reconcile = [] group_tax = {} account_def = property_obj.get(cr, uid, 'property_account_receivable', 'res.partner', context=context).id order_account = order.partner_id and order.partner_id.property_account_receivable and order.partner_id.property_account_receivable.id or account_def or curr_c.account_receivable.id # Create an entry for the sale move_id = account_move_obj.create( cr, uid, { 'journal_id': order.sale_journal.id, }, context=context) # Create an move for each order line for line in order.lines: tax_amount = 0 taxes = [t for t in line.product_id.taxes_id] computed = account_tax_obj.compute_all( cr, uid, taxes, line.price_unit * (100.0 - line.discount) / 100.0, line.qty) computed_taxes = computed['taxes'] for tax in computed_taxes: tax_amount += round(tax['amount'], 2) group_key = (tax['tax_code_id'], tax['base_code_id'], tax['account_collected_id']) if group_key in group_tax: group_tax[group_key] += round(tax['amount'], 2) else: group_tax[group_key] = round(tax['amount'], 2) amount = line.price_subtotal # Search for the income account if line.product_id.property_account_income.id: income_account = line.product_id.property_account_income.id elif line.product_id.categ_id.property_account_income_categ.id: income_account = line.product_id.categ_id.property_account_income_categ.id else: raise osv.except_osv(_('Error !'), _('There is no income '\ 'account defined for this product: "%s" (id:%d)') \ % (line.product_id.name, line.product_id.id, )) # Empty the tax list as long as there is no tax code: tax_code_id = False tax_amount = 0 while computed_taxes: tax = computed_taxes.pop(0) if amount > 0: tax_code_id = tax['base_code_id'] tax_amount = line.price_subtotal * tax['base_sign'] else: tax_code_id = tax['ref_base_code_id'] tax_amount = line.price_subtotal * tax['ref_base_sign'] # If there is one we stop if tax_code_id: break # Create a move for the line account_move_line_obj.create( cr, uid, { 'name': line.name, 'date': order.date_order[:10], 'ref': order.name, 'quantity': line.qty, 'product_id': line.product_id.id, 'move_id': move_id, 'account_id': income_account, 'company_id': comp_id, 'credit': ((amount > 0) and amount) or 0.0, 'debit': ((amount < 0) and -amount) or 0.0, 'journal_id': order.sale_journal.id, 'period_id': period, 'tax_code_id': tax_code_id, 'tax_amount': tax_amount, 'partner_id': order.partner_id and order.partner_id.id or False }, context=context) # For each remaining tax with a code, whe create a move line for tax in computed_taxes: if amount > 0: tax_code_id = tax['base_code_id'] tax_amount = line.price_subtotal * tax['base_sign'] else: tax_code_id = tax['ref_base_code_id'] tax_amount = line.price_subtotal * tax['ref_base_sign'] if not tax_code_id: continue account_move_line_obj.create( cr, uid, { 'name': "Tax" + line.name, 'date': order.date_order[:10], 'ref': order.name, 'product_id': line.product_id.id, 'quantity': line.qty, 'move_id': move_id, 'account_id': income_account, 'company_id': comp_id, 'credit': 0.0, 'debit': 0.0, 'journal_id': order.sale_journal.id, 'period_id': period, 'tax_code_id': tax_code_id, 'tax_amount': tax_amount, }, context=context) # Create a move for each tax group (tax_code_pos, base_code_pos, account_pos) = (0, 1, 2) for key, amount in group_tax.items(): account_move_line_obj.create( cr, uid, { 'name': 'Tax', 'date': order.date_order[:10], 'ref': order.name, 'move_id': move_id, 'company_id': comp_id, 'quantity': line.qty, 'product_id': line.product_id.id, 'account_id': key[account_pos], 'credit': ((amount > 0) and amount) or 0.0, 'debit': ((amount < 0) and -amount) or 0.0, 'journal_id': order.sale_journal.id, 'period_id': period, 'tax_code_id': key[tax_code_pos], 'tax_amount': amount, }, context=context) # counterpart to_reconcile.append(account_move_line_obj.create(cr, uid, { 'name': order.name, 'date': order.date_order[:10], 'ref': order.name, 'move_id': move_id, 'company_id': comp_id, 'account_id': order_account, 'credit': ((order.amount_total < 0) and -order.amount_total)\ or 0.0, 'debit': ((order.amount_total > 0) and order.amount_total)\ or 0.0, 'journal_id': order.sale_journal.id, 'period_id': period, 'partner_id': order.partner_id and order.partner_id.id or False }, context=context)) self.write(cr, uid, order.id, { 'state': 'done', 'account_move': move_id }, context=context) return True def action_payment(self, cr, uid, ids, context=None): print "file: point_of_sale fun: action_payment" return self.write(cr, uid, ids, {'state': 'payment'}, context=context) def action_paid(self, cr, uid, ids, context=None): print "file: point_of_sale fun: action_paid" context = context or {} self.create_picking(cr, uid, ids, context=None) self.write(cr, uid, ids, {'state': 'paid'}, context=context) return True def action_cancel(self, cr, uid, ids, context=None): print "file: point_of_sale fun: action_cancel" self.write(cr, uid, ids, {'state': 'cancel'}, context=context) return True def action_done(self, cr, uid, ids, context=None): print "file: point_of_sale fun: action_done" self.create_account_move(cr, uid, ids, context=context) return True
class medical_pediatricsymptomschecklist(osv.osv): _name = 'medical.patient.psc' _description = 'Pediatric Symptoms Checklist' _columns = { 'patient' : fields.many2one('medical.patient', 'Patient', required=True), 'evaluation_date' : fields.many2one('medical.appointment', 'Appointment Date',help="Enter or select the date / ID of the appointment related to this evaluation",required=True), 'evaluation_start' : fields.datetime('Date', required=True), 'user_id' : fields.many2one('res.users', 'Healh Professional', readonly=True), 'notes' : fields.text('Notes'), 'psc_aches_pains' : fields.selection([ (None, ''), ('0', 'Never'), ('1', 'Sometimes'), ('2', 'Often'), ], 'Complains of aches and pains'), 'psc_spend_time_alone' : fields.selection([ (None, ''), ('0', 'Never'), ('1', 'Sometimes'), ('2', 'Often'), ], 'Spends more time alone'), 'psc_tires_easily' : fields.selection([ (None, ''), ('0', 'Never'), ('1', 'Sometimes'), ('2', 'Often'), ], 'Tires easily, has little energy'), 'psc_fidgety' : fields.selection([ (None, ''), ('0', 'Never'), ('1', 'Sometimes'), ('2', 'Often'), ], 'Fidgety, unable to sit still'), 'psc_trouble_with_teacher' : fields.selection([ (None, ''), ('0', 'Never'), ('1', 'Sometimes'), ('2', 'Often'), ], 'Has trouble with teacher'), 'psc_less_interest_in_school' : fields.selection([ (None, ''), ('0', 'Never'), ('1', 'Sometimes'), ('2', 'Often'), ], 'Less interested in school'), 'psc_acts_as_driven_by_motor' : fields.selection([ (None, ''), ('0', 'Never'), ('1', 'Sometimes'), ('2', 'Often'), ], 'Acts as if driven by a motor'), 'psc_daydreams_too_much' : fields.selection([ (None, ''), ('0', 'Never'), ('1', 'Sometimes'), ('2', 'Often'), ], 'Daydreams too much'), 'psc_distracted_easily' : fields.selection([ (None, ''), ('0', 'Never'), ('1', 'Sometimes'), ('2', 'Often'), ], 'Distracted easily'), 'psc_afraid_of_new_situations' : fields.selection([ (None, ''), ('0', 'Never'), ('1', 'Sometimes'), ('2', 'Often'), ], 'Is afraid of new situations'), 'psc_sad_unhappy' : fields.selection([ (None, ''), ('0', 'Never'), ('1', 'Sometimes'), ('2', 'Often'), ], 'Feels sad, unhappy'), 'psc_irritable_angry' : fields.selection([ (None, ''), ('0', 'Never'), ('1', 'Sometimes'), ('2', 'Often'), ], 'Is irritable, angry'), 'psc_feels_hopeless' : fields.selection([ (None, ''), ('0', 'Never'), ('1', 'Sometimes'), ('2', 'Often'), ], 'Feels hopeless'), 'psc_trouble_concentrating' : fields.selection([ (None, ''), ('0', 'Never'), ('1', 'Sometimes'), ('2', 'Often'), ], 'Has trouble concentrating'), 'psc_less_interested_in_friends' : fields.selection([ (None, ''), ('0', 'Never'), ('1', 'Sometimes'), ('2', 'Often'), ], 'Less interested in friends'), 'psc_fights_with_others' : fields.selection([ (None, ''), ('0', 'Never'), ('1', 'Sometimes'), ('2', 'Often'), ], 'Fights with other children'), 'psc_absent_from_school' : fields.selection([ (None, ''), ('0', 'Never'), ('1', 'Sometimes'), ('2', 'Often'), ], 'Absent from school'), 'psc_school_grades_dropping' : fields.selection([ (None, ''), ('0', 'Never'), ('1', 'Sometimes'), ('2', 'Often'), ], 'School grades dropping'), 'psc_down_on_self' : fields.selection([ (None, ''), ('0', 'Never'), ('1', 'Sometimes'), ('2', 'Often'), ], 'Is down on him or herself'), 'psc_visit_doctor_finds_ok' : fields.selection([ (None, ''), ('0', 'Never'), ('1', 'Sometimes'), ('2', 'Often'), ], 'Visits the doctor with doctor finding nothing wrong'), 'psc_trouble_sleeping' : fields.selection([ (None, ''), ('0', 'Never'), ('1', 'Sometimes'), ('2', 'Often'), ], 'Has trouble sleeping'), 'psc_worries_a_lot' : fields.selection([ (None, ''), ('0', 'Never'), ('1', 'Sometimes'), ('2', 'Often'), ], 'Worries a lot'), 'psc_wants_to_be_with_parents' : fields.selection([ (None, ''), ('0', 'Never'), ('1', 'Sometimes'), ('2', 'Often'), ], 'Wants to be with you more than before'), 'psc_feels_is_bad_child' : fields.selection([ (None, ''), ('0', 'Never'), ('1', 'Sometimes'), ('2', 'Often'), ], 'Feels he or she is bad'), 'psc_takes_unnecesary_risks' : fields.selection([ (None, ''), ('0', 'Never'), ('1', 'Sometimes'), ('2', 'Often'), ], 'Takes unnecessary risks'), 'psc_gets_hurt_often' : fields.selection([ (None, ''), ('0', 'Never'), ('1', 'Sometimes'), ('2', 'Often'), ], 'Gets hurt frequently'), 'psc_having_less_fun' : fields.selection([ (None, ''), ('0', 'Never'), ('1', 'Sometimes'), ('2', 'Often'), ], 'Seems to be having less fun'), 'psc_act_as_younger' : fields.selection([ (None, ''), ('0', 'Never'), ('1', 'Sometimes'), ('2', 'Often'), ], 'Acts younger than children his or her age'), 'psc_does_not_listen_to_rules' : fields.selection([ (None, ''), ('0', 'Never'), ('1', 'Sometimes'), ('2', 'Often'), ], 'Does not listen to rules'), 'psc_does_not_show_feelings' : fields.selection([ (None, ''), ('0', 'Never'), ('1', 'Sometimes'), ('2', 'Often'), ], 'Does not show feelings'), 'psc_does_not_get_people_feelings' : fields.selection([ (None, ''), ('0', 'Never'), ('1', 'Sometimes'), ('2', 'Often'), ], 'Does not get people feelings'), 'psc_teases_others' : fields.selection([ (None, ''), ('0', 'Never'), ('1', 'Sometimes'), ('2', 'Often'), ], 'Teases others'), 'psc_blames_others' : fields.selection([ (None, ''), ('0', 'Never'), ('1', 'Sometimes'), ('2', 'Often'), ], 'Blames others for his or her troubles'), 'psc_takes_things_from_others' : fields.selection([ (None, ''), ('0', 'Never'), ('1', 'Sometimes'), ('2', 'Often'), ], 'Takes things that do not belong to him or her'), 'psc_refuses_to_share' : fields.selection([ (None, ''), ('0', 'Never'), ('1', 'Sometimes'), ('2', 'Often'), ], 'Refuses to share'), 'psc_total' : fields.integer('PSC Total'), } _defaults = { 'user_id': lambda obj, cr, uid, context: uid, 'psc_total' : 0, 'evaluation_start': fields.date.context_today, } def on_change_with_psc_total(self, cr, uid, ids,psc_aches_pains,psc_spend_time_alone,psc_tires_easily,psc_fidgety,psc_trouble_with_teacher,psc_less_interest_in_school,psc_acts_as_driven_by_motor,psc_daydreams_too_much,psc_distracted_easily,psc_afraid_of_new_situations,psc_sad_unhappy,psc_irritable_angry,psc_feels_hopeless,psc_trouble_concentrating,psc_less_interested_in_friends,psc_fights_with_others,psc_absent_from_school,psc_school_grades_dropping,psc_down_on_self,psc_visit_doctor_finds_ok,psc_trouble_sleeping,psc_worries_a_lot,psc_wants_to_be_with_parents,psc_feels_is_bad_child,psc_takes_unnecesary_risks,psc_gets_hurt_often,psc_having_less_fun,psc_act_as_younger,psc_does_not_listen_to_rules,psc_does_not_show_feelings,psc_does_not_get_people_feelings,psc_teases_others,psc_takes_things_from_others,psc_refuses_to_share,context=None): psc_aches_pains = psc_aches_pains or '0' psc_spend_time_alone = psc_spend_time_alone or '0' psc_tires_easily = psc_tires_easily or '0' psc_fidgety = psc_fidgety or '0' psc_trouble_with_teacher = psc_trouble_with_teacher or '0' psc_less_interest_in_school = psc_less_interest_in_school or '0' psc_acts_as_driven_by_motor = psc_acts_as_driven_by_motor or '0' psc_daydreams_too_much = psc_daydreams_too_much or '0' psc_distracted_easily = psc_distracted_easily or '0' psc_afraid_of_new_situations = psc_afraid_of_new_situations or '0' psc_sad_unhappy = psc_sad_unhappy or '0' psc_irritable_angry = psc_irritable_angry or '0' psc_feels_hopeless = psc_feels_hopeless or '0' psc_trouble_concentrating = psc_trouble_concentrating or '0' psc_less_interested_in_friends = psc_less_interested_in_friends or '0' psc_fights_with_others = psc_fights_with_others or '0' psc_absent_from_school = psc_absent_from_school or '0' psc_school_grades_dropping = psc_school_grades_dropping or '0' psc_down_on_self = psc_down_on_self or '0' psc_visit_doctor_finds_ok = psc_visit_doctor_finds_ok or '0' psc_trouble_sleeping = psc_trouble_sleeping or '0' psc_worries_a_lot = psc_worries_a_lot or '0' psc_wants_to_be_with_parents = psc_wants_to_be_with_parents or '0' psc_feels_is_bad_child = psc_feels_is_bad_child or '0' psc_takes_unnecesary_risks = psc_takes_unnecesary_risks or '0' psc_gets_hurt_often = psc_gets_hurt_often or '0' psc_having_less_fun = psc_having_less_fun or '0' psc_act_as_younger = psc_act_as_younger or '0' psc_does_not_listen_to_rules = psc_does_not_listen_to_rules or '0' psc_does_not_show_feelings = psc_does_not_show_feelings or '0' psc_does_not_get_people_feelings = psc_does_not_get_people_feelings or '0' psc_teases_others = psc_teases_others or '0' psc_takes_things_from_others = psc_takes_things_from_others or '0' psc_refuses_to_share = psc_refuses_to_share or '0' psc_total = int(psc_aches_pains) + int(psc_spend_time_alone) + \ int(psc_tires_easily) + int(psc_fidgety) + \ int(psc_trouble_with_teacher) + \ int(psc_less_interest_in_school) + \ int(psc_acts_as_driven_by_motor) + \ int(psc_daydreams_too_much) + int(psc_distracted_easily) + \ int(psc_afraid_of_new_situations) + int(psc_sad_unhappy) + \ int(psc_irritable_angry) + int(psc_feels_hopeless) + \ int(psc_trouble_concentrating) + \ int(psc_less_interested_in_friends) + \ int(psc_fights_with_others) + int(psc_absent_from_school) + \ int(psc_school_grades_dropping) + int(psc_down_on_self) + \ int(psc_visit_doctor_finds_ok) + int(psc_trouble_sleeping) + \ int(psc_worries_a_lot) + int(psc_wants_to_be_with_parents) + \ int(psc_feels_is_bad_child) + int(psc_takes_unnecesary_risks) + \ int(psc_gets_hurt_often) + int(psc_having_less_fun) + \ int(psc_act_as_younger) + int(psc_does_not_listen_to_rules) + \ int(psc_does_not_show_feelings) + \ int(psc_does_not_get_people_feelings) + \ int(psc_teases_others) + \ int(psc_takes_things_from_others) + \ int(psc_refuses_to_share) #query = _("update medical_patient_psc set psc_total=%s where patient=%s and evaluation_date=%s")%(psc_total,str(patient),str(evaluation_date)) #cr.execute(query) return {'value': {'psc_total': psc_total}}
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 medical_newborn(osv.osv): _name="medical.newborn" _description = "Newborn Information" _columns = { 'name': fields.char ('Newborn ID', size=128, help="Enter Newborn ID",required=True), 'mother': fields.many2one ('medical.patient', 'Mother'), 'newborn_name': fields.char ('Baby\'s name', size=128), 'birth_date': fields.datetime ('Date Of Birth', required=True), 'photo' : fields.binary('Picture'), 'sex' : fields.selection([ ('m', 'Male'), ('f', 'Female'), ('a', 'Ambiguous genitalia') ], 'Sex', required=True), 'cephalic_perimeter' : fields.integer('Cephalic Perimeter',help="Perimeter in centimeters (cm)"), 'length' : fields.integer('Length', help="Perimeter in centimeters (cm)"), 'weight' : fields.integer('Weight', help="Weight in grams (g)"), 'apgar1' : fields.integer('APGAR 1st minute'), 'apgar5' : fields.integer('APGAR 5th minute'), 'apgar_scores' : fields.one2many('medical.neonatal.apgar', 'name','APGAR scores'), 'meconium' : fields.boolean('Meconium'), 'congenital_diseases' : fields.one2many('medical.patient.disease','newborn_id', 'Congenital diseases'), 'reanimation_stimulation' : fields.boolean('Stimulation'), 'reanimation_aspiration' : fields.boolean('Aspiration'), 'reanimation_intubation' : fields.boolean('Intubation'), 'reanimation_mask' : fields.boolean('Mask'), 'reanimation_oxygen' : fields.boolean('Oxygen'), 'test_vdrl' : fields.boolean('VDRL'), 'test_toxo' : fields.boolean('Toxoplasmosis'), 'test_chagas' : fields.boolean('Chagas'), 'test_billirubin' : fields.boolean('Billirubin'), 'test_audition' : fields.boolean('Audition'), 'test_metabolic' : fields.boolean('Metabolic ("heel stick screening")', help="Test for Fenilketonuria, Congenital Hypothyroidism, " "Quistic Fibrosis, Galactosemia"), 'neonatal_ortolani' : fields.boolean('Positive Ortolani'), 'neonatal_barlow' : fields.boolean('Positive Barlow'), 'neonatal_hernia' : fields.boolean('Hernia'), 'neonatal_ambiguous_genitalia' : fields.boolean('Ambiguous Genitalia'), 'neonatal_erbs_palsy' : fields.boolean('Erbs Palsy'), 'neonatal_hematoma' : fields.boolean('Hematomas'), 'neonatal_talipes_equinovarus' : fields.boolean('Talipes Equinovarus'), 'neonatal_polydactyly' : fields.boolean('Polydactyly'), 'neonatal_syndactyly' : fields.boolean('Syndactyly'), 'neonatal_moro_reflex' : fields.boolean('Moro Reflex'), 'neonatal_grasp_reflex' : fields.boolean('Grasp Reflex'), 'neonatal_stepping_reflex' : fields.boolean('Stepping Reflex'), 'neonatal_babinski_reflex' : fields.boolean('Babinski Reflex'), 'neonatal_blink_reflex' : fields.boolean('Blink Reflex'), 'neonatal_sucking_reflex' : fields.boolean('Sucking Reflex'), 'neonatal_swimming_reflex' : fields.boolean('Swimming Reflex'), 'neonatal_tonic_neck_reflex' : fields.boolean('Tonic Neck Reflex'), 'neonatal_rooting_reflex' : fields.boolean('Rooting Reflex'), 'neonatal_palmar_crease' : fields.boolean('Transversal Palmar Crease'), 'medication' : fields.one2many('medical.patient.medication','newborn_id', 'Medication'), 'responsible' : fields.many2one('medical.physician', 'Doctor in charge',help="Signed by the health professional"), 'dismissed' : fields.datetime('Discharged'), 'bd' : fields.boolean('Stillbirth'), 'died_at_delivery' : fields.boolean('Died at delivery room'), 'died_at_the_hospital' : fields.boolean('Died at the hospital'), 'died_being_transferred' : fields.boolean('Died being transferred',help="The baby died being transferred to another health institution"), 'tod' : fields.datetime('Time of Death'), 'cod' : fields.many2one('medical.pathology', 'Cause of death'), 'notes' : fields.text('Notes'), } _sql_constraints = [ ('name_uniq', 'unique(name)', 'The Newborn ID must be unique !'), ] def print_card(self, cr, uid, ids, context=None): assert len(ids) == 1, 'This option should only be used for a single id at a time' datas = { 'model': 'medical.newborn', 'ids': ids, 'form': self.read(cr, uid, ids[0], context=context), } return {'type': 'ir.actions.report.xml', 'report_name': 'newborn.card', 'datas': datas, 'nodestroy': True}
('text/html', 'HTML Body'), ], 'Mail Contents'), #I like GMAIL which allows putting same mail in many folders #Lets plan it for 0.9 'folder':fields.selection([ ('drafts', 'Drafts'), ('outbox', 'Outbox'), ('trash', 'Trash'), ('sent', 'Sent Items'), ], 'Folder', required=True), 'state':fields.selection([ ('na', 'Not Applicable'), ('sending', 'Sending'), ], 'Status', required=True), 'date_mail':fields.datetime('Rec/Sent Date', help="Date on which Email Sent or Received"), 'history':fields.text( 'History', readonly=True, store=True) } _defaults = { 'state': lambda * a: 'na', 'folder': lambda * a: 'outbox', } def unlink(self, cr, uid, ids, context=None): """ It just changes the folder of the item to "Trash", if it is no in Trash folder yet, or completely deletes it if it is already in Trash.
class kg_po_register_wiz(osv.osv_memory): _name = 'kg.po.register.wiz' _columns = { 'product_id': fields.many2many('product.product', 'kg_po_stm_pro', 'order_id', 'product_id', 'Product Name'), 'supplier': fields.many2many('res.partner', 'kg_po_stm_sup', 'order_id', 'supplier_id', 'Supplier'), 'filter': fields.selection([('filter_no', 'No Filters'), ('filter_date', 'Date')], "Filter by", required=True), 'date_from': fields.date("Start Date"), 'date_to': fields.date("End Date"), 'print_date': fields.datetime('Creation Date', readonly=True), 'printed_by': fields.many2one('res.users', 'Printed By', readonly=True), 'status': fields.selection([('approved', 'Approved'), ('cancelled', 'Cancelled'), ('pending', 'Pending')], "Status"), 'company_id': fields.many2one('res.company', 'Company Name'), 'dep_project': fields.many2one('kg.project.master', 'Dept/Project Name'), ##### } _defaults = { 'filter': 'filter_date', 'date_from': time.strftime('%Y-%m-%d'), 'date_to': time.strftime('%Y-%m-%d'), 'print_date': fields.datetime.now, 'printed_by': lambda obj, cr, uid, context: uid, 'company_id': lambda self, cr, uid, c: self.pool.get('res.company'). _company_default_get(cr, uid, 'kg.pi.detail.wizard', context=c), } def _date_validation_check(self, cr, uid, ids, context=None): for val_date in self.browse(cr, uid, ids, context=context): if val_date.date_from <= val_date.date_to: return True return False _constraints = [ (_date_validation_check, 'You must select an correct Start Date and End Date !!', ['Valid_date']), ] def _build_contexts(self, cr, uid, ids, data, context=None): if context is None: context = {} result = {} result['date_from'] = 'date_from' in data['form'] and data['form'][ 'date_from'] or False result['date_to'] = 'date_to' in data['form'] and data['form'][ 'date_to'] or False if data['form']['filter'] == 'filter_date': result['date_from'] = data['form']['date_from'] result['date_to'] = data['form']['date_to'] return result def date_indian_format(self, date_pyformat): date_contents = date_pyformat.split("-") date_indian = date_contents[2] + "/" + date_contents[ 1] + "/" + date_contents[0] return date_indian def check_report(self, cr, uid, ids, context=None): if context is None: context = {} data = {} data['ids'] = context.get('active_ids', []) data['model'] = context.get('active_model', 'ir.ui.menu') data['form'] = self.read(cr, uid, ids, [])[0] used_context = self._build_contexts(cr, uid, ids, data, context=context) data['form']['used_context'] = used_context return self._print_report(cr, uid, ids, data, context=context) def pre_print_report(self, cr, uid, ids, data, context=None): if context is None: context = {} data['form'].update(self.read(cr, uid, ids, [], context=context)[0]) return data def _print_report(self, cr, uid, ids, data, context=None): rec = self.browse(cr, uid, ids[0]) if context is None: context = {} data = self.pre_print_report(cr, uid, ids, data, context=context) data['form'].update(self.read(cr, uid, ids[0])) if data['form']: date_from = str(data['form']['date_from']) date_to = str(data['form']['date_to']) data['form']['date_from_ind'] = self.date_indian_format(date_from) data['form']['date_to_ind'] = self.date_indian_format(date_to) company_id = data['form']['company_id'][0] com_rec = self.pool.get('res.company').browse(cr, uid, company_id) data['form']['company'] = com_rec.name data['form']['printed_by'] = rec.printed_by.name if data['form']['status'] == 'approved': data['form']['status_name'] = 'Approved' elif data['form']['status'] == 'cancelled': data['form']['status_name'] = 'Cancelled' elif data['form']['status'] == 'pending': data['form']['status_name'] = 'Pending' else: data['form']['status_name'] = '' cr_date = datetime.strptime(rec.print_date, '%Y-%m-%d %H:%M:%S') date = cr_date.strftime('%d/%m/%Y %H:%M:%S') data['form']['print_date'] = date return { 'type': 'ir.actions.report.xml', 'report_name': 'kg.po.register', 'datas': data, 'name': 'PO Register' }
cr.commit() else: locate_val = 'Active' cr.execute("UPDATE product_listing SET state='%s' where id=%d"%(locate_val,each_ids.id,)) cr.commit() res[each_ids.id] = { 'time_remain_function': locate, 'state':locate_val, } return res _columns = { 'name': fields.char('Item ID', size=64), 'prod_list':fields.many2one('product.product', string='Product Name',readonly= True), 'shop_id':fields.many2one('sale.shop', string='Shop Name'), 'ebay_end_time':fields.datetime('End Time',size=64), 'start_time':fields.datetime('Start Time',size=64), 'is_cancel':fields.boolean('Is Cancelled',readonly=True), 'cancel_listing' : fields.boolean('Cancel Listing'), 'ending_reason': fields.selection([('Incorrect','The start price or reserve price is incorrect'),('LostOrBroken','The item was lost or broken'),('NotAvailable','The item is no longer available for sale'),('OtherListingError','The listing contained an error'),('SellToHighBidder','The listing has qualifying bids')],'Ending Reason'), 'type': fields.char('Type',size=64), 'related_template':fields.many2one('ebayerp.template','Template'), 'listing_duration' : fields.char('Listing Duration',size=64), 'time_remain' : fields.char('Time Remaining',size=64), 'time_remain_function': fields.function(_get_time_remain_funtion, method=True, string='Remaining Time', type='char', multi='_get_time_remain_funtion'), 'product_listing_id': fields.one2many('current.details', 'current_details_ids','Product listing id'), 'state':fields.selection([('Active','Active'),('Inactive','Expired')],'Status',readonly=True), 'condtn':fields.selection([('1000','New'),('1500','New other (see details)'),('2000','Manufacturer refurbished'),('2500','Seller refurbished'),('3000','Used'),('7000','For parts or not working')],'Condition'), 'ebay_name':fields.char('Ebay Title',size=256), 'time_rem':fields.char('Time Remain',size=256), }
class OeMedicalPatient(osv.Model): _name = 'oemedical.patient' def _get_name(self, cr, uid, ids, field_name, arg, context=None): res = {} for record in self.browse(cr, uid, ids, context=context): res[record.id] = record.patient_id.name return res def onchange_name(self, cr, uid, ids, first_name, last_name, slastname, context=None): if first_name == False: first_name = '' if last_name == False: last_name = '' if slastname == False: slastname = '' res = { 'value': { 'name': first_name + ' ' + last_name + ' ' + slastname } } return res def _get_age(self, cr, uid, ids, field_name, arg, context=None): res = {} age = '' now = datetime.now() for record in self.browse(cr, uid, ids, context=context): if (record.dob): dob = datetime.strptime(str(record.dob), '%Y-%m-%d') if record.deceased: dod = datetime.strptime(record.dod, '%Y-%m-%d %H:%M:%S') delta = relativedelta(dod, dob) deceased = ' (deceased)' else: delta = relativedelta(now, dob) deceased = '' years_months_days = str(delta.years) + 'y ' \ + str(delta.months) + 'm ' \ + str(delta.days) + 'd' + deceased else: years_months_days = 'No DoB !' # Return the age in format y m d when the caller is the field name if field_name == 'age': age = years_months_days res[record.id] = age return res _columns = { 'patient_id': fields.many2one('res.partner', string='Patient', required=True, help='Patient', domain=[('category_id', '=', 'Patient')]), 'name': fields.function(_get_name, type='char', string='Patient Name', help="", multi=False), 'family': fields.many2one('oemedical.family', string='Family', help='Family Code'), 'photo': fields.binary(string='Picture'), 'sex': fields.selection([ ('m', 'Male'), ('f', 'Female'), ], string='Gender', required=True), 'blood_type': fields.selection([ ('A', 'A'), ('B', 'B'), ('AB', 'AB'), ('O', 'O'), ], string='Blood Type'), 'rh': fields.selection([ ('+', '+'), ('-', '-'), ], string='Rh'), 'general_info': fields.text(string='General Information', help='General information about the patient'), 'primary_care_doctor': fields.many2one('oemedical.physician', 'Primary Care Doctor', help='Current primary care / family doctor'), 'childbearing_age': fields.boolean('Potential for Childbearing'), 'medications': fields.one2many( 'oemedical.patient.medication', 'patient_id', string='Medications', ), 'evaluations': fields.one2many( 'oemedical.patient.evaluation', 'patient_id', string='Evaluations', ), 'critical_info': fields.text( string='Important disease, allergy or procedures information', help= 'Write any important information on the patient\'s disease, surgeries, allergies, ...' ), 'diseases': fields.one2many('oemedical.patient.disease', 'patient_id', string='Diseases', help='Mark if the patient has died'), 'ethnic_group': fields.many2one( 'oemedical.ethnicity', string='Ethnic group', ), 'ssn': fields.char(size=256, string='CC', readonly=True), 'vaccinations': fields.one2many( 'oemedical.vaccination', 'patient_id', 'Vaccinations', ), 'dob': fields.date(string='DoB'), 'age': fields.function( _get_age, type='char', string='Age', help= "It shows the age of the patient in years(y), months(m) and days(d).\nIf the patient has died, the age shown is the age at time of death, the age corresponding to the date on the death certificate. It will show also \"deceased\" on the field", multi=False), 'marital_status': fields.selection([ ('s', 'Single'), ('m', 'Married'), ('w', 'Widowed'), ('d', 'Divorced'), ('x', 'Separated'), ('z', 'law marriage'), ], string='Marital Status', sort=False), 'dod': fields.datetime(string='Date of Death'), 'current_insurance': fields.many2one( 'oemedical.insurance', string='Insurance', help= 'Insurance information. You may choose from the different insurances belonging to the patient' ), 'cod': fields.many2one( 'oemedical.pathology', string='Cause of Death', ), 'identification_code': fields.char(size=256, string='ID', help='Patient Identifier provided by the Health Center'), 'deceased': fields.boolean(string='Deceased'), 'street': fields.char('Street', size=128), 'street2': fields.char('Street2', size=128), 'zip': fields.char('Zip', change_default=True, size=24), 'city': fields.char('City', size=128), 'state_id': fields.many2one("res.country.state", 'State'), 'country_id': fields.many2one('res.country', 'Country'), 'email': fields.char('Email', size=240), 'phone': fields.char('Phone', size=64), 'fax': fields.char('Fax', size=64), 'mobile': fields.char('Mobile', size=64), } _defaults = { 'identification_code': lambda obj, cr, uid, context: obj.pool.get('ir.sequence').get( cr, uid, 'oemedical.patient'), 'photo': lambda self, cr, uid, ctx={}: self.pool.get('res.partner'). _get_default_image(cr, uid, False, ctx, colorize=True), 'ssn': lambda self, cr, uid, ctx={}: self.pool.get( 'res.partner')._get_ced_ruc(cr, uid, False), } def create(self, cr, uid, vals, context=None): sequence = unicode( self.pool.get('ir.sequence').get(cr, uid, 'oemedical.patient')) vals['identification_code'] = sequence return super(OeMedicalPatient, self).create(cr, uid, vals, context=context)
("multipart/alternative", "Plain Text & HTML with no attachments"), ("multipart/related", "Intermixed content"), ("text/plain", "Plain Text"), ("text/html", "HTML Body"), ], "Mail Contents", ), # I like GMAIL which allows putting same mail in many folders # Lets plan it for 0.9 "folder": fields.selection( [("drafts", "Drafts"), ("outbox", "Outbox"), ("trash", "Trash"), ("sent", "Sent Items")], "Folder", required=True, ), "state": fields.selection([("na", "Not Applicable"), ("sending", "Sending")], "Status", required=True), "date_mail": fields.datetime("Rec/Sent Date", help="Date on which Email Sent or Received"), "history": fields.text("History", readonly=True, store=True), } _defaults = {"state": lambda *a: "na", "folder": lambda *a: "outbox"} def unlink(self, cr, uid, ids, context=None): """ It just changes the folder of the item to "Trash", if it is no in Trash folder yet, or completely deletes it if it is already in Trash. """ to_update = [] to_remove = [] for mail in self.browse(cr, uid, ids, context=context): if mail.folder == "trash": to_remove.append(mail.id)
class perinatal(osv.osv): _name = "medical.perinatal" _description = "perinatal information" _columns = { 'name': fields.char('code', size=128), 'gravida_number': fields.integer('Gravida #'), 'abortion': fields.boolean('Abortion'), 'admission_date': fields.datetime('Admission date', help="Date when she was admitted to give birth"), 'prenatal_evaluations': fields.integer('Prenatal evaluations', help="Number of visits to the doctor during pregnancy"), 'start_labor_mode': fields.selection([ ('n', 'Normal'), ('i', 'Induced'), ('c', 'c-section'), ], 'Labor mode', select=True), 'gestational_weeks': fields.integer('Gestational weeks'), 'gestational_days': fields.integer('Gestational days'), 'fetus_presentation': fields.selection([ ('n', 'Correct'), ('o', 'Occiput / Cephalic Posterior'), ('fb', 'Frank Breech'), ('cb', 'Complete Breech'), ('t', 'Transverse Lie'), ('t', 'Footling Breech'), ], 'Fetus Presentation', select=True), 'placenta_incomplete': fields.boolean('Incomplete Placenta'), 'placenta_retained': fields.boolean('Retained Placenta'), 'episiotomy': fields.boolean('Episiotomy'), 'vaginal_tearing': fields.boolean('Vaginal tearing'), 'forceps': fields.boolean('Use of forceps'), 'monitoring': fields.many2many('medical.perinatal.monitor', 'patient_perinatal_monitor_rel', 'patient_id', 'monitor_ids', 'Monitors'), 'newborn': fields.many2many('medical.newborn', 'patient_newborn_rel', 'patient_id', 'newborn_ids', 'Newborn info'), 'puerperium_monitor': fields.many2many('medical.puerperium.monitor', 'patient_puerperium_monitor_rel', 'patient_id', 'puerperium_ids', 'Puerperium monitor'), 'medication': fields.many2many('medical.medicament', 'patient_labor_rel', 'medicament_id', 'patient_id', 'Medicaments and anesthesics'), 'dismissed': fields.datetime('Dismissed from hospital'), 'died_at_delivery': fields.boolean('Died at delivery room'), 'died_at_the_hospital': fields.boolean('Died at the hospital'), 'died_being_transferred': fields.boolean( 'Died being transferred', help= "The mother died being transferred to another health institution"), 'notes': fields.text('Notes'), }
class newborn(osv.osv): _name = "medical.newborn" _description = "newborn information" _columns = { 'name': fields.char('Baby\'s name', size=128), 'code': fields.char('Newborn ID', size=64, required=True), 'birth_date': fields.datetime('Date of Birth', required=True), 'photo': fields.binary('Picture'), 'sex': fields.selection([ ('m', 'Male'), ('f', 'Female'), ], 'Sex', select=True, required=True), 'cephalic_perimeter': fields.integer('Cephalic Perimeter'), 'length': fields.integer('Length'), 'weight': fields.integer('Weight'), 'apgar1': fields.integer('APGAR 1st minute'), 'apgar5': fields.integer('APGAR 5th minute'), 'meconium': fields.boolean('Meconium'), 'congenital_diseases': fields.many2many('medical.patient.disease', 'newborn_disease_rel', 'patient_id', 'congenital_id', 'Congenital diseases'), 'reanimation_stimulation': fields.boolean('Stimulation'), 'reanimation_aspiration': fields.boolean('Aspiration'), 'reanimation_intubation': fields.boolean('Intubation'), 'reanimation_mask': fields.boolean('Mask'), 'reanimation_oxygen': fields.boolean('Oxygen'), 'test_vdrl': fields.boolean('VDRL'), 'test_toxo': fields.boolean('Toxoplasmosis'), 'test_chagas': fields.boolean('Chagas'), 'test_billirubin': fields.boolean('Billirubin'), 'test_audition': fields.boolean('Audition'), 'test_metabolic': fields.boolean( 'The metabolic / genetic ("heel stick")', help= "Test for Fenilketonuria, Congenital Hypothyroidism, Quistic Fibrosis, Galactosemia" ), 'medication': fields.many2many('medical.medicament', 'newborn_labor_rel', 'medicament_id', 'patient_id', 'Medicaments and anesthesics'), 'responsible': fields.many2one('medical.physician', 'Doctor in charge', help="Signed by the health professional"), 'dismissed': fields.datetime('Dismissed from hospital'), 'bd': fields.boolean('Born dead'), 'died_at_delivery': fields.boolean('Died at delivery room'), 'died_at_the_hospital': fields.boolean('Died at the hospital'), 'died_being_transferred': fields.boolean( 'Died being transferred', help="The baby died being transferred to another health institution" ), 'tod': fields.datetime('Time of Death'), 'cod': fields.many2one('medical.pathology', 'Cause of death'), 'notes': fields.text('Notes'), } _sql_constraints = [('code_uniq', 'unique (code)', 'The newborn ID must be unique')]
class report_partner_affected_bycase(osv.osv): """View with partner affected by blockade case""" _name = "report.partner.affected.bycase" _auto = False _columns = { 'id': fields.integer('Id', readonly=True), 'prodlot_id': fields.many2one('stock.production.lot', 'Production Lot', readonly=True, select=True), 'product_id': fields.many2one('product.product', 'Product', readonly=True, select=True), 'product_qty': fields.float('Quantity', readonly=True), 'case_id': fields.many2one('block.prodlot.cases', 'Blockade Case', readonly=True, select=True), 'picking_id': fields.many2one('stock.picking', 'Picking', readonly=True, select=True), 'sale_line_id': fields.many2one('sale.order.line', 'Sale Order Line', select=2, readonly=True), 'partner_id': fields.many2one('res.partner', 'Costumer', readonly=True, select=True), 'vat': fields.char('Vat', size=12, readonly=True), 'fax': fields.char('Fax', size=12, readonly=True), 'city': fields.char('City', size=32, readonly=True), 'phone': fields.char('Phone', size=12, readonly=True), 'zip': fields.char('Zip', size=7, readonly=True), 'country_id': fields.many2one('res.country', 'Country', readonly=True, select=2), 'email': fields.char('Email', size=32, readonly=True), 'date': fields.datetime('Date', readonly=True), } def init(self, cr): """creates view when install""" drop_view_if_exists(cr, 'report_partner_affected_bycase') cr.execute(""" create or replace view report_partner_affected_bycase as ( select stock_move.id as id, prodlots.id as prodlot_id, prodlots.case_id, stock_move.picking_id, stock_move.date, stock_move.sale_line_id, res_partner.id as partner_id, res_partner.vat, res_partner.fax, res_partner.city, res_partner.phone, res_partner.zip, res_partner.country_id, res_partner.email, prodlots.product_id as product_id, stock_move.product_qty from stock_move inner join (select distinct stock_production_lot.*, case_id from stock_production_lot inner join blocked_prodlots_cases_ids on id = blocked_prodlot) as prodlots on stock_move.prodlot_id = prodlots.id inner join stock_location on stock_move.location_dest_id = stock_location.id inner join res_partner on res_partner.id = stock_location.partner_id) """) def unlink(self, cr, uid, ids, context={}): """not can delete, beacause is database view""" raise osv.except_osv(_('Error !'), _('You cannot delete any record!'))