class sprint_kanban(osv.Model): def set_done(self, cr, uid, ids, context=None): self.write(cr, uid, ids, {'state': 'done'}, context=context) return True def set_cancel(self, cr, uid, ids, context=None): self.write(cr, uid, ids, {'state': 'cancelled'}, context=context) return True def set_pending(self, cr, uid, ids, context=None): self.write(cr, uid, ids, {'state': 'pending'}, context=context) return True def set_open(self, cr, uid, ids, context=None): self.write(cr, uid, ids, {'state': 'open'}, context=context) return True _name = 'sprint.kanban' _inherit = ['mail.thread', 'ir.needaction_mixin'] _columns = { 'use_phases': fields.boolean('Phases', help="""Check this field if you plan to use phase-based scheduling"""), 'name': fields.char('Name Sprint', 264, required=True), 'project_id': fields.many2one('project.project', 'Project', ondelete="cascade"), 'description': fields.text('Description'), 'datestart': fields.date('Start Date'), 'dateend': fields.date('End Date'), 'color': fields.integer('Color Index'), 'members': fields.many2many('res.users', 'project_user_rel', 'project_id', 'uid', 'Project Members', states={ 'close': [('readonly', True)], 'cancelled': [('readonly', True)], }), 'priority': fields.selection([('4', 'Very Low'), ('3', 'Low'), ('2', 'Medium'), ('1', 'Important'), ('0', 'Very important')], 'Priority', select=True), 'state': fields.selection( [('draft', 'New'), ('open', 'In Progress'), ('cancelled', 'Cancelled'), ('pending', 'Pending'), ('done', 'Done')], 'Status', required=True, ), 'user_id': fields.many2one('res.users', 'Assigned to'), 'kanban_state': fields.selection([('normal', 'Normal'), ('blocked', 'Blocked'), ('done', 'Ready To Pull')], 'Kanban State', help="""A task's kanban state indicate special situations affecting it:\n * Normal is the default situation\n" * Blocked indicates something is preventing the progress of this task\n * Ready To Pull indicates the task is ready to be pulled to the next stage""", readonly=True, required=False), } def set_kanban_state_blocked(self, cr, uid, ids, context=None): self.write(cr, uid, ids, {'kanban_state': 'blocked'}, context=context) return False def set_kanban_state_normal(self, cr, uid, ids, context=None): self.write(cr, uid, ids, {'kanban_state': 'normal'}, context=context) return False def set_kanban_state_done(self, cr, uid, ids, context=None): self.write(cr, uid, ids, {'kanban_state': 'done'}, context=context) return False def set_priority(self, cr, uid, ids, priority, *args): return self.write(cr, uid, ids, {'priority': priority}) def set_high_priority(self, cr, uid, ids, *args): return self.set_priority(cr, uid, ids, '1') def set_normal_priority(self, cr, uid, ids, *args): return self.set_priority(cr, uid, ids, '2') _defaults = { 'state': 'draft', 'priority': '1', }
class event_track(osv.osv): _name = "event.track" _description = 'Event Tracks' _order = 'priority, date' _inherit = ['mail.thread', 'ir.needaction_mixin', 'website.seo.metadata'] def _website_url(self, cr, uid, ids, field_name, arg, context=None): res = dict.fromkeys(ids, '') for track in self.browse(cr, uid, ids, context=context): res[track.id] = "/event/%s/track/%s" % (slug( track.event_id), slug(track)) return res _columns = { 'name': fields.char('Track Title', required=True, translate=True), 'user_id': fields.many2one('res.users', 'Responsible'), 'speaker_ids': fields.many2many('res.partner', string='Speakers'), 'tag_ids': fields.many2many('event.track.tag', string='Tags'), 'stage_id': fields.many2one('event.track.stage', 'Stage'), 'description': fields.html('Track Description', translate=True), 'date': fields.datetime('Track Date'), 'duration': fields.float('Duration', digits=(16, 2)), 'location_id': fields.many2one('event.track.location', 'Location'), 'event_id': fields.many2one('event.event', 'Event', required=True), 'color': fields.integer('Color Index'), 'priority': fields.selection([('3', 'Low'), ('2', 'Medium (*)'), ('1', 'High (**)'), ('0', 'Highest (***)')], 'Priority', required=True), 'website_published': fields.boolean('Available in the website'), 'website_url': fields.function(_website_url, string="Website url", type="char"), 'image': fields.related('speaker_ids', 'image', type='binary', readonly=True) } def set_priority(self, cr, uid, ids, priority, context={}): return self.write(cr, uid, ids, {'priority': priority}) def _default_stage_id(self, cr, uid, context={}): stage_obj = self.pool.get('event.track.stage') ids = stage_obj.search(cr, uid, [], context=context) return ids and ids[0] or False _defaults = { 'user_id': lambda self, cr, uid, ctx: uid, 'website_published': lambda self, cr, uid, ctx: False, 'duration': lambda *args: 1.5, 'stage_id': _default_stage_id, 'priority': '2' } def _read_group_stage_ids(self, cr, uid, ids, domain, read_group_order=None, access_rights_uid=None, context=None): stage_obj = self.pool.get('event.track.stage') result = stage_obj.name_search(cr, uid, '', context=context) return result, {} _group_by_full = { 'stage_id': _read_group_stage_ids, }
class django_panel_settings(osv.osv_memory): _name = 'django.panel.settings' _inherit = 'res.config.settings' def set_default_aws_access_id(self,cr,uid,ids,context=None): params = self.pool.get('ir.config_parameter') myself = self.browse(cr,uid,ids[0],context=context) params.set_param(cr, uid, 'aws_access_id', (myself.aws_access_id or '').strip(), groups=['base.group_system'], context=None) def get_default_aws_access_id(self,cr,uid,ids,context=None): params = self.pool.get('ir.config_parameter') aws_access_id = params.get_param(cr, uid, 'aws_access_id',default='',context=context) return dict(aws_access_id=aws_access_id) def set_default_website_url(self,cr,uid,ids,context=None): params = self.pool.get('ir.config_parameter') myself = self.browse(cr,uid,ids[0],context=context) params.set_param(cr, uid, 'website_url', (myself.website_url or '').strip(), groups=['base.group_system'], context=None) def get_default_website_url(self,cr,uid,ids,context=None): params = self.pool.get('ir.config_parameter') website_url = params.get_param(cr, uid, 'website_url',default='',context=context) return dict(website_url=website_url) def set_default_website_username(self,cr,uid,ids,context=None): params = self.pool.get('ir.config_parameter') myself = self.browse(cr,uid,ids[0],context=context) params.set_param(cr, uid, 'website_username', (myself.website_username or '').strip(), groups=['base.group_system'], context=None) def get_default_website_username(self,cr,uid,ids,context=None): params = self.pool.get('ir.config_parameter') website_username = params.get_param(cr, uid, 'website_username',default='',context=context) return dict(website_username=website_username) def set_default_website_pwd(self,cr,uid,ids,context=None): params = self.pool.get('ir.config_parameter') myself = self.browse(cr,uid,ids[0],context=context) params.set_param(cr, uid, 'website_pwd', (myself.website_pwd or '').strip(), groups=['base.group_system'], context=None) def get_default_website_pwd(self,cr,uid,ids,context=None): params = self.pool.get('ir.config_parameter') website_pwd = params.get_param(cr, uid, 'website_pwd',default='',context=context) return dict(website_pwd=website_pwd) def set_default_aws_secret_key(self,cr,uid,ids,context=None): params = self.pool.get('ir.config_parameter') myself = self.browse(cr,uid,ids[0],context=context) params.set_param(cr, uid, 'aws_secret_key', (myself.aws_secret_key or '').strip(), groups=['base.group_system'], context=None) def get_default_aws_secret_key(self,cr,uid,ids,context=None): params = self.pool.get('ir.config_parameter') aws_secret_key = params.get_param(cr, uid, 'aws_secret_key',default='',context=context) return dict(aws_secret_key=aws_secret_key) # def set_default_website_banner_key(self,cr,uid,ids,context=None): # params = self.pool.get('ir.config_parameter') # myself = self.browse(cr,uid,ids[0],context=context) # params.set_param(cr, uid, 'website_banner_key', (myself.website_banner_key or '').strip(), groups=['base.group_system'], context=None) # # def get_default_website_banner_key(self,cr,uid,ids,context=None): # params = self.pool.get('ir.config_parameter') # website_banner_key = params.get_param(cr, uid, 'website_banner_key',default='',context=context) # return dict(website_banner_key=website_banner_key) def set_default_root_bucket(self,cr,uid,ids,context=None): params = self.pool.get('ir.config_parameter') myself = self.browse(cr,uid,ids[0],context=context) params.set_param(cr, uid, 'root_bucket', (myself.root_bucket or '').strip(), groups=['base.group_system'], context=None) def get_default_root_bucket(self,cr,uid,ids,context=None): params = self.pool.get('ir.config_parameter') root_bucket = params.get_param(cr, uid, 'root_bucket',default='',context=context) return dict(root_bucket=root_bucket) def set_default_aws_base_url(self,cr,uid,ids,context=None): params = self.pool.get('ir.config_parameter') myself = self.browse(cr,uid,ids[0],context=context) params.set_param(cr, uid, 'aws_base_url', (myself.aws_base_url or '').strip(), groups=['base.group_system'], context=None) def get_default_aws_base_url(self,cr,uid,ids,context=None): params = self.pool.get('ir.config_parameter') aws_base_url = params.get_param(cr, uid, 'aws_base_url',default='',context=context) return dict(aws_base_url=aws_base_url) # def set_default_website_policy_key(self,cr,uid,ids,context=None): # params = self.pool.get('ir.config_parameter') # myself = self.browse(cr,uid,ids[0],context=context) # params.set_param(cr, uid, 'website_policy_key', (myself.website_policy_key or '').strip(), groups=['base.group_system'], context=None) # # def get_default_website_policy_key(self,cr,uid,ids,context=None): # params = self.pool.get('ir.config_parameter') # website_policy_key = params.get_param(cr, uid, 'website_policy_key',default='',context=context) # return dict(website_policy_key=website_policy_key) def set_default_meta_keywords(self,cr,uid,ids,context=None): params = self.pool.get('ir.config_parameter') myself = self.browse(cr,uid,ids[0],context=context) params.set_param(cr, uid, 'meta_keywords', (myself.meta_keywords or '').strip(), groups=['base.group_system'], context=None) def get_default_meta_keywords(self,cr,uid,ids,context=None): params = self.pool.get('ir.config_parameter') meta_keywords = params.get_param(cr, uid, 'meta_keywords',default='',context=context) return dict(meta_keywords=meta_keywords) def set_default_meta_description(self,cr,uid,ids,context=None): params = self.pool.get('ir.config_parameter') myself = self.browse(cr,uid,ids[0],context=context) params.set_param(cr, uid, 'meta_description', (myself.meta_description or '').strip(), groups=['base.group_system'], context=None) def get_default_meta_description(self,cr,uid,ids,context=None): params = self.pool.get('ir.config_parameter') meta_description = params.get_param(cr, uid, 'meta_description',default='',context=context) return dict(meta_description=meta_description) def set_default_site_name(self,cr,uid,ids,context=None): params = self.pool.get('ir.config_parameter') myself = self.browse(cr,uid,ids[0],context=context) params.set_param(cr, uid, 'site_name', (myself.site_name or '').strip(), groups=['base.group_system'], context=None) def get_default_site_name(self,cr,uid,ids,context=None): params = self.pool.get('ir.config_parameter') site_name = params.get_param(cr, uid, 'site_name',default='',context=context) return dict(site_name=site_name) def set_default_attribute_value_ids(self,cr,uid,ids,context=None): myself = self.browse(cr,uid,ids[0],context=context) params = self.pool.get('ir.config_parameter') attribute_value_ids = map(lambda x:x.id,myself.attribute_value_ids) params.set_param(cr, uid, 'attribute_value_ids', (attribute_value_ids), groups=['base.group_system'], context=None) def get_default_attribute_value_ids(self,cr,uid,ids,context=None): params = self.pool.get('ir.config_parameter') try: attribute_value_ids = params.get_param(cr, uid, 'attribute_value_ids',default='[]',context=context) return dict(attribute_value_ids=[(6,0,eval(attribute_value_ids))]) except Exception as e: raise osv.except_osv('Error','Please check the value of Volumes not available for Retailers. It is invalid!') def set_default_mailing_list_id(self,cr,uid,ids,context=None): myself = self.browse(cr,uid,ids[0],context=context) params = self.pool.get('ir.config_parameter') params.set_param(cr, uid, 'mailing_list_id', (myself.mailing_list_id.id), groups=['base.group_system'], context=None) def get_default_mailing_list_id(self,cr,uid,ids,context=None): params = self.pool.get('ir.config_parameter') mailing_list_id = params.get_param(cr, uid, 'mailing_list_id',default=[],context=context) try: return dict(mailing_list_id=eval(mailing_list_id)) except Exception as e: return [] def _get_domain_volume(self,context=None): # We have access to self.env in this context. ids = self.env.ref('jjuice.attribute_vol').id return [('attribute_id','=', ids)] def set_default_attributes_available_ids(self,cr,uid,ids,context=None): myself = self.browse(cr,uid,ids[0],context=context) params = self.pool.get('ir.config_parameter') attributes_available_ids = map(lambda x:x.id,myself.attributes_available_ids) params.set_param(cr, uid, 'attributes_available_ids', (attributes_available_ids), groups=['base.group_system'], context=None) def get_default_attributes_available_ids(self,cr,uid,ids,context=None): params = self.pool.get('ir.config_parameter') try: attributes_available_ids = params.get_param(cr, uid, 'attributes_available_ids',default='[]',context=context) return dict(attributes_available_ids=[(6,0,eval(attributes_available_ids))]) except Exception as e: raise osv.except_osv('Error','Please check the value of Volumes available for website display . It is invalid!') def set_default_aboutus_banner(self,cr,uid,ids,context=None): myself = self.browse(cr,uid,ids[0],context=context) s3_object = self.pool.get('s3.object') existing_banner_ids = s3_object.search(cr,uid,[('aboutus_banner','=',True),('id','!=',myself.aboutus_banner.id)]) if existing_banner_ids: for i in existing_banner_ids: s3_object.unlink(cr,uid,i) s3_object.write(cr,uid,myself.aboutus_banner.id,{'aboutus_banner':True}) def get_default_aboutus_banner(self,cr,uid,ids,context=None): s3_object_ids = self.pool.get('s3.object').search(cr,uid,[('aboutus_banner','=',True)],limit=1) if s3_object_ids: return dict(aboutus_banner=s3_object_ids[0]) else: return dict(aboutus_banner=False) def set_default_checkout_banner(self,cr,uid,ids,context=None): myself = self.browse(cr,uid,ids[0],context=context) s3_object = self.pool.get('s3.object') existing_banner_ids = s3_object.search(cr,uid,[('checkout_banner','=',True),('id','!=',myself.checkout_banner.id)]) if existing_banner_ids: for i in existing_banner_ids: s3_object.unlink(cr,uid,i) s3_object.write(cr,uid,myself.checkout_banner.id,{'checkout_banner':True}) def get_default_checkout_banner(self,cr,uid,ids,context=None): s3_object_ids = self.pool.get('s3.object').search(cr,uid,[('checkout_banner','=',True)],limit=1) if s3_object_ids: return dict(checkout_banner=s3_object_ids[0]) else: return dict(checkout_banner=False) def set_default_contactus_banner(self,cr,uid,ids,context=None): myself = self.browse(cr,uid,ids[0],context=context) s3_object = self.pool.get('s3.object') existing_banner_ids = s3_object.search(cr,uid,[('contactus_banner','=',True),('id','!=',myself.contactus_banner.id)]) if existing_banner_ids: for i in existing_banner_ids: s3_object.unlink(cr,uid,i) s3_object.write(cr,uid,myself.contactus_banner.id,{'contactus_banner':True}) def get_default_contactus_banner(self,cr,uid,ids,context=None): s3_object_ids = self.pool.get('s3.object').search(cr,uid,[('contactus_banner','=',True)],limit=1) if s3_object_ids: return dict(contactus_banner=s3_object_ids[0]) else: return dict(contactus_banner=False) def set_default_customerreview_banner(self,cr,uid,ids,context=None): myself = self.browse(cr,uid,ids[0],context=context) s3_object = self.pool.get('s3.object') existing_banner_ids = s3_object.search(cr,uid,[('customerreview_banner','=',True),('id','!=',myself.customerreview_banner.id)]) if existing_banner_ids: for i in existing_banner_ids: s3_object.unlink(cr,uid,i) s3_object.write(cr,uid,myself.customerreview_banner.id,{'customerreview_banner':True}) def get_default_customerreview_banner(self,cr,uid,ids,context=None): s3_object_ids = self.pool.get('s3.object').search(cr,uid,[('customerreview_banner','=',True)],limit=1) if s3_object_ids: return dict(customerreview_banner=s3_object_ids[0]) else: return dict(customerreview_banner=False) def set_default_promo_business_ids(self,cr,uid,ids,context=None): myself = self.browse(cr,uid,ids[0],context=context) params = self.pool.get('ir.config_parameter') promo_business_ids = map(lambda x:x.id,myself.promo_business_ids) params.set_param(cr, uid, 'promo_business_ids', (promo_business_ids), groups=['base.group_system'], context=None) def get_default_promo_business_ids(self,cr,uid,ids,context=None): params = self.pool.get('ir.config_parameter') try: promo_business_ids = params.get_param(cr, uid, 'promo_business_ids',default='[]',context=context) return dict(promo_business_ids=[(6,0,eval(promo_business_ids))]) except Exception as e: raise osv.except_osv('Error','Please check the value of business promotions. It is invalid!') def set_default_promo_non_business_ids(self,cr,uid,ids,context=None): myself = self.browse(cr,uid,ids[0],context=context) params = self.pool.get('ir.config_parameter') promo_non_business_ids = map(lambda x:x.id,myself.promo_non_business_ids) params.set_param(cr, uid, 'promo_non_business_ids', (promo_non_business_ids), groups=['base.group_system'], context=None) def get_default_promo_non_business_ids(self,cr,uid,ids,context=None): params = self.pool.get('ir.config_parameter') try: promo_non_business_ids = params.get_param(cr, uid, 'promo_non_business_ids',default='[]',context=context) return dict(promo_non_business_ids=[(6,0,eval(promo_non_business_ids))]) except Exception as e: raise osv.except_osv('Error','Please check the value of Volumes not available for Retailers. It is invalid!') def set_default_privacy_policy_banner(self,cr,uid,ids,context=None): myself = self.browse(cr,uid,ids[0],context=context) s3_object = self.pool.get('s3.object') existing_banner_ids = s3_object.search(cr,uid,[('privacy_policy_banner','=',True),('id','!=',myself.privacy_policy_banner.id)]) if existing_banner_ids: for i in existing_banner_ids: s3_object.unlink(cr,uid,i) s3_object.write(cr,uid,myself.privacy_policy_banner.id,{'privacy_policy_banner':True}) def get_default_privacy_policy_banner(self,cr,uid,ids,context=None): s3_object_ids = self.pool.get('s3.object').search(cr,uid,[('privacy_policy_banner','=',True)],limit=1) if s3_object_ids: return dict(privacy_policy_banner=s3_object_ids[0]) else: return dict(privacy_policy_banner=False) def set_default_terms_conditions_banner(self,cr,uid,ids,context=None): myself = self.browse(cr,uid,ids[0],context=context) s3_object = self.pool.get('s3.object') existing_banner_ids = s3_object.search(cr,uid,[('terms_conditions_banner','=',True),('id','!=',myself.terms_conditions_banner.id)]) if existing_banner_ids: for i in existing_banner_ids: s3_object.unlink(cr,uid,i) s3_object.write(cr,uid,myself.terms_conditions_banner.id,{'terms_conditions_banner':True}) def get_default_terms_conditions_banner(self,cr,uid,ids,context=None): s3_object_ids = self.pool.get('s3.object').search(cr,uid,[('terms_conditions_banner','=',True)],limit=1) if s3_object_ids: return dict(terms_conditions_banner=s3_object_ids[0]) else: return dict(terms_conditions_banner=False) def set_default_search_banner(self,cr,uid,ids,context=None): myself = self.browse(cr,uid,ids[0],context=context) s3_object = self.pool.get('s3.object') existing_banner_ids = s3_object.search(cr,uid,[('search_banner','=',True),('id','!=',myself.search_banner.id)]) if existing_banner_ids: for i in existing_banner_ids: s3_object.unlink(cr,uid,i) s3_object.write(cr,uid,myself.search_banner.id,{'search_banner':True}) def get_default_search_banner(self,cr,uid,ids,context=None): s3_object_ids = self.pool.get('s3.object').search(cr,uid,[('search_banner','=',True)],limit=1) if s3_object_ids: return dict(search_banner=s3_object_ids[0]) else: return dict(search_banner=False) def set_default_shipping_returns_policy_banner(self,cr,uid,ids,context=None): myself = self.browse(cr,uid,ids[0],context=context) s3_object = self.pool.get('s3.object') existing_banner_ids = s3_object.search(cr,uid,[('shipping_returns_policy_banner','=',True),('id','!=',myself.shipping_returns_policy_banner.id)]) if existing_banner_ids: for i in existing_banner_ids: s3_object.unlink(cr,uid,i) s3_object.write(cr,uid,myself.shipping_returns_policy_banner.id,{'shipping_returns_policy_banner':True}) def get_default_shipping_returns_policy_banner(self,cr,uid,ids,context=None): s3_object_ids = self.pool.get('s3.object').search(cr,uid,[('shipping_returns_policy_banner','=',True)],limit=1) if s3_object_ids: return dict(shipping_returns_policy_banner=s3_object_ids[0]) else: return dict(shipping_returns_policy_banner=False) def set_default_contactus_banner_500340(self, cr, uid, ids, context=None): myself = self.browse(cr, uid, ids[0], context=context) s3_object = self.pool.get('s3.object') existing_banner_ids = s3_object.search(cr, uid, [("contactus_banner_500340", '=', True), ('id', '!=', myself.contactus_banner_500340.id)]) if existing_banner_ids: for i in existing_banner_ids: s3_object.unlink(cr, uid, i) s3_object.write(cr, uid, myself.contactus_banner_500340.id, {'contactus_banner_500340': True}) def get_default_contactus_banner_500340(self, cr, uid, ids, context=None): s3_object_ids = self.pool.get('s3.object').search(cr, uid, [('contactus_banner_500340', '=', True)], limit=1) if s3_object_ids: return dict(contactus_banner_500340=s3_object_ids[0]) else: return dict(contactus_banner_500340=False) def get_default_company_logo(self,cr,uid,ids,context=None): s3_object_ids = self.pool.get('s3.object').search(cr,uid,[('company_logo','=',True)],limit=1) if s3_object_ids: return dict(company_logo=s3_object_ids[0]) else: return dict(company_logo=False) def set_default_company_logo(self,cr,uid,ids,context=None): myself = self.browse(cr,uid,ids[0],context=context) s3_object = self.pool.get('s3.object') existing_banner_ids = s3_object.search(cr,uid,[('company_logo','=',True),('id','!=',myself.company_logo.id)]) if existing_banner_ids: for i in existing_banner_ids: s3_object.unlink(cr,uid,i) s3_object.write(cr,uid,myself.checkout_banner.id,{'company_logo':True}) _columns = { 'site_name':fields.char("Site Name"), 'aws_access_id' : fields.char("AWS Access ID"), 'aws_secret_key' : fields.char('AWS Secret Key'), 'root_bucket':fields.char("Root Bucket"), # 'website_banner_key' : fields.char("Website Banner Bucket Key"), # 'website_policy_key' : fields.char("Website Policy Bucket Key"), # 'volume_key':fields.char("Volumes Bucket Key"), 'aws_base_url':fields.char("S3 Base URL",help="This is required so that when determining the url we do not have to send extra request to determine the location of the bucket"), 'meta_keywords':fields.text("Meta Keywords"), 'meta_description':fields.text('Meta Description'), 'attribute_value_ids':fields.many2many('product.attribute.value','django_panel_settings_attribute_value',column1='django_panel_settings_id',column2='attribute_value_id', string = "Volumes available to Normal Website Visitors",domain=_get_domain_volume, ), 'mailing_list_id':fields.many2one('mail.mass_mailing.list','News Letter Mailing List'), 'attributes_available_ids':fields.many2many('product.attribute.value','django_panel_settings_attribute_value_available',column1='django_panel_settings_id',column2='attribute_value_id', string = "Volumes available to Businesses",domain=_get_domain_volume, ), 'shipping_returns_policy_banner':fields.many2one('s3.object',string="Shipping & Returns Policy Banner"), 'aboutus_banner':fields.many2one('s3.object',string="About Us Banner"), 'checkout_banner':fields.many2one('s3.object',string="Checkout Banner"), 'terms_conditions_banner':fields.many2one('s3.object',string="Terms & Conditions Banner"), 'privacy_policy_banner':fields.many2one('s3.object',string="Privacy Policy Banner"), 'search_banner':fields.many2one('s3.object',string = "Search Banner"), 'contactus_banner':fields.many2one('s3.object',string="Contact Us Banner"), 'company_logo':fields.many2one('s3.object',string="Company Logo"), 'contactus_banner_500340': fields.many2one('s3.object', string="Contact Us Banner (500x340)"), 'customerreview_banner':fields.many2one('s3.object',string="Customer Review Banner"), 'promo_business_ids':fields.many2many('website.policy','django_panel_settings_website_policy',column1='django_panel_settings_id',column2='policy_id', string = "Business Promotions"), 'promo_non_business_ids':fields.many2many('website.policy','django_panel_settings_non_business_website_policy',column1='django_panel_settings_id',column2='policy_id', string = "Non Business Promotions"), 'website_url':fields.char('Website URL'), 'website_username':fields.char('Website Username'), 'website_pwd': fields.char('Website Password'), }
class project_issue(osv.Model): _name = "project.issue" _description = "Project Issue" _order = "priority desc, create_date desc" _inherit = ['mail.thread', 'ir.needaction_mixin'] _mail_post_access = 'read' def _get_default_partner(self, cr, uid, context=None): if context is None: context = {} if 'default_project_id' in context: project = self.pool.get('project.project').browse( cr, uid, context['default_project_id'], context=context) if project and project.partner_id: return project.partner_id.id return False def _get_default_stage_id(self, cr, uid, context=None): """ Gives default stage_id """ if context is None: context = {} return self.stage_find(cr, uid, [], context.get('default_project_id'), [('fold', '=', False)], context=context) def _read_group_stage_ids(self, cr, uid, ids, domain, read_group_order=None, access_rights_uid=None, context=None): if context is None: context = {} access_rights_uid = access_rights_uid or uid stage_obj = self.pool.get('project.task.type') order = stage_obj._order # lame hack to allow reverting search, should just work in the trivial case if read_group_order == 'stage_id desc': order = "%s desc" % order # retrieve team_id from the context, add them to already fetched columns (ids) if 'default_project_id' in context: search_domain = [ '|', ('project_ids', '=', context['default_project_id']), ('id', 'in', ids) ] else: search_domain = [('id', 'in', ids)] # perform search stage_ids = stage_obj._search(cr, uid, search_domain, order=order, access_rights_uid=access_rights_uid, context=context) result = stage_obj.name_get(cr, access_rights_uid, stage_ids, context=context) # restore order of the search result.sort( lambda x, y: cmp(stage_ids.index(x[0]), stage_ids.index(y[0]))) fold = {} for stage in stage_obj.browse(cr, access_rights_uid, stage_ids, context=context): fold[stage.id] = stage.fold or False return result, fold def _compute_day(self, cr, uid, ids, fields, args, context=None): """ @param cr: the current row, from the database cursor, @param uid: the current user’s ID for security checks, @param ids: List of Openday’s IDs @return: difference between current date and log date @param context: A standard dictionary for contextual values """ Calendar = self.pool['resource.calendar'] res = dict((res_id, {}) for res_id in ids) for issue in self.browse(cr, uid, ids, context=context): values = { 'day_open': 0.0, 'day_close': 0.0, 'working_hours_open': 0.0, 'working_hours_close': 0.0, 'days_since_creation': 0.0, 'inactivity_days': 0.0, } # if the working hours on the project are not defined, use default ones (8 -> 12 and 13 -> 17 * 5), represented by None calendar_id = None if issue.project_id and issue.project_id.resource_calendar_id: calendar_id = issue.project_id.resource_calendar_id.id dt_create_date = datetime.strptime(issue.create_date, DEFAULT_SERVER_DATETIME_FORMAT) if issue.date_open: dt_date_open = datetime.strptime( issue.date_open, DEFAULT_SERVER_DATETIME_FORMAT) values['day_open'] = (dt_date_open - dt_create_date ).total_seconds() / (24.0 * 3600) values['working_hours_open'] = Calendar._interval_hours_get( cr, uid, calendar_id, dt_create_date, dt_date_open, timezone_from_uid=issue.user_id.id or uid, exclude_leaves=False, context=context) if issue.date_closed: dt_date_closed = datetime.strptime( issue.date_closed, DEFAULT_SERVER_DATETIME_FORMAT) values['day_close'] = (dt_date_closed - dt_create_date ).total_seconds() / (24.0 * 3600) values['working_hours_close'] = Calendar._interval_hours_get( cr, uid, calendar_id, dt_create_date, dt_date_closed, timezone_from_uid=issue.user_id.id or uid, exclude_leaves=False, context=context) days_since_creation = datetime.today() - dt_create_date values['days_since_creation'] = days_since_creation.days if issue.date_action_last: inactive_days = datetime.today() - datetime.strptime( issue.date_action_last, DEFAULT_SERVER_DATETIME_FORMAT) elif issue.date_last_stage_update: inactive_days = datetime.today() - datetime.strptime( issue.date_last_stage_update, DEFAULT_SERVER_DATETIME_FORMAT) else: inactive_days = datetime.today() - datetime.strptime( issue.create_date, DEFAULT_SERVER_DATETIME_FORMAT) values['inactivity_days'] = inactive_days.days # filter only required values for field in fields: res[issue.id][field] = values[field] return res def on_change_project(self, cr, uid, ids, project_id, context=None): if project_id: project = self.pool.get('project.project').browse(cr, uid, project_id, context=context) if project and project.partner_id: return {'value': {'partner_id': project.partner_id.id}} return {} _columns = { 'id': fields.integer('ID', readonly=True), 'name': fields.char('Issue', required=True), 'active': fields.boolean('Active', required=False), 'create_date': fields.datetime('Creation Date', readonly=True, select=True), 'write_date': fields.datetime('Update Date', readonly=True), 'days_since_creation': fields.function(_compute_day, string='Days since creation date', \ multi='compute_day', type="integer", help="Difference in days between creation date and current date", groups='base.group_user'), 'date_deadline': fields.date('Deadline'), 'team_id': fields.many2one('crm.team', 'Sales Team', oldname='section_id',\ select=True, help='Sales team to which Case belongs to.\ Define Responsible user and Email account for mail gateway.' ), 'partner_id': fields.many2one('res.partner', 'Contact', select=1), 'company_id': fields.many2one('res.company', 'Company'), 'description': fields.text('Private Note'), 'kanban_state': fields.selection([('normal', 'Normal'),('blocked', 'Blocked'),('done', 'Ready for next stage')], 'Kanban State', track_visibility='onchange', help="A Issue's kanban state indicates special situations affecting it:\n" " * Normal is the default situation\n" " * Blocked indicates something is preventing the progress of this issue\n" " * Ready for next stage indicates the issue is ready to be pulled to the next stage", required=True), 'email_from': fields.char('Email', size=128, help="These people will receive email.", select=1), 'email_cc': fields.char('Watchers Emails', size=256, help="These email addresses will be added to the CC field of all inbound and outbound emails for this record before being sent. Separate multiple email addresses with a comma"), 'date_open': fields.datetime('Assigned', readonly=True, select=True), # Project Issue fields 'date_closed': fields.datetime('Closed', readonly=True, select=True), 'date': fields.datetime('Date'), 'date_last_stage_update': fields.datetime('Last Stage Update', select=True), 'channel': fields.char('Channel', help="Communication channel."), 'tag_ids': fields.many2many('project.tags', string='Tags'), 'priority': fields.selection([('0','Low'), ('1','Normal'), ('2','High')], 'Priority', select=True), 'stage_id': fields.many2one ('project.task.type', 'Stage', track_visibility='onchange', select=True, domain="[('project_ids', '=', project_id)]", copy=False), 'project_id': fields.many2one('project.project', 'Project', track_visibility='onchange', select=True), 'duration': fields.float('Duration'), 'task_id': fields.many2one('project.task', 'Task', domain="[('project_id','=',project_id)]", help="You can link this issue to an existing task or directly create a new one from here"), 'day_open': fields.function(_compute_day, string='Days to Assign', multi='compute_day', type="float", store={'project.issue': (lambda self, cr, uid, ids, c={}: ids, ['date_open'], 10)}, groups='base.group_user'), 'day_close': fields.function(_compute_day, string='Days to Close', multi='compute_day', type="float", store={'project.issue': (lambda self, cr, uid, ids, c={}: ids, ['date_closed'], 10)}, groups='base.group_user'), 'user_id': fields.many2one('res.users', 'Assigned to', required=False, select=1, track_visibility='onchange'), 'working_hours_open': fields.function(_compute_day, string='Working Hours to assign the Issue', multi='compute_day', type="float", store={'project.issue': (lambda self, cr, uid, ids, c={}: ids, ['date_open'], 10)}, groups='base.group_user'), 'working_hours_close': fields.function(_compute_day, string='Working Hours to close the Issue', multi='compute_day', type="float", store={'project.issue': (lambda self, cr, uid, ids, c={}: ids, ['date_closed'], 10)}, groups='base.group_user'), 'inactivity_days': fields.function(_compute_day, string='Days since last action', multi='compute_day', type="integer", help="Difference in days between last action and current date", groups='base.group_user'), 'color': fields.integer('Color Index'), 'user_email': fields.related('user_id', 'email', type='char', string='User Email', readonly=True), 'date_action_last': fields.datetime('Last Action', readonly=1), 'date_action_next': fields.datetime('Next Action', readonly=1), 'legend_blocked': fields.related("stage_id", "legend_blocked", type="char", string='Kanban Blocked Explanation'), 'legend_done': fields.related("stage_id", "legend_done", type="char", string='Kanban Valid Explanation'), 'legend_normal': fields.related("stage_id", "legend_normal", type="char", string='Kanban Ongoing Explanation'), } _defaults = { 'active': 1, 'team_id': lambda s, cr, uid, c: s.pool['crm.team']._get_default_team_id( cr, uid, context=c), 'stage_id': lambda s, cr, uid, c: s._get_default_stage_id(cr, uid, c), 'company_id': lambda s, cr, uid, c: s.pool['res.users']._get_company( cr, uid, context=c), 'priority': '0', 'kanban_state': 'normal', 'date_last_stage_update': fields.datetime.now, 'user_id': lambda obj, cr, uid, context: uid, } _group_by_full = {'stage_id': _read_group_stage_ids} def copy(self, cr, uid, id, default=None, context=None): issue = self.read(cr, uid, [id], ['name'], context=context)[0] if not default: default = {} default = default.copy() default.update(name=_('%s (copy)') % (issue['name'])) return super(project_issue, self).copy(cr, uid, id, default=default, context=context) def create(self, cr, uid, vals, context=None): context = dict(context or {}) if vals.get('project_id') and not context.get('default_project_id'): context['default_project_id'] = vals.get('project_id') if vals.get('user_id') and not vals.get('date_open'): vals['date_open'] = fields.datetime.now() if 'stage_id' in vals: vals.update( self.onchange_stage_id(cr, uid, None, vals.get('stage_id'), context=context)['value']) # context: no_log, because subtype already handle this create_context = dict(context, mail_create_nolog=True) return super(project_issue, self).create(cr, uid, vals, context=create_context) def write(self, cr, uid, ids, vals, context=None): # stage change: update date_last_stage_update if 'stage_id' in vals: vals.update( self.onchange_stage_id(cr, uid, ids, vals.get('stage_id'), context=context)['value']) vals['date_last_stage_update'] = fields.datetime.now() if 'kanban_state' not in vals: vals['kanban_state'] = 'normal' # user_id change: update date_open if vals.get('user_id') and 'date_open' not in vals: vals['date_open'] = fields.datetime.now() return super(project_issue, self).write(cr, uid, ids, vals, context) def onchange_task_id(self, cr, uid, ids, task_id, context=None): if not task_id: return {'value': {}} task = self.pool.get('project.task').browse(cr, uid, task_id, context=context) return { 'value': { 'user_id': task.user_id.id, } } def onchange_partner_id(self, cr, uid, ids, partner_id, context=None): """ This function returns value of partner email address based on partner :param part: Partner's id """ if partner_id: partner = self.pool['res.partner'].browse(cr, uid, partner_id, context) return {'value': {'email_from': partner.email}} return {'value': {'email_from': False}} def get_empty_list_help(self, cr, uid, help, context=None): context = dict(context or {}) context['empty_list_help_model'] = 'project.project' context['empty_list_help_id'] = context.get('default_project_id') context['empty_list_help_document_name'] = _("issues") return super(project_issue, self).get_empty_list_help(cr, uid, help, context=context) # ------------------------------------------------------- # Stage management # ------------------------------------------------------- def onchange_stage_id(self, cr, uid, ids, stage_id, context=None): if not stage_id: return {'value': {}} stage = self.pool['project.task.type'].browse(cr, uid, stage_id, context=context) if stage.fold: return {'value': {'date_closed': fields.datetime.now()}} return {'value': {'date_closed': False}} def stage_find(self, cr, uid, cases, team_id, domain=[], order='sequence', context=None): """ Override of the base.stage method Parameter of the stage search taken from the issue: - type: stage type must be the same or 'both' - team_id: if set, stages must belong to this team or be a default case """ if isinstance(cases, (int, long)): cases = self.browse(cr, uid, cases, context=context) # collect all team_ids team_ids = [] if team_id: team_ids.append(team_id) for task in cases: if task.project_id: team_ids.append(task.project_id.id) # OR all team_ids and OR with case_default search_domain = [] if team_ids: search_domain += [('|')] * (len(team_ids) - 1) for team_id in team_ids: search_domain.append(('project_ids', '=', team_id)) search_domain += list(domain) # perform search, return the first found stage_ids = self.pool.get('project.task.type').search(cr, uid, search_domain, order=order, context=context) if stage_ids: return stage_ids[0] return False # ------------------------------------------------------- # Mail gateway # ------------------------------------------------------- def _track_subtype(self, cr, uid, ids, init_values, context=None): record = self.browse(cr, uid, ids[0], context=context) if 'kanban_state' in init_values and record.kanban_state == 'blocked': return 'project_issue.mt_issue_blocked' elif 'kanban_state' in init_values and record.kanban_state == 'done': return 'project_issue.mt_issue_ready' elif 'user_id' in init_values and record.user_id: # assigned -> new return 'project_issue.mt_issue_new' elif 'stage_id' in init_values and record.stage_id and record.stage_id.sequence <= 1: # start stage -> new return 'project_issue.mt_issue_new' elif 'stage_id' in init_values: return 'project_issue.mt_issue_stage' return super(project_issue, self)._track_subtype(cr, uid, ids, init_values, context=context) def _notification_group_recipients(self, cr, uid, ids, message, recipients, done_ids, group_data, context=None): """ Override the mail.thread method to handle project users and officers recipients. Indeed those will have specific action in their notification emails: creating tasks, assigning it. """ group_project_user = self.pool['ir.model.data'].xmlid_to_res_id( cr, uid, 'project.group_project_user') group_user = self.pool['ir.model.data'].xmlid_to_res_id( cr, uid, 'base.group_user') for recipient in recipients: if recipient.id in done_ids: continue if recipient.user_ids and group_project_user in recipient.user_ids[ 0].groups_id.ids: group_data['group_project_user'] |= recipient elif not recipient.user_ids: group_data['partner'] |= recipient else: group_data['user'] |= recipient done_ids.add(recipient.id) return super(project_issue, self)._notification_group_recipients(cr, uid, ids, message, recipients, done_ids, group_data, context=context) def _notification_get_recipient_groups(self, cr, uid, ids, message, recipients, context=None): res = super(project_issue, self)._notification_get_recipient_groups(cr, uid, ids, message, recipients, context=context) new_action_id = self.pool['ir.model.data'].xmlid_to_res_id( cr, uid, 'project_issue.project_issue_categ_act0') take_action = self._notification_link_helper(cr, uid, ids, 'assign', context=context) new_action = self._notification_link_helper(cr, uid, ids, 'new', context=context, action_id=new_action_id) task_record = self.browse(cr, uid, ids[0], context=context) actions = [] if not task_record.user_id: actions.append({'url': take_action, 'title': _('I take it')}) else: actions.append({'url': new_action, 'title': _('New Issue')}) res['group_project_user'] = {'actions': actions} return res @api.cr_uid_context def message_get_reply_to(self, cr, uid, ids, default=None, context=None): """ Override to get the reply_to of the parent project. """ issues = self.browse(cr, SUPERUSER_ID, ids, context=context) project_ids = set( [issue.project_id.id for issue in issues if issue.project_id]) aliases = self.pool['project.project'].message_get_reply_to( cr, uid, list(project_ids), default=default, context=context) return dict( (issue.id, aliases.get(issue.project_id and issue.project_id.id or 0, False)) for issue in issues) def message_get_suggested_recipients(self, cr, uid, ids, context=None): recipients = super(project_issue, self).message_get_suggested_recipients( cr, uid, ids, context=context) try: for issue in self.browse(cr, uid, ids, context=context): if issue.partner_id: issue._message_add_suggested_recipient( recipients, partner=issue.partner_id, reason=_('Customer')) elif issue.email_from: issue._message_add_suggested_recipient( recipients, email=issue.email_from, reason=_('Customer Email')) except AccessError: # no read access rights -> just ignore suggested recipients because this imply modifying followers pass return recipients def email_split(self, cr, uid, ids, msg, context=None): email_list = tools.email_split((msg.get('to') or '') + ',' + (msg.get('cc') or '')) # check left-part is not already an alias issue_ids = self.browse(cr, uid, ids, context=context) aliases = [ issue.project_id.alias_name for issue in issue_ids if issue.project_id ] return filter(lambda x: x.split('@')[0] not in aliases, email_list) def message_new(self, cr, uid, msg, custom_values=None, context=None): """ Overrides mail_thread message_new that is called by the mailgateway through message_process. This override updates the document according to the email. """ if custom_values is None: custom_values = {} context = dict(context or {}, state_to='draft') defaults = { 'name': msg.get('subject') or _("No Subject"), 'email_from': msg.get('from'), 'email_cc': msg.get('cc'), 'partner_id': msg.get('author_id', False), 'user_id': False, } defaults.update(custom_values) res_id = super(project_issue, self).message_new(cr, uid, msg, custom_values=defaults, context=context) email_list = self.email_split(cr, uid, [res_id], msg, context=context) partner_ids = filter( None, self._find_partner_from_emails(cr, uid, [res_id], email_list, force_create=False, context=context)) self.message_subscribe(cr, uid, [res_id], partner_ids, context=context) return res_id def message_update(self, cr, uid, ids, msg, update_vals=None, context=None): """ Override to update the issue according to the email. """ email_list = self.email_split(cr, uid, ids, msg, context=context) partner_ids = filter( None, self._find_partner_from_emails(cr, uid, ids, email_list, force_create=False, context=context)) self.message_subscribe(cr, uid, ids, partner_ids, context=context) return super(project_issue, self).message_update(cr, uid, ids, msg, update_vals=update_vals, context=context) @api.cr_uid_ids_context @api.returns('mail.message', lambda value: value.id) def message_post(self, cr, uid, thread_id, subtype=None, context=None, **kwargs): """ Overrides mail_thread message_post so that we can set the date of last action field when a new message is posted on the issue. """ if context is None: context = {} res = super(project_issue, self).message_post(cr, uid, thread_id, subtype=subtype, context=context, **kwargs) if thread_id and subtype: self.write(cr, SUPERUSER_ID, thread_id, {'date_action_last': fields.datetime.now()}, context=context) return res
class pos_most_sold_product_wzd(osv.osv_memory): _name = 'pos.most.sold.product.wzd' _description = 'Most Sold Products' _columns = { 'nbr_product': fields.integer('Nr. Products', help="Number of most sold products"), 'nbr_records': fields.integer('Nr. Records', help="Number of records"), 'date_start': fields.date('Date Start', required=True), 'date_end': fields.date('Date End', required=True), 'partner_ids': fields.many2many('res.partner', 'pos_most_sold_product_partner_rel', 'partner_id', 'wizard_id', 'Customers'), } _defaults = { 'nbr_product': 1, 'nbr_records': 40, 'date_start': lambda *a: time.strftime('%Y-%m-01'), 'date_end': fields.date.context_today, } def execute_query(self, cr, uid, ids, create_parent=False, context=None): obj = self.browse(cr, uid, ids[0]) query = """ select * from ( SELECT *, ROW_NUMBER() OVER () as fila FROM ( SELECT s.partner_id AS partner_id, l.product_id AS product_id, SUM (l.qty * u.factor) AS product_qty, MIN (l.price_unit) AS product_unit_price, SUM (l.qty * l.price_unit) AS price_total, to_char(date_trunc('day',s.date_order),'YYYY-MM-DD')::text as date_order, ROW_NUMBER() OVER (PARTITION BY s.partner_id ORDER BY SUM (l.qty * u.factor) DESC ) row_num, cl.name as client_name FROM pos_order_line AS l LEFT JOIN pos_order s ON (s. ID = l.order_id) LEFT JOIN res_partner cl ON (s.partner_id = cl.ID) LEFT JOIN product_product P ON (P . ID = l.product_id) LEFT JOIN product_template pt ON (pt. ID = P .product_tmpl_id) LEFT JOIN product_uom u ON (u. ID = pt.uom_id) %s GROUP BY s.partner_id, cl.name, l.product_id, to_char(date_trunc('day',s.date_order),'YYYY-MM-DD')::text ORDER BY cl.name, l.product_id, to_char(date_trunc('day',s.date_order),'YYYY-MM-DD')::text DESC, SUM (l.qty * u.factor) DESC ) A WHERE A.row_num <= %s ) B WHERE B.fila <= %s """ partner_ids = [] with_customers = False if obj.partner_ids: with_customers = True for p in obj.partner_ids: if p.id not in partner_ids: partner_ids.append(p.id) whereCondition = ' ' if with_customers: filter_values = (obj.date_start, obj.date_end, tuple(partner_ids)) whereCondition = " where cast(s.date_order as date) BETWEEN '%s' and '%s' and s.partner_id in %s " % filter_values else: filter_values = (obj.date_start, obj.date_end) whereCondition = " where cast(s.date_order as date) BETWEEN '%s' and '%s'" % filter_values str_query = query % (whereCondition, obj.nbr_product, obj.nbr_records) cr.execute(str_query) lines = cr.fetchall() line_ids = self.pool.get('pos.most.sold.product.line').search( cr, uid, []) self.pool.get('pos.most.sold.product.line').unlink(cr, uid, line_ids) rpt_lines = [] for line in lines: if line[0]: vals = { 'partner_id': line[0], 'product_id': line[1], 'product_qty': line[2], 'product_unit_price': line[3], 'price_total': line[4], 'date_order': line[5] } if not create_parent: rpt_lines.append( self.pool.get('pos.most.sold.product.line').create( cr, uid, vals)) else: rpt_lines.append((0, 0, vals)) if create_parent: line_ids = self.pool.get('pos.most.sold.product').search( cr, uid, []) self.pool.get('pos.most.sold.product').unlink(cr, uid, line_ids) dict_parent = { 'nbr_product': obj.nbr_product, 'date_start': obj.date_start, 'date_end': obj.date_end, 'user_id': uid, 'line_ids': rpt_lines } return [ self.pool.get('pos.most.sold.product').create( cr, uid, dict_parent) ] else: return rpt_lines def show_sale_analysis_view(self, cr, uid, ids, context=None): rpt_lines = self.execute_query(cr, uid, ids, False, context) if rpt_lines: mod_obj = self.pool.get('ir.model.data') res = mod_obj.get_object_reference( cr, uid, 'my_point_of_sale', 'view_report_pos_most_sold_product_graph') res_id = res and res[1] or False return { 'name': 'Products Sale Analysis', 'view_type': 'form', 'view_mode': 'graph', 'view_id': [res_id], 'res_model': 'pos.most.sold.product.line', 'type': 'ir.actions.act_window', 'target': 'current', } def print_report_pdf(self, cr, uid, ids, context=None): if context is None: context = {} rpt_lines = self.execute_query(cr, uid, ids, True, context) datas = {'ids': rpt_lines} return { 'type': 'ir.actions.report.xml', 'report_name': 'pos_most_sold_product_report', 'datas': datas, }
class stock_landed_cost(osv.osv): _name = 'stock.landed.cost' _description = 'Stock Landed Cost' _inherit = 'mail.thread' def _total_amount(self, cr, uid, ids, name, args, context=None): result = {} for cost in self.browse(cr, uid, ids, context=context): total = 0.0 for line in cost.cost_lines: total += line.price_unit result[cost.id] = total return result def _get_cost_line(self, cr, uid, ids, context=None): cost_to_recompute = [] for line in self.pool.get('stock.landed.cost.lines').browse( cr, uid, ids, context=context): cost_to_recompute.append(line.cost_id.id) return cost_to_recompute def get_valuation_lines(self, cr, uid, ids, picking_ids=None, context=None): picking_obj = self.pool.get('stock.picking') lines = [] if not picking_ids: return lines for picking in picking_obj.browse(cr, uid, picking_ids): for move in picking.move_lines: #it doesn't make sense to make a landed cost for a product that isn't set as being valuated in real time at real cost if move.product_id.valuation != 'real_time' or move.product_id.cost_method != 'real': continue total_cost = 0.0 total_qty = move.product_qty weight = move.product_id and move.product_id.weight * move.product_qty volume = move.product_id and move.product_id.volume * move.product_qty for quant in move.quant_ids: total_cost += quant.cost vals = dict(product_id=move.product_id.id, move_id=move.id, quantity=move.product_uom_qty, former_cost=total_cost * total_qty, weight=weight, volume=volume) lines.append(vals) if not lines: raise UserError( _('The selected picking does not contain any move that would be impacted by landed costs. Landed costs are only possible for products configured in real time valuation with real price costing method. Please make sure it is the case, or you selected the correct picking' )) return lines _columns = { 'name': fields.char('Name', track_visibility='always', readonly=True, copy=False), 'date': fields.date('Date', required=True, states={'done': [('readonly', True)]}, track_visibility='onchange', copy=False), 'picking_ids': fields.many2many('stock.picking', string='Pickings', states={'done': [('readonly', True)]}, copy=False), 'cost_lines': fields.one2many('stock.landed.cost.lines', 'cost_id', 'Cost Lines', states={'done': [('readonly', True)]}, copy=True), 'valuation_adjustment_lines': fields.one2many('stock.valuation.adjustment.lines', 'cost_id', 'Valuation Adjustments', states={'done': [('readonly', True)]}), 'description': fields.text('Item Description', states={'done': [('readonly', True)]}), 'amount_total': fields.function(_total_amount, type='float', string='Total', digits=0, store={ 'stock.landed.cost': (lambda self, cr, uid, ids, c={}: ids, ['cost_lines'], 20), 'stock.landed.cost.lines': (_get_cost_line, ['price_unit', 'quantity', 'cost_id'], 20), }, track_visibility='always'), 'state': fields.selection([('draft', 'Draft'), ('done', 'Posted'), ('cancel', 'Cancelled')], 'State', readonly=True, track_visibility='onchange', copy=False), 'account_move_id': fields.many2one('account.move', 'Journal Entry', readonly=True, copy=False), 'account_journal_id': fields.many2one('account.journal', 'Account Journal', required=True, states={'done': [('readonly', True)]}), } _defaults = { 'name': lambda obj, cr, uid, context: obj.pool.get('ir.sequence').next_by_code( cr, uid, 'stock.landed.cost'), 'state': 'draft', 'date': fields.date.context_today, } def _create_accounting_entries(self, cr, uid, line, move_id, qty_out, context=None): product_obj = self.pool.get('product.template') cost_product = line.cost_line_id and line.cost_line_id.product_id if not cost_product: return False accounts = product_obj.browse(cr, uid, line.product_id.product_tmpl_id.id, context=context).get_product_accounts() debit_account_id = accounts.get( 'stock_valuation', False) and accounts['stock_valuation'].id or False already_out_account_id = accounts['stock_output'].id credit_account_id = line.cost_line_id.account_id.id or cost_product.property_account_expense_id.id or cost_product.categ_id.property_account_expense_categ_id.id if not credit_account_id: raise UserError( _('Please configure Stock Expense Account for product: %s.') % (cost_product.name)) return self._create_account_move_line(cr, uid, line, move_id, credit_account_id, debit_account_id, qty_out, already_out_account_id, context=context) def _create_account_move_line(self, cr, uid, line, move_id, credit_account_id, debit_account_id, qty_out, already_out_account_id, context=None): """ Generate the account.move.line values to track the landed cost. Afterwards, for the goods that are already out of stock, we should create the out moves """ aml_obj = self.pool.get('account.move.line') if context is None: context = {} ctx = context.copy() ctx['check_move_validity'] = False base_line = { 'name': line.name, 'move_id': move_id, 'product_id': line.product_id.id, 'quantity': line.quantity, } debit_line = dict(base_line, account_id=debit_account_id) credit_line = dict(base_line, account_id=credit_account_id) diff = line.additional_landed_cost if diff > 0: debit_line['debit'] = diff credit_line['credit'] = diff else: # negative cost, reverse the entry debit_line['credit'] = -diff credit_line['debit'] = -diff aml_obj.create(cr, uid, debit_line, context=ctx) aml_obj.create(cr, uid, credit_line, context=ctx) #Create account move lines for quants already out of stock if qty_out > 0: debit_line = dict(debit_line, name=(line.name + ": " + str(qty_out) + _(' already out')), quantity=qty_out, account_id=already_out_account_id) credit_line = dict(credit_line, name=(line.name + ": " + str(qty_out) + _(' already out')), quantity=qty_out, account_id=debit_account_id) diff = diff * qty_out / line.quantity if diff > 0: debit_line['debit'] = diff credit_line['credit'] = diff else: # negative cost, reverse the entry debit_line['credit'] = -diff credit_line['debit'] = -diff aml_obj.create(cr, uid, debit_line, context=ctx) aml_obj.create(cr, uid, credit_line, context=ctx) self.pool.get('account.move').assert_balanced(cr, uid, [move_id], context=context) return True def _create_account_move(self, cr, uid, cost, context=None): vals = { 'journal_id': cost.account_journal_id.id, 'date': cost.date, 'ref': cost.name } return self.pool.get('account.move').create(cr, uid, vals, context=context) def _check_sum(self, cr, uid, landed_cost, context=None): """ Will check if each cost line its valuation lines sum to the correct amount and if the overall total amount is correct also """ costcor = {} tot = 0 for valuation_line in landed_cost.valuation_adjustment_lines: if costcor.get(valuation_line.cost_line_id): costcor[valuation_line. cost_line_id] += valuation_line.additional_landed_cost else: costcor[valuation_line. cost_line_id] = valuation_line.additional_landed_cost tot += valuation_line.additional_landed_cost prec = self.pool['decimal.precision'].precision_get(cr, uid, 'Account') # float_compare returns 0 for equal amounts res = not bool( float_compare(tot, landed_cost.amount_total, precision_digits=prec)) for costl in costcor.keys(): if float_compare(costcor[costl], costl.price_unit, precision_digits=prec): res = False return res def button_validate(self, cr, uid, ids, context=None): quant_obj = self.pool.get('stock.quant') for cost in self.browse(cr, uid, ids, context=context): if cost.state != 'draft': raise UserError(_('Only draft landed costs can be validated')) if not cost.valuation_adjustment_lines or not self._check_sum( cr, uid, cost, context=context): raise UserError( _('You cannot validate a landed cost which has no valid valuation adjustments lines. Did you click on Compute?' )) move_id = self._create_account_move(cr, uid, cost, context=context) quant_dict = {} for line in cost.valuation_adjustment_lines: if not line.move_id: continue per_unit = line.final_cost / line.quantity diff = per_unit - line.former_cost_per_unit quants = [quant for quant in line.move_id.quant_ids] for quant in quants: if quant.id not in quant_dict: quant_dict[quant.id] = quant.cost + diff else: quant_dict[quant.id] += diff for key, value in quant_dict.items(): print value quant_obj.write(cr, uid, key, {'cost': value}, context=context) qty_out = 0 for quant in line.move_id.quant_ids: if quant.location_id.usage != 'internal': qty_out += quant.qty self._create_accounting_entries(cr, uid, line, move_id, qty_out, context=context) self.write(cr, uid, cost.id, { 'state': 'done', 'account_move_id': move_id }, context=context) self.pool.get('account.move').post(cr, uid, [move_id], context=context) return True def button_cancel(self, cr, uid, ids, context=None): cost = self.browse(cr, uid, ids, context=context) if cost.state == 'done': raise UserError( _('Validated landed costs cannot be cancelled, ' 'but you could create negative landed costs to reverse them') ) return cost.write({'state': 'cancel'}) def unlink(self, cr, uid, ids, context=None): # cancel or raise first self.button_cancel(cr, uid, ids, context) return super(stock_landed_cost, self).unlink(cr, uid, ids, context=context) def compute_landed_cost(self, cr, uid, ids, context=None): line_obj = self.pool.get('stock.valuation.adjustment.lines') unlink_ids = line_obj.search(cr, uid, [('cost_id', 'in', ids)], context=context) line_obj.unlink(cr, uid, unlink_ids, context=context) digits = dp.get_precision('Product Price')(cr) towrite_dict = {} for cost in self.browse(cr, uid, ids, context=None): if not cost.picking_ids: continue picking_ids = [p.id for p in cost.picking_ids] total_qty = 0.0 total_cost = 0.0 total_weight = 0.0 total_volume = 0.0 total_line = 0.0 vals = self.get_valuation_lines(cr, uid, [cost.id], picking_ids=picking_ids, context=context) for v in vals: for line in cost.cost_lines: v.update({'cost_id': cost.id, 'cost_line_id': line.id}) self.pool.get('stock.valuation.adjustment.lines').create( cr, uid, v, context=context) total_qty += v.get('quantity', 0.0) total_cost += v.get('former_cost', 0.0) total_weight += v.get('weight', 0.0) total_volume += v.get('volume', 0.0) total_line += 1 for line in cost.cost_lines: value_split = 0.0 for valuation in cost.valuation_adjustment_lines: value = 0.0 if valuation.cost_line_id and valuation.cost_line_id.id == line.id: if line.split_method == 'by_quantity' and total_qty: per_unit = (line.price_unit / total_qty) value = valuation.quantity * per_unit elif line.split_method == 'by_weight' and total_weight: per_unit = (line.price_unit / total_weight) value = valuation.weight * per_unit elif line.split_method == 'by_volume' and total_volume: per_unit = (line.price_unit / total_volume) value = valuation.volume * per_unit elif line.split_method == 'equal': value = (line.price_unit / total_line) elif line.split_method == 'by_current_cost_price' and total_cost: per_unit = (line.price_unit / total_cost) value = valuation.former_cost * per_unit else: value = (line.price_unit / total_line) if digits: value = float_round(value, precision_digits=digits[1], rounding_method='UP') value = min(value, line.price_unit - value_split) value_split += value if valuation.id not in towrite_dict: towrite_dict[valuation.id] = value else: towrite_dict[valuation.id] += value if towrite_dict: for key, value in towrite_dict.items(): line_obj.write(cr, uid, key, {'additional_landed_cost': value}, context=context) return True def _track_subtype(self, cr, uid, ids, init_values, context=None): record = self.browse(cr, uid, ids[0], context=context) if 'state' in init_values and record.state == 'done': return 'stock_landed_costs.mt_stock_landed_cost_open' return super(stock_landed_cost, self)._track_subtype(cr, uid, ids, init_values, context=context)
class MassMailingCampaign(osv.Model): """Model of mass mailing campaigns. """ _name = "mail.mass_mailing.campaign" _description = 'Mass Mailing Campaign' def _get_statistics(self, cr, uid, ids, name, arg, context=None): """ Compute statistics of the mass mailing campaign """ results = {} cr.execute( """ SELECT c.id as campaign_id, COUNT(s.id) AS total, COUNT(CASE WHEN s.sent is not null THEN 1 ELSE null END) AS sent, COUNT(CASE WHEN s.scheduled is not null AND s.sent is null AND s.exception is null THEN 1 ELSE null END) AS scheduled, COUNT(CASE WHEN s.scheduled is not null AND s.sent is null AND s.exception is not null THEN 1 ELSE null END) AS failed, COUNT(CASE WHEN s.id is not null AND s.bounced is null THEN 1 ELSE null END) AS delivered, COUNT(CASE WHEN s.opened is not null THEN 1 ELSE null END) AS opened, COUNT(CASE WHEN s.replied is not null THEN 1 ELSE null END) AS replied , COUNT(CASE WHEN s.bounced is not null THEN 1 ELSE null END) AS bounced FROM mail_mail_statistics s RIGHT JOIN mail_mass_mailing_campaign c ON (c.id = s.mass_mailing_campaign_id) WHERE c.id IN %s GROUP BY c.id """, (tuple(ids), )) for row in cr.dictfetchall(): results[row.pop('campaign_id')] = row total = row['total'] or 1 row['delivered'] = row['sent'] - row['bounced'] row['received_ratio'] = 100.0 * row['delivered'] / total row['opened_ratio'] = 100.0 * row['opened'] / total row['replied_ratio'] = 100.0 * row['replied'] / total return results _columns = { 'name': fields.char('Name', required=True), 'stage_id': fields.many2one('mail.mass_mailing.stage', 'Stage', required=True), 'user_id': fields.many2one( 'res.users', 'Responsible', required=True, ), 'category_ids': fields.many2many('mail.mass_mailing.category', 'mail_mass_mailing_category_rel', 'category_id', 'campaign_id', string='Categories'), 'mass_mailing_ids': fields.one2many( 'mail.mass_mailing', 'mass_mailing_campaign_id', 'Mass Mailings', ), 'unique_ab_testing': fields.boolean( 'AB Testing', help= 'If checked, recipients will be mailed only once, allowing to send' 'various mailings in a single campaign to test the effectiveness' 'of the mailings.'), 'color': fields.integer('Color Index'), # stat fields 'total': fields.function(_get_statistics, string='Total', type='integer', multi='_get_statistics'), 'scheduled': fields.function(_get_statistics, string='Scheduled', type='integer', multi='_get_statistics'), 'failed': fields.function(_get_statistics, string='Failed', type='integer', multi='_get_statistics'), 'sent': fields.function(_get_statistics, string='Sent Emails', type='integer', multi='_get_statistics'), 'delivered': fields.function( _get_statistics, string='Delivered', type='integer', multi='_get_statistics', ), 'opened': fields.function( _get_statistics, string='Opened', type='integer', multi='_get_statistics', ), 'replied': fields.function(_get_statistics, string='Replied', type='integer', multi='_get_statistics'), 'bounced': fields.function(_get_statistics, string='Bounced', type='integer', multi='_get_statistics'), 'received_ratio': fields.function( _get_statistics, string='Received Ratio', type='integer', multi='_get_statistics', ), 'opened_ratio': fields.function( _get_statistics, string='Opened Ratio', type='integer', multi='_get_statistics', ), 'replied_ratio': fields.function( _get_statistics, string='Replied Ratio', type='integer', multi='_get_statistics', ), } def _get_default_stage_id(self, cr, uid, context=None): stage_ids = self.pool['mail.mass_mailing.stage'].search( cr, uid, [], limit=1, context=context) return stage_ids and stage_ids[0] or False _defaults = { 'user_id': lambda self, cr, uid, ctx=None: uid, 'stage_id': lambda self, *args: self._get_default_stage_id(*args), } def get_recipients(self, cr, uid, ids, model=None, context=None): """Return the recipients of a mailing campaign. This is based on the statistics build for each mailing. """ Statistics = self.pool['mail.mail.statistics'] res = dict.fromkeys(ids, False) for cid in ids: domain = [('mass_mailing_campaign_id', '=', cid)] if model: domain += [('model', '=', model)] stat_ids = Statistics.search(cr, uid, domain, context=context) res[cid] = set(stat.res_id for stat in Statistics.browse( cr, uid, stat_ids, context=context)) return res
"rent.order", "Rent Reference", required=True, ondelete="cascade", select=True, readonly=True, states={"draft": [("readonly", False)]}, ), "sequence": fields.integer("Sequence"), "product_id": fields.many2one( "product.product", "Product", domain=[("is_rent", "=", True)], change_default=True ), "invoice_lines": fields.many2many( "account.invoice.line", "rent_order_line_invoice_rel", "order_line_id", "invoice_id", "Invoice Lines", readonly=True, ), "price_unit": fields.float( "Unit Price", required=True, digits_compute=dp.get_precision("Product Price"), readonly=True, states={"draft": [("readonly", False)]}, ), "price_subtotal": fields.function(_amount_line, string="Subtotal", digits_compute=dp.get_precision("Account")), "tax_id": fields.many2many( "account.tax", "rent_order_tax", "order_line_id",
class delivery_grid(osv.osv): _name = "delivery.grid" _description = "Delivery Grid" _columns = { 'name': fields.char('Grid Name', required=True), 'sequence': fields.integer( 'Sequence', required=True, help= "Gives the sequence order when displaying a list of delivery grid." ), 'carrier_id': fields.many2one('delivery.carrier', 'Carrier', required=True, ondelete='cascade'), 'country_ids': fields.many2many('res.country', 'delivery_grid_country_rel', 'grid_id', 'country_id', 'Countries'), 'state_ids': fields.many2many('res.country.state', 'delivery_grid_state_rel', 'grid_id', 'state_id', 'States'), 'zip_from': fields.char('Start Zip', size=12), 'zip_to': fields.char('To Zip', size=12), 'line_ids': fields.one2many('delivery.grid.line', 'grid_id', 'Grid Line', copy=True), 'active': fields.boolean( 'Active', help= "If the active field is set to False, it will allow you to hide the delivery grid without removing it." ), } _defaults = { 'active': lambda *a: 1, 'sequence': lambda *a: 1, } _order = 'sequence' def get_price(self, cr, uid, id, order, dt, context=None): total = 0 weight = 0 volume = 0 quantity = 0 product_uom_obj = self.pool.get('product.uom') for line in order.order_line: if not line.product_id or line.is_delivery: continue q = product_uom_obj._compute_qty(cr, uid, line.product_uom.id, line.product_uom_qty, line.product_id.uom_id.id) weight += (line.product_id.weight or 0.0) * q volume += (line.product_id.volume or 0.0) * q quantity += q total = order.amount_total or 0.0 return self.get_price_from_picking(cr, uid, id, total, weight, volume, quantity, context=context) def get_price_from_picking(self, cr, uid, id, total, weight, volume, quantity, context=None): grid = self.browse(cr, uid, id, context=context) price = 0.0 ok = False price_dict = { 'price': total, 'volume': volume, 'weight': weight, 'wv': volume * weight, 'quantity': quantity } for line in grid.line_ids: test = eval(line.type + line.operator + str(line.max_value), price_dict) if test: if line.price_type == 'variable': price = line.list_price * price_dict[line.variable_factor] else: price = line.list_price ok = True break if not ok: raise osv.except_osv( _("Unable to fetch delivery method!"), _("Selected product in the delivery method doesn't fulfill any of the delivery grid(s) criteria." )) return price
class fee_defaulters(osv.osv_memory): """ This wizard was initially developed for printing defaulter students list only, now we are using this for fee analysis purpose, other reports are also added to this, later on its name will be change in .py and xml file --last updated: 31 DEC 17 by Shahid """ def _get_active_session(self, cr, uid, context={}): ssn = self.pool.get('sms.session').search(cr, uid, [('state', '=', 'Active')]) if ssn: return ssn[0] _name = "fee.defaulters" _description = "Prints defaulter list" _columns = { "session": fields.many2one( 'sms.session', 'Session', help= "Select A session , you can also print reprts from previous session." ), "class_id": fields.many2many('sms.academiccalendar', 'sms_academiccalendar_class_fee', 'thisobj_id', 'academiccalendar_id', 'Class', domain="[('session_id','=',session)]"), "fee_type_list": fields.many2many('smsfee.feetypes', 'fee_defaulters_feetype_rel', 'fee_defaulters_id', 'smsfee_feetypes_id', 'SS'), 'report_type': fields.selection( [('summary', 'Print Summary (Donot show monthly Details'), ('detailed', 'Detailed Report')], 'Options'), 'category': fields.selection([('Academics', 'Academics'), ('Transport', 'Transport'), ('All', 'All Fee Categories')], 'Fee Category'), 'order_by': fields.selection( [('sms_student.name', 'Student Name'), ('sms_student.registration_no', 'Registration No'), ('sms_student.state', 'Admission Status'), ('sms_academiccalendar.name,sms_student.name', 'Class')], 'Order By'), 'show_phone_no': fields.boolean('Display Contact No'), 'developer_mode': fields.boolean('For Developer'), 'base_amount': fields.integer( 'Dues Greater Than', help= 'Enter an amount e.g 1000, it will search all students having dues greater or equal to 1000.' ), 'student_type': fields.selection([('Current', 'Current'), ('Withdrawn', 'Withdrawn')], 'Student Type', readonly=True), } _defaults = { 'session': _get_active_session, 'category': 'Academics', 'base_amount': 1, 'order_by': 'sms_student.registration_no', 'student_type': 'Current', } def print_defaulter_summary(self, cr, uid, ids, data): result = [] datas = { 'ids': [], 'active_ids': '', 'model': 'smsfee.classfees.register', 'form': self.read(cr, uid, ids)[0], } return { 'type': 'ir.actions.report.xml', 'report_name': 'smsfee_defaulter_studnent_list_name', 'datas': datas, } def print_fee_analysis_ms_excel(self, cr, uid, ids, data): print("print_fee_analysis_ms_excel called") result = [] book = xlwt.Workbook() header_top = xlwt.Style.easyxf( 'font: bold 0, color white, height 250;' 'align: vertical center, horizontal center, wrap on;' 'borders: left thin, right thin, bottom thick;' 'pattern: pattern solid, fore_colour gray80;') header_feetypes = xlwt.Style.easyxf( 'font: bold 0, color white, , height 250;' 'align: vertical center, horizontal center, wrap on;' 'borders: left thin, right thin, bottom thick;' 'pattern: pattern solid, fore_colour light_blue;') header_months = xlwt.Style.easyxf( 'font: bold 0, color black, height 250;' 'align: vertical center, horizontal center, wrap on;' 'borders: left thin, right thin, bottom thick;' 'pattern: pattern solid, fore_colour light_green;') student_white_rows = xlwt.Style.easyxf( 'font: bold 0, color black, height 250;' 'align: vertical center, horizontal left, wrap on;' 'borders: left thin, right thin, bottom thick;' 'pattern: pattern solid, fore_colour white;') student_grey_rows = xlwt.Style.easyxf( 'font: bold 0, color black, height 250;' 'align: vertical center, horizontal left, wrap on;' 'borders: left thin, right thin, bottom thick;' 'pattern: pattern solid, fore_colour gray25 ;') paid_fee = xlwt.Style.easyxf( 'font: bold 0, color black, height 250;' 'align: vertical center, horizontal left, wrap on;' 'borders: left thin, right thin, bottom thick;' 'pattern: pattern solid, fore_colour white;') unpaid_fee = xlwt.Style.easyxf( 'font: bold 0, color black, height 250;' 'align: vertical center, horizontal left, wrap on;' 'borders:top_color red, bottom_color red, right_color red, left_color red,\ left thin, right thin, top thin, bottom thin;' 'pattern: pattern solid, fore_colour white;' 'font: color red') selected_fee_list = [] for f in self.browse(cr, uid, ids): if not f.fee_type_list: raise osv.except_osv( ('Please Select Fee'), ('Defaulter Excel Report Fees to be included')) for s in f.fee_type_list: selected_fee_list.append(s.id) #classes = self.pool.get('sms.academiccalendar').browse(cr,uid,41) #loop via classes, for each class there will be 1 sheet collected_classes = [] for f in self.browse(cr, uid, ids): if f.class_id: for cls2 in f.class_id: collected_classes.append(cls2.id) # sql1 = """SELECT id,name from sms_academiccalendar where id in""" +str(collected_classes +"""" ORDER BY name """ # cr.execute(sql1) # classes = cr.fetchall() classes = self.pool.get('sms.academiccalendar').browse( cr, uid, collected_classes) class_ctr = 1 row = 0 for this_class in classes: print("this_class.name", this_class.name) sheet1 = book.add_sheet(str(class_ctr) + " " + str(this_class.class_id.name), cell_overwrite_ok=True) title = this_class.class_id.name class_ctr = class_ctr + 1 _col = (sheet1.col(0)).width = 100 * 20 _col = (sheet1.col(1)).width = 400 * 20 # _col = (sheet1.row(2)).height = 300 * 15 # _col = (sheet1.row(2)).height = 200 * 15 sheet1.write(3, 0, 'Rego NO', header_top) sheet1.write(3, 1, 'Name', header_top) #Find all fee types of this class and arrange in one reow of excel #changes: added subtype in select query sqlfees = """ SELECT smsfee_feetypes.id,smsfee_feetypes.name, CASE WHEN (subtype != 'Monthly_Fee') THEN '01' WHEN (subtype= 'Monthly_Fee') THEN '02' ELSE '00' END AS sequence_no from smsfee_feetypes where smsfee_feetypes.category = '"""+str(f.category)+ """' ORDER BY sequence_no,smsfee_feetypes.name """ # changes: interchanged category.name and seq no cr.execute(sqlfees) feerec = cr.fetchall() col_fee = 2 # this is the column no in sheet for fee header fee_ids_list = [] month_dict_ids = {} adm_dict_ids = {} annual_dict_ids = {} feerec2 = [] for feere in feerec: for id in selected_fee_list: if id == feere[0]: feerec2.append(feere) for fee in feerec2: fee_ids_list.append(fee[0]) print("this_class", this_class, "this_class.session_id", this_class.session_id, "/nthis_class.session_id.id", this_class.session_id.id) sql3 = """SELECT id,name from sms_session_months where session_id = """ + str( this_class.session_id.id ) + """ order by session_year, to_date(name,'Month') """ cr.execute(sql3) months = cr.fetchall() annual_number = 4 #testing git branch 2 if fee[0] == 2: if fee[0] == 2: month_ids_list = [] for this_month in months: if f.developer_mode: ft_name = str(fee[1]) + "\n" + str( this_month[1] ) + "\nmonth_id:" + str( this_month[0]) + "\nfee_id:" + str( fee[0]) else: ft_name = str(fee[1]) + "\n" + str( this_month[1])[:3].upper() + str( this_month[1])[-5:] sheet1.write_merge(r1=0, c1=0, r2=2, c2=11) _col = ( sheet1.row(col_fee)).height = 100 * 10 #cell width for fee type other than months _col = ( sheet1.col(col_fee)).width = 200 * 20 sheet1.write(0, 2, title, header_top) sheet1.write(3, col_fee, ft_name, header_feetypes) month_ids_list.append(this_month[0]) month_dict_ids[this_month[0] + fee[0]] = col_fee col_fee = col_fee + 1 else: annual_dict_ids[fee[0]] = col_fee annual_number = annual_number + 1 sheet1.write_merge(r1=0, c1=0, r2=2, c2=11) _col = (sheet1.row(col_fee)).height = 100 * 10 _col = (sheet1.col(col_fee)).width = 200 * 20 sheet1.write(0, 2, title, header_feetypes) if f.developer_mode: ft_name = str(fee[1]) + "\nfee_id:" + str( fee[0]) else: ft_name = str(fee[1]) sheet1.write(3, col_fee, ft_name, header_feetypes) #popluate dict1 for non mnthly fees col_fee = col_fee + 1 #get students for selected class print "total " + str( fee_ids_list) + " fee ids in fee_ids_list" print("this_class_id ", this_class.id) sql4 = """ SELECT id,registration_no, name,state from sms_student where current_class= """ + str( this_class.id) + """ order by registration_no,name """ cr.execute(sql4) students = cr.fetchall() row = 4 color = True #set column again to start iele left most for this_student in students: color = not color _col = (sheet1.col(1)).width = 200 * 20 _col = (sheet1.col(1)).height = 400 * 20 _col = (sheet1.row(row)).height = 200 * 10 if color: sheet1.write(row, 0, this_student[1], student_grey_rows) sheet1.write(row, 1, this_student[2], student_grey_rows) else: sheet1.write(row, 0, this_student[1], student_white_rows) sheet1.write(row, 1, this_student[2], student_white_rows) # print("student id",this_student[0],"\nmonth ids",month_ids_list ,"\nfee ids",fee_ids_list ) #now loop via the fees dictionaru for this student col_fee = 2 col_month = 25 col_adminiistrative = 13 for fees2 in fee_ids_list: if 2 in selected_fee_list: for month2 in month_ids_list: sql5 = """select id,fee_month,fee_amount,generic_fee_type,state,receipt_no,date_fee_paid from smsfee_studentfee where student_id = """ + str( this_student[0]) + """ and generic_fee_type= """ + str( fees2 ) + """ and fee_month=""" + str(month2) cr.execute(sql5) stdfee = cr.fetchall() print("stdfee", stdfee) for found_fee in stdfee: #print( "generic fee type",fees2,"fee_month",month2,"this_student",this_student[0]) if found_fee[3] == 2: if found_fee[4] == 'fee_paid': if f.developer_mode: label = 'Paid Amount:\n' + str( found_fee[2] ) + "\nmonth_id:" + str( month2 ) + "\nfee_id:" + str( fees2 ) + "\nfee_id_genric:" + str( found_fee[3] ) + '\n' + 'Bill No:' + str( found_fee[5] ) + '\n' + 'Date On :\n' + str( found_fee[6]) print 'labellll', label else: label = 'Paid Amount:\n' + str( found_fee[2] ) + '\nBill No:' + str( found_fee[5] ) + '\n' + 'Date On:\n' + str( found_fee[6]) sheet1.write( row, month_dict_ids[month2 + fees2], label, paid_fee) col_month = col_month + 1 col_fee = col_fee + 1 else: if f.developer_mode: label = 'Fee Amount:\n' + str( found_fee[2] ) + "\nmonth_id:" + str( month2 ) + "\nfee_id:" + str( fees2 ) + "\nfee_id_genric:" + str( found_fee[3]) else: label = 'Fee Amount\n' + str( found_fee[2]) sheet1.write( row, month_dict_ids[month2 + fees2], label, unpaid_fee) col_month = col_month + 1 col_fee = col_fee + 1 else: if found_fee[4] == 'fee_paid': if f.developer_mode: label = 'Paid Amount:\n' + str( found_fee[2] ) + "\nmonth_id:" + str( month2 ) + "\nfee_id:" + str( fees2 ) + "\nfee_id_genric:" + str( found_fee[3]) else: label = 'Paid Amount:\n' + str( found_fee[2] ) + '\nBill No:' + str( found_fee[5] ) + '\n' + 'Date On:\n' + str( found_fee[6]) sheet1.write( row, annual_dict_ids[fees2], label, student_white_rows) else: if f.developer_mode: label = 'Fee Amount:\n' + str( found_fee[2] ) + "\nmonth_id:" + str( month2 ) + "\nfee_id:" + str( fees2 ) + "\nfee_id_genric:" + str( found_fee[3]) else: label = 'Fee Amount:\n ' + str( found_fee[2]) sheet1.write( row, annual_dict_ids[fees2], label, student_white_rows) # if found_fee[3] !='02': # sheet1.write(row,annual_dict_ids[fees2[0]], label,student_rows) # print("found fee",found_fee ,"\nsearch on ______generic id____",fees2,"\nthis_student.......",this_student[0],"\nmonth",month2) # # label = str(found_fee[2])+"\nmonth_id:"+str(month2)+"\nfee_id:"+str(fees2)+"\nfee_id_genric:"+str(found_fee[3]) # print "label:",label # sheet1.write(row,col_fee, label,student_rows) col_fee = col_fee + 1 else: sql6 = """select id,fee_month,fee_amount,generic_fee_type,state from smsfee_studentfee where student_id = """ + str( this_student[0]) + """ and generic_fee_type= """ + str( fees2) cr.execute(sql6) stdfee = cr.fetchall() for found_fee in stdfee: #print( "generic fee type",fees2,"fee_month",month2,"this_student",this_student[0]) if found_fee[3] == 2: if found_fee[4] == 'fee_paid': if f.developer_mode: label = 'Paid Amount\n' + str( found_fee[2] ) + "\nfee_id:" + str( fees2 ) + "\nfee_id_genric:" + str( found_fee[3] ) + '\n' + 'Bill No:' + str( found_fee[5] ) + '\n' + 'Date On :\n' + str( found_fee[6]) else: label = 'Paid Amount\n: ' + str( found_fee[2] ) + '\nBill No:' + str( found_fee[5] ) + '\n' + 'Date On:\n' + str( found_fee[6]) sheet1.write( row, month_dict_ids[fees2], label, paid_fee) col_month = col_month + 1 col_fee = col_fee + 1 else: if f.developer_mode: label = 'Fee Amount:\n ' + str( found_fee[2] ) + "\nfee_id:" + str( fees2 ) + "\nfee_id_genric:" + str( found_fee[3]) else: label = 'Fee Amount:\n ' + str( found_fee[2]) sheet1.write( row, month_dict_ids[fees2], label, unpaid_fee) col_month = col_month + 1 col_fee = col_fee + 1 else: if found_fee[4] == 'fee_paid': if f.developer_mode: label = 'Paid Amount:\n' + str( found_fee[2] ) + "\nmonth_id:" + "\nfee_id:" + str( fees2 ) + "\nfee_id_genric:" + str( found_fee[3] ) + '\nBill No:' + str( found_fee[5] ) + '\n' + 'Date On:\n' + str( found_fee[6]) else: label = 'Paid Amount:\n ' + str( found_fee[2] ) + '\nBill No:' + str( found_fee[5] ) + '\n' + 'Date On :' + str( found_fee[6]) sheet1.write( row, annual_dict_ids[fees2], label, student_white_rows) else: if f.developer_mode: label = 'Fee Amount:\n ' + str( found_fee[2] ) + "\nmonth_id:" + "\nfee_id:" + str( fees2 ) + "\nfee_id_genric:" + str( found_fee[3] ) + '\nBill No:' + str( found_fee[5] ) + '\n' + 'Date On:\n' + str( found_fee[6]) else: label = 'Fee Amount:\n ' + str( found_fee[2]) sheet1.write( row, annual_dict_ids[fees2], label, student_white_rows) # if found_fee[3] !='02': # sheet1.write(row,annual_dict_ids[fees2[0]], label,student_rows) # print("found fee",found_fee ,"\nsearch on ______generic id____",fees2,"\nthis_student.......",this_student[0],"\nmonth",month2) # # label = str(found_fee[2])+"\nmonth_id:"+str(month2)+"\nfee_id:"+str(fees2)+"\nfee_id_genric:"+str(found_fee[3]) # print "label:",label # sheet1.write(row,col_fee, label,student_rows) col_fee = col_fee + 1 row = row + 1 print "generating exel" path = os.path.join(os.path.expanduser('~'), 'file.xls') book.save(path) def print_defaulter_detailed(self, cr, uid, ids, data): result = [] datas = { 'ids': [], 'active_ids': '', 'model': 'smsfee.classfees.register', 'form': self.read(cr, uid, ids)[0], } return { 'type': 'ir.actions.report.xml', 'report_name': 'smsfee_annaul_defaulter_list_name', 'datas': datas, }
class Post(osv.Model): _name = 'forum.post' _description = 'Forum Post' _inherit = ['mail.thread', 'website.seo.metadata'] _order = "is_correct DESC, vote_count DESC" def _get_user_vote(self, cr, uid, ids, field_name, arg, context): res = dict.fromkeys(ids, 0) vote_ids = self.pool['forum.post.vote'].search(cr, uid, [('post_id', 'in', ids), ('user_id', '=', uid)], context=context) for vote in self.pool['forum.post.vote'].browse(cr, uid, vote_ids, context=context): res[vote.post_id.id] = vote.vote return res def _get_vote_count(self, cr, uid, ids, field_name, arg, context): res = dict.fromkeys(ids, 0) for post in self.browse(cr, uid, ids, context=context): for vote in post.vote_ids: res[post.id] += int(vote.vote) return res def _get_post_from_vote(self, cr, uid, ids, context=None): result = {} for vote in self.pool['forum.post.vote'].browse(cr, uid, ids, context=context): result[vote.post_id.id] = True return result.keys() def _get_user_favourite(self, cr, uid, ids, field_name, arg, context): res = dict.fromkeys(ids, False) for post in self.browse(cr, uid, ids, context=context): if uid in [f.id for f in post.favourite_ids]: res[post.id] = True return res def _get_favorite_count(self, cr, uid, ids, field_name, arg, context): res = dict.fromkeys(ids, 0) for post in self.browse(cr, uid, ids, context=context): res[post.id] += len(post.favourite_ids) return res def _get_post_from_hierarchy(self, cr, uid, ids, context=None): post_ids = set(ids) for post in self.browse(cr, SUPERUSER_ID, ids, context=context): if post.parent_id: post_ids.add(post.parent_id.id) return list(post_ids) def _get_child_count(self, cr, uid, ids, field_name=False, arg={}, context=None): res = dict.fromkeys(ids, 0) for post in self.browse(cr, uid, ids, context=context): if post.parent_id: res[post.parent_id.id] = len(post.parent_id.child_ids) else: res[post.id] = len(post.child_ids) return res def _get_uid_answered(self, cr, uid, ids, field_name, arg, context=None): res = dict.fromkeys(ids, False) for post in self.browse(cr, uid, ids, context=context): res[post.id] = any(answer.create_uid.id == uid for answer in post.child_ids) return res def _get_has_validated_answer(self, cr, uid, ids, field_name, arg, context=None): res = dict.fromkeys(ids, False) ans_ids = self.search(cr, uid, [('parent_id', 'in', ids), ('is_correct', '=', True)], context=context) for answer in self.browse(cr, uid, ans_ids, context=context): res[answer.parent_id.id] = True return res def _is_self_reply(self, cr, uid, ids, field_name, arg, context=None): res = dict.fromkeys(ids, False) for post in self.browse(cr, uid, ids, context=context): res[post. id] = post.parent_id and post.parent_id.create_uid == post.create_uid or False return res _columns = { 'name': fields.char('Title', size=128), 'forum_id': fields.many2one('forum.forum', 'Forum', required=True), 'content': fields.html('Content'), 'tag_ids': fields.many2many('forum.tag', 'forum_tag_rel', 'forum_id', 'forum_tag_id', 'Tags'), 'state': fields.selection([('active', 'Active'), ('close', 'Close'), ('offensive', 'Offensive')], 'Status'), 'views': fields.integer('Number of Views'), 'active': fields.boolean('Active'), 'is_correct': fields.boolean( 'Valid Answer', help='Correct Answer or Answer on this question accepted.'), 'website_message_ids': fields.one2many( 'mail.message', 'res_id', domain=lambda self: ['&', ('model', '=', self._name), ('type', '=', 'comment')], string='Post Messages', help="Comments on forum post", ), # history 'create_date': fields.datetime('Asked on', select=True, readonly=True), 'create_uid': fields.many2one('res.users', 'Created by', select=True, readonly=True), 'write_date': fields.datetime('Update on', select=True, readonly=True), 'write_uid': fields.many2one('res.users', 'Updated by', select=True, readonly=True), # vote fields 'vote_ids': fields.one2many('forum.post.vote', 'post_id', 'Votes'), 'user_vote': fields.function(_get_user_vote, string='My Vote', type='integer'), 'vote_count': fields.function(_get_vote_count, string="Votes", type='integer', store={ 'forum.post': (lambda self, cr, uid, ids, c={}: ids, ['vote_ids'], 10), 'forum.post.vote': (_get_post_from_vote, [], 10), }), # favorite fields 'favourite_ids': fields.many2many('res.users', string='Favourite'), 'user_favourite': fields.function(_get_user_favourite, string="My Favourite", type='boolean'), 'favourite_count': fields.function(_get_favorite_count, string='Favorite Count', type='integer', store={ 'forum.post': (lambda self, cr, uid, ids, c={}: ids, ['favourite_ids'], 10), }), # hierarchy 'parent_id': fields.many2one('forum.post', 'Question', ondelete='cascade'), 'self_reply': fields.function(_is_self_reply, 'Reply to own question', type='boolean', store={ 'forum.post': (lambda self, cr, uid, ids, c={}: ids, ['parent_id', 'create_uid'], 10), }), 'child_ids': fields.one2many('forum.post', 'parent_id', 'Answers'), 'child_count': fields.function(_get_child_count, string="Answers", type='integer', store={ 'forum.post': (_get_post_from_hierarchy, ['parent_id', 'child_ids'], 10), }), 'uid_has_answered': fields.function( _get_uid_answered, string='Has Answered', type='boolean', ), 'has_validated_answer': fields.function(_get_has_validated_answer, string='Has a Validated Answered', type='boolean', store={ 'forum.post': (_get_post_from_hierarchy, ['parent_id', 'child_ids', 'is_correct'], 10), }), # closing 'closed_reason_id': fields.many2one('forum.post.reason', 'Reason'), 'closed_uid': fields.many2one('res.users', 'Closed by', select=1), 'closed_date': fields.datetime('Closed on', readonly=True), } _defaults = { 'state': 'active', 'views': 0, 'active': True, 'vote_ids': list(), 'favourite_ids': list(), 'child_ids': list(), } def create(self, cr, uid, vals, context=None): if context is None: context = {} create_context = dict(context, mail_create_nolog=True) post_id = super(Post, self).create(cr, uid, vals, context=create_context) # post message + subtype depending on parent_id if vals.get("parent_id"): parent = self.browse(cr, SUPERUSER_ID, vals['parent_id'], context=context) body = _( '<p><a href="forum/%s/question/%s">New Answer Posted</a></p>' % (slug(parent.forum_id), slug(parent))) self.message_post(cr, uid, parent.id, subject=_('Re: %s') % parent.name, body=body, subtype='website_forum.mt_answer_new', context=context) else: self.message_post(cr, uid, post_id, subject=vals.get('name', ''), body=_('New Question Created'), subtype='website_forum.mt_question_new', context=context) self.pool['res.users'].add_karma( cr, SUPERUSER_ID, [uid], self.pool['forum.forum']._karma_gen_quest_new, context=context) return post_id def write(self, cr, uid, ids, vals, context=None): Forum = self.pool['forum.forum'] # update karma when accepting/rejecting answers if 'is_correct' in vals: mult = 1 if vals['is_correct'] else -1 for post in self.browse(cr, uid, ids, context=context): if vals['is_correct'] != post.is_correct: self.pool['res.users'].add_karma( cr, SUPERUSER_ID, [post.create_uid.id], Forum._karma_gen_ans_accepted * mult, context=context) self.pool['res.users'].add_karma( cr, SUPERUSER_ID, [uid], Forum._karma_gen_ans_accept * mult, context=context) res = super(Post, self).write(cr, uid, ids, vals, context=context) # if post content modify, notify followers if 'content' in vals or 'name' in vals: for post in self.browse(cr, uid, ids, context=context): if post.parent_id: body, subtype = _( 'Answer Edited'), 'website_forum.mt_answer_edit' obj_id = post.parent_id.id else: body, subtype = _( 'Question Edited'), 'website_forum.mt_question_edit' obj_id = post.id self.message_post(cr, uid, obj_id, body=_(body), subtype=subtype, context=context) return res def vote(self, cr, uid, ids, upvote=True, context=None): Vote = self.pool['forum.post.vote'] vote_ids = Vote.search(cr, uid, [('post_id', 'in', ids), ('user_id', '=', uid)], context=context) if vote_ids: for vote in Vote.browse(cr, uid, vote_ids, context=context): if upvote: new_vote = '0' if vote.vote == '-1' else '1' else: new_vote = '0' if vote.vote == '1' else '-1' Vote.write(cr, uid, vote_ids, {'vote': new_vote}, context=context) else: for post_id in ids: new_vote = '1' if upvote else '-1' Vote.create(cr, uid, { 'post_id': post_id, 'vote': new_vote }, context=context) return { 'vote_count': self._get_vote_count(cr, uid, ids, None, None, context=context)[ids[0]] } def set_viewed(self, cr, uid, ids, context=None): cr.execute("""UPDATE forum_post SET views = views+1 WHERE id IN %s""", (tuple(ids), )) return True def _get_access_link(self, cr, uid, mail, partner, context=None): post = self.pool['forum.post'].browse(cr, uid, mail.res_id, context=context) res_id = post.parent_id and "%s#answer-%s" % (post.parent_id.id, post.id) or post.id return "/forum/%s/question/%s" % (post.forum_id.id, res_id)
class asset_custody_management(osv.osv_memory): _name = "asset.custody.management" _description = "management custodies" USERS_SELECTION = [ ('admin', 'Supply Department'), ('tech', 'Techncial Services Department'), ('arms', 'Arms Department'), ] _columns = { 'type': fields.selection([('product', 'product'), ('category', 'category'), ('employee', 'employee'), ('department', 'department')], "Type"), #'office_id': fields.many2one('office.office','office', ), 'department_id': fields.many2one( 'hr.department', 'Department', ), 'cat_id': fields.many2one( 'product.category', 'Category', ), 'product_id': fields.many2one( 'product.product', 'Product', ), 'office_ids': fields.many2many('office.office', 'office_management_wizard_rel', 'management', 'office_id', string='office'), 'executing_agency': fields.selection(USERS_SELECTION, 'Executing Agency', select=True, help='Department Which this request will executed it', required="1"), } def print_report(self, cr, uid, ids, context=None): data = self.read(cr, uid, ids, [], context=context)[0] context = { 'department_id': data['department_id'], 'executing_agency': data['executing_agency'], 'office_id': data['office_ids'], 'product_id': data['product_id'], 'cat_id': data['cat_id'], } datas = { 'ids': [], 'model': 'asset.custody', 'form': data, 'context': context } return { 'type': 'ir.actions.report.xml', 'report_name': 'asset.custody.management', 'datas': datas, }
class kg_pattern_request(osv.osv): _name = "kg.pattern.request" _description = "Pattern Request" _order = "entry_date desc" _columns = { ### Header Details #### 'name': fields.char('Request No.', size=128, select=True), 'entry_date': fields.date('Request Date', required=True), 'note': fields.text('Notes'), 'remarks': fields.text('Remarks'), 'cancel_remark': fields.text('Cancel Remarks'), 'active': fields.boolean('Active'), 'state': fields.selection([('draft', 'Draft'), ('confirmed', 'Confirmed'), ('cancel', 'Cancelled')], 'Status', readonly=True), 'production_line_ids': fields.many2many('kg.production', 'm2m_pattern_request_details', 'request_id', 'production_id', 'Production Lines', domain="[('state','=','draft')]"), 'line_ids': fields.one2many('ch.pattern.request.line', 'header_id', "Request Line Details"), 'flag_reqline': fields.boolean('Request Line Created'), ### Entry Info #### 'company_id': fields.many2one('res.company', 'Company Name', readonly=True), 'crt_date': fields.datetime('Creation Date', readonly=True), 'user_id': fields.many2one('res.users', 'Created By', readonly=True), 'confirm_date': fields.datetime('Confirmed Date', readonly=True), 'confirm_user_id': fields.many2one('res.users', 'Confirmed By', readonly=True), 'cancel_date': fields.datetime('Cancelled Date', readonly=True), 'cancel_user_id': fields.many2one('res.users', 'Cancelled By', readonly=True), 'update_date': fields.datetime('Last Updated Date', readonly=True), 'update_user_id': fields.many2one('res.users', 'Last Updated By', readonly=True), } _defaults = { 'company_id': lambda self, cr, uid, c: self.pool.get('res.company'). _company_default_get(cr, uid, 'kg_pattern_request', context=c), 'entry_date': lambda *a: time.strftime('%Y-%m-%d'), 'user_id': lambda obj, cr, uid, context: uid, 'crt_date': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'), 'active': True, 'state': 'draft' } def onchange_production_ids(self, cr, uid, ids, production_line_ids): new_ids = production_line_ids[0][2] if ids: if new_ids != []: cr.execute( ''' select request_id,request_line_id,production_id from tmp_pattern_request_details where production_id not in %s and request_id = %s ''', [tuple(new_ids), ids[0]]) deleted_ids = cr.dictfetchall() if deleted_ids: for item in deleted_ids: cr.execute( ''' select count(request_line_id) from tmp_pattern_request_details where request_line_id = %s and request_id = %s ''', [item['request_line_id'], ids[0]]) req_line_count = cr.fetchone() if req_line_count[0] == 1: del_sql = """ delete from ch_pattern_request_line where header_id=%s and id = %s """ % ( ids[0], item['request_line_id']) cr.execute(del_sql) del_sql = """ delete from tmp_pattern_request_details where request_id=%s and production_id = %s and request_line_id = %s """ % ( ids[0], item['production_id'], item['request_line_id']) cr.execute(del_sql) if new_ids == []: del_sql = """ delete from ch_pattern_request_line where header_id=%s """ % ( ids[0]) cr.execute(del_sql) del_sql = """ delete from tmp_pattern_request_details where request_id=%s """ % ( ids[0]) cr.execute(del_sql) return True def update_line_items(self, cr, uid, ids, context=None): entry = self.browse(cr, uid, ids[0]) production_obj = self.pool.get('kg.production') request_line_obj = self.pool.get('ch.pattern.request.line') del_sql = """ delete from ch_pattern_request_line where header_id=%s """ % ( ids[0]) cr.execute(del_sql) #del_sql = """ delete from tmp_pattern_request_details where request_id=%s """ %(ids[0]) #cr.execute(del_sql) if entry.production_line_ids: """ produc_line_ids = map(lambda x:x.id,entry.production_line_ids) produc_line_browse = production_obj.browse(cr,uid,produc_line_ids) produc_line_browse = sorted(produc_line_browse, key=lambda k: k.pattern_id.id) groups = [] for key, group in groupby(produc_line_browse, lambda x: x.pattern_id.id): groups.append(map(lambda r:r,group)) for key,group in enumerate(groups): """ for line_item in entry.production_line_ids: vals = { 'header_id': entry.id, 'pattern_id': line_item.pattern_id.id, 'pattern_name': line_item.pattern_id.pattern_name, 'production_id': line_item.id, 'order_ref_no': line_item.order_ref_no, 'pump_model_id': line_item.pump_model_id.id, 'moc_id': line_item.moc_id.id, } request_line_id = request_line_obj.create(cr, uid, vals) """ cr.execute(''' insert into tmp_pattern_request_details(request_id,request_line_id,production_id,creation_date) values(%s,%s,%s,now()) ''',[entry.id,request_line_id,line_item.id]) """ self.write(cr, uid, ids, {'flag_reqline': True}) return True def entry_confirm(self, cr, uid, ids, context=None): entry = self.browse(cr, uid, ids[0]) issue_obj = self.pool.get('kg.pattern.issue') if not entry.line_ids: raise osv.except_osv( _('Warning!'), _('System not allow to confirm without Request Items !!')) ### Issue Creation against Pattern Request ### for req_item in entry.line_ids: vals = { 'name': self.pool.get('ir.sequence').get(cr, uid, 'kg.pattern.issue'), 'request_id': entry.id, 'request_date': entry.entry_date, 'request_line_id': req_item.id, 'pattern_id': req_item.pattern_id.id, 'pattern_name': req_item.pattern_id.pattern_name, 'order_ref_no': req_item.order_ref_no, 'pump_model_id': req_item.pump_model_id.id, 'moc_id': req_item.moc_id.id, 'requested_qty': req_item.qty, 'state': 'open', } issue_id = issue_obj.create(cr, uid, vals) self.write( cr, uid, ids, { 'name': self.pool.get('ir.sequence').get(cr, uid, 'kg.pattern.request'), 'state': 'confirmed', 'confirm_user_id': uid, 'confirm_date': time.strftime('%Y-%m-%d %H:%M:%S') }) cr.execute( ''' update ch_pattern_request_line set state = 'confirmed' where header_id = %s ''', [ids[0]]) return True def entry_cancel(self, cr, uid, ids, context=None): entry = self.browse(cr, uid, ids[0]) if entry.cancel_remark == False: raise osv.except_osv(_('Warning!'), _('Cancellation Remarks is must !!')) self.write( cr, uid, ids, { 'state': 'cancel', 'cancel_user_id': uid, 'cancel_date': time.strftime('%Y-%m-%d %H:%M:%S'), 'transac_state': 'cancel' }) cr.execute( ''' update ch_pattern_request_line set state = 'cancel' where header_id = %s ''', [ids[0]]) return True def unlink(self, cr, uid, ids, context=None): unlink_ids = [] for rec in self.browse(cr, uid, ids): if rec.state == 'confirmed': raise osv.except_osv(_('Warning!'), _('You can not delete this entry !!')) return osv.osv.unlink(self, cr, uid, ids, context=context) def write(self, cr, uid, ids, vals, context=None): vals.update({ 'update_date': time.strftime('%Y-%m-%d %H:%M:%S'), 'update_user_id': uid }) return super(kg_pattern_request, self).write(cr, uid, ids, vals, context) def _future_entry_date_check(self, cr, uid, ids, context=None): rec = self.browse(cr, uid, ids[0]) today = date.today() today = str(today) today = datetime.strptime(today, '%Y-%m-%d') entry_date = rec.entry_date entry_date = str(entry_date) entry_date = datetime.strptime(entry_date, '%Y-%m-%d') if entry_date > today: return False return True _constraints = [ (_future_entry_date_check, 'System not allow to save with future date. !!', ['']), ]
'qty' : fields.function(_qty_all_1,type="float",string='Bonus Qty',digits_compute=dp.get_precision('Product Unit of Measure')), 'uom_id' : fields.many2one('product.uom','UoM',required=True), 'uom_id2' : fields.many2one('product.uom','UoM',required=True), 'value' : fields.float('Price Value',domain=[('is_percent','=',False)]), 'per_product' : fields.boolean('Per Product'), 'persentase' : fields.float('Percent Value', digits_compute= dp.get_precision('Discount'),domain=[('is_percent','=',True)]), 'multi' : fields.boolean('Multiples'), 'is_active' : fields.boolean('Active?'), 'date_from' : fields.date('Start Date', required=True), 'date_to' : fields.date('End Date', required=True), 'condition_ids' : fields.one2many('master.condition','discount_id','Value Condition'), 'condition2_ids' : fields.one2many('master.condition2','discount_id','Product Condition'), 'condition3_ids' : fields.one2many('master.condition3','discount_id','Product Condition 2'), 'condition4_ids' : fields.one2many('master.condition4','discount_id','Product Condition 3'), 'condition5_ids' : fields.one2many('master.condition5','discount_id','Product Condition 4'), 'group_price_ids' : fields.many2many('res.partner.category', id1='discount_id', id2='category_id', string='Group Price Category'), 'is_percent' : fields.boolean('Is Percent'), 'is_flat' : fields.boolean('Flat'), 'type' :fields.selection([('regular','Regular Discount'),('promo','Promo Discount'),('extra','Extra Discount'),('cash','Cash Discount'),('mix','Mix Discount')],string='Type Discount',required=True), 'min_qty_product' : fields.float('Min. Product Item',digits_compute=dp.get_precision('Product Unit of Measure')), 'multi2' : fields.boolean('Value Condition'), 'multi3' : fields.boolean('Multiples for New Product'), # 'multi_sel' : fields.selection([('general','General Multiples'),('specific','Specific Multiples for New Product')],string="Multiples"), 'product_id2' : fields.many2one('product.product','Bonus New Product'), 'qty2_2' : fields.float('Bonus Qty', digits_compute=dp.get_precision('Product Unit of Measure')), 'qty2' : fields.function(_qty_all_2,type="float",string='Bonus Qty',digits_compute=dp.get_precision('Product Unit of Measure')), 'is_category': fields.boolean('Category Condition'), 'location_ids' : fields.many2many('sale.shop',id1='discount_id',id2='location_id',string='Location'), }
class MassMailing(osv.Model): """ MassMailing models a wave of emails for a mass mailign campaign. A mass mailing is an occurence of sending emails. """ _name = 'mail.mass_mailing' _description = 'Mass Mailing' # number of periods for tracking mail_mail statistics _period_number = 6 _order = 'sent_date DESC' def __get_bar_values(self, cr, uid, obj, domain, read_fields, value_field, groupby_field, date_begin, context=None): """ Generic method to generate data for bar chart values using SparklineBarWidget. This method performs obj.read_group(cr, uid, domain, read_fields, groupby_field). :param obj: the target model (i.e. crm_lead) :param domain: the domain applied to the read_group :param list read_fields: the list of fields to read in the read_group :param str value_field: the field used to compute the value of the bar slice :param str groupby_field: the fields used to group :return list section_result: a list of dicts: [ { 'value': (int) bar_column_value, 'tootip': (str) bar_column_tooltip, } ] """ date_begin = date_begin.date() section_result = [{ 'value': 0, 'tooltip': ustr((date_begin + relativedelta.relativedelta(days=i)).strftime('%d %B %Y')), } for i in range(0, self._period_number)] group_obj = obj.read_group(cr, uid, domain, read_fields, groupby_field, context=context) field = obj._fields.get(groupby_field.split(':')[0]) pattern = tools.DEFAULT_SERVER_DATE_FORMAT if field.type == 'date' else tools.DEFAULT_SERVER_DATETIME_FORMAT for group in group_obj: group_begin_date = datetime.strptime(group['__domain'][0][2], pattern).date() timedelta = relativedelta.relativedelta(group_begin_date, date_begin) section_result[timedelta.days] = { 'value': group.get(value_field, 0), 'tooltip': group.get(groupby_field) } return section_result def _get_daily_statistics(self, cr, uid, ids, field_name, arg, context=None): """ Get the daily statistics of the mass mailing. This is done by a grouping on opened and replied fields. Using custom format in context, we obtain results for the next 6 days following the mass mailing date. """ obj = self.pool['mail.mail.statistics'] res = {} for mailing in self.browse(cr, uid, ids, context=context): res[mailing.id] = {} date = mailing.sent_date if mailing.sent_date else mailing.create_date date_begin = datetime.strptime( date, tools.DEFAULT_SERVER_DATETIME_FORMAT) date_end = date_begin + relativedelta.relativedelta( days=self._period_number - 1) date_begin_str = date_begin.strftime( tools.DEFAULT_SERVER_DATETIME_FORMAT) date_end_str = date_end.strftime( tools.DEFAULT_SERVER_DATETIME_FORMAT) domain = [('mass_mailing_id', '=', mailing.id), ('opened', '>=', date_begin_str), ('opened', '<=', date_end_str)] res[mailing.id]['opened_daily'] = json.dumps( self.__get_bar_values(cr, uid, obj, domain, ['opened'], 'opened_count', 'opened:day', date_begin, context=context)) domain = [('mass_mailing_id', '=', mailing.id), ('replied', '>=', date_begin_str), ('replied', '<=', date_end_str)] res[mailing.id]['replied_daily'] = json.dumps( self.__get_bar_values(cr, uid, obj, domain, ['replied'], 'replied_count', 'replied:day', date_begin, context=context)) return res def _get_statistics(self, cr, uid, ids, name, arg, context=None): """ Compute statistics of the mass mailing """ results = {} cr.execute( """ SELECT m.id as mailing_id, COUNT(s.id) AS total, COUNT(CASE WHEN s.sent is not null THEN 1 ELSE null END) AS sent, COUNT(CASE WHEN s.scheduled is not null AND s.sent is null AND s.exception is null THEN 1 ELSE null END) AS scheduled, COUNT(CASE WHEN s.scheduled is not null AND s.sent is null AND s.exception is not null THEN 1 ELSE null END) AS failed, COUNT(CASE WHEN s.sent is not null AND s.bounced is null THEN 1 ELSE null END) AS delivered, COUNT(CASE WHEN s.opened is not null THEN 1 ELSE null END) AS opened, COUNT(CASE WHEN s.replied is not null THEN 1 ELSE null END) AS replied, COUNT(CASE WHEN s.bounced is not null THEN 1 ELSE null END) AS bounced FROM mail_mail_statistics s RIGHT JOIN mail_mass_mailing m ON (m.id = s.mass_mailing_id) WHERE m.id IN %s GROUP BY m.id """, (tuple(ids), )) for row in cr.dictfetchall(): results[row.pop('mailing_id')] = row total = row['total'] or 1 row['received_ratio'] = 100.0 * row['delivered'] / total row['opened_ratio'] = 100.0 * row['opened'] / total row['replied_ratio'] = 100.0 * row['replied'] / total return results def _get_mailing_model(self, cr, uid, context=None): res = [] for model_name in self.pool: model = self.pool[model_name] if hasattr(model, '_mail_mass_mailing') and getattr( model, '_mail_mass_mailing'): res.append((model._name, getattr(model, '_mail_mass_mailing'))) res.append(('mail.mass_mailing.contact', _('Mailing List'))) return res # indirections for inheritance _mailing_model = lambda self, *args, **kwargs: self._get_mailing_model( *args, **kwargs) _columns = { 'name': fields.char('Subject', required=True), 'email_from': fields.char('From', required=True), 'create_date': fields.datetime('Creation Date'), 'sent_date': fields.datetime('Sent Date', oldname='date', copy=False), 'body_html': fields.html('Body'), 'attachment_ids': fields.many2many('ir.attachment', 'mass_mailing_ir_attachments_rel', 'mass_mailing_id', 'attachment_id', 'Attachments'), 'mass_mailing_campaign_id': fields.many2one( 'mail.mass_mailing.campaign', 'Mass Mailing Campaign', ondelete='set null', ), 'state': fields.selection( [('draft', 'Draft'), ('test', 'Tested'), ('done', 'Sent')], string='Status', required=True, copy=False, ), 'color': fields.related( 'mass_mailing_campaign_id', 'color', type='integer', string='Color Index', ), # mailing options 'reply_to_mode': fields.selection( [('thread', 'In Document'), ('email', 'Specified Email Address')], string='Reply-To Mode', required=True, ), 'reply_to': fields.char('Reply To', help='Preferred Reply-To Address'), # recipients 'mailing_model': fields.selection(_mailing_model, string='Recipients Model', required=True), 'mailing_domain': fields.char('Domain', oldname='domain'), 'contact_list_ids': fields.many2many( 'mail.mass_mailing.list', 'mail_mass_mailing_list_rel', string='Mailing Lists', ), 'contact_ab_pc': fields.integer( 'AB Testing percentage', help= 'Percentage of the contacts that will be mailed. Recipients will be taken randomly.' ), # statistics data 'statistics_ids': fields.one2many( 'mail.mail.statistics', 'mass_mailing_id', 'Emails Statistics', ), 'total': fields.function( _get_statistics, string='Total', type='integer', multi='_get_statistics', ), 'scheduled': fields.function( _get_statistics, string='Scheduled', type='integer', multi='_get_statistics', ), 'failed': fields.function( _get_statistics, string='Failed', type='integer', multi='_get_statistics', ), 'sent': fields.function( _get_statistics, string='Sent', type='integer', multi='_get_statistics', ), 'delivered': fields.function( _get_statistics, string='Delivered', type='integer', multi='_get_statistics', ), 'opened': fields.function( _get_statistics, string='Opened', type='integer', multi='_get_statistics', ), 'replied': fields.function( _get_statistics, string='Replied', type='integer', multi='_get_statistics', ), 'bounced': fields.function( _get_statistics, string='Bounced', type='integer', multi='_get_statistics', ), 'received_ratio': fields.function( _get_statistics, string='Received Ratio', type='integer', multi='_get_statistics', ), 'opened_ratio': fields.function( _get_statistics, string='Opened Ratio', type='integer', multi='_get_statistics', ), 'replied_ratio': fields.function( _get_statistics, string='Replied Ratio', type='integer', multi='_get_statistics', ), # daily ratio 'opened_daily': fields.function( _get_daily_statistics, string='Opened', type='char', multi='_get_daily_statistics', ), 'replied_daily': fields.function( _get_daily_statistics, string='Replied', type='char', multi='_get_daily_statistics', ) } def default_get(self, cr, uid, fields, context=None): res = super(MassMailing, self).default_get(cr, uid, fields, context=context) if 'reply_to_mode' in fields and not 'reply_to_mode' in res and res.get( 'mailing_model'): if res['mailing_model'] in [ 'res.partner', 'mail.mass_mailing.contact' ]: res['reply_to_mode'] = 'email' else: res['reply_to_mode'] = 'thread' return res _defaults = { 'state': 'draft', 'email_from': lambda self, cr, uid, ctx=None: self.pool[ 'mail.message']._get_default_from(cr, uid, context=ctx), 'reply_to': lambda self, cr, uid, ctx=None: self.pool['mail.message']. _get_default_from(cr, uid, context=ctx), 'mailing_model': 'mail.mass_mailing.contact', 'contact_ab_pc': 100, } #------------------------------------------------------ # Technical stuff #------------------------------------------------------ def copy_data(self, cr, uid, id, default=None, context=None): mailing = self.browse(cr, uid, id, context=context) default = dict(default or {}, name=_('%s (copy)') % mailing.name) return super(MassMailing, self).copy_data(cr, uid, id, default, context=context) def read_group(self, cr, uid, domain, fields, groupby, offset=0, limit=None, context=None, orderby=False, lazy=True): """ Override read_group to always display all states. """ if groupby and groupby[0] == "state": # Default result structure # states = self._get_state_list(cr, uid, context=context) states = [('draft', 'Draft'), ('test', 'Tested'), ('done', 'Sent')] read_group_all_states = [{ '__context': { 'group_by': groupby[1:] }, '__domain': domain + [('state', '=', state_value)], 'state': state_value, 'state_count': 0, } for state_value, state_name in states] # Get standard results read_group_res = super(MassMailing, self).read_group(cr, uid, domain, fields, groupby, offset=offset, limit=limit, context=context, orderby=orderby) # Update standard results with default results result = [] for state_value, state_name in states: res = filter(lambda x: x['state'] == state_value, read_group_res) if not res: res = filter(lambda x: x['state'] == state_value, read_group_all_states) res[0]['state'] = [state_value, state_name] result.append(res[0]) return result else: return super(MassMailing, self).read_group(cr, uid, domain, fields, groupby, offset=offset, limit=limit, context=context, orderby=orderby) #------------------------------------------------------ # Views & Actions #------------------------------------------------------ def on_change_model_and_list(self, cr, uid, ids, mailing_model, list_ids, context=None): value = {} if mailing_model == 'mail.mass_mailing.contact': mailing_list_ids = set() for item in list_ids: if isinstance(item, (int, long)): mailing_list_ids.add(item) elif len(item) == 3: mailing_list_ids |= set(item[2]) if mailing_list_ids: value['mailing_domain'] = "[('list_id', 'in', %s)]" % list( mailing_list_ids) else: value['mailing_domain'] = "[('list_id', '=', False)]" else: value['mailing_domain'] = False return {'value': value} def action_duplicate(self, cr, uid, ids, context=None): copy_id = None for mid in ids: copy_id = self.copy(cr, uid, mid, context=context) if copy_id: return { 'type': 'ir.actions.act_window', 'view_type': 'form', 'view_mode': 'form', 'res_model': 'mail.mass_mailing', 'res_id': copy_id, 'context': context, } return False def action_test_mailing(self, cr, uid, ids, context=None): ctx = dict(context, default_mass_mailing_id=ids[0]) return { 'name': _('Test Mailing'), 'type': 'ir.actions.act_window', 'view_mode': 'form', 'res_model': 'mail.mass_mailing.test', 'target': 'new', 'context': ctx, } def action_edit_html(self, cr, uid, ids, context=None): if not len(ids) == 1: raise ValueError('One and only one ID allowed for this action') mail = self.browse(cr, uid, ids[0], context=context) url = '/website_mail/email_designer?model=mail.mass_mailing&res_id=%d&template_model=%s&enable_editor=1' % ( ids[0], mail.mailing_model) return { 'name': _('Open with Visual Editor'), 'type': 'ir.actions.act_url', 'url': url, 'target': 'self', } #------------------------------------------------------ # Email Sending #------------------------------------------------------ def get_recipients(self, cr, uid, mailing, context=None): if mailing.mailing_domain: domain = eval(mailing.mailing_domain) res_ids = self.pool[mailing.mailing_model].search(cr, uid, domain, context=context) else: res_ids = [] domain = [('id', 'in', res_ids)] # randomly choose a fragment if mailing.contact_ab_pc < 100: contact_nbr = self.pool[mailing.mailing_model].search( cr, uid, domain, count=True, context=context) topick = int(contact_nbr / 100.0 * mailing.contact_ab_pc) if mailing.mass_mailing_campaign_id and mailing.mass_mailing_campaign_id.unique_ab_testing: already_mailed = self.pool[ 'mail.mass_mailing.campaign'].get_recipients( cr, uid, [mailing.mass_mailing_campaign_id.id], context=context)[mailing.mass_mailing_campaign_id.id] else: already_mailed = set([]) remaining = set(res_ids).difference(already_mailed) if topick > len(remaining): topick = len(remaining) res_ids = random.sample(remaining, topick) return res_ids def send_mail(self, cr, uid, ids, context=None): author_id = self.pool['res.users'].browse( cr, uid, uid, context=context).partner_id.id for mailing in self.browse(cr, uid, ids, context=context): # instantiate an email composer + send emails res_ids = self.get_recipients(cr, uid, mailing, context=context) if not res_ids: raise Warning('Please select recipients.') comp_ctx = dict(context, active_ids=res_ids) composer_values = { 'author_id': author_id, 'attachment_ids': [(4, attachment.id) for attachment in mailing.attachment_ids], 'body': mailing.body_html, 'subject': mailing.name, 'model': mailing.mailing_model, 'email_from': mailing.email_from, 'record_name': False, 'composition_mode': 'mass_mail', 'mass_mailing_id': mailing.id, 'mailing_list_ids': [(4, l.id) for l in mailing.contact_list_ids], 'no_auto_thread': mailing.reply_to_mode != 'thread', } if mailing.reply_to_mode == 'email': composer_values['reply_to'] = mailing.reply_to composer_id = self.pool['mail.compose.message'].create( cr, uid, composer_values, context=comp_ctx) self.pool['mail.compose.message'].send_mail(cr, uid, [composer_id], context=comp_ctx) self.write(cr, uid, [mailing.id], { 'sent_date': fields.datetime.now(), 'state': 'done' }, context=context) return True
'department_id':fields.related('employee_id','department_id', type='many2one', relation='hr.department', string='Department', store=True), 'job_id':fields.related('employee_id','job_id', type='many2one', relation='hr.job', string='Title', store=True), 'emp_code':fields.related('employee_id','emp_code', type='char', string='Employee Code', store=True), 'mobile_phone':fields.related('employee_id','mobile_phone', type='char', string='Work Mobile', store=True), 'borrow_money_residual':fields.related('employee_id','money_residual', type='float', string='Borrowed residual', readonly=True), 'dimmission_reason':fields.text('Dimission Reason', required=True), 'advice_to_company':fields.text('Advice to company'), 'employment_start':fields.date('Employment Started'), 'date_request':fields.date('Request Date', required=True), 'date_done':fields.date('Done Date', required=False, readonly=True), 'approve_ids': fields.one2many('hr.dimission.item', 'dimission_id', 'Approvals', domain=[('type','=','approve')]), 'transfer_ids': fields.one2many('hr.dimission.item', 'dimission_id', 'Transfers', domain=[('type','=','transfer')]), 'payslip_id': fields.many2many('hr.emppay', string='Payslip'), 'attrpt_ids': fields.many2many('hr.rpt.attend.month', string='Attendance Reports'), 'hr_clock_ids': fields.function(_emp_clocks, string='HR Clocks', type='many2many', relation='hr.clock', readonly=True), 'attachment_lines': fields.one2many('ir.attachment', 'hr_admission_id','Attachment'), 'company_id':fields.many2one('res.company', 'Company', required=True), 'state': fields.selection([ ('draft', 'Draft'), ('in_progress', 'In Progress'), ('done', 'Done'), ('cancel', 'Cancel'), ], 'Status', select=True, readonly=True), } _defaults = { 'state': 'draft',
class website(osv.osv): def _get_menu(self, cr, uid, ids, name, arg, context=None): res = {} menu_obj = self.pool.get('website.menu') for id in ids: menu_ids = menu_obj.search(cr, uid, [('parent_id', '=', False), ('website_id', '=', id)], order='id', context=context) res[id] = menu_ids and menu_ids[0] or False return res _name = "website" # Avoid website.website convention for conciseness (for new api). Got a special authorization from xmo and rco _description = "Website" _columns = { 'name': fields.char('Website Name'), 'domain': fields.char('Website Domain'), 'company_id': fields.many2one('res.company', string="Company"), 'language_ids': fields.many2many('res.lang', 'website_lang_rel', 'website_id', 'lang_id', 'Languages'), 'default_lang_id': fields.many2one('res.lang', string="Default language"), 'default_lang_code': fields.related('default_lang_id', 'code', type="char", string="Default language code", store=True), 'social_twitter': fields.char('Twitter Account'), 'social_facebook': fields.char('Facebook Account'), 'social_github': fields.char('GitHub Account'), 'social_linkedin': fields.char('LinkedIn Account'), 'social_youtube': fields.char('Youtube Account'), 'social_googleplus': fields.char('Google+ Account'), 'google_analytics_key': fields.char('Google Analytics Key'), 'user_id': fields.many2one('res.users', string='Public User'), 'compress_html': fields.boolean('Compress HTML'), 'cdn_activated': fields.boolean('Activate CDN for assets'), 'cdn_url': fields.char('CDN Base URL'), 'cdn_filters': fields.text('CDN Filters', help="URL matching those filters will be rewritten using the CDN Base URL"), 'partner_id': fields.related('user_id','partner_id', type='many2one', relation='res.partner', string='Public Partner'), 'menu_id': fields.function(_get_menu, relation='website.menu', type='many2one', string='Main Menu') } _defaults = { 'user_id': lambda self,cr,uid,c: self.pool['ir.model.data'].xmlid_to_res_id(cr, openerp.SUPERUSER_ID, 'base.public_user'), 'company_id': lambda self,cr,uid,c: self.pool['ir.model.data'].xmlid_to_res_id(cr, openerp.SUPERUSER_ID,'base.main_company'), 'compress_html': False, 'cdn_activated': False, 'cdn_url': '//localhost:8069/', 'cdn_filters': '\n'.join(DEFAULT_CDN_FILTERS), } # cf. Wizard hack in website_views.xml def noop(self, *args, **kwargs): pass def write(self, cr, uid, ids, vals, context=None): self._get_languages.clear_cache(self) return super(website, self).write(cr, uid, ids, vals, context) def new_page(self, cr, uid, name, template='website.default_page', ispage=True, context=None): context = context or {} imd = self.pool.get('ir.model.data') view = self.pool.get('ir.ui.view') template_module, template_name = template.split('.') # completely arbitrary max_length page_name = slugify(name, max_length=50) page_xmlid = "%s.%s" % (template_module, page_name) try: # existing page imd.get_object_reference(cr, uid, template_module, page_name) except ValueError: # new page _, template_id = imd.get_object_reference(cr, uid, template_module, template_name) website_id = context.get('website_id') key = template_module+'.'+page_name page_id = view.copy(cr, uid, template_id, {'website_id': website_id, 'key': key}, context=context) page = view.browse(cr, uid, page_id, context=context) page.write({ 'arch': page.arch.replace(template, page_xmlid), 'name': page_name, 'page': ispage, }) return page_xmlid def page_for_name(self, cr, uid, ids, name, module='website', context=None): # whatever return '%s.%s' % (module, slugify(name, max_length=50)) def page_exists(self, cr, uid, ids, name, module='website', context=None): try: name = (name or "").replace("/page/website.", "").replace("/page/", "") if not name: return False return self.pool["ir.model.data"].get_object_reference(cr, uid, module, name) except: return False @openerp.tools.ormcache(skiparg=3) def _get_languages(self, cr, uid, id, context=None): website = self.browse(cr, uid, id) return [(lg.code, lg.name) for lg in website.language_ids] def get_cdn_url(self, cr, uid, uri, context=None): # Currently only usable in a website_enable request context if request and request.website and not request.debug: cdn_url = request.website.cdn_url cdn_filters = (request.website.cdn_filters or '').splitlines() for flt in cdn_filters: if flt and re.match(flt, uri): return urlparse.urljoin(cdn_url, uri) return uri def get_languages(self, cr, uid, ids, context=None): return self._get_languages(cr, uid, ids[0], context=context) def get_alternate_languages(self, cr, uid, ids, req=None, context=None): langs = [] if req is None: req = request.httprequest default = self.get_current_website(cr, uid, context=context).default_lang_code uri = req.path if req.query_string: uri += '?' + req.query_string shorts = [] for code, name in self.get_languages(cr, uid, ids, context=context): lg_path = ('/' + code) if code != default else '' lg = code.split('_') shorts.append(lg[0]) lang = { 'hreflang': ('-'.join(lg)).lower(), 'short': lg[0], 'href': req.url_root[0:-1] + lg_path + uri, } langs.append(lang) for lang in langs: if shorts.count(lang['short']) == 1: lang['hreflang'] = lang['short'] return langs @openerp.tools.ormcache(skiparg=4) def _get_current_website_id(self, cr, uid, domain_name, context=None): website_id = 1 if request: ids = self.search(cr, uid, [('domain', '=', domain_name)], context=context) if ids: website_id = ids[0] return website_id def get_current_website(self, cr, uid, context=None): domain_name = request.httprequest.environ.get('HTTP_HOST', '').split(':')[0] website_id = self._get_current_website_id(cr, uid, domain_name, context=context) return self.browse(cr, uid, website_id, context=context) def is_publisher(self, cr, uid, ids, context=None): Access = self.pool['ir.model.access'] is_website_publisher = Access.check(cr, uid, 'ir.ui.view', 'write', False, context=context) return is_website_publisher def is_user(self, cr, uid, ids, context=None): Access = self.pool['ir.model.access'] return Access.check(cr, uid, 'ir.ui.menu', 'read', False, context=context) def get_template(self, cr, uid, ids, template, context=None): if not isinstance(template, (int, long)) and '.' not in template: template = 'website.%s' % template View = self.pool['ir.ui.view'] view_id = View.get_view_id(cr, uid, template, context=context) if not view_id: raise NotFound return View.browse(cr, uid, view_id, context=context) def _render(self, cr, uid, ids, template, values=None, context=None): # TODO: remove this. (just kept for backward api compatibility for saas-3) return self.pool['ir.ui.view'].render(cr, uid, template, values=values, context=context) def render(self, cr, uid, ids, template, values=None, status_code=None, context=None): # TODO: remove this. (just kept for backward api compatibility for saas-3) return request.render(template, values, uid=uid) def pager(self, cr, uid, ids, url, total, page=1, step=30, scope=5, url_args=None, context=None): # Compute Pager page_count = int(math.ceil(float(total) / step)) page = max(1, min(int(page if str(page).isdigit() else 1), page_count)) scope -= 1 pmin = max(page - int(math.floor(scope/2)), 1) pmax = min(pmin + scope, page_count) if pmax - pmin < scope: pmin = pmax - scope if pmax - scope > 0 else 1 def get_url(page): _url = "%s/page/%s" % (url, page) if page > 1 else url if url_args: _url = "%s?%s" % (_url, werkzeug.url_encode(url_args)) return _url return { "page_count": page_count, "offset": (page - 1) * step, "page": { 'url': get_url(page), 'num': page }, "page_start": { 'url': get_url(pmin), 'num': pmin }, "page_previous": { 'url': get_url(max(pmin, page - 1)), 'num': max(pmin, page - 1) }, "page_next": { 'url': get_url(min(pmax, page + 1)), 'num': min(pmax, page + 1) }, "page_end": { 'url': get_url(pmax), 'num': pmax }, "pages": [ {'url': get_url(page), 'num': page} for page in xrange(pmin, pmax+1) ] } def rule_is_enumerable(self, rule): """ Checks that it is possible to generate sensible GET queries for a given rule (if the endpoint matches its own requirements) :type rule: werkzeug.routing.Rule :rtype: bool """ endpoint = rule.endpoint methods = rule.methods or ['GET'] converters = rule._converters.values() if not ('GET' in methods and endpoint.routing['type'] == 'http' and endpoint.routing['auth'] in ('none', 'public') and endpoint.routing.get('website', False) and all(hasattr(converter, 'generate') for converter in converters) and endpoint.routing.get('website')): return False # dont't list routes without argument having no default value or converter spec = inspect.getargspec(endpoint.method.original_func) # remove self and arguments having a default value defaults_count = len(spec.defaults or []) args = spec.args[1:(-defaults_count or None)] # check that all args have a converter return all( (arg in rule._converters) for arg in args) def enumerate_pages(self, cr, uid, ids, query_string=None, context=None): """ Available pages in the website/CMS. This is mostly used for links generation and can be overridden by modules setting up new HTML controllers for dynamic pages (e.g. blog). By default, returns template views marked as pages. :param str query_string: a (user-provided) string, fetches pages matching the string :returns: a list of mappings with two keys: ``name`` is the displayable name of the resource (page), ``url`` is the absolute URL of the same. :rtype: list({name: str, url: str}) """ router = request.httprequest.app.get_db_router(request.db) # Force enumeration to be performed as public user url_list = [] for rule in router.iter_rules(): if not self.rule_is_enumerable(rule): continue converters = rule._converters or {} if query_string and not converters and (query_string not in rule.build([{}], append_unknown=False)[1]): continue values = [{}] convitems = converters.items() # converters with a domain are processed after the other ones gd = lambda x: hasattr(x[1], 'domain') and (x[1].domain <> '[]') convitems.sort(lambda x, y: cmp(gd(x), gd(y))) for (i,(name, converter)) in enumerate(convitems): newval = [] for val in values: query = i==(len(convitems)-1) and query_string for v in converter.generate(request.cr, uid, query=query, args=val, context=context): newval.append( val.copy() ) v[name] = v['loc'] del v['loc'] newval[-1].update(v) values = newval for value in values: domain_part, url = rule.build(value, append_unknown=False) page = {'loc': url} for key,val in value.items(): if key.startswith('__'): page[key[2:]] = val if url in ('/sitemap.xml',): continue if url in url_list: continue url_list.append(url) yield page def search_pages(self, cr, uid, ids, needle=None, limit=None, context=None): name = (needle or "").replace("/page/website.", "").replace("/page/", "") res = [] for page in self.enumerate_pages(cr, uid, ids, query_string=name, context=context): if needle in page['loc']: res.append(page) if len(res) == limit: break return res def kanban(self, cr, uid, ids, model, domain, column, template, step=None, scope=None, orderby=None, context=None): step = step and int(step) or 10 scope = scope and int(scope) or 5 orderby = orderby or "name" get_args = dict(request.httprequest.args or {}) model_obj = self.pool[model] relation = model_obj._columns.get(column)._obj relation_obj = self.pool[relation] get_args.setdefault('kanban', "") kanban = get_args.pop('kanban') kanban_url = "?%s&kanban=" % werkzeug.url_encode(get_args) pages = {} for col in kanban.split(","): if col: col = col.split("-") pages[int(col[0])] = int(col[1]) objects = [] for group in model_obj.read_group(cr, uid, domain, ["id", column], groupby=column): obj = {} # browse column relation_id = group[column][0] obj['column_id'] = relation_obj.browse(cr, uid, relation_id) obj['kanban_url'] = kanban_url for k, v in pages.items(): if k != relation_id: obj['kanban_url'] += "%s-%s" % (k, v) # pager number = model_obj.search(cr, uid, group['__domain'], count=True) obj['page_count'] = int(math.ceil(float(number) / step)) obj['page'] = pages.get(relation_id) or 1 if obj['page'] > obj['page_count']: obj['page'] = obj['page_count'] offset = (obj['page']-1) * step obj['page_start'] = max(obj['page'] - int(math.floor((scope-1)/2)), 1) obj['page_end'] = min(obj['page_start'] + (scope-1), obj['page_count']) # view data obj['domain'] = group['__domain'] obj['model'] = model obj['step'] = step obj['orderby'] = orderby # browse objects object_ids = model_obj.search(cr, uid, group['__domain'], limit=step, offset=offset, order=orderby) obj['object_ids'] = model_obj.browse(cr, uid, object_ids) objects.append(obj) values = { 'objects': objects, 'range': range, 'template': template, } return request.website._render("website.kanban_contain", values) def kanban_col(self, cr, uid, ids, model, domain, page, template, step, orderby, context=None): html = "" model_obj = self.pool[model] domain = safe_eval(domain) step = int(step) offset = (int(page)-1) * step object_ids = model_obj.search(cr, uid, domain, limit=step, offset=offset, order=orderby) object_ids = model_obj.browse(cr, uid, object_ids) for object_id in object_ids: html += request.website._render(template, {'object_id': object_id}) return html def _image_placeholder(self, response): # file_open may return a StringIO. StringIO can be closed but are # not context managers in Python 2 though that is fixed in 3 with contextlib.closing(openerp.tools.misc.file_open( os.path.join('web', 'static', 'src', 'img', 'placeholder.png'), mode='rb')) as f: response.data = f.read() return response.make_conditional(request.httprequest) def _image(self, cr, uid, model, id, field, response, max_width=maxint, max_height=maxint, cache=None, context=None): """ Fetches the requested field and ensures it does not go above (max_width, max_height), resizing it if necessary. Resizing is bypassed if the object provides a $field_big, which will be interpreted as a pre-resized version of the base field. If the record is not found or does not have the requested field, returns a placeholder image via :meth:`~._image_placeholder`. Sets and checks conditional response parameters: * :mailheader:`ETag` is always set (and checked) * :mailheader:`Last-Modified is set iif the record has a concurrency field (``__last_update``) The requested field is assumed to be base64-encoded image data in all cases. """ Model = self.pool[model] id = int(id) ids = Model.search(cr, uid, [('id', '=', id)], context=context) if not ids and 'website_published' in Model._fields: ids = Model.search(cr, openerp.SUPERUSER_ID, [('id', '=', id), ('website_published', '=', True)], context=context) if not ids: return self._image_placeholder(response) concurrency = '__last_update' [record] = Model.read(cr, openerp.SUPERUSER_ID, [id], [concurrency, field], context=context) if concurrency in record: server_format = openerp.tools.misc.DEFAULT_SERVER_DATETIME_FORMAT try: response.last_modified = datetime.datetime.strptime( record[concurrency], server_format + '.%f') except ValueError: # just in case we have a timestamp without microseconds response.last_modified = datetime.datetime.strptime( record[concurrency], server_format) # Field does not exist on model or field set to False if not record.get(field): # FIXME: maybe a field which does not exist should be a 404? return self._image_placeholder(response) response.set_etag(hashlib.sha1(record[field]).hexdigest()) response.make_conditional(request.httprequest) if cache: response.cache_control.max_age = cache response.expires = int(time.time() + cache) # conditional request match if response.status_code == 304: return response data = record[field].decode('base64') image = Image.open(cStringIO.StringIO(data)) response.mimetype = Image.MIME[image.format] filename = '%s_%s.%s' % (model.replace('.', '_'), id, str(image.format).lower()) response.headers['Content-Disposition'] = 'inline; filename="%s"' % filename if (not max_width) and (not max_height): response.data = data return response w, h = image.size max_w = int(max_width) if max_width else maxint max_h = int(max_height) if max_height else maxint if w < max_w and h < max_h: response.data = data else: size = (max_w, max_h) img = image_resize_and_sharpen(image, size, preserve_aspect_ratio=True) image_save_for_web(img, response.stream, format=image.format) # invalidate content-length computed by make_conditional as # writing to response.stream does not do it (as of werkzeug 0.9.3) del response.headers['Content-Length'] return response def image_url(self, cr, uid, record, field, size=None, context=None): """Returns a local url that points to the image field of a given browse record.""" model = record._name id = '%s_%s' % (record.id, hashlib.sha1(record.sudo().write_date).hexdigest()[0:7]) size = '' if size is None else '/%s' % size return '/website/image/%s/%s/%s%s' % (model, id, field, size)
('integer', fields.integer()), ('float', fields.float()), ('decimal', fields.float(digits=(16, 3))), ('string.bounded', fields.char('unknown', size=16)), ('string.required', fields.char('unknown', size=None, required=True)), ('string', fields.char('unknown', size=None)), ('date', fields.date()), ('datetime', fields.datetime()), ('text', fields.text()), ('selection', fields.selection([(1, "Foo"), (2, "Bar"), (3, "Qux"), (4, '')])), # here use size=-1 to store the values as integers instead of strings ('selection.function', fields.selection(selection_fn, size=-1)), # just relate to an integer ('many2one', fields.many2one('export.integer')), ('one2many', fields.one2many('export.one2many.child', 'parent_id')), ('many2many', fields.many2many('export.many2many.other')), ('function', fields.function(function_fn, fnct_inv=function_fn_write, type="integer")), # related: specialization of fields.function, should work the same way # TODO: reference ] for name, field in models: class NewModel(orm.Model): _name = 'export.%s' % name _columns = { 'const': fields.integer(), 'value': field, } _defaults = { 'const': 4, }
class proforma_invoice_line(osv.osv): def _amount_line(self, cr, uid, ids, prop, unknow_none, unknow_dict): res = {} tax_obj = self.pool.get('account.tax') cur_obj = self.pool.get('res.currency') for line in self.browse(cr, uid, ids): price = line.price_unit taxes = tax_obj.compute_all(cr, uid, line.invoice_line_tax_id, price, line.quantity, product=line.product_id, partner=line.invoice_id.partner_id) res[line.id] = taxes['total'] if line.invoice_id: cur = line.invoice_id.currency_id res[line.id] = cur_obj.round(cr, uid, cur, res[line.id]) return res _name = "proforma.invoice.line" _description = "Proforma Invoice Line" _order = "invoice_id,sequence,id" _columns = { 'name': fields.text('Description', required=True), 'origin': fields.char( 'Source Document', size=256, help= "Reference of the document that produced this proforma invoice."), 'sequence': fields.integer( 'Sequence', help="Gives the sequence of this line when displaying the invoice." ), 'invoice_id': fields.many2one('proforma.invoice', 'Proforma Invoice', ondelete='cascade', select=True), 'uom_id': fields.many2one('product.uom', 'Unit of Measure', ondelete='set null', select=True), 'product_id': fields.many2one('product.product', 'Product', ondelete='set null', select=True), 'price_unit': fields.float('Unit Price', required=True, digits_compute=dp.get_precision('Product Price')), 'price_subtotal': fields.function(_amount_line, string='Amount', type="float", digits_compute=dp.get_precision('Account')), 'invoice_line_tax_id': fields.many2many('account.tax', 'proforma_invoice_line_tax', 'proforma_invoice_line_id', 'tax_id', 'Taxes', domain=[('parent_id', '=', False)]), 'quantity': fields.float( 'Quantity', digits_compute=dp.get_precision('Product Unit of Measure'), required=True), 'company_id': fields.related('invoice_id', 'company_id', type='many2one', relation='res.company', string='Company', store=True, readonly=True), 'partner_id': fields.related('invoice_id', 'partner_id', type='many2one', relation='res.partner', string='Partner', store=True) } _defaults = { 'quantity': 1, 'price_unit': 0.0, 'sequence': 10, }
class cashback_lines_wizard(osv.osv_memory): _name = "cashback.lines.wizard" _columns = { "customer_ids": fields.many2many( 'res.partner', 'cashback_lines_wizard_partner_rel', 'wiz_id', 'partner_id', 'Customers', ), "cashback_id": fields.many2one('account.cashback', "Cashback"), "current_customer_ids": fields.many2many( 'res.partner', 'cashback_lines_current_partner_rel', 'wiz_id', 'partner_id', 'Existing Customers', ), "start_date": fields.date("Start Date", required=True), "end_date": fields.date("End Date", required=True), } def default_get(self, cr, uid, fields, context=None): res = super(cashback_lines_wizard, self).default_get(cr, uid, fields, context=context) if context.get('active_id', False): cashback = self.pool.get('account.cashback').browse( cr, uid, context.get('active_id')) current_customer_ids = [ x.name and x.name.id for x in cashback.line_ids ] res.update({ 'cashback_id': context.get('active_id', False), 'current_customer_ids': current_customer_ids, 'start_date': cashback.start_date, 'end_date': cashback.end_date, }) return res def generate(self, cr, uid, ids, context=None): if not context: context = {} wiz = self.browse(cr, uid, ids[0], context=context) for partner in wiz.customer_ids: value = { "name": partner and partner.id, "start_date": wiz.start_date, "end_date": wiz.end_date, "current_disc": partner.current_discount or 0.0, "cashback_id": wiz.cashback_id and wiz.cashback_id.id or False, "omzet_before_disc": 0.0, "omzet_after_disc": 0.0, "omzet_paid": 0.0, "deposit": 0.0, "proposed_disc": 0.0, "cash_back_amt": 0.0, } print "xxxxxxxxxxxxxxxxx", value self.pool.get('account.cashback.line').create(cr, uid, value) return True
class account_sat_related_wizard(osv.osv_memory): """ Relacion plan de cuentas SAT con el plan de cuentas """ _name = 'account.sat.related.wizard' _description = 'Relacionar cuentas SAT' _columns = { 'id': fields.integer('ID'), 'name': fields.char('Nombre'), 'account_sat_id': fields.many2one('account.account.sat', 'Cuenta SAT', domain=[('type', '!=', 'view')], select="1"), #'account_apply_ids': fields.one2many('account.sat.related.apply.wizard', 'wizard_id', 'Cuentas aplicadas'), 'account_apply_ids': fields.many2many('account.account', 'account_sat_related_apply_wizard_rel', 'wizard_id', 'account_id', 'Cuentas aplicadas', domain=[('type', '!=', 'view')]), 'account_ids': fields.one2many('account.sat.related.account.wizard', 'wizard_id', 'Plan contable'), 'filter': fields.char('Filtrar cuenta', size=164), } _defaults = {'name': 'Relacion Cuentas SAT'} def onchange_account_sat_id(self, cr, uid, ids, account_sat_id, filter, context=None): """ Actualiza la informacion de los movimientos pendientes de relacionar """ acc_obj = self.pool.get('account.account') acc_line_rel = [] acc_line_ids = [] if account_sat_id: # Genera filtros para obtener las cuentas filter_search = [('account_sat_id', '=', False), ('type', '!=', 'view')] if filter: filter_search.append('|') filter_search.append(('name', 'ilike', '%' + filter + '%')) filter_search.append(('code', 'ilike', '%' + filter + '%')) # Busca las cuentas pendientes de conciliar account_ids = acc_obj.search(cr, uid, filter_search) if account_ids: # Recorre los movimientos y los agrega en la vista de banco for account_id in account_ids: val = { 'account_id': account_id, } acc_line_ids.append(val) # Busca las cuentas conciliadas con la cuenta acc_line_rel = acc_obj.search( cr, uid, [('account_sat_id', '=', account_sat_id), ('type', '!=', 'view')]) # Actualiza los valores de retorno return { 'value': { 'account_ids': acc_line_ids, 'account_apply_ids': acc_line_rel } } def onchange_filter(self, cr, uid, ids, filter, account_sat_id, account_apply_ids, context=None): """ Filtra la lista de cuentas que estan pendientes de aplicar """ acc_obj = self.pool.get('account.account') acc_line_ids = [] apply_ids = [] # Valida que ya este seleccionada una cuenta sat y este guardado if account_sat_id: # Descarta las cuentas que estan ya sobre la lista for acc in account_apply_ids: print "************* acc ******* ", acc if acc[0] == 6: apply_ids = acc[2] # Genera filtros para obtener las cuentas filter_search = [ '|', ('account_sat_id', '=', account_sat_id), ('account_sat_id', '=', False), ('type', '!=', 'view'), ('id', 'not in', apply_ids) ] if filter: filter_search.append('|') filter_search.append(('name', 'ilike', '%' + filter + '%')) filter_search.append(('code', 'ilike', '%' + filter + '%')) # Busca las cuentas pendientes de conciliar acc_ids = acc_obj.search(cr, uid, filter_search, context=context) for account_id in acc_ids: val = {'account_id': account_id} acc_line_ids.append(val) # Actualiza los valores de retorno return {'value': {'account_ids': acc_line_ids}} def action_related_auto(self, cr, uid, ids, context=None): act_obj = self.pool.get('account.account') acc_obj = self.pool.get('account.account.sat') accounts = [ (1111001000, 101.01), (1111002000, 101.01), (1111003000, 101.01), (111301, 102.01), (11130201000, 102.01), (11130202000, 102.02), (11130203000, 103.01), (1114001000, 103.01), (1115001000, 103.01), (1115002000, 103.03), (1115003000, 105.01), (1115004000, 105.01), (1121001000, 105.01), (1122001000, 105.01), #107.05 (1123001000, 105.02), (1122004000, 107.01), (1122005000, 107.01), (1124001000, 107.02), (1125001000, 107.05), #107.05 (1125002000, 107.05), #107.05 (1125003000, 107.05), #107.05 (1125004000, 107.02), (1125008000, 120.01), (1125009000, 115.01), (1128001000, 115.01), (1129001000, 115.01), (1131001000, 115.01), (1131002000, 115.01), (1131003000, 174.01), (1131009000, 109.01), (1134001000, 184.02), (1151006000, 118.02), (1151007000, 119.01), (1151004000, 118.01), (1211001000, 151.01), (1211005000, 152.01), (1211007000, 153.01), (1211009000, 154.01), (1211011000, 155.01), (1212001000, 156.01), (1212007000, 171.01), (1212009000, 171.02), (1212011000, 171.03), (1212015000, 171.04), (2111001000, 171.05), (2122001000, 179.01), (2124001000, 177.01), (2151001000, 202.01), (2161005000, 201.01), (2161006000, 203.18), (2161007000, 210.04), (2171001000, 210.07), (2173001000, 211.01), (2173002000, 203.18), (2173003000, 203.18), (2175004000, 203.18), (2175005000, 213.04), (2175006000, 210.01), (2175014000, 215.01), (2175017000, 213.03), (2175021000, 213.03), (2191001000, 213.03), (2191002000, 216.1), (2201111000, 216.01), (2201112000, 216.02), (2201113000, 216.04), (2201114000, 216.03), (2201115000, 216.1), (2201116000, 216.1), (2201117000, 213.01), (2201118000, 252.01), (2202111000, 252.05), (2511001000, 252.17), (2581001000, 301.01), (2591001000, 301.04), (3111001000, 304.01), (3131001000, 305.01), (3211001000, 303.01), (3211002000, 301.03), (3311001000, 306.01), (3311002000, 306.01), (4511002000, 401.01), (4511003000, 401.01), (5111001000, 401.13), (5111002000, 401.16), (5111003000, 402.01), (5112001000, 601.72), (5114001000, 601.61), (6111001000, 601.84), (7111001000, 601.84), (7111002000, 601.84), (7111003000, 601.61), (7111004000, 601.61), (7111005000, 601.84), (7111006000, 601.84), (7111007000, 601.72), (7111008000, 601.76), (7111009000, 601.01), (7111010000, 601.01), (7111011000, 601.03), (7131001000, 601.05), (7131002000, 601.1), (7131003000, 601.16), (7131004000, 601.15), (7131005000, 601.25), (7131006000, 601.25), (7131007000, 601.17), (7131008000, 601.25), (7131009000, 601.25), (7131010000, 601.25), (7131011000, 601.27), (7131012000, 601.25), (7131013000, 601.06), (7131016000, 601.07), (7131017000, 601.29), (7131019000, 601.25), (7131020000, 601.49), (7131021000, 601.31), (7131025000, 601.25), (7131030000, 601.25), (7131031000, 601.25), (7131033000, 601.56), (7131035000, 601.56), (7131036000, 601.56), (7151001000, 601.56), (7151002000, 601.56), (7151003000, 601.53), (7151004000, 601.38), (7151005000, 601.79), (7151006000, 601.52), (7151007000, 601.5), (7151009000, 601.51), (7151010000, 601.54), (7151012000, 601.55), (7151013000, 601.54), (7151014000, 601.49), (7151015000, 601.83), (7151016000, 601.49), (7151017000, 601.84), (7151018000, 601.64), (7151019000, 601.84), (7151021000, 601.61), (7151022000, 601.84), (7151023000, 601.46), (7151024000, 601.45), (7151025000, 601.84), (7151026000, 601.84), (7151027000, 601.84), (7151028000, 601.84), (7151029000, 601.72), (7151030000, 601.84), (7151031000, 601.38), (7151032000, 601.64), (7151033000, 601.49), (7151035000, 601.48), (7151036000, 601.84), (7151039000, 601.57), (7151040000, 601.83), (7151041000, 601.32), (7151043000, 601.84), (7151044000, 601.61), (7151045000, 613.01), (7151046000, 613.02), (7151047000, 613.03), (7151048000, 613.04), (7131037000, 613.05), (7161002000, 614.01), (7161003000, 701.04), (7161004000, 701.1), (7161005000, 701.1), (7161006000, 701.04), (7162001000, 601.59), (9111001000, 703.21), (9111002000, 701.01), (9111003000, 703.21), (9111004000, 701.01), (9113099000, 702.04), (9113002000, 702.05), (9113006000, 702.1), (9113010000, 704.23), (9113012000, 704.19), (9211001000, 702.01), (9211002000, 702.1), (9211003000, 704.23), (9212001000, 114.01), (9212002000, 113.08), (9212003000, 119.01), (9212004000, 110.01), (1152001000, 207.01), (1151005000, 704.23), (1152005000, 703.21), (1152, 113.04), (2202119000, 113.07), (9212006000, 113.01), (11130204000, 113.02), (2124002000, 113.03), (2511002000, 183.01), (2511002001, 216.11), (2511002002, 211.02), (2511003000, 211.03), (2511004000, 217.01), (3912, 208.01), (3911000001, 601.26), (3911000002, 601.28), (3911000003, 614.02), (3911000004, 614.1), (3911000005, 113.08), (3912000001, 613.05), (3912000002, 703.21), (3912000003, 703.21), (3911000006, 118.01), (1212013000, 206.01), (1152002000, 501.01), (1152003000, 174.01), (3912000004, 304.02), (7171002000, 304.01), (7171003000, 216.03), (7171004000, 216.1), (7171, 216.04), (717, 216.1), (13, 105.02), (1371001000, 704.23), (1371, 704.23), (137, 601.58), (7161008000, 213.02), (4511001000, 601.31), (1151008000, 210.06), (1152007000, 601.62), (1153001000, 205.02), (1153002000, 601.6), (1153003000, 601.46), (1221001000, 113.08), (1221003000, 182.01), (1251, 184.03), (1251001000, 184.03), (127, 184.02), (1271, 216.1), (1272, 611.01), (1272001, 607.01), (1272001001, 703.09), (1272001002, 601.21), (1272001003, 601.34), (1272001004, 601.84) ] for account in accounts: act_ids = act_obj.search(cr, uid, [('code', '=', str(account[0]))]) acc_ids = acc_obj.search(cr, uid, [('code', '=', str(account[1]))]) for act_act in act_obj.browse(cr, uid, act_ids): act = act_act.id for acc_sat in acc_obj.browse(cr, uid, acc_ids): acc = acc_sat.id cr.execute( """update account_account set account_sat_id = %s where id = %s""" % (acc, act)) cr.commit() def action_related_account(self, cr, uid, ids, context=None): """ Hace la aplicacion sobre las cuentas relacionadas """ # Recorre los registros a validar for wizard in self.browse(cr, uid, ids, context=context): acc_ids = [] # Si no hay una cuenta sat no aplica la relacion if not wizard.account_sat_id: continue # Obtiene el total a cargar en las transacciones for account in wizard.account_apply_ids: # Actualiza la lista de cuentas a relacionar acc_ids.append(account.id) # Actualiza la informacion de las cuentas sobre la cuenta SAT self.pool.get('account.account.sat').write( cr, uid, [wizard.account_sat_id.id], {'account_ids': [[6, False, acc_ids]]}, context=context) # Elimina registros anteriores reg_ids = self.search(cr, uid, [], context=context) self.unlink(cr, uid, reg_ids, context=context) # Actualiza variable de retorno context.update({'default_account_sat_id': False}) dummy, view_id = self.pool.get('ir.model.data').get_object_reference( cr, uid, 'account_sat', 'account_sat_related_wizard_form_view') return { 'name': _("Relacionar Cuentas SAT"), 'view_mode': 'form', 'view_id': view_id, 'view_type': 'form', 'res_model': 'account.sat.related.wizard', 'type': 'ir.actions.act_window', 'nodestroy': True, 'target': 'inline', 'domain': '[]', 'context': context, #'res_id' : res_id, # id of the object to which to redirected } def action_related_cancel(self, cr, uid, ids, context=None): """ Hace la cancelacion de la relacion de cuentas """ # Elimina registros anteriores reg_ids = self.search(cr, uid, [], context=context) self.unlink(cr, uid, reg_ids, context=context) # Actualiza variable de retorno context.update({'default_account_sat_id': False}) dummy, view_id = self.pool.get('ir.model.data').get_object_reference( cr, uid, 'account_sat', 'account_sat_related_wizard_form_view') return { 'name': _("Relacionar Cuentas SAT"), 'view_mode': 'form', 'view_id': view_id, 'view_type': 'form', 'res_model': 'account.sat.related.wizard', 'type': 'ir.actions.act_window', 'nodestroy': True, 'target': 'inline', 'domain': '[]', 'context': context, #'res_id' : res_id, # id of the object to which to redirected } def action_remove(self, cr, uid, ids, context=None): """ Quita la relacion de las cuentas relacionadas a la cuenta sat """ if context is None: context = {} self.write(cr, uid, ids, {'account_apply_ids': [[6, False, []]]}, context=context) return True def action_apply(self, cr, uid, ids, context=None): """ Actualiza el valor del monto aplicado sobre las lineas seleccionadas """ if context is None: context = {} line_ids = [] # Recorre las lineas de las cuentas a aplicar for wizard in self.browse(cr, uid, ids, context=context): # Agrega al arreglo los ids a aplicar a la cuenta sat for line in wizard.account_ids: if line.account_id: line_ids.append(line.account_id.id) # Agrega al arrelog los ids ya aplycados for line in wizard.account_apply_ids: line_ids.append(line.id) print "************ line_ids ******* ", line_ids self.write(cr, uid, ids, { 'account_apply_ids': [[6, False, line_ids]], 'account_ids': [[6, False, []]] }, context=context) return False def button_dummy(self, cr, uid, ids, context=None): """ Actualiza el valor del monto aplicado sobre las lineas seleccionadas """ if context is None: context = {} acc_obj = self.pool.get('account.account') line_obj = self.pool.get('account.sat.related.account.wizard') line_rel_obj = self.pool.get('account.sat.related.apply.wizard') acc_line_rel = [] acc_line_ids = [] # Obtiene la cuenta sat wizard = self.browse(cr, uid, ids[0], context=context) account_sat_id = wizard.account_sat_id.id or False wizard_id = wizard.id # Elimina las lineas relacionadas line_ids = line_obj.search(cr, uid, [('wizard_id', '=', wizard_id)]) line_obj.unlink(cr, uid, line_ids, context=context) line_rel_ids = line_obj.search(cr, uid, [('wizard_id', '=', wizard_id)]) line_rel_obj.unlink(cr, uid, line_rel_ids, context=context) # Busca las cuentas pendientes de conciliar acc_ids = acc_obj.search(cr, uid, [('account_sat_id', '=', False), ('type', '!=', 'view')]) for account_id in acc_ids: val = {'wizard_id': wizard_id, 'account_id': account_id} line_obj.create(cr, uid, val, context=context) #acc_line_ids.append(val) if account_sat_id: # Busca las cuentas conciliadas con la cuenta account_ids = acc_obj.search( cr, uid, [('account_sat_id', '=', account_sat_id), ('type', '!=', 'view')]) if account_ids: # Recorre los movimientos y los agrega en la vista de banco for account_id in account_ids: val = { 'wizard_id': wizard_id, 'account_id': account_id, } line_rel_obj.create(cr, uid, val, context=context) #acc_line_rel.append(val) self.write(cr, uid, ids, {}, context=context) return True
class partner_vat_intra(osv.osv_memory): """ Partner Vat Intra """ _name = "partner.vat.intra" _description = 'Partner VAT Intra' def _get_xml_data(self, cr, uid, context=None): if context.get('file_save', False): return base64.encodestring(context['file_save'].encode('utf8')) return '' def _get_europe_country(self, cursor, user, context=None): return self.pool.get('res.country').search(cursor, user, [ ('code', 'in', [ 'AT', 'BG', 'CY', 'CZ', 'DK', 'EE', 'FI', 'FR', 'DE', 'GR', 'HU', 'IE', 'IT', 'LV', 'LT', 'LU', 'MT', 'NL', 'PL', 'PT', 'RO', 'SK', 'SI', 'ES', 'SE', 'GB' ]) ]) _columns = { 'name': fields.char('File Name'), 'period_code': fields.char( 'Period Code', size=6, required=True, help= '''This is where you have to set the period code for the intracom declaration using the format: ppyyyy PP can stand for a month: from '01' to '12'. PP can stand for a trimester: '31','32','33','34' The first figure means that it is a trimester, The second figure identify the trimester. PP can stand for a complete fiscal year: '00'. YYYY stands for the year (4 positions). '''), 'period_ids': fields.many2many( 'account.period', 'account_period_rel', 'acc_id', 'period_id', 'Period (s)', help= 'Select here the period(s) you want to include in your intracom declaration' ), 'tax_code_id': fields.many2one('account.tax.code', 'Company', domain=[('parent_id', '=', False)], help="Keep empty to use the user's company", required=True), 'test_xml': fields.boolean('Test XML file', help="Sets the XML output as test file"), 'mand_id': fields.char( 'Reference', help="Reference given by the Representative of the sending company." ), 'msg': fields.text('File created', readonly=True), 'no_vat': fields.text( 'Partner With No VAT', readonly=True, help= "The Partner whose VAT number is not defined and they are not included in XML File." ), 'file_save': fields.binary('Save File', readonly=True), 'country_ids': fields.many2many('res.country', 'vat_country_rel', 'vat_id', 'country_id', 'European Countries'), 'comments': fields.text('Comments'), } def _get_tax_code(self, cr, uid, context=None): obj_tax_code = self.pool.get('account.tax.code') obj_user = self.pool.get('res.users') company_id = obj_user.browse(cr, uid, uid, context=context).company_id.id tax_code_ids = obj_tax_code.search(cr, uid, [('company_id', '=', company_id), ('parent_id', '=', False)], context=context) return tax_code_ids and tax_code_ids[0] or False _defaults = { 'country_ids': _get_europe_country, 'file_save': _get_xml_data, 'name': 'vat_intra.xml', 'tax_code_id': _get_tax_code, } def _get_datas(self, cr, uid, ids, context=None): """Collects require data for vat intra xml :param ids: id of wizard. :return: dict of all data to be used to generate xml for Partner VAT Intra. :rtype: dict """ if context is None: context = {} obj_user = self.pool.get('res.users') obj_sequence = self.pool.get('ir.sequence') obj_partner = self.pool.get('res.partner') xmldict = {} post_code = street = city = country = data_clientinfo = '' seq = amount_sum = 0 wiz_data = self.browse(cr, uid, ids[0], context=context) comments = wiz_data.comments if wiz_data.tax_code_id: data_company = wiz_data.tax_code_id.company_id else: data_company = obj_user.browse(cr, uid, uid, context=context).company_id # Get Company vat company_vat = data_company.partner_id.vat if not company_vat: raise osv.except_osv( _('Insufficient Data!'), _('No VAT number associated with your company.')) company_vat = company_vat.replace(' ', '').upper() issued_by = company_vat[:2] if len(wiz_data.period_code) != 6: raise osv.except_osv(_('Error!'), _('Period code is not valid.')) if not wiz_data.period_ids: raise osv.except_osv(_('Insufficient Data!'), _('Please select at least one Period.')) p_id_list = obj_partner.search(cr, uid, [('vat', '!=', False)], context=context) if not p_id_list: raise osv.except_osv( _('Insufficient Data!'), _('No partner has a VAT number associated with him.')) seq_declarantnum = obj_sequence.next_by_code(cr, uid, 'declarantnum') dnum = company_vat[2:] + seq_declarantnum[-4:] addr = obj_partner.address_get(cr, uid, [data_company.partner_id.id], ['invoice']) email = data_company.partner_id.email or '' phone = data_company.partner_id.phone or '' if addr.get('invoice', False): ads = obj_partner.browse(cr, uid, [addr['invoice']])[0] city = (ads.city or '') post_code = (ads.zip or '') if ads.street: street = ads.street if ads.street2: street += ' ' street += ads.street2 if ads.country_id: country = ads.country_id.code if not country: country = company_vat[:2] if not email: raise osv.except_osv( _('Insufficient Data!'), _('No email address associated with the company.')) if not phone: raise osv.except_osv(_('Insufficient Data!'), _('No phone associated with the company.')) xmldict.update({ 'company_name': data_company.name, 'company_vat': company_vat, 'vatnum': company_vat[2:], 'mand_id': wiz_data.mand_id, 'sender_date': str(time.strftime('%Y-%m-%d')), 'street': street, 'city': city, 'post_code': post_code, 'country': country, 'email': email, 'phone': phone.replace('/', '').replace('.', '').replace('(', '').replace( ')', '').replace(' ', ''), 'period': wiz_data.period_code, 'clientlist': [], 'comments': comments, 'issued_by': issued_by, }) #tax code 44: services #tax code 46L: normal good deliveries #tax code 46T: ABC good deliveries #tax code 48xxx: credite note on tax code xxx codes = ('44', '46L', '46T', '48s44', '48s46L', '48s46T') cr.execute( '''SELECT p.name As partner_name, l.partner_id AS partner_id, p.vat AS vat, (CASE WHEN t.code = '48s44' THEN '44' WHEN t.code = '48s46L' THEN '46L' WHEN t.code = '48s46T' THEN '46T' ELSE t.code END) AS intra_code, SUM(CASE WHEN t.code in ('48s44','48s46L','48s46T') THEN -l.tax_amount ELSE l.tax_amount END) AS amount FROM account_move_line l LEFT JOIN account_tax_code t ON (l.tax_code_id = t.id) LEFT JOIN res_partner p ON (l.partner_id = p.id) WHERE t.code IN %s AND l.period_id IN %s AND t.company_id = %s GROUP BY p.name, l.partner_id, p.vat, intra_code''', (codes, tuple([p.id for p in wiz_data.period_ids]), data_company.id)) p_count = 0 for row in cr.dictfetchall(): if not row['vat']: row['vat'] = '' p_count += 1 seq += 1 amt = row['amount'] or 0.0 amount_sum += amt intra_code = row['intra_code'] == '44' and 'S' or ( row['intra_code'] == '46L' and 'L' or (row['intra_code'] == '46T' and 'T' or '')) xmldict['clientlist'].append({ 'partner_name': row['partner_name'], 'seq': seq, 'vatnum': row['vat'][2:].replace(' ', '').upper(), 'vat': row['vat'], 'country': row['vat'][:2], 'amount': round(amt, 2), 'intra_code': row['intra_code'], 'code': intra_code }) xmldict.update({ 'dnum': dnum, 'clientnbr': str(seq), 'amountsum': round(amount_sum, 2), 'partner_wo_vat': p_count }) return xmldict def create_xml(self, cursor, user, ids, context=None): """Creates xml that is to be exported and sent to estate for partner vat intra. :return: Value for next action. :rtype: dict """ mod_obj = self.pool.get('ir.model.data') xml_data = self._get_datas(cursor, user, ids, context=context) month_quarter = xml_data['period'][:2] year = xml_data['period'][2:] data_file = '' # Can't we do this by etree? data_head = """<?xml version="1.0" encoding="ISO-8859-1"?> <ns2:IntraConsignment xmlns="http://www.minfin.fgov.be/InputCommon" xmlns:ns2="http://www.minfin.fgov.be/IntraConsignment" IntraListingsNbr="1"> <ns2:Representative> <RepresentativeID identificationType="NVAT" issuedBy="%(issued_by)s">%(vatnum)s</RepresentativeID> <Name>%(company_name)s</Name> <Street>%(street)s</Street> <PostCode>%(post_code)s</PostCode> <City>%(city)s</City> <CountryCode>%(country)s</CountryCode> <EmailAddress>%(email)s</EmailAddress> <Phone>%(phone)s</Phone> </ns2:Representative>""" % (xml_data) if xml_data['mand_id']: data_head += '\n\t\t<ns2:RepresentativeReference>%(mand_id)s</ns2:RepresentativeReference>' % ( xml_data) data_comp_period = '\n\t\t<ns2:Declarant>\n\t\t\t<VATNumber>%(vatnum)s</VATNumber>\n\t\t\t<Name>%(company_name)s</Name>\n\t\t\t<Street>%(street)s</Street>\n\t\t\t<PostCode>%(post_code)s</PostCode>\n\t\t\t<City>%(city)s</City>\n\t\t\t<CountryCode>%(country)s</CountryCode>\n\t\t\t<EmailAddress>%(email)s</EmailAddress>\n\t\t\t<Phone>%(phone)s</Phone>\n\t\t</ns2:Declarant>' % ( xml_data) if month_quarter.startswith('3'): data_comp_period += '\n\t\t<ns2:Period>\n\t\t\t<ns2:Quarter>' + month_quarter[ 1] + '</ns2:Quarter> \n\t\t\t<ns2:Year>' + year + '</ns2:Year>\n\t\t</ns2:Period>' elif month_quarter.startswith('0') and month_quarter.endswith('0'): data_comp_period += '\n\t\t<ns2:Period>\n\t\t\t<ns2:Year>' + year + '</ns2:Year>\n\t\t</ns2:Period>' else: data_comp_period += '\n\t\t<ns2:Period>\n\t\t\t<ns2:Month>' + month_quarter + '</ns2:Month> \n\t\t\t<ns2:Year>' + year + '</ns2:Year>\n\t\t</ns2:Period>' data_clientinfo = '' for client in xml_data['clientlist']: if not client['vatnum']: raise osv.except_osv( _('Insufficient Data!'), _('No vat number defined for %s.') % client['partner_name']) data_clientinfo += '\n\t\t<ns2:IntraClient SequenceNumber="%(seq)s">\n\t\t\t<ns2:CompanyVATNumber issuedBy="%(country)s">%(vatnum)s</ns2:CompanyVATNumber>\n\t\t\t<ns2:Code>%(code)s</ns2:Code>\n\t\t\t<ns2:Amount>%(amount).2f</ns2:Amount>\n\t\t</ns2:IntraClient>' % ( client) data_decl = '\n\t<ns2:IntraListing SequenceNumber="1" ClientsNbr="%(clientnbr)s" DeclarantReference="%(dnum)s" AmountSum="%(amountsum).2f">' % ( xml_data) data_file += data_head + data_decl + data_comp_period + data_clientinfo + '\n\t\t<ns2:Comment>%(comments)s</ns2:Comment>\n\t</ns2:IntraListing>\n</ns2:IntraConsignment>' % ( xml_data) context = dict(context or {}) context['file_save'] = data_file model_data_ids = mod_obj.search(cursor, user, [('model', '=', 'ir.ui.view'), ('name', '=', 'view_vat_intra_save')], context=context) resource_id = mod_obj.read(cursor, user, model_data_ids, fields=['res_id'], context=context)[0]['res_id'] return { 'name': _('Save'), 'context': context, 'view_type': 'form', 'view_mode': 'form', 'res_model': 'partner.vat.intra', 'views': [(resource_id, 'form')], 'view_id': 'view_vat_intra_save', 'type': 'ir.actions.act_window', 'target': 'new', } def preview(self, cr, uid, ids, context=None): xml_data = self._get_datas(cr, uid, ids, context=context) datas = {'ids': [], 'model': 'partner.vat.intra', 'form': xml_data} return self.pool['report'].get_action( cr, uid, [], 'l10n_be.report_l10nvatintraprint', data=datas, context=context)
class website(osv.osv): def _get_menu_website(self, cr, uid, ids, context=None): # IF a menu is changed, update all websites return self.search(cr, uid, [], context=context) def _get_menu(self, cr, uid, ids, name, arg, context=None): root_domain = [('parent_id', '=', False)] menus = self.pool.get('website.menu').search(cr, uid, root_domain, order='id', context=context) menu = menus and menus[0] or False return dict(map(lambda x: (x, menu), ids)) def _get_public_user(self, cr, uid, ids, name='public_user', arg=(), context=None): ref = self.get_public_user(cr, uid, context=context) return dict(map(lambda x: (x, ref), ids)) _name = "website" # Avoid website.website convention for conciseness (for new api). Got a special authorization from xmo and rco _description = "Website" _columns = { 'name': fields.char('Domain'), 'company_id': fields.many2one('res.company', string="Company"), 'language_ids': fields.many2many('res.lang', 'website_lang_rel', 'website_id', 'lang_id', 'Languages'), 'default_lang_id': fields.many2one('res.lang', string="Default language"), 'default_lang_code': fields.related('default_lang_id', 'code', type="char", string="Default language code", store=True), 'social_twitter': fields.char('Twitter Account'), 'social_facebook': fields.char('Facebook Account'), 'social_github': fields.char('GitHub Account'), 'social_linkedin': fields.char('LinkedIn Account'), 'social_youtube': fields.char('Youtube Account'), 'social_googleplus': fields.char('Google+ Account'), 'google_analytics_key': fields.char('Google Analytics Key'), 'user_id': fields.many2one('res.users', string='Public User'), 'public_user': fields.function(_get_public_user, relation='res.users', type='many2one', string='Public User'), 'menu_id': fields.function(_get_menu, relation='website.menu', type='many2one', string='Main Menu', store={ 'website.menu': (_get_menu_website, ['sequence', 'parent_id', 'website_id'], 10) }) } # cf. Wizard hack in website_views.xml def noop(self, *args, **kwargs): pass def write(self, cr, uid, ids, vals, context=None): self._get_languages.clear_cache(self) return super(website, self).write(cr, uid, ids, vals, context) def new_page(self, cr, uid, name, template='website.default_page', ispage=True, context=None): context = context or {} imd = self.pool.get('ir.model.data') view = self.pool.get('ir.ui.view') template_module, template_name = template.split('.') # completely arbitrary max_length page_name = slugify(name, max_length=50) page_xmlid = "%s.%s" % (template_module, page_name) try: # existing page imd.get_object_reference(cr, uid, template_module, page_name) except ValueError: # new page _, template_id = imd.get_object_reference(cr, uid, template_module, template_name) page_id = view.copy(cr, uid, template_id, context=context) page = view.browse(cr, uid, page_id, context=context) page.write({ 'arch': page.arch.replace(template, page_xmlid), 'name': page_name, 'page': ispage, }) imd.create(cr, uid, { 'name': page_name, 'module': template_module, 'model': 'ir.ui.view', 'res_id': page_id, 'noupdate': True }, context=context) return page_xmlid def page_for_name(self, cr, uid, ids, name, module='website', context=None): # whatever return '%s.%s' % (module, slugify(name, max_length=50)) def page_exists(self, cr, uid, ids, name, module='website', context=None): page = self.page_for_name(cr, uid, ids, name, module=module, context=context) try: self.pool["ir.model.data"].get_object_reference( cr, uid, module, name) except: return False def get_public_user(self, cr, uid, context=None): uid = openerp.SUPERUSER_ID res = self.pool['ir.model.data'].get_object_reference( cr, uid, 'base', 'public_user') return res and res[1] or False @openerp.tools.ormcache(skiparg=3) def _get_languages(self, cr, uid, id, context=None): website = self.browse(cr, uid, id) return [(lg.code, lg.name) for lg in website.language_ids] def get_languages(self, cr, uid, ids, context=None): return self._get_languages(cr, uid, ids[0]) def get_current_website(self, cr, uid, context=None): # TODO: Select website, currently hard coded return self.pool['website'].browse(cr, uid, 1, context=context) def preprocess_request(self, cr, uid, ids, request, context=None): # TODO FP: is_website_publisher and editable in context should be removed # for performance reasons (1 query per image to load) but also to be cleaner # I propose to replace this by a group 'base.group_website_publisher' on the # view that requires it. Access = request.registry['ir.model.access'] is_website_publisher = Access.check(cr, uid, 'ir.ui.view', 'write', False, context) lang = request.context['lang'] is_master_lang = lang == request.website.default_lang_code request.redirect = lambda url: werkzeug.utils.redirect(url_for(url)) request.context.update( is_master_lang=is_master_lang, editable=is_website_publisher, translatable=not is_master_lang, ) def get_template(self, cr, uid, ids, template, context=None): if '.' not in template: template = 'website.%s' % template module, xmlid = template.split('.', 1) model, view_id = request.registry[ "ir.model.data"].get_object_reference(cr, uid, module, xmlid) return self.pool["ir.ui.view"].browse(cr, uid, view_id, context=context) def _render(self, cr, uid, ids, template, values=None, context=None): user = self.pool.get("res.users") if not context: context = {} # Take a context qweb_values = context.copy() # add some values if values: qweb_values.update(values) # fill some defaults qweb_values.update( request=request, json=simplejson, website=request.website, url_for=url_for, keep_query=keep_query, slug=slug, res_company=request.website.company_id, user_id=user.browse(cr, uid, uid), quote_plus=werkzeug.url_quote_plus, ) qweb_values.setdefault('editable', False) # in edit mode ir.ui.view will tag nodes context['inherit_branding'] = qweb_values['editable'] view = self.get_template(cr, uid, ids, template) if 'main_object' not in qweb_values: qweb_values['main_object'] = view return view.render(qweb_values, engine='website.qweb', context=context) def render(self, cr, uid, ids, template, values=None, status_code=None, context=None): def callback(template, values, context): return self._render(cr, uid, ids, template, values, context) if values is None: values = {} return LazyResponse(callback, status_code=status_code, template=template, values=values, context=context) def pager(self, cr, uid, ids, url, total, page=1, step=30, scope=5, url_args=None, context=None): # Compute Pager page_count = int(math.ceil(float(total) / step)) page = max(1, min(int(page), page_count)) scope -= 1 pmin = max(page - int(math.floor(scope / 2)), 1) pmax = min(pmin + scope, page_count) if pmax - pmin < scope: pmin = pmax - scope if pmax - scope > 0 else 1 def get_url(page): _url = "%spage/%s/" % (url, page) if url_args: _url = "%s?%s" % (_url, werkzeug.url_encode(url_args)) return _url return { "page_count": page_count, "offset": (page - 1) * step, "page": { 'url': get_url(page), 'num': page }, "page_start": { 'url': get_url(pmin), 'num': pmin }, "page_previous": { 'url': get_url(max(pmin, page - 1)), 'num': max(pmin, page - 1) }, "page_next": { 'url': get_url(min(pmax, page + 1)), 'num': min(pmax, page + 1) }, "page_end": { 'url': get_url(pmax), 'num': pmax }, "pages": [{ 'url': get_url(page), 'num': page } for page in xrange(pmin, pmax + 1)] } def rule_is_enumerable(self, rule): """ Checks that it is possible to generate sensible GET queries for a given rule (if the endpoint matches its own requirements) :type rule: werkzeug.routing.Rule :rtype: bool """ endpoint = rule.endpoint methods = rule.methods or ['GET'] converters = rule._converters.values() return ( 'GET' in methods and endpoint.routing['type'] == 'http' and endpoint.routing['auth'] in ('none', 'public') and endpoint.routing.get('website', False) # preclude combinatorial explosion by only allowing a single converter and len(converters) <= 1 # ensure all converters on the rule are able to generate values for # themselves and all( hasattr(converter, 'generate') for converter in converters) ) and self.endpoint_is_enumerable(rule) def endpoint_is_enumerable(self, rule): """ Verifies that it's possible to generate a valid url for the rule's endpoint :type rule: werkzeug.routing.Rule :rtype: bool """ spec = inspect.getargspec(rule.endpoint.method) # if *args bail the f**k out, only dragons can live there if spec.varargs: return False # remove all arguments with a default value from the list defaults_count = len(spec.defaults or []) # spec.defaults can be None # a[:-0] ~ a[:0] ~ [] -> replace defaults_count == 0 by None to get # a[:None] ~ a args = spec.args[:(-defaults_count or None)] # params with defaults were removed, leftover allowed are: # * self (technically should be first-parameter-of-instance-method but whatever) # * any parameter mapping to a converter return all((arg == 'self' or arg in rule._converters) for arg in args) def enumerate_pages(self, cr, uid, ids, query_string=None, context=None): """ Available pages in the website/CMS. This is mostly used for links generation and can be overridden by modules setting up new HTML controllers for dynamic pages (e.g. blog). By default, returns template views marked as pages. :param str query_string: a (user-provided) string, fetches pages matching the string :returns: a list of mappings with two keys: ``name`` is the displayable name of the resource (page), ``url`` is the absolute URL of the same. :rtype: list({name: str, url: str}) """ router = request.httprequest.app.get_db_router(request.db) # Force enumeration to be performed as public user uid = self.get_public_user(cr, uid, context=context) for rule in router.iter_rules(): if not self.rule_is_enumerable(rule): continue converters = rule._converters filtered = bool(converters) if converters: # allow single converter as decided by fp, checked by # rule_is_enumerable [(name, converter)] = converters.items() converter_values = converter.generate(request.cr, uid, query=query_string, context=context) generated = ({ k: v } for k, v in itertools.izip( itertools.repeat(name), converter_values)) else: # force single iteration for literal urls generated = [{}] for values in generated: domain_part, url = rule.build(values, append_unknown=False) page = {'name': url, 'url': url} if not filtered and query_string and not self.page_matches( cr, uid, page, query_string, context=context): continue yield page def search_pages(self, cr, uid, ids, needle=None, limit=None, context=None): return list( itertools.islice( self.enumerate_pages(cr, uid, ids, query_string=needle, context=context), limit)) def page_matches(self, cr, uid, page, needle, context=None): """ Checks that a "page" matches a user-provide search string. The default implementation attempts to perform a non-contiguous substring match of the page's name. :param page: {'name': str, 'url': str} :param needle: str :rtype: bool """ haystack = page['name'].lower() needle = iter(needle.lower()) n = next(needle) end = object() for char in haystack: if char != n: continue n = next(needle, end) # found all characters of needle in haystack in order if n is end: return True return False def kanban(self, cr, uid, ids, model, domain, column, template, step=None, scope=None, orderby=None, context=None): step = step and int(step) or 10 scope = scope and int(scope) or 5 orderby = orderby or "name" get_args = dict(request.httprequest.args or {}) model_obj = self.pool[model] relation = model_obj._columns.get(column)._obj relation_obj = self.pool[relation] get_args.setdefault('kanban', "") kanban = get_args.pop('kanban') kanban_url = "?%s&kanban=" % werkzeug.url_encode(get_args) pages = {} for col in kanban.split(","): if col: col = col.split("-") pages[int(col[0])] = int(col[1]) objects = [] for group in model_obj.read_group(cr, uid, domain, ["id", column], groupby=column): obj = {} # browse column relation_id = group[column][0] obj['column_id'] = relation_obj.browse(cr, uid, relation_id) obj['kanban_url'] = kanban_url for k, v in pages.items(): if k != relation_id: obj['kanban_url'] += "%s-%s" % (k, v) # pager number = model_obj.search(cr, uid, group['__domain'], count=True) obj['page_count'] = int(math.ceil(float(number) / step)) obj['page'] = pages.get(relation_id) or 1 if obj['page'] > obj['page_count']: obj['page'] = obj['page_count'] offset = (obj['page'] - 1) * step obj['page_start'] = max( obj['page'] - int(math.floor((scope - 1) / 2)), 1) obj['page_end'] = min(obj['page_start'] + (scope - 1), obj['page_count']) # view data obj['domain'] = group['__domain'] obj['model'] = model obj['step'] = step obj['orderby'] = orderby # browse objects object_ids = model_obj.search(cr, uid, group['__domain'], limit=step, offset=offset, order=orderby) obj['object_ids'] = model_obj.browse(cr, uid, object_ids) objects.append(obj) values = { 'objects': objects, 'range': range, 'template': template, } return request.website._render("website.kanban_contain", values) def kanban_col(self, cr, uid, ids, model, domain, page, template, step, orderby, context=None): html = "" model_obj = self.pool[model] domain = safe_eval(domain) step = int(step) offset = (int(page) - 1) * step object_ids = model_obj.search(cr, uid, domain, limit=step, offset=offset, order=orderby) object_ids = model_obj.browse(cr, uid, object_ids) for object_id in object_ids: html += request.website._render(template, {'object_id': object_id}) return html
class export_report(osv.osv): _name = 'export.report' def _default_uom(self, cr, uid, context=None): if context is None:context = {} res = self.pool.get('product.uom').search(cr, uid, [('name', 'ilike', 'Nos')]) return res and res[0] or False def _ng_default_uom(self, cr, uid, context=None): if context is None:context = {} res = self.pool.get('product.uom').search(cr, uid, [('name', 'ilike', 'kg')]) return res and res[0] or False def _total(self, cr, uid, ids, name, args, context=None): """ Process -total of all lines(net wt and gross wt) """ result = dict([(id, {'net_wt_total': 0.0,'gross_wt_total':0.0,'total_qty':0.0,'count':0}) for id in ids]) net_wt_total,gross_wt_total,total_qty,count = 0.0,0.0,0.0,0 for ex in self.browse(cr, uid, ids, context=context): for l in ex.line_ids: count += 1 net_wt_total += l.net_wt gross_wt_total += l.gross_wt total_qty += l.qty result[ex.id]['net_wt_total'] = net_wt_total result[ex.id]['gross_wt_total'] = gross_wt_total result[ex.id]['total_qty'] = total_qty result[ex.id]['count'] = count return result _columns = { 'name': fields.char('Name', readonly=True), 'date': fields.datetime('Creation Date', required=True), 'exporter_id': fields.many2one('res.partner', 'Exporter', required=True), 'buyer_id': fields.many2one('res.partner', 'Buyer(if other than consignee)', required=True, domain=[('customer', '=', True)]), 'consignee_id': fields.many2one('res.partner', 'Consignee', required=True, domain=[('customer', '=', True)]), 'origin_country': fields.char('Country of Origin of Goods', required=True), 'dest_country': fields.char('Country of Final Destination', required=True), 'pre_carriage_by': fields.char('Pre-Carriage by'), 'place_pre_carrier': fields.char('Place of Receipt Pre-Carrier'), 'v_f_no': fields.char('Vessal/Flight No.'), 'landing_port': fields.char('Port of Loading'), 'discharge_port': fields.char('Port of Discharge'), 'final_dest': fields.char('Final Destination'), 'no_of_packages': fields.char('No. & kind of Pkgs.'), 'container_no': fields.char('Marks & Nos./Container No.'), 'depends_on': fields.selection([('delivey_order', 'Delivery Order'), ('manually', 'Manually')], 'Depends', required=True), 'delivery_ids': fields.many2many('stock.picking.out', 'delivery_export_id', 'delivery_id', 'export_id', 'Delivery Orders', domain=[('type', '=', 'out')]), 'line_ids': fields.one2many('export.line', 'export_id', 'Lines'), 'inv_no': fields.char('Invoice Number', required=True), 'inv_date': fields.date('Invoice Date'), 'buyer_ref': fields.char("Buyer's Ref No.", required=True), 'buyer_date': fields.date("Buyer's Date."), 'other_ref': fields.char("Other Reference(s)."), 'notes': fields.text('Description'), 'total_qty': fields.function(_total, multi='c', type='float', string='Total Qty',digits_compute=dp.get_precision('Product Unit of Measure')), 'net_wt_total': fields.function(_total, multi='c', type='float', string='Net Wt. Total',digits_compute=dp.get_precision('Product Unit of Measure')), 'gross_wt_total': fields.function(_total, multi='c', type='float', string='Gross Wt. Total',digits_compute=dp.get_precision('Product Unit of Measure')), 'count': fields.function(_total, multi='c', type='integer', string='count',digits_compute=dp.get_precision('Product Unit of Measure')), 'uom': fields.many2one('product.uom', 'UoM', required=True), 'n_uom': fields.many2one('product.uom', 'Net Wt. UoM', required=True), 'g_uom': fields.many2one('product.uom', 'Gross Wt. UoM', required=True), } _defaults = { 'name': lambda obj, cr, uid, context: obj.pool.get('ir.sequence').get(cr, uid, 'export.report'), 'date': time.strftime(DEFAULT_SERVER_DATETIME_FORMAT), 'uom':_default_uom, 'n_uom':_ng_default_uom, 'g_uom':_ng_default_uom, 'depends_on':'manually' } def load_items(self, cr, uid, ids , context=None): """ -Process -Add delivery lines from delivery order """ exp_obj = self.pool.get('export.line') data = self.browse(cr, uid, ids[0]) added_line = [] if data.delivery_ids: for do in data.delivery_ids: for mv in do.move_lines: desc = self.pool.get('product.product').name_get(cr, uid, [mv.product_id.id], context=context)[0][1] added_line.append({ 'product_id':mv.product_id.id, 'product_desc':desc, 'qty':mv.product_qty or 0.0, 'export_id':ids[0], }) cr.execute(""" DELETE FROM export_line WHERE export_id = %s""" % (ids[0])) if added_line: for c in added_line: exp_obj.create(cr, uid, c) return True def action_print(self,cr, uid, ids, context=None): """ Process - Action to print export report Before printing , required to check all data fullfill that reports. """ context = context or {} if not ids: raise osv.except_osv( _('Error!'),_('You cannot print report this report because some miss-match values.')) data = self.read(cr, uid, ids[0], [], context=context) if not data['line_ids']: raise osv.except_osv(_('Warning!'),_('No Delivery lines found')) return { 'type': 'ir.actions.report.xml', 'report_name': 'export.do.order', 'datas': { 'ids': [ids[0]], 'model': 'export.report', 'form': data }, }
class AccountAgingWizardPartner(osv.osv_memory): _name = 'account.aging.wizard.partner' _description = 'Account Aging Wizard Partner' _rec_name = 'partner_id' _order = 'name' def _get_amount(self, cr, uid, ids, field_names, arg, context=None): context = dict(context or {}) res = {} for line in self.browse(cr, uid, ids, context=context): direction = line.aaw_id.direction == 'past' spans = [ line.aaw_id.period_length * x * (direction and 1 or -1) for x in range(5) ] res[line.id] = dict((fn, 0.0) for fn in field_names) for doc in line.document_ids: if 'residual' in field_names: res[line.id]['residual'] += doc.residual if 'payment' in field_names: res[line.id]['payment'] += doc.payment if 'total' in field_names: res[line.id]['total'] += doc.total if 'not_due' in field_names and not direction: # We will use same field not due to store all due amounts if doc.due_days > 0: res[line.id]['not_due'] += doc.residual if 'span01' in field_names and not direction: if doc.due_days <= 0 and doc.due_days > spans[1]: res[line.id]['span01'] += doc.residual if 'span02' in field_names and not direction: if doc.due_days <= spans[1] and doc.due_days > spans[2]: res[line.id]['span02'] += doc.residual if 'span03' in field_names and not direction: if doc.due_days <= spans[2] and doc.due_days > spans[3]: res[line.id]['span03'] += doc.residual if 'span04' in field_names and not direction: if doc.due_days <= spans[3] and doc.due_days > spans[4]: res[line.id]['span04'] += doc.residual if 'span05' in field_names and not direction: if doc.due_days <= spans[4]: res[line.id]['span05'] += doc.residual if 'not_due' in field_names and direction: if doc.due_days <= 0: res[line.id]['not_due'] += doc.residual if 'span01' in field_names and direction: if doc.due_days > 0 and doc.due_days <= spans[1]: res[line.id]['span01'] += doc.residual if 'span02' in field_names and direction: if doc.due_days > spans[1] and doc.due_days <= spans[2]: res[line.id]['span02'] += doc.residual if 'span03' in field_names and direction: if doc.due_days > spans[2] and doc.due_days <= spans[3]: res[line.id]['span03'] += doc.residual if 'span04' in field_names and direction: if doc.due_days > spans[3] and doc.due_days <= spans[4]: res[line.id]['span04'] += doc.residual if 'span05' in field_names and direction: if doc.due_days > spans[4]: res[line.id]['span05'] += doc.residual return res def _get_aawp(self, cr, uid, ids, context=None): context = dict(context or {}) res = {} for line in self.browse(cr, uid, ids, context=context): res[line.aawp_id.id] = True return res.keys() _columns = { 'partner_id': fields.many2one( 'res.partner', 'Partner', required=True, ), 'name': fields.related('partner_id', 'name', string='Name', type='char', store=True), 'aaw_id': fields.many2one('account.aging.wizard', 'Account Aging Wizard', help='Account Aging Wizard Holder'), 'document_ids': fields.one2many('account.aging.wizard.document', 'aawp_id', 'Documents', help='Balance by Currency'), 'aml_ids': fields.many2many('account.move.line', 'aaw_id', 'Journal Items', help='Journal Items'), 'currency_id': fields.many2one( 'res.currency', 'Currency', required=True, ), 'total': fields.function(_get_amount, string='Total', store={ _name: (lambda self, cr, uid, ids, cx: ids, [], 15), 'account.aging.wizard.document': (_get_aawp, [], 15), }, multi='amounts', type='float'), 'payment': fields.function(_get_amount, string='Payment', store={ _name: (lambda self, cr, uid, ids, cx: ids, [], 15), 'account.aging.wizard.document': (_get_aawp, [], 15), }, multi='amounts', type='float'), 'residual': fields.function(_get_amount, string='Residual', store={ _name: (lambda self, cr, uid, ids, cx: ids, [], 15), 'account.aging.wizard.document': (_get_aawp, [], 15), }, multi='amounts', type='float'), 'not_due': fields.function(_get_amount, string='Not Due', store={ _name: (lambda self, cr, uid, ids, cx: ids, [], 15), 'account.aging.wizard.document': (_get_aawp, [], 15), }, multi='amounts', type='float'), 'span01': fields.function(_get_amount, string='span01', store={ _name: (lambda self, cr, uid, ids, cx: ids, [], 15), 'account.aging.wizard.document': (_get_aawp, [], 15), }, multi='amounts', type='float'), 'span02': fields.function(_get_amount, string='span02', store={ _name: (lambda self, cr, uid, ids, cx: ids, [], 15), 'account.aging.wizard.document': (_get_aawp, [], 15), }, multi='amounts', type='float'), 'span03': fields.function(_get_amount, string='span03', store={ _name: (lambda self, cr, uid, ids, cx: ids, [], 15), 'account.aging.wizard.document': (_get_aawp, [], 15), }, multi='amounts', type='float'), 'span04': fields.function(_get_amount, string='span04', store={ _name: (lambda self, cr, uid, ids, cx: ids, [], 15), 'account.aging.wizard.document': (_get_aawp, [], 15), }, multi='amounts', type='float'), 'span05': fields.function(_get_amount, string='span05', store={ _name: (lambda self, cr, uid, ids, cx: ids, [], 15), 'account.aging.wizard.document': (_get_aawp, [], 15), }, multi='amounts', type='float'), 'aawc_id': fields.many2one('account.aging.wizard.currency', 'Account Aging Wizard Currency', help='Account Aging Wizard Currency Holder'), }
class merge_pickings(osv.osv_memory): _inherit = "merge.pickings" _columns = { 'picking_ids': fields.many2many( 'stock.picking', 'merge_do_picking_rel', 'merge_do_id', 'picking_id', 'Pickings', required=True, domain= "[('state', '=', 'done'), ('type', '=', type), ('partner_id', '=', partner_id),('invoice_state', '=', '2binvoiced')]" ), } def type_change(self, cr, uid, ids, tipe): domain = {'partner_id': [('customer', '=', True)]} if tipe == 'in': domain = {'partner_id': [('supplier', '=', True)]} return { 'value': { 'picking_ids': None, 'partner_id': None }, 'domain': domain } def merge_orders(self, cr, uid, ids, context={}): pool_data = self.pool.get('ir.model.data') journal_obj = self.pool.get('account.journal') pool_invoice = self.pool.get('account.invoice') pool_picking = self.pool.get('stock.picking') pool_partner = self.pool.get('res.partner') pool_invoice_line = self.pool.get('account.invoice.line') data = self.browse(cr, uid, ids, context=context)[0] picking_ids = [x.id for x in data['picking_ids']] partner_obj = data['partner_id'] print data, "=++++++++++++++++++++++" # Valisasi Invoice Picking Cek Po apakah sudah ada Invoice for x in picking_ids: pick = pool_picking.browse(cr, uid, x) invoice = [] print pick.purchase_id.id, "::::::::::::::::::" if pick.purchase_id.id: print "AAAAAAAA" cr.execute( "SELECT invoice_id FROM purchase_invoice_rel WHERE purchase_id = %s", [pick.purchase_id.id]) invoice = map(lambda x: x[0], cr.fetchall()) if invoice: raise osv.except_osv( _('Warning!'), _('Picking ' + pick.name + ' dari PO ' + pick.purchase_id.name[:6] + ' Tidak Dapat Di Buat Invoice Dari Consolidate Picking')) alamat = pool_partner.address_get(cr, uid, [partner_obj.id], ['contact', 'invoice']) address_contact_id = alamat['contact'] address_invoice_id = alamat['invoice'] picking = pool_picking.browse(cr, uid, picking_ids[0], context=context) namepick = False origin = False if data.type == 'out': type_inv = 'out_invoice' account_id = partner_obj.property_account_receivable.id curency = picking.sale_id.pricelist_id.currency_id.id journal_ids = journal_obj.search(cr, uid, [('type', '=', 'sale'), ('company_id', '=', 1)], limit=1) origin = '' namepick = '' for picking in pool_picking.browse(cr, uid, picking_ids, context=context): if picking.note_id.id: origin += picking.origin + ':' + ( picking.note_id.name)[:7] + ', ' else: origin += picking.origin + ', ' namepick += picking.sale_id.client_order_ref + ', ' elif data.type == 'in': type_inv = 'in_invoice' account_id = partner_obj.property_account_payable.id curency = picking.purchase_id.pricelist_id.currency_id.id journal_ids = journal_obj.search(cr, uid, [('type', '=', 'purchase'), ('company_id', '=', 1)], limit=1) if not journal_ids: raise osv.except_osv( ('Error !'), ('There is no sale/purchase journal defined for this company')) invoice_id = pool_invoice.create( cr, uid, { 'name': namepick[:-2] if namepick else 'Merged Invoice for ' + partner_obj.name + ' on ' + time.strftime('%Y-%m-%d %H:%M:%S'), # 'name': 'Merged Invoice for '+ partner_obj.name + ' on ' + time.strftime('%Y-%m-%d %H:%M:%S'), 'type': type_inv, 'account_id': account_id, 'partner_id': partner_obj.id, 'journal_id': journal_ids[0] or False, 'address_invoice_id': address_invoice_id, 'address_contact_id': address_contact_id, 'date_invoice': time.strftime('%Y-%m-%d'), 'user_id': uid, 'origin': origin[:-2] if origin else False, 'currency_id': curency or False, 'picking_ids': [(6, 0, picking_ids)] }) # Daftarkan Ke Purchase Invoice Rel add_po_id = [] for y in picking_ids: pick2 = pool_picking.browse(cr, uid, y) add_po_id += [pick2.purchase_id.id] #convert list into set cek_unique = set(add_po_id) #convert back to list add_po_id = list(cek_unique) # Filter PO ID yang sama, Handle jika Multi Picking dari PO yang sama unique_list = [ e for i, e in enumerate(add_po_id) if add_po_id.index(e) == i ] if data.type == 'in': for a in add_po_id: cr.execute( 'insert into purchase_invoice_rel (purchase_id,invoice_id) values (%s,%s)', (a, invoice_id)) for picking in pool_picking.browse(cr, uid, picking_ids, context=context): pool_picking.write(cr, uid, [picking.id], { 'invoice_state': 'invoiced', 'invoice_id': invoice_id }) for move_line in picking.move_lines: disc_amount = 0 if data.type == 'out': price_unit = pool_picking._get_price_unit_invoice( cr, uid, move_line, 'out_invoice') tax_ids = pool_picking._get_taxes_invoice( cr, uid, move_line, 'out_invoice') line_account_id = move_line.product_id.product_tmpl_id.property_account_income.id or move_line.product_id.categ_id.property_account_income_categ.id elif data.type == 'in': price_unit = pool_picking._get_price_unit_invoice( cr, uid, move_line, 'in_invoice') tax_ids = pool_picking._get_taxes_invoice( cr, uid, move_line, 'in_invoice') line_account_id = move_line.product_id.product_tmpl_id.property_account_expense.id or move_line.product_id.categ_id.property_account_expense_categ.id disc_amount = move_line.purchase_line_id.discount_nominal discount = pool_picking._get_discount_invoice( cr, uid, move_line) origin = picking.origin + ':' + (picking.name).strip() #origin = (picking.delivery_note).strip() +';'+ (picking.name).strip() if picking.note_id: # search op line id by move line ID cekopline = self.pool.get('order.preparation.line').search( cr, uid, [('move_id', '=', move_line.id)]) op_line = self.pool.get('order.preparation.line').browse( cr, uid, cekopline) if op_line: for opl in op_line: #Search DN Line ID By OP Line ID cek = self.pool.get('delivery.note.line').search( cr, uid, [('op_line_id', '=', opl.id)]) product_dn = self.pool.get( 'delivery.note.line').browse(cr, uid, cek)[0] if cek: pool_invoice_line.create( cr, uid, { 'name': product_dn.name, 'picking_id': picking.id, 'origin': origin, 'uos_id': move_line.product_uos.id or move_line.product_uom.id, 'product_id': move_line.product_id.id, 'price_unit': price_unit, 'discount': discount, 'quantity': move_line.product_qty, 'invoice_id': invoice_id, 'invoice_line_tax_id': [(6, 0, tax_ids) ], 'account_analytic_id': pool_picking. _get_account_analytic_invoice( cr, uid, picking, move_line), 'account_id': self.pool.get( 'account.fiscal.position' ).map_account( cr, uid, partner_obj. property_account_position, line_account_id), 'amount_discount': disc_amount }) else: raise osv.except_osv( ('Perhatian..!!'), ('No Delivery Note Tidak Ditemukan')) # end for else: pool_invoice_line.create( cr, uid, { # 'name': picking.origin +':'+ (picking.name).strip(), #move_line.name, 'name': move_line.name, 'picking_id': picking.id, 'origin': origin, 'uos_id': move_line.product_uos.id or move_line.product_uom.id, 'product_id': move_line.product_id.id, 'price_unit': price_unit, 'discount': discount, 'quantity': move_line.product_qty, 'invoice_id': invoice_id, 'invoice_line_tax_id': [(6, 0, tax_ids)], 'account_analytic_id': pool_picking._get_account_analytic_invoice( cr, uid, picking, move_line), 'account_id': self.pool.get( 'account.fiscal.position').map_account( cr, uid, partner_obj.property_account_position, line_account_id), 'amount_discount': disc_amount }) else: pool_invoice_line.create( cr, uid, { # 'name': picking.origin +':'+ (picking.name).strip(), #move_line.name, 'name': move_line.name, 'picking_id': picking.id, 'origin': origin, 'uos_id': move_line.product_uos.id or move_line.product_uom.id, 'product_id': move_line.product_id.id, 'price_unit': price_unit, 'discount': discount, 'quantity': move_line.product_qty, 'invoice_id': invoice_id, 'invoice_line_tax_id': [(6, 0, tax_ids)], 'account_analytic_id': pool_picking._get_account_analytic_invoice( cr, uid, picking, move_line), 'account_id': self.pool. get('account.fiscal.position').map_account( cr, uid, partner_obj.property_account_position, line_account_id), 'amount_discount': disc_amount }) pool_invoice.button_compute(cr, uid, [invoice_id], context=context, set_total=False) action_model, action_id = pool_data.get_object_reference( cr, uid, 'account', "invoice_form") if data.type == 'in': action_model, action_id = pool_data.get_object_reference( cr, uid, 'account', "invoice_supplier_form") action_pool = self.pool.get(action_model) res_id = action_model and action_id or False action = action_pool.read(cr, uid, action_id, context=context) action['name'] = 'Merged Invoice' action['view_type'] = 'form' action['view_mode'] = 'form' action['view_id'] = [res_id] action['res_model'] = 'account.invoice' action['type'] = 'ir.actions.act_window' action['target'] = 'current' action['res_id'] = invoice_id return action
class grap_timesheet(Model): _description = 'Time Sheet' _name = 'grap.timesheet' _order = 'min_date, max_date, type_id' # Fields Function Section def _get_amount_activity(self, cr, uid, ids, pFields, args, context=None): res = {} for gt in self.browse(cr, uid, ids, context=context): fmt = '%Y-%m-%d %H:%M:%S' d1 = datetime.strptime(gt.min_date, fmt) d2 = datetime.strptime(gt.max_date, fmt) amount = (d2 - d1).seconds / 3600.0 res[gt.id] = { 'amount': amount, 'activity_qty': len(gt.activity_ids), 'amount_per_activity': amount / len(gt.activity_ids), } return res def _get_timesheet_group_id(self, cr, uid, ids, pFields, args, context=None): return dict([(x, False) for x in ids]) def _set_timesheet_group_id(self, cr, uid, pId, field_name, field_value, args, context=None): pass # Columns section _columns = { 'name': fields.char('Name', size=256, required=True), 'user_id': fields.many2one('res.users', 'User', required=True), 'min_date': fields.datetime(string='Minimum date', required=True), 'max_date': fields.datetime(string='Maximum date', required=True), 'activity_ids': fields.many2many('grap.activity', 'grap_timesheet_activity_rel', 'timesheet_id', 'activity_id', 'Activities', required=True), 'type_id': fields.many2one('grap.timesheet.type', 'Work Type', required=True), 'timesheet_group_id': fields.function(_get_timesheet_group_id, type='many2one', fnct_inv=_set_timesheet_group_id, relation='grap.timesheet.group', string='Group'), 'amount': fields.function(_get_amount_activity, type='float', string='Hours', help='Specifies the amount of worked hours.', multi='activity', store={ 'grap.timesheet': (lambda self, cr, uid, ids, context=None: ids, [ 'activity_ids', 'min_date', 'max_date', ], 10) }), 'activity_qty': fields.function(_get_amount_activity, type='integer', string='Activities Quantity', multi='activity', store={ 'grap.timesheet': (lambda self, cr, uid, ids, context=None: ids, [ 'activity_ids', 'min_date', 'max_date', ], 10) }), 'amount_per_activity': fields.function(_get_amount_activity, type='float', string='Amount Per Activity', multi='activity', store={ 'grap.timesheet': (lambda self, cr, uid, ids, context=None: ids, [ 'activity_ids', 'min_date', 'max_date', ], 10) }), } # Default Section def _get_default_min_date(self, cr, uid, context=None): # TODO Make now without minut return fields.date.context_today(self, cr, uid, context=context) def _get_default_max_date(self, cr, uid, context=None): return fields.date.context_today(self, cr, uid, context=context) _defaults = { 'name': '/', 'user_id': lambda obj, cr, uid, context: uid, 'min_date': _get_default_min_date, 'max_date': _get_default_max_date, } # Views section def on_change_timesheet_group_id(self, cr, uid, ids, timesheet_group_id, context=None): if not timesheet_group_id: values = {} else: gtg_obj = self.pool['grap.timesheet.group'] gtg = gtg_obj.browse(cr, uid, timesheet_group_id, context=context) values = {'activity_ids': [x.id for x in gtg.activity_ids]} return {'value': values}
class event_event(osv.osv): _inherit = "event.event" def _list_tz(self, cr, uid, context=None): # put POSIX 'Etc/*' entries at the end to avoid confusing users - see bug 1086728 return [(tz, tz) for tz in sorted(pytz.all_timezones, key=lambda tz: tz if not tz.startswith('Etc/') else '_')] def _count_tracks(self, cr, uid, ids, field_name, arg, context=None): return { event.id: len(event.track_ids) for event in self.browse(cr, uid, ids, context=context) } def _get_tracks_tag_ids(self, cr, uid, ids, field_names, arg=None, context=None): res = dict.fromkeys(ids, []) for event in self.browse(cr, uid, ids, context=context): for track in event.track_ids: res[event.id] += [tag.id for tag in track.tag_ids] res[event.id] = list(set(res[event.id])) return res _columns = { 'tag_ids': fields.many2many('event.tag', string='Tags'), 'track_ids': fields.one2many('event.track', 'event_id', 'Tracks'), 'sponsor_ids': fields.one2many('event.sponsor', 'event_id', 'Sponsorships'), 'blog_id': fields.many2one('blog.blog', 'Event Blog'), 'show_track_proposal': fields.boolean('Talks Proposals'), 'show_tracks': fields.boolean('Multiple Tracks'), 'show_blog': fields.boolean('News'), 'count_tracks': fields.function(_count_tracks, type='integer', string='Tracks'), 'tracks_tag_ids': fields.function(_get_tracks_tag_ids, type='one2many', relation='event.track.tag', string='Tags of Tracks'), 'allowed_track_tag_ids': fields.many2many('event.track.tag', string='Accepted Tags', help="List of available tags for track proposals."), 'timezone_of_event': fields.selection(_list_tz, 'Event Timezone', size=64), } _defaults = { 'show_track_proposal': False, 'show_tracks': False, 'show_blog': False, 'timezone_of_event': lambda self, cr, uid, c: self.pool.get('res.users').browse( cr, uid, uid, c).tz, } def _get_new_menu_pages(self, cr, uid, event, context=None): context = context or {} result = super(event_event, self)._get_new_menu_pages(cr, uid, event, context=context) if event.show_tracks: result.append((_('Talks'), '/event/%s/track' % slug(event))) result.append((_('Agenda'), '/event/%s/agenda' % slug(event))) if event.blog_id: result.append((_('News'), '/blogpost' + slug(event.blog_ig))) if event.show_track_proposal: result.append((_('Talk Proposals'), '/event/%s/track_proposal' % slug(event))) return result
class res_partner(osv.osv): """ Inherits partner and adds CRM information in the partner form """ _inherit = 'res.partner' def _opportunity_meeting_count(self, cr, uid, ids, field_name, arg, context=None): res = dict( map(lambda x: (x, { 'opportunity_count': 0, 'meeting_count': 0 }), ids)) # the user may not have access rights for opportunities or meetings try: for partner in self.browse(cr, uid, ids, context): res[partner.id] = { 'opportunity_count': len(partner.opportunity_ids), 'meeting_count': len(partner.meeting_ids), } except: pass return res _columns = { 'section_id': fields.many2one('crm.case.section', 'Sales Team'), 'opportunity_ids': fields.one2many('crm.lead', 'partner_id',\ 'Leads and Opportunities', domain=[('probability', 'not in', ['0', '100'])]), 'meeting_ids': fields.many2many('calendar.event', 'calendar_event_partner_rel','partner_id', 'meeting_id', 'Meetings'), 'phonecall_ids': fields.one2many('crm.phonecall', 'partner_id',\ 'Phonecalls'), 'opportunity_count': fields.function(_opportunity_meeting_count, string="Opportunity", type='integer', multi='opp_meet'), 'meeting_count': fields.function(_opportunity_meeting_count, string="# Meetings", type='integer', multi='opp_meet'), } def copy(self, cr, uid, record_id, default=None, context=None): if default is None: default = {} default.update({ 'opportunity_ids': [], 'meeting_ids': [], 'phonecall_ids': [] }) return super(res_partner, self).copy(cr, uid, record_id, default, context) def redirect_partner_form(self, cr, uid, partner_id, context=None): search_view = self.pool.get('ir.model.data').get_object_reference( cr, uid, 'base', 'view_res_partner_filter') value = { 'domain': "[]", 'view_type': 'form', 'view_mode': 'form,tree', 'res_model': 'res.partner', 'res_id': int(partner_id), 'view_id': False, 'context': context, 'type': 'ir.actions.act_window', 'search_view_id': search_view and search_view[1] or False } return value def make_opportunity(self, cr, uid, ids, opportunity_summary, planned_revenue=0.0, probability=0.0, partner_id=None, context=None): categ_obj = self.pool.get('crm.case.categ') categ_ids = categ_obj.search(cr, uid, [('object_id.model', '=', 'crm.lead')]) lead_obj = self.pool.get('crm.lead') opportunity_ids = {} for partner in self.browse(cr, uid, ids, context=context): if not partner_id: partner_id = partner.id opportunity_id = lead_obj.create( cr, uid, { 'name': opportunity_summary, 'planned_revenue': planned_revenue, 'probability': probability, 'partner_id': partner_id, 'categ_ids': categ_ids and categ_ids[0:1] or [], 'type': 'opportunity' }, context=context) opportunity_ids[partner_id] = opportunity_id return opportunity_ids
class unefa_generar_lista_semestre(osv.TransientModel): """ Este wizard es para crear listas por semestre de todos los estudiantes. """ _name = "unefa.generar_lista_semestre" _description = "Crear lista de estudiantes por semesre" _columns = { 'carrera_id': fields.many2one( 'unefa.carrera', 'Carrera', required=True, readonly=True, ), 'turno': fields.selection([('nocturno', 'NOCTURNO'), ('diurno', 'DIURNO')], 'Turno', readonly=True), 'periodo_id': fields.many2one('unefa.conf.periodo_academico', 'Período Académico', required=True), 'pensum_id': fields.many2one('unefa.pensum', 'Pensum', required=True), 'semestre_ids': fields.many2many('unefa.semestre', 'unefa_list_semestre_rel', 'lista_id', 'semestre_id', 'Semestres') } def carrera_turno_default(self, cr, uid, ids, context=None): coordinador_obj = self.pool.get('res.users') coordinador_data = coordinador_obj.browse(cr, uid, uid) carrera_id = coordinador_data['coordinacion_id']['carrera_id']['id'] turno = coordinador_data['coordinacion_id']['regimen'] value = { 'carrera_id': carrera_id, 'turno': turno, } return {'value': value} def domain_semestre_ofertados(self, cr, uid, ids, carrera_id, turno, pensum_id, periodo_id, context=None): if pensum_id: list_semestres_ids = [] oferta_obj = self.pool.get('unefa.oferta_academica') oferta_ids = oferta_obj.search(cr, uid, [ ('carrera_id', '=', carrera_id), ('turno', '=', turno), ('periodo_id', '=', periodo_id), ]) oferta_data = oferta_obj.browse(cr, uid, oferta_ids) for oferta in oferta_data: for pensum in oferta.pensum_ids: if pensum.pensum_id.id == pensum_id: for semestre in pensum.semestres_ids: list_semestres_ids.append(semestre.semestre_id.id) domain = { 'semestre_ids': [('id', '=', list([6, False, list_semestres_ids]))] } return {'domain': domain} def generar_listas_semestres(self, cr, uid, ids, context=None): url = '/descargar/listas_estudiantes_semestre/%d' % ids[0] return { 'type': 'ir.actions.act_url', 'url': url, 'target': 'new', } def create(self, cr, uid, vals, context=None): vals.update({ 'carrera_id': self.carrera_turno_default(cr, uid, [])['value']['carrera_id'], 'turno': self.carrera_turno_default(cr, uid, [])['value']['turno'], }) return super(unefa_generar_lista_semestre, self).create(cr, uid, vals, context=context)
class hr_employee_overtime_wiz(osv.TransientModel): _name = 'hr.employee.overtime.wiz' _description = 'Allocation dheures sup par employees' _columns = { 'date': fields.date('Date', required=True), 'hours': fields.float('Heures Alloué', required=True), 'period_id': fields.many2one('account.period', 'Periode Salariale', required=True), 'depts': fields.many2many('hr.department', 'summ_dept_rel', 'sum_id', 'dept_id', 'Department(s)'), 'employee_ids': fields.many2many('hr.employee', 'summ_dept_emp_rel', 'sum_id', 'emp_id', 'Employee(s)'), 'type': fields.selection([('hs', 'Heures Supplementaires'), ('ferie', 'Ferie'), ('nuit', 'Nuit'), ('nuit_extra', 'Nuit Extra')], 'Type', required=True), } def _get_depts(self, cursor, user, context={}): employee = self.pool.get('hr.employee').search( cursor, user, [('user_id', '=', user)]) dept_id = self.pool.get('hr.employee').browse( cursor, user, employee, context={})[0].department_id.id depts = self.pool.get('hr.department').search( cursor, user, [('parent_id', 'in', [dept_id])]) depts.append(dept_id) return depts def _get_employee(self, cursor, user, context={}): employee = self.pool.get('hr.employee').search( cursor, user, [('user_id', '=', user)]) dept_id = self.pool.get('hr.employee').browse( cursor, user, employee, context={})[0].department_id.id depts = self.pool.get('hr.department').search( cursor, user, [('parent_id', 'in', [dept_id])]) depts.append(dept_id) return self.pool.get('hr.employee').search( cursor, user, [('department_id', 'in', depts)]) def _from_date(self, cursor, user, context={}): return datetime.date.today().strftime('%Y-%m-%d') _defaults = { 'date': _from_date, 'depts': _get_depts, 'employee_ids': _get_employee, 'type': 'hs', } def generate_leaves(self, cr, uid, ids, context=None): data = self.read(cr, uid, ids, [])[0] planning_obj = self.pool.get('hr.employee.overtime') if not data['employee_ids']: raise osv.except_osv( _('Error'), _('You have to select at least 1 Employee. And try again')) created = [] st = datetime.datetime.strptime(data['date'], '%Y-%m-%d') for employee in data['employee_ids']: print data['period_id'] print data['period_id'][0] print data['hours'] print data['type'] created.append( planning_obj.create( cr, uid, { 'type': data['type'], 'name': employee, 'date': st, 'period_id': data['period_id'][0], 'hours': data['hours'], 'state': 'draft' })) return { 'domain': "[('id','in', [" + ','.join(map(str, created)) + "])]", 'name': 'Planning', 'view_type': 'form', 'view_mode': 'tree,form', 'res_model': 'hr.employee.overtime', 'view_id': False, 'type': 'ir.actions.act_window', }
'sequence': fields.integer('Priority', help="Give to the more specialized category, a higher priority to have them in top of the list."), } class product_category(osv.osv): _inherit = 'product.category' def calculate_total_routes(self, cr, uid, ids, name, args, context=None): res = {} for categ in self.browse(cr, uid, ids, context=context): categ2 = categ routes = [x.id for x in categ.route_ids] while categ2.parent_id: categ2 = categ2.parent_id routes += [x.id for x in categ2.route_ids] res[categ.id] = routes return res _columns = { 'route_ids': fields.many2many('stock.location.route', 'stock_location_route_categ', 'categ_id', 'route_id', 'Routes', domain="[('product_categ_selectable', '=', True)]"), 'removal_strategy_id': fields.many2one('product.removal', 'Force Removal Strategy', help="Set a specific removal strategy that will be used regardless of the source location for this product category"), 'total_route_ids': fields.function(calculate_total_routes, relation='stock.location.route', type='many2many', string='Total routes', readonly=True), } _columns = { 'route_ids': fields.many2many('stock.location.route', 'stock_location_route_categ', 'categ_id', 'route_id', 'Routes', domain="[('product_categ_selectable', '=', True)]"), 'removal_strategy_id': fields.many2one('product.removal', 'Force Removal Strategy', help="Set a specific removal strategy that will be used regardless of the source location for this product category"), 'total_route_ids': fields.function(calculate_total_routes, relation='stock.location.route', type='many2many', string='Total routes', readonly=True), }
class nucleo(osv.osv): _name = 'unefa.nucleo' _rec_name = 'nombre' _columns = { 'nombre': fields.char('Sede', size=80, required=True, help='Aquí se coloca el nombre de la sede'), 'decano': fields.char('Decano', size=80, required=True, help='Aquí se coloca el nombre del decano de la sede'), 'unidad_academica': fields.char( 'Jefe Unidad Académica', size=80, required=True, help='Aquí se coloca el nombre del jefe de la unidad académica'), 'tipo_sede': fields.selection([('nucleo', 'NÚCLEO'), ('extension', 'EXTENCIÓN'), ('ampliacion', 'AMPLIACIÓN')], 'Tipo de sede', required=True, help='Aquí selecciona el tipo de sede.'), 'redi_id': fields.many2one( 'unefa.redi', 'REDI', required=True, help='Aquí se coloca la REDI donde está ubicada el sede'), 'region_id': fields.many2one( 'unefa.region_defensa_integral', 'Región Defensa Integral', required=True, help= 'Aquí se coloca la Región de Defensa Integral donde está ubicada el sede' ), 'direccion': fields.text('Dirección', required=True, help='Aquí se coloca el dirección del núcleo'), 'universidad_id': fields.many2one('res.company', 'Universidad'), 'carrera_ids': fields.many2many('unefa.carrera', 'unefa_nucleo_carrera', 'nucleo_id', 'carrera_id', 'Carreras'), 'telefono': fields.char('Teléfono', size=64, required=True, help='Aquí se coloca el Telefono del nucleo'), 'estado_id': fields.many2one('unefa.estados', 'Estado', required=True), 'municipio_id': fields.many2one('unefa.municipios', 'Municipio', required=True), 'parroquia_id': fields.many2one('unefa.parroquias', 'Parroquia', required=True), 'direccion': fields.char('Dirección', size=80, required=True, help='Aquí se coloca la dirección de la sede'), 'active': fields.boolean( 'Activo', help='Si esta activo el motor lo incluira en la vista...'), } _defaults = { 'active': True, } _sql_constraints = [('nucleo_uniq', 'unique(nombre)', 'El Nucleo que ingresó ya ha sido registrado.')] _order = 'create_date desc, id desc' def cp_limpiar_campos(self, cr, uid, ids, campo, context=None): return {'value': {campo: ''}} def create(self, cr, uid, vals, context=None): vals.update({ 'nombre': vals['nombre'].upper(), 'direccion': vals['direccion'].upper(), 'decano': vals['direccion'].upper(), 'unidad_academica': vals['direccion'].upper(), }) return super(nucleo, self).create(cr, uid, vals, context=context) def write(self, cr, uid, ids, vals, context=None): if 'nombre' in vals.keys(): vals.update({ 'nombre': vals['nombre'].upper(), }) if 'direccion' in vals.keys(): vals.update({ 'direccion': vals['direccion'].upper(), }) if 'unidad_academica' in vals.keys(): vals.update({ 'unidad_academica': vals['unidad_academica'].upper(), }) if 'decano' in vals.keys(): vals.update({ 'decano': vals['decano'].upper(), }) return super(nucleo, self).write(cr, uid, ids, vals, context=context)
def _order_lines_from_invoice(self, cr, uid, ids, context=None): # direct access to the m2m table is the less convoluted way to achieve this (and is ok ACL-wise) cr.execute("""SELECT DISTINCT sol.id FROM sale_order_invoice_rel rel JOIN sale_order_line sol ON (sol.order_id = rel.order_id) WHERE rel.invoice_id = ANY(%s)""", (list(ids),)) return [i[0] for i in cr.fetchall()] _name = 'sale.order.line' _description = 'Sales Order Line' _columns = { 'order_id': fields.many2one('sale.order', 'Order Reference', required=True, ondelete='cascade', select=True, readonly=True, states={'draft':[('readonly',False)]}), 'name': fields.text('Description', required=True, readonly=True, states={'draft': [('readonly', False)]}), 'sequence': fields.integer('Sequence', help="Gives the sequence order when displaying a list of sales order lines."), 'product_id': fields.many2one('product.product', 'Product', domain=[('sale_ok', '=', True)], change_default=True), 'invoice_lines': fields.many2many('account.invoice.line', 'sale_order_line_invoice_rel', 'order_line_id', 'invoice_id', 'Invoice Lines', readonly=True), 'invoiced': fields.function(_fnct_line_invoiced, string='Invoiced', type='boolean', store={ 'account.invoice': (_order_lines_from_invoice, ['state'], 10), 'sale.order.line': (lambda self,cr,uid,ids,ctx=None: ids, ['invoice_lines'], 10)}), 'price_unit': fields.float('Unit Price', required=True, digits_compute= dp.get_precision('Product Price'), readonly=True, states={'draft': [('readonly', False)]}), 'type': fields.selection([('make_to_stock', 'from stock'), ('make_to_order', 'on order')], 'Procurement Method', required=True, readonly=True, states={'draft': [('readonly', False)]}, help="From stock: When needed, the product is taken from the stock or we wait for replenishment.\nOn order: When needed, the product is purchased or produced."), 'price_subtotal': fields.function(_amount_line, string='Subtotal', digits_compute= dp.get_precision('Account')), 'tax_id': fields.many2many('account.tax', 'sale_order_tax', 'order_line_id', 'tax_id', 'Taxes', readonly=True, states={'draft': [('readonly', False)]}), 'address_allotment_id': fields.many2one('res.partner', 'Allotment Partner',help="A partner to whom the particular product needs to be allotted."), 'product_uom_qty': fields.float('Quantity', digits_compute= dp.get_precision('Product UoS'), required=True, readonly=True, states={'draft': [('readonly', False)]}), 'product_uom': fields.many2one('product.uom', 'Unit of Measure ', required=True, readonly=True, states={'draft': [('readonly', False)]}), 'product_uos_qty': fields.float('Quantity (UoS)' ,digits_compute= dp.get_precision('Product UoS'), readonly=True, states={'draft': [('readonly', False)]}), 'product_uos': fields.many2one('product.uom', 'Product UoS'), 'discount': fields.float('Discount (%)', digits_compute= dp.get_precision('Discount'), readonly=True, states={'draft': [('readonly', False)]}),
class sale_configuration(osv.TransientModel): _inherit = 'sale.config.settings' _columns = { 'group_product_variant': fields.selection( [(0, "No variants on products"), (1, 'Products can have several attributes, defining variants (Example: size, color,...)' )], "Product Variants", help= 'Work with product variant allows you to define some variant of the same products, an ease the product management in the ecommerce for example', implied_group='product.group_product_variant'), 'group_sale_pricelist': fields.boolean( "Use pricelists to adapt your price per customers", implied_group='product.group_sale_pricelist', help= """Allows to manage different prices based on rules per category of customers. Example: 10% for retailers, promotion of 5 EUR on this product, etc.""" ), 'group_pricelist_item': fields.boolean("Show pricelists to customers", implied_group='product.group_pricelist_item'), 'group_product_pricelist': fields.boolean("Show pricelists On Products", implied_group='product.group_product_pricelist'), 'group_uom': fields.selection( [(0, 'Products have only one unit of measure (easier)'), (1, 'Some products may be sold/purchased in different unit of measures (advanced)' )], "Unit of Measures", implied_group='product.group_uom', help= """Allows you to select and maintain different units of measure for products.""" ), 'group_discount_per_so_line': fields.selection( [(0, 'No discount on sales order lines, global discount only'), (1, 'Allow discounts on sales order lines')], "Discount", implied_group='sale.group_discount_per_so_line'), 'group_display_incoterm': fields.selection( [(0, 'No incoterm on reports'), (1, 'Show incoterms on sale orders and invoices')], "Incoterms", implied_group='sale.group_display_incoterm', help= "The printed reports will display the incoterms for the sale orders and the related invoices" ), 'module_sale_margin': fields.selection( [(0, 'Salespeople do not need to view margins when quoting'), (1, 'Display margins on quotations and sales orders')], "Margins"), 'module_website_sale_digital': fields.selection( [(0, 'No digital products'), (1, 'Allows to sell downloadable content from the portal')], "Digital Products"), 'module_website_quote': fields.selection( [(0, 'Print quotes or send by email'), (1, 'Send online quotations based on templates (advanced)')], "Online Quotations"), 'group_sale_delivery_address': fields.selection([ (0, "Invoicing and shipping addresses are always the same (Example: services companies)" ), (1, 'Have 3 fields on sales orders: customer, invoice address, delivery address' ) ], "Customer Addresses", implied_group='sale.group_delivery_invoice_address'), 'sale_pricelist_setting': fields.selection( [('fixed', 'A single sale price per product'), ('percentage', 'Different prices per customer segment'), ('formula', 'Advanced pricing based on formula')], required=True, help='Fix Price: all price manage from products sale price.\n' 'Different prices per Customer: you can assign price on buying of minimum quantity in products sale tab.\n' 'Advanced pricing based on formula: You can have all the rights on pricelist' ), 'default_invoice_policy': fields.selection( [('order', 'Invoice ordered quantities'), ('delivery', 'Invoice delivered quantities'), ('cost', 'Invoice based on costs (time and material, expenses)')], 'Default Invoicing', default_model='product.template'), 'deposit_property_account_income_id': fields.property( type="many2one", relation="account.account", string="Income Account", domain=[('deprecated', '=', False)], help= "This account will be used for invoices instead of the default one to value sales for the deposit." ), 'deposit_taxes_ids': fields.many2many('account.tax', 'product_taxes_rel', 'prod_id', 'tax_id', string='Customer Taxes', domain=[('type_tax_use', '=', 'sale')]), } _defaults = { 'sale_pricelist_setting': 'fixed', 'default_invoice_policy': 'order', } def set_sale_defaults(self, cr, uid, ids, context=None): sale_price = self.browse(cr, uid, ids, context=context).sale_pricelist_setting res = self.pool.get('ir.values').set_default(cr, uid, 'sale.config.settings', 'sale_pricelist_setting', sale_price) return res def onchange_sale_price(self, cr, uid, ids, sale_pricelist_setting, context=None): if sale_pricelist_setting == 'percentage': return { 'value': { 'group_product_pricelist': True, 'group_sale_pricelist': True, 'group_pricelist_item': False } } if sale_pricelist_setting == 'formula': return { 'value': { 'group_pricelist_item': True, 'group_sale_pricelist': True, 'group_product_pricelist': False } } return { 'value': { 'group_pricelist_item': False, 'group_sale_pricelist': False, 'group_product_pricelist': False } } def get_default_deposit_values(self, cr, uid, fields, context=None): deposit_product_template = self.pool['ir.model.data'].xmlid_to_object( cr, uid, 'sale.advance_product_1', context=context) return { 'deposit_property_account_income_id': deposit_product_template.product_variant_ids. property_account_income_id.id, 'deposit_taxes_ids': deposit_product_template.product_variant_ids.taxes_id.ids } def set_deposit_values(self, cr, uid, ids, context=None): if context is None: context = {} config_value = self.browse(cr, uid, ids, context=context) deposit_product_template = self.pool['ir.model.data'].xmlid_to_object( cr, uid, 'sale.advance_product_1', context=context) deposit_product_template.product_variant_ids.write({ 'property_account_income_id': config_value.deposit_property_account_income_id.id, 'taxes_id': [(6, 0, config_value.deposit_taxes_ids.ids)], })
cr, uid, line.taxes_id, line.price, line.qty, line.product_id, line.back_order_id.partner_id ) cur = line.back_order_id.pricelist_id.currency_id res[line.id] = cur_obj.round(cr, uid, cur, taxes["total"]) return res def _get_uom_id(self, cr, uid, context=None): try: proxy = self.pool.get("ir.model.data") result = proxy.get_object_reference(cr, uid, "product", "product_uom_unit") return result[1] except Exception, ex: return False _columns = { # 'location_destination_id': fields.many2one('stock.location', 'Stock Destination Location'), # 'location_id': fields.many2one('stock.location', 'Stock Source Location'), "product_id": fields.many2one("product.product", "Product"), "back_order_id": fields.many2one("back.to.back.order", "Back Order"), "qty": fields.float("Quantity"), "price": fields.float("Unit Price"), "subtotal": fields.function(_amount_line, string="Subtotal", digits_compute=dp.get_precision("Account")), "taxes_id": fields.many2many("account.tax", "purchase_order_taxe", "ord_id", "tax_id", "Taxes"), "product_uom": fields.many2one("product.uom", "Product Unit of Measure", required=True), } _defaults = {"product_uom": _get_uom_id} # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
class procurement_order(osv.osv): _inherit = 'procurement.order' _columns = { 'bom_id': fields.many2one('mrp.bom', 'BoM', ondelete='cascade', select=True), 'property_ids': fields.many2many('mrp.property', 'procurement_property_rel', 'procurement_id', 'property_id', 'Properties'), 'production_id': fields.many2one('mrp.production', 'Manufacturing Order'), } def propagate_cancel(self, cr, uid, procurement, context=None): if procurement.rule_id.action == 'manufacture' and procurement.production_id: self.pool.get('mrp.production').action_cancel( cr, uid, [procurement.production_id.id], context=context) return super(procurement_order, self).propagate_cancel(cr, uid, procurement, context=context) def _run(self, cr, uid, procurement, context=None): if procurement.rule_id and procurement.rule_id.action == 'manufacture': #make a manufacturing order for the procurement return self.make_mo(cr, uid, [procurement.id], context=context)[procurement.id] return super(procurement_order, self)._run(cr, uid, procurement, context=context) def _check(self, cr, uid, procurement, context=None): if procurement.production_id and procurement.production_id.state == 'done': # TOCHECK: no better method? return True return super(procurement_order, self)._check(cr, uid, procurement, context=context) def check_bom_exists(self, cr, uid, ids, context=None): """ Finds the bill of material for the product from procurement order. @return: True or False """ for procurement in self.browse(cr, uid, ids, context=context): properties = [x.id for x in procurement.property_ids] bom_id = self.pool.get('mrp.bom')._bom_find( cr, uid, product_id=procurement.product_id.id, properties=properties, context=context) if not bom_id: return False return True def _get_date_planned(self, cr, uid, procurement, context=None): format_date_planned = datetime.strptime( procurement.date_planned, DEFAULT_SERVER_DATETIME_FORMAT) date_planned = format_date_planned - relativedelta( days=procurement.product_id.produce_delay or 0.0) date_planned = date_planned - relativedelta( days=procurement.company_id.manufacturing_lead) return date_planned def _prepare_mo_vals(self, cr, uid, procurement, context=None): res_id = procurement.move_dest_id and procurement.move_dest_id.id or False newdate = self._get_date_planned(cr, uid, procurement, context=context) bom_obj = self.pool.get('mrp.bom') if procurement.bom_id: bom_id = procurement.bom_id.id routing_id = procurement.bom_id.routing_id.id else: properties = [x.id for x in procurement.property_ids] bom_id = bom_obj._bom_find( cr, uid, product_id=procurement.product_id.id, properties=properties, context=dict(context, company_id=procurement.company_id.id)) bom = bom_obj.browse(cr, uid, bom_id, context=context) routing_id = bom.routing_id.id return { 'origin': procurement.origin, 'product_id': procurement.product_id.id, 'product_qty': procurement.product_qty, 'product_uom': procurement.product_uom.id, 'product_uos_qty': procurement.product_uos and procurement.product_uos_qty or False, 'product_uos': procurement.product_uos and procurement.product_uos.id or False, 'location_src_id': procurement.location_id.id, 'location_dest_id': procurement.location_id.id, 'bom_id': bom_id, 'routing_id': routing_id, 'date_planned': newdate.strftime('%Y-%m-%d %H:%M:%S'), 'move_prod_id': res_id, 'company_id': procurement.company_id.id, } def make_mo(self, cr, uid, ids, context=None): """ Make Manufacturing(production) order from procurement @return: New created Production Orders procurement wise """ res = {} production_obj = self.pool.get('mrp.production') procurement_obj = self.pool.get('procurement.order') for procurement in procurement_obj.browse(cr, uid, ids, context=context): if self.check_bom_exists(cr, uid, [procurement.id], context=context): #create the MO as SUPERUSER because the current user may not have the rights to do it (mto product launched by a sale for example) vals = self._prepare_mo_vals(cr, uid, procurement, context=context) produce_id = production_obj.create( cr, SUPERUSER_ID, vals, context=dict(context, force_company=procurement.company_id.id)) res[procurement.id] = produce_id self.write(cr, uid, [procurement.id], {'production_id': produce_id}) self.production_order_create_note(cr, uid, procurement, context=context) production_obj.action_compute( cr, uid, [produce_id], properties=[x.id for x in procurement.property_ids]) production_obj.signal_workflow(cr, uid, [produce_id], 'button_confirm') else: res[procurement.id] = False self.message_post(cr, uid, [procurement.id], body=_("No BoM exists for this product!"), context=context) return res def production_order_create_note(self, cr, uid, procurement, context=None): body = _("Manufacturing Order <em>%s</em> created.") % ( procurement.production_id.name, ) self.message_post(cr, uid, [procurement.id], body=body, context=context)
'to_{0}_state'.format(ATTR_USE_DOM_PINVOICE[0]): fields.many2one( 'res.country.state', 'State', domain="[('country_id','=',to_{0}_country)]".format(ATTR_USE_DOM_PINVOICE[0])), 'to_{0}_country'.format(ATTR_USE_DOM_PSHIPPER[0]): fields.many2one( 'res.country', 'Country'), 'to_{0}_state'.format(ATTR_USE_DOM_PSHIPPER[0]): fields.many2one( 'res.country.state', 'State', domain="[('country_id','=',to_{0}_country)]".format(ATTR_USE_DOM_PSHIPPER[0])), # These are the Fiscal Attributes which are checked at runtime on the invoice-line level. As a many2many you can # select a custom number out of the Fiscal Attributes Table. Typically you might want to constrain the choice to # an above set Fiscal Domain (optional). Typically when parametrizing you might filter by Attribute Use (eg. # 'partner' or 'product' cases for convenience. (planned partner specific roles: 'seller' 'invoiced partner' # 'shipped partner' 'fiscal_attributes_id': fields.many2many( 'account.fiscal.attribute', 'fiscal_attribute_rel', 'rule_id', 'attr_id', 'Fiscal Attributes', # TODO this probably might result in problems as templates do not have field company_id domain="[('company_id','=',company_id),('fiscal_domain_id','=',fiscal_domain_id)]"), 'use_sale': fields.boolean('Sales Order'), 'use_invoice': fields.boolean('Invoices'), 'use_purchase': fields.boolean('Purchases'), 'use_picking': fields.boolean('Picking'), 'date_start': fields.date( 'from', help="Starting date for this rule to be valid."), 'date_end': fields.date( 'until', help="Ending date for this rule to be valid."), 'vat_rule': fields.selection( [('with', 'With VAT number'), ('both', 'With or Without VAT number'), ('without', 'Without VAT number')], "VAT Rule", help=("Choose if the customer need to have the"
def _get_uom_id(self, cr, uid, context=None): try: proxy = self.pool.get('ir.model.data') result = proxy.get_object_reference(cr, uid, 'product', 'product_uom_unit') return result[1] except Exception, ex: return False _columns = { # 'location_destination_id': fields.many2one('stock.location', 'Stock Destination Location'), # 'location_id': fields.many2one('stock.location', 'Stock Source Location'), 'product_id': fields.many2one('product.product', 'Product'), 'back_order_id': fields.many2one('back.to.back.order', 'Back Order'), 'qty': fields.float('Quantity'), 'price': fields.float('Unit Price'), 'subtotal': fields.function(_amount_line, string='Subtotal', digits_compute= dp.get_precision('Account')), 'taxes_id': fields.many2many('account.tax', 'purchase_order_taxe', 'ord_id', 'tax_id', 'Taxes'), 'product_uom': fields.many2one('product.uom', 'Product Unit of Measure', required=True), } _defaults = { 'product_uom' : _get_uom_id, } # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: