예제 #1
0
class res_request(osv.osv):
    _name = 'res.request'

    def request_send(self, cr, uid, ids, *args):
        for id in ids:
            cr.execute('update res_request set state=%s,date_sent=%s where id=%s', ('waiting', time.strftime('%Y-%m-%d %H:%M:%S'), id))
            cr.execute('select act_from,act_to,body,date_sent from res_request where id=%s', (id,))
            values = cr.dictfetchone()
            if values['body'] and (len(values['body']) > 128):
                values['name'] = values['body'][:125] + '...'
            else:
                values['name'] = values['body'] or '/'
            values['req_id'] = id
            self.pool.get('res.request.history').create(cr, uid, values)
        return True

    def request_reply(self, cr, uid, ids, *args):
        for id in ids:
            cr.execute("update res_request set state='active', act_from=%s, act_to=act_from, trigger_date=NULL, body='' where id=%s", (uid,id))
        return True

    def request_close(self, cr, uid, ids, *args):
        self.write(cr, uid, ids, {'state':'closed'})
        return True

    def request_get(self, cr, uid):
        cr.execute('select id from res_request where act_to=%s and (trigger_date<=%s or trigger_date is null) and active=True and state != %s', (uid,time.strftime('%Y-%m-%d'), 'closed'))
        ids = map(lambda x:x[0], cr.fetchall())
        cr.execute('select id from res_request where act_from=%s and (act_to<>%s) and (trigger_date<=%s or trigger_date is null) and active=True and state != %s', (uid,uid,time.strftime('%Y-%m-%d'), 'closed'))
        ids2 = map(lambda x:x[0], cr.fetchall())
        return (ids, ids2)

    _columns = {
        'create_date': fields.datetime('Created Date', readonly=True),
        'name': fields.char('Subject', states={'waiting':[('readonly',True)],'active':[('readonly',True)],'closed':[('readonly',True)]}, required=True, size=128),
        'active': fields.boolean('Active'),
        'priority': fields.selection([('0','Low'),('1','Normal'),('2','High')], 'Priority', states={'waiting':[('readonly',True)],'closed':[('readonly',True)]}, required=True),
        'act_from': fields.many2one('res.users', 'From', required=True, readonly=True, states={'closed':[('readonly',True)]}, select=1),
        'act_to': fields.many2one('res.users', 'To', required=True, states={'waiting':[('readonly',True)],'closed':[('readonly',True)]}, select=1),
        'body': fields.text('Request', states={'waiting':[('readonly',True)],'closed':[('readonly',True)]}),
        'date_sent': fields.datetime('Date', readonly=True),
        'trigger_date': fields.datetime('Trigger Date', states={'waiting':[('readonly',True)],'closed':[('readonly',True)]}, select=1),
        'ref_partner_id':fields.many2one('res.partner', 'Partner Ref.', states={'closed':[('readonly',True)]}),
        'ref_doc1':fields.reference('Document Ref 1', selection=_links_get, size=128, states={'closed':[('readonly',True)]}),
        'ref_doc2':fields.reference('Document Ref 2', selection=_links_get, size=128, states={'closed':[('readonly',True)]}),
        'state': fields.selection([('draft','draft'),('waiting','waiting'),('active','active'),('closed','closed')], 'State', required=True, readonly=True),
        'history': fields.one2many('res.request.history','req_id', 'History')
    }
    _defaults = {
        'act_from': lambda obj,cr,uid,context=None: uid,
        'state': 'draft',
        'active': True,
        'priority': '1',
    }
    _order = 'priority desc, trigger_date, create_date desc'
    _table = 'res_request'
예제 #2
0
class project_reference(osv.osv):
    _inherit = "project.task"

    _columns = {
        'ref_partner_id':
        fields.many2one('res.partner', 'Partner Ref.'),
        'ref_doc1':
        fields.reference('Document Ref 1', selection=_links_get, size=128),
        'ref_doc2':
        fields.reference('Document Ref 2', selection=_links_get, size=128),
    }
예제 #3
0
class ir_attachment(osv.osv):
    _inherit = "ir.attachment"

    #    def _ref (self, cr, uid, ids, field_name, arg, context) :
    #       res = {}
    #       for obj in self.browse (cr, uid, ids) :
    #           if obj.res_model and obj.res_id :
    #               res[obj.id] = obj.res_model + ",%s" % obj.res_id
    #           else :
    #                res[obj.id] = False
    #       return res
    #    # end def _ref

    #    _columns  = \
    #        { 'ref' : fields.function
    #            ( _ref
    #            , type     = 'char', size=128
    #            , method   = True
    #            , string   = 'Migration aid'
    #            , store    = True
    #            , readonly = True
    #            )
    #        }

    def _links_get(self, cr, uid, context={}):
        obj = self.pool.get("res.request.link")
        ids = obj.search(cr, uid, [])
        res = obj.read(cr, uid, ids, ["object", "name"], context)
        return [(r["object"], r["name"]) for r in res]

    # ende def _links_get

    _columns  = \
        { 'ref' : fields.reference('Migration aid', selection=_links_get, size=128, readonly=True)}
예제 #4
0
class crm_opportunity(osv.osv):
    """ Opportunity Cases """
    _order = "priority,date_action,id desc"
    _inherit = 'crm.lead'
    _columns = {
        # From crm.case
        'partner_address_id': fields.many2one('res.partner.address', 'Partner Contact', \
                                 domain="[('partner_id','=',partner_id)]"),

        # Opportunity fields
        'probability': fields.float('Probability (%)',group_operator="avg"),
        'planned_revenue': fields.float('Expected Revenue'),
        'ref': fields.reference('Reference', selection=crm._links_get, size=128),
        'ref2': fields.reference('Reference 2', selection=crm._links_get, size=128),
        'phone': fields.char("Phone", size=64),
        'date_deadline': fields.date('Expected Closing'),
        'date_action': fields.date('Next Action Date'),
        'title_action': fields.char('Next Action', size=64),
        'stage_id': fields.many2one('crm.case.stage', 'Stage', domain="[('type','=','opportunity')]"),
     }

    def _case_close_generic(self, cr, uid, ids, find_stage, *args):
        res = super(crm_opportunity, self).case_close(cr, uid, ids, *args)
        for case in self.browse(cr, uid, ids):
            #if the case is not an opportunity close won't change the stage
            if not case.type == 'opportunity':
                return res

            value = {}
            stage_id = find_stage(cr, uid, 'opportunity', case.section_id.id
                                  or False)
            if stage_id:
                stage_obj = self.pool.get('crm.case.stage').browse(
                    cr, uid, stage_id)
                value.update({'stage_id': stage_id})
                if stage_obj.on_change:
                    value.update({'probability': stage_obj.probability})

            #Done un crm.case
            #value.update({'date_closed': time.strftime('%Y-%m-%d %H:%M:%S')})

            self.write(cr, uid, ids, value)
        return res
예제 #5
0
class qc_test_template(osv.osv):
    """
    A template is a group of proofs to with the values that make them valid.
    """

    _name = 'qc.test.template'
    _description='Test Template'

    def _links_get(self, cr, uid, context=None):
        #TODO: Select models
        obj = self.pool.get('res.request.link')
        ids = obj.search(cr, uid, [], context=context)
        res = obj.read(cr, uid, ids, ['object', 'name'], context)
        return [(r['object'], r['name']) for r in res]

    def _default_name(self, cr, uid, context=None):
        if context and context.get('reference_model', False):
            id = context.get('reference_id')
            if not id:
                id = context.get('active_id')
            if id:
                source=self.pool.get(context['reference_model']).browse(cr, uid, id, context)
                if hasattr(source, 'name'):
                    return source.name

    def _default_object_id(self, cr, uid, context=None):
        if context and context.get('reference_model', False):
            return '%s,%d' % (context['reference_model'], context['reference_id'])
        else:
            return False

    def _default_type(self, cr, uid, context=None):
        if context and context.get('reference_model'):
            return 'related'
        else:
            return False


    _columns = {
        'active':fields.boolean('Active', select="1"),
        'name': fields.char('Name', size=200, required=True,translate=True,select="1"),
        'test_template_line_ids':fields.one2many('qc.test.template.line','test_template_id', 'Lines' ),
        'object_id':fields.reference('Reference Object', selection=_links_get, size=128 ) ,
        'fill_correct_values':fields.boolean('Fill With Correct Values' ),
        'type':fields.selection([('generic','Generic'),('related','Related')], 'Type' , select="1"),
        'category_id': fields.many2one('qc.test.template.category','Category'),
        'trig_on' : fields.many2one('qc.test.template.trigger', 'Trigger'),
    }

    _defaults = {
        'name': _default_name,
        'active': lambda *a: True,
        'object_id': _default_object_id,
        'type': _default_type,
    }
예제 #6
0
class account_account_records(osv.osv):
    _name = 'account.account.records'
    _auto = False
    _description = 'Records by Accounts'
    _rec_name = 'record_id'
    _columns = {
        'record_id':
        fields.reference('Record',
                         selection=_links_get,
                         size=128,
                         readonly=True),
        'model_id':
        fields.many2one('ir.model', 'Model', readonly=True),
        'value_id':
        fields.integer('Value', readonly=True),
        'field_id':
        fields.many2one('ir.model.fields', 'Field', readonly=True),
    }

    def _get_records(self, cr, uid=1, id=None, context=None):
        if context is None:
            context = {}
        res = []

        imf_obj = self.pool.get('ir.model.fields')
        #~ imf_ids = imf_obj.search(cr,uid,[('ttype','=','many2one'),('relation','=','account.account'),('model','!=','account.account'),('view_load','=',False)])
        imf_ids = imf_obj.search(cr, uid,
                                 [('ttype', '=', 'many2one'),
                                  ('relation', '=', 'account.account'),
                                  ('model', '!=', 'account.account')])

        if imf_ids:
            for each in imf_obj.browse(cr, uid, imf_ids, context=context):
                if not each.model_id.osv_memory:
                    cr.execute(
                        """SELECT attname FROM pg_attribute WHERE attrelid = (SELECT oid FROM pg_class WHERE relname = '%s') AND attname = '%s'"""
                        % (each.model.replace('.', '_'), each.name))
                    value = cr.fetchall()
                    if not value:
                        continue

                    res.append(
                        """SELECT COALESCE(%s,NULL) as value_id, CASE WHEN id > 0 THEN (%s || id) END AS record_id, CASE WHEN id > 0 THEN %s END AS field_id, CASE WHEN id > 0 THEN %s END AS model_id, CASE WHEN id > 0 THEN (%s * %s + id) END AS id FROM %s"""
                        % (each.name, "'%s,'" % each.model, each.id,
                           each.model_id.id, each.id, each.model_id.id,
                           each.model.replace('.', '_')))
            res = ' UNION '.join(res)
        return res

    def init(self, cr):
        tools.drop_view_if_exists(cr, 'account_account_records')
        cr.execute("""
            CREATE OR REPLACE view account_account_records AS (%s)
        """ % (self._get_records(cr, 1), ))
예제 #7
0
class stock_move(osv.osv):
    _inherit = "stock.move"
    
    def _get_selection_list(self, cr, uid, context=None):
        #@return a list of tuples. tuples containing model name and name of the record
        model_obj = self.pool.get('ir.model')
        ids = model_obj.search(cr, uid, [('name', 'not ilike', '.')])
        res = model_obj.read(cr, uid, ids, ['model', 'name'])
        return [(r['model'], r['name']) for r in res] + [('', '')]

    _columns = {
        'origin_document': fields.reference("Origin Document", selection=_get_selection_list, size=None)
    }
예제 #8
0
class account_cashflow_provision_line(osv.osv):
    _inherit = 'account.cashflow.provision.line'

    def _get_reference_model(self, cr, uid, context=None):
        res = super(account_cashflow_provision_line, self)._get_reference_model(cr, uid, context=context)
        res += [('account.cash.operation','Cash Management Operation')]
        return res
    
    _columns = {
        'origin': fields.reference('Originating Transaction', size=128, readonly=True,
            selection=_get_reference_model,
            help='This field contains a reference to the transaction that originated the creation of this provision.'),
    }
예제 #9
0
파일: period_check.py 프로젝트: raji91/OE7
class reconcile_item(osv.osv_memory):
    _name = "fg_account.reconcile.item"

    _columns = {
        'ref_doc':
        fields.reference('单据',
                         selection=[('fg_sale.order', '销售订单'),
                                    ('fg_account.bill', '收款单')],
                         size=128,
                         readonly=True),
        'o_date':
        fields.date('单据日期', readonly=True),
        'name':
        fields.char('单号', size=24),
        'o_partner':
        fields.many2one('res.partner', '客户', readonly=True),
        't':
        fields.char('项目', size=12, readonly=True),
        'reconciled':
        fields.boolean('已对账', readonly=True),
        'cleared':
        fields.boolean('已清账', readonly=True),
        'amount':
        fields.float('金额', digits=(16, 4), readonly=True),
        'balance':
        fields.float('余额', digits=(16, 4), readonly=True),
        'note':
        fields.text('附注'),
    }

    _order = 'o_date asc'

    def button_view(self, cr, uid, ids, context=None):
        record = self.browse(cr, uid, ids)[0]

        r = {
            'type': 'ir.actions.act_window',
            'name': '查看单据',
            'view_mode': 'form',
            'view_type': 'form',
            'res_model': record.ref_doc._table_name,
            'res_id': record.ref_doc.id,
            'target': 'new',
            'context': context,
        }
        #if record.ref_doc._table_name == 'fg_account.bill':
        #    r['res_id'] = record.id - 1000000000
        #
        #print r

        return r
예제 #10
0
class ineco_jasper_report_params(osv.osv):
    
    _name = 'ineco.jasper.report.params'
    _description = 'Ineco Jasper Report Parameter'
    _columns = {
        'param_name': fields.char('Name', size=250, required=True),
        'param_uristring': fields.char('uriString', size=250, required=True),
        'param_label': fields.char('Label', size=250, required=True),
        'reference_id':fields.reference('Document', selection=_links_get, size=128),        
        'report_id': fields.many2one('ineco.jasper.report', 'Report', ondelete="cascade"),
    }
    _sql_constraints = [
        ('name_uniq', 'unique(param_name,report_id)', 'Report and Parameters must be unique!'),
    ]
예제 #11
0
class detail_ledger(osv.osv_memory):
    '''
    根据输入的科目和期间、辅助核算项目输出《明细账》
    现金日记账,现金外币账,数量金额明细账,三栏帐,外币往来帐
    '''
    def _get_co(self, cr, uid, context=None):
        return [('res.partner', '往来')]

    _name = 'detail.ledger'
    _descript = u'明细账'
    _columns = {
        'acc_id': fields.many2one('fi.acc', u'会计科目', required=True),
        'period_from': fields.many2one('fi.period', u'开始期间', required=True),
        'period_to': fields.many2one('fi.period', u'截至期间', required=True),
        'co_obj': fields.reference(u'辅助核算项目', selection=_get_co, size=128),
    }

    def default_get(self, cr, uid, fields, context=None):
        return {
            'acc_id':
            context.get('active_id', None),
            'period_to':
            self.pool.get('fi.period').find(cr, uid, context=context),
            'period_from':
            self.pool.get('fi.period').find(cr, uid, context=context),
        }

    def print_report(self, cr, uid, ids, context=None):
        datas = {}
        res = self.read(cr,
                        uid,
                        ids[0],
                        ['acc_id', 'period_from', 'period_to', 'co_obj'],
                        context=context)
        acc = self.pool.get('fi.acc').browse(cr,
                                             uid,
                                             res['acc_id'][0],
                                             context=context)
        datas['ids'] = [
            res['acc_id'][0],
        ]
        datas['period_to'] = res['period_to'][0]
        datas['period_from'] = res['period_from'][0]
        datas['cost_obj'] = res['co_obj']
        return {
            'type': 'ir.actions.report.xml',
            'report_name': acc.format,
            'datas': datas
        }
예제 #12
0
class xml_template_ref(osv.osv):
    _name = "xml.template.ref"
    _description = "XML Template Reference"
    _order = "name"

    def _links_get(self, cr, uid, context={}):
        obj = self.pool.get("res.request.link")
        ids = obj.search(cr, uid, [])
        res = obj.read(cr, uid, ids, ["object", "name"], context)
        return [(r["object"], r["name"]) for r in res]

    # ende def _links_get

    _columns  = \
        { "xml_template_id" : fields.many2one("xml.template", "XML Template", required=True, ondelete="cascade")
        , "name"            : fields.reference('Reference', selection=_links_get, size=128, required=True)
        }
예제 #13
0
class subscription_subscription_history(osv.osv):
    _name = "subscription.subscription.history"
    _description = "Subscription history"
    _rec_name = 'date'
    _columns = {
        'date':
        fields.datetime('Date'),
        'subscription_id':
        fields.many2one('subscription.subscription',
                        'Subscription',
                        ondelete='cascade'),
        'document_id':
        fields.reference('Source Document',
                         required=True,
                         selection=_get_document_types,
                         size=128),
    }
예제 #14
0
class subscription_subscription_history(osv.osv):
    _name = "subscription.subscription.history"
    _description = "Subscription history"
    _rec_name = 'date'
    _columns = {
        'date':
        fields.datetime('Date'),
        'subscription_id':
        fields.many2one('subscription.subscription',
                        'Subscription',
                        ondelete='cascade'),
        'document_id':
        fields.reference('Source Document',
                         required=True,
                         selection=[('account.invoice', 'Invoice'),
                                    ('sale.order', 'Sale Order')],
                         size=128),
    }
예제 #15
0
class letter_ref(osv.osv):
    _name = 'letter.ref'

    def _name_get_intref(self, cr, uid, ids, prop, unknow_none, context=None):
        if not len(ids):
            return []
        reads = self.read(cr, uid, ids, ['id', 'int_ref'], context=context)
        res = []
        for record in reads:
            try:
                (model_name, obj_id) = record['int_ref'].split(',')
                if model_name and obj_id:
                    obj_id = int(obj_id)
                    model = self.pool.get(model_name)
                    obj_name = model.name_get(cr, uid, [obj_id])[0]
                    if obj_name and len(obj_name) > 1:
                        print(record['id'], obj_name[1])
                        res.append((record['id'], obj_name[1]))
            except:
                print repr(traceback.extract_tb(sys.exc_traceback))
        return dict(res)

    _columns = {
        'name':
        fields.char('Name', size=128, help="Subject of letter"),
        'int_ref':
        fields.reference('Reference', selection=_links_get, size=128),
        'ref_name':
        fields.function(_name_get_intref,
                        method=True,
                        type="char",
                        string="Letter Reference"),
        'letter_id':
        fields.many2one('res.letter', "Letter"),
    }
    _defaults = {
        'name':
        lambda self, cr, uid, context: self.pool.get('ir.sequence').get(
            cr, uid, 'letter.ref'),
    }
예제 #16
0
class res_partner_event(osv.osv):
    _name = "res.partner.event"
    _columns = {
        'name':
        fields.char('Events', size=64, required=True),
        'som':
        fields.many2one('res.partner.som', 'State of Mind'),
        'description':
        fields.text('Description'),
        'planned_cost':
        fields.float('Planned Cost'),
        'planned_revenue':
        fields.float('Planned Revenue'),
        'probability':
        fields.float('Probability (0.50)'),
        'document':
        fields.reference('Document', selection=_links_get, size=128),
        'partner_id':
        fields.many2one('res.partner', 'Partner', select=True),
        'date':
        fields.datetime('Date', size=16),
        'user_id':
        fields.many2one('res.users', 'User'),
        'canal_id':
        fields.many2one('res.partner.canal', 'Channel'),
        'partner_type':
        fields.selection([('customer', 'Customer'), ('retailer', 'Retailer'),
                          ('prospect', 'Commercial Prospect')],
                         'Partner Relation'),
        'type':
        fields.selection([('sale', 'Sale Opportunity'),
                          ('purchase', 'Purchase Offer'),
                          ('prospect', 'Prospect Contact')], 'Type of Event'),
        'event_ical_id':
        fields.char('iCal id', size=64),
    }
    _order = 'date desc'
    _defaults = {
        'date': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'),
    }
예제 #17
0
class etl_mapping_line(osv.Model):
    def _get_map_ref(self, cr, uid, context=None):
        return [('res.partner', 'Partner')]

    _name = 'etl.mapping.line'
    _description = 'ETL Mapping Line'
    _columns = {
        'mapping_id':
        fields.many2one('etl.mapping', string='Mapping', required=True),
        'name':
        fields.char('Original Char', 256, required=True),
        'map_char':
        fields.char('Map Char', 256),
        'map_id':
        fields.integer('Map Id'),
        'map_xml_id':
        fields.char('Map XML Id', 128),
        'map_ref':
        fields.reference(
            'Map Reference',
            _get_map_ref,
            64,
            help=
            "Use this field only in case the destinity server is equal to your local OpenERP server"
        ),
        'is_default':
        fields.boolean(
            'Default',
            help=
            "This row is selected when the value is not equal to another lines"
        )
    }
    _defaults = {
        'is_default': False,
    }
    _sql_constraints = [
        ('mapping_name_uniq', 'unique(mapping_id,name)',
         'The mapping and source char must be unique!'),
    ]
예제 #18
0
class ir_attachment_ref(osv.osv):
    _name = "ir.attachment.ref"
    _description = "Attachment Reference"

    def _links_get(self, cr, uid, context={}):
        obj = self.pool.get("res.request.link")
        ids = obj.search(cr, uid, [])
        res = obj.read(cr, uid, ids, ["object", "name"], context)
        return [(r["object"], r["name"]) for r in res]

    # ende def _links_get

    _columns  = \
        { "ir_attachment_id" : fields.many2one("ir.attachment", "Attachment", required=True, ondelete="cascade")
        , "name"             : fields.reference('Reference', selection=_links_get, size=128, required=True)
        }
    _sql_constraints = \
        [( "ir_attachment_ref_name_index"
         , "unique (name)"
         , "The Reference has to be unique!"
         )
        ]
예제 #19
0
class admin_property(osv.osv):
    _name = 'admin.property'
    _description = 'Tables to handle properties specific to each admin project'

    _columns = {
        'name':
        fields.char('Property Name', required=True, size=128),
        'value':
        fields.char('Property Value', required=True, size=600),
        'ref_record':
        fields.reference('Record Ref', selection=_links_get, size=128),
    }

    _sql_constraints = [
        ('name_ref_uniq', 'unique (name)',
         'The property name must be unique !'),
    ]

    def _get_project_property_by_name(self, cr, uid, name):
        result = None
        property_ids = self.search(cr, uid, [('name', '=', name)])
        if property_ids:
            property_obj = self.browse(cr, uid, property_ids[0])
            if property_obj.ref_record:
                # update the value if needed
                if property_obj.ref_record.name != property_obj.value:
                    self.write(cr, uid, [property_obj.id],
                               {'value': property_obj.ref_record.name})

            result = property_obj
        return result

    def write(self, cr, uid, ids, vals, context=None):
        if vals.get('name'):
            del vals['name']
        return super(admin_property, self).write(cr, uid, ids, vals, context)
예제 #20
0
class qc_test(osv.osv):
    """
    This model contains an instance of a test template.
    """

    _name = 'qc.test'

    def _success(self, cr, uid, ids, field_name, arg, context=None):
        result = {}
        for test in self.browse(cr, uid, ids, context):
            success = True
            proof={}
            for line in test.test_line_ids:
                proof[ line.proof_id.id ] = proof.get(line.proof_id.id,False) or line.success

            for p in proof:
                if not proof[p]:
                    success = False
                    break
            result[test.id] = success
        return result

    def _links_get(self, cr, uid, context=None):
        # TODO: Select models
        obj = self.pool.get('res.request.link')
        ids = obj.search(cr, uid, [], context=context)
        res = obj.read(cr, uid, ids, ['object', 'name'], context)
        return [(r['object'], r['name']) for r in res]

    def _default_object_id(self, cr, uid, context=None):
        if context and context.get('reference_model', False):
            return '%s,%d' % (context['reference_model'], context['reference_id'])
        else:
            return False

    _columns = {
        'name': fields.datetime('Date',required=True, readonly=True, states={'draft':[('readonly',False)]}, select="1"),
        'object_id':fields.reference('Reference', selection=_links_get, size=128, readonly=True, states={'draft':[('readonly',False)]}, select="1"),
        'test_template_id': fields.many2one('qc.test.template','Test', states={'success':[('readonly',True)], 'failed':[('readonly',True)]}, select="1"),
        'test_line_ids': fields.one2many( 'qc.test.line', 'test_id', 'Test Lines', states={'success':[('readonly',True)], 'failed':[('readonly',True)]}),
        'test_internal_note': fields.text('Internal Note', states={'success':[('readonly',True)], 'failed':[('readonly',True)]}),
        'test_external_note': fields.text('External Note', states={'success':[('readonly',True)], 'failed':[('readonly',True)]}),
        'state': fields.selection([
            ('draft','Draft'),
            ('waiting','Waiting Supervisor Approval'),
            ('success','Quality Success'),
            ('failed','Quality Failed'),
        ], 'State', readonly=True, select="1"),
        'success': fields.function(_success, method=True, type='boolean', string='Success', help='This field will be active if all tests have succeeded.',select="1"),
        'enabled': fields.boolean('Enabled', readonly=True, help='If a quality control test is not enabled it means it can not be moved from "Quality Success" or "Quality Failed" state.',select="1"),
    }
    _defaults = {
        'name' : lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'),
        'state': lambda *a: 'draft',
        'object_id': _default_object_id,
        'enabled': lambda *a: True,
    }

    def copy(self, cr, uid, id, default=None,context=None):
        if context == None:
            context = {}

        if default == None:
            default = {}
        default['name'] = time.strftime('%Y-%m-%d %H:%M:%S')
        return super( qc_test, self).copy( cr, uid, id, default, context)

    def create(self, cr, uid, datas, context=None):
        if context and context.get('reference_model', False):
            datas['object_id'] = context['reference_model'] + "," + str(context['reference_id'])
        return super(osv.osv, self).create(cr, uid, datas, context=context)

    def qc_test_success(self, cr, uid, ids, context):
        self.write(cr, uid, ids, {
            'state' : 'success'
        }, context)
        return True

    def qc_test_failed(self, cr, uid, ids, context):
        self.write(cr, uid, ids, {
            'state' : 'failed'
        }, context)
        return True

    def test_state(self, cr, uid, ids, mode, *args):
        quality_check=False
        if mode == 'failed':
            return not quality_check
        if mode == 'success':
            return quality_check
        return False

    def set_test_template(self, cr, uid, ids, template_id, force_fill=False, context=None):
        if context == None:
            context={}
        for id in ids:
            self.pool.get('qc.test').write( cr, uid, id, {
                'test_template_id' : template_id
            }, context)

            test = self.pool.get('qc.test').browse( cr, uid, id, context )

            if len(test.test_line_ids) > 0:
                self.pool.get( 'qc.test.line' ).unlink(cr, uid, [x.id for x in test.test_line_ids], context )

            fill=False
            if test.test_template_id.fill_correct_values:
                fill=True


            for line in test.test_template_id.test_template_line_ids:
                data = {
                    'test_id': id,
                    'method_id': line.method_id.id,
                    'proof_id': line.proof_id.id,
                    'test_template_line_id': line.id,
                    'notes': line.notes,
                    'min_value': line.min_value,
                    'max_value': line.max_value,
                    'uom_id': line.uom_id.id,
                    'test_uom_id': line.uom_id.id,
                    'proof_type': line.type,
                }
                if fill or force_fill :
                    if line.type == 'qualitative':
                        # Fill wiht the first correct value finded.
                        data['actual_value_ql'] = len(line.valid_value_ids) and line.valid_value_ids[0] and  line.valid_value_ids[0].id or False

                    else:
                        # Fill with value inside rang.
                        data['actual_value_qt'] =line.min_value
                        data['test_uom_id'] = line.uom_id.id

                test_line_id = self.pool.get('qc.test.line').create( cr,uid,data , context)
                self.pool.get('qc.test.line').write(cr, uid, [test_line_id], {
                        'valid_value_ids': [(6, 0,[x.id for x in line.valid_value_ids ])]
                    })
예제 #21
0
class actions_server(osv.osv):

    def _select_signals(self, cr, uid, context=None):
        cr.execute("""SELECT distinct w.osv, t.signal FROM wkf w, wkf_activity a, wkf_transition t
                      WHERE w.id = a.wkf_id AND
                            (t.act_from = a.id OR t.act_to = a.id) AND
                            t.signal IS NOT NULL""")
        result = cr.fetchall() or []
        res = []
        for rs in result:
            if rs[0] is not None and rs[1] is not None:
                line = rs[1], "%s - (%s)" % (rs[1], rs[0])
                res.append(line)
        return res

    def _select_objects(self, cr, uid, context=None):
        model_pool = self.pool.get('ir.model')
        ids = model_pool.search(cr, uid, [('name','not ilike','.')])
        res = model_pool.read(cr, uid, ids, ['model', 'name'])
        return [(r['model'], r['name']) for r in res] +  [('','')]

    def change_object(self, cr, uid, ids, copy_object, state, context=None):
        if state == 'object_copy' and copy_object:
            if context is None:
                context = {}
            model_pool = self.pool.get('ir.model')
            model = copy_object.split(',')[0]
            mid = model_pool.search(cr, uid, [('model','=',model)])
            return {
                'value': {'srcmodel_id': mid[0]},
                'context': context
            }
        else:
            return {}

    _name = 'ir.actions.server'
    _table = 'ir_act_server'
    _sequence = 'ir_actions_id_seq'
    _order = 'sequence,name'
    _columns = {
        'name': fields.char('Action Name', required=True, size=64, translate=True),
        'condition' : fields.char('Condition', size=256, required=True,
                                  help="Condition that is tested before the action is executed, "
                                       "and prevent execution if it is not verified.\n"
                                       "Example: object.list_price > 5000\n"
                                       "It is a Python expression that can use the following values:\n"
                                       " - self: ORM model of the record on which the action is triggered\n"
                                       " - object or obj: browse_record of the record on which the action is triggered\n"
                                       " - pool: ORM model pool (i.e. self.pool)\n"
                                       " - time: Python time module\n"
                                       " - cr: database cursor\n"
                                       " - uid: current user id\n"
                                       " - context: current context"),
        'state': fields.selection([
            ('client_action','Client Action'),
            ('dummy','Dummy'),
            ('loop','Iteration'),
            ('code','Python Code'),
            ('trigger','Trigger'),
            ('email','Email'),
            ('sms','SMS'),
            ('object_create','Create Object'),
            ('object_copy','Copy Object'),
            ('object_write','Write Object'),
            ('other','Multi Actions'),
        ], 'Action Type', required=True, size=32, help="Type of the Action that is to be executed"),
        'code':fields.text('Python Code', help="Python code to be executed if condition is met.\n"
                                               "It is a Python block that can use the same values as for the condition field"),
        'sequence': fields.integer('Sequence', help="Important when you deal with multiple actions, the execution order will be decided based on this, low number is higher priority."),
        'model_id': fields.many2one('ir.model', 'Object', required=True, help="Select the object on which the action will work (read, write, create)."),
        'action_id': fields.many2one('ir.actions.actions', 'Client Action', help="Select the Action Window, Report, Wizard to be executed."),
        'trigger_name': fields.selection(_select_signals, string='Trigger Signal', size=128, help="The workflow signal to trigger"),
        'wkf_model_id': fields.many2one('ir.model', 'Target Object', help="The object that should receive the workflow signal (must have an associated workflow)"),
        'trigger_obj_id': fields.many2one('ir.model.fields','Relation Field', help="The field on the current object that links to the target object record (must be a many2one, or an integer field with the record ID)"),
        'email': fields.char('Email Address', size=512, help="Expression that returns the email address to send to. Can be based on the same values as for the condition field.\n"
                                                             "Example: object.invoice_address_id.email, or '*****@*****.**'"),
        'subject': fields.char('Subject', size=1024, translate=True, help="Email subject, may contain expressions enclosed in double brackets based on the same values as those "
                                                                          "available in the condition field, e.g. `Hello [[ object.partner_id.name ]]`"),
        'message': fields.text('Message', translate=True, help="Email contents, may contain expressions enclosed in double brackets based on the same values as those "
                                                                          "available in the condition field, e.g. `Dear [[ object.partner_id.name ]]`"),
        'mobile': fields.char('Mobile No', size=512, help="Provides fields that be used to fetch the mobile number, e.g. you select the invoice, then `object.invoice_address_id.mobile` is the field which gives the correct mobile number"),
        'sms': fields.char('SMS', size=160, translate=True),
        'child_ids': fields.many2many('ir.actions.server', 'rel_server_actions', 'server_id', 'action_id', 'Other Actions'),
        'usage': fields.char('Action Usage', size=32),
        'type': fields.char('Action Type', size=32, required=True),
        'srcmodel_id': fields.many2one('ir.model', 'Model', help="Object in which you want to create / write the object. If it is empty then refer to the Object field."),
        'fields_lines': fields.one2many('ir.server.object.lines', 'server_id', 'Field Mappings.'),
        'record_id':fields.many2one('ir.model.fields', 'Create Id', help="Provide the field name where the record id is stored after the create operations. If it is empty, you can not track the new record."),
        'write_id':fields.char('Write Id', size=256, help="Provide the field name that the record id refers to for the write operation. If it is empty it will refer to the active id of the object."),
        'loop_action':fields.many2one('ir.actions.server', 'Loop Action', help="Select the action that will be executed. Loop action will not be avaliable inside loop."),
        'expression':fields.char('Loop Expression', size=512, help="Enter the field/expression that will return the list. E.g. select the sale order in Object, and you can have loop on the sales order line. Expression = `object.order_line`."),
        'copy_object': fields.reference('Copy Of', selection=_select_objects, size=256),
    }
    _defaults = {
        'state': lambda *a: 'dummy',
        'condition': lambda *a: 'True',
        'type': lambda *a: 'ir.actions.server',
        'sequence': lambda *a: 5,
        'code': lambda *a: """# You can use the following variables:
#  - self: ORM model of the record on which the action is triggered
#  - object: browse_record of the record on which the action is triggered if there is one, otherwise None
#  - pool: ORM model pool (i.e. self.pool)
#  - time: Python time module
#  - cr: database cursor
#  - uid: current user id
#  - context: current context
# If you plan to return an action, assign: action = {...}
""",
    }

    def get_email(self, cr, uid, action, context):
        obj_pool = self.pool.get(action.model_id.model)
        id = context.get('active_id')
        obj = obj_pool.browse(cr, uid, id)

        fields = None

        if '/' in action.email.complete_name:
            fields = action.email.complete_name.split('/')
        elif '.' in action.email.complete_name:
            fields = action.email.complete_name.split('.')

        for field in fields:
            try:
                obj = getattr(obj, field)
            except Exception:
                _logger.exception('Failed to parse: %s', field)

        return obj

    def get_mobile(self, cr, uid, action, context):
        obj_pool = self.pool.get(action.model_id.model)
        id = context.get('active_id')
        obj = obj_pool.browse(cr, uid, id)

        fields = None

        if '/' in action.mobile.complete_name:
            fields = action.mobile.complete_name.split('/')
        elif '.' in action.mobile.complete_name:
            fields = action.mobile.complete_name.split('.')

        for field in fields:
            try:
                obj = getattr(obj, field)
            except Exception:
                _logger.exception('Failed to parse: %s', field)

        return obj

    def merge_message(self, cr, uid, keystr, action, context=None):
        if context is None:
            context = {}

        def merge(match):
            obj_pool = self.pool.get(action.model_id.model)
            id = context.get('active_id')
            obj = obj_pool.browse(cr, uid, id)
            exp = str(match.group()[2:-2]).strip()
            result = eval(exp,
                          {
                            'object': obj,
                            'context': dict(context), # copy context to prevent side-effects of eval
                            'time': time,
                          })
            if result in (None, False):
                return str("--------")
            return tools.ustr(result)

        com = re.compile('(\[\[.+?\]\])')
        message = com.sub(merge, keystr)

        return message

    # Context should contains:
    #   ids : original ids
    #   id  : current id of the object
    # OUT:
    #   False : Finnished correctly
    #   ACTION_ID : Action to launch

    # FIXME: refactor all the eval() calls in run()!
    def run(self, cr, uid, ids, context=None):
        if context is None:
            context = {}
        user = self.pool.get('res.users').browse(cr, uid, uid)
        for action in self.browse(cr, uid, ids, context):
            obj = None
            obj_pool = self.pool.get(action.model_id.model)
            if context.get('active_model') == action.model_id.model and context.get('active_id'):
                obj = obj_pool.browse(cr, uid, context['active_id'], context=context)
            cxt = {
                'self': obj_pool,
                'object': obj,
                'obj': obj,
                'pool': self.pool,
                'time': time,
                'cr': cr,
                'context': dict(context), # copy context to prevent side-effects of eval
                'uid': uid,
                'user': user
            }
            expr = eval(str(action.condition), cxt)
            if not expr:
                continue

            if action.state=='client_action':
                if not action.action_id:
                    raise osv.except_osv(_('Error'), _("Please specify an action to launch !"))
                return self.pool.get(action.action_id.type)\
                    .read(cr, uid, action.action_id.id, context=context)

            if action.state=='code':
                eval(action.code, cxt, mode="exec", nocopy=True) # nocopy allows to return 'action'
                if 'action' in cxt:
                    return cxt['action']

            if action.state == 'email':
                email_from = config['email_from']
                address = str(action.email)
                try:
                    address =  eval(str(action.email), cxt)
                except:
                    pass

                if not address:
                    _logger.info('No partner email address specified, not sending any email.')
                    continue

                if not email_from:
                    _logger.debug('--email-from command line option is not specified, using a fallback value instead.')
                    if user.user_email:
                        email_from = user.user_email
                    else:
                        email_from = "%s@%s" % (user.login, gethostname())

                subject = self.merge_message(cr, uid, action.subject, action, context)
                body = self.merge_message(cr, uid, action.message, action, context)

                ir_mail_server = self.pool.get('ir.mail_server')
                msg = ir_mail_server.build_email(email_from, [address], subject, body)
                res_email = ir_mail_server.send_email(cr, uid, msg)
                if res_email:
                    _logger.info('Email successfully sent to: %s', address)
                else:
                    _logger.warning('Failed to send email to: %s', address)

            if action.state == 'trigger':
                wf_service = netsvc.LocalService("workflow")
                model = action.wkf_model_id.model
                m2o_field_name = action.trigger_obj_id.name
                target_id = obj_pool.read(cr, uid, context.get('active_id'), [m2o_field_name])[m2o_field_name]
                target_id = target_id[0] if isinstance(target_id,tuple) else target_id
                wf_service.trg_validate(uid, model, int(target_id), action.trigger_name, cr)

            if action.state == 'sms':
                #TODO: set the user and password from the system
                # for the sms gateway user / password
                # USE smsclient module from extra-addons
                _logger.warning('SMS Facility has not been implemented yet. Use smsclient module!')

            if action.state == 'other':
                res = []
                for act in action.child_ids:
                    context['active_id'] = context['active_ids'][0]
                    result = self.run(cr, uid, [act.id], context)
                    if result:
                        res.append(result)
                return res

            if action.state == 'loop':
                expr = eval(str(action.expression), cxt)
                context['object'] = obj
                for i in expr:
                    context['active_id'] = i.id
                    result = self.run(cr, uid, [action.loop_action.id], context)

            if action.state == 'object_write':
                res = {}
                for exp in action.fields_lines:
                    euq = exp.value
                    if exp.type == 'equation':
                        expr = eval(euq, cxt)
                    else:
                        expr = exp.value
                    res[exp.col1.name] = expr

                if not action.write_id:
                    if not action.srcmodel_id:
                        obj_pool = self.pool.get(action.model_id.model)
                        obj_pool.write(cr, uid, [context.get('active_id')], res)
                    else:
                        write_id = context.get('active_id')
                        obj_pool = self.pool.get(action.srcmodel_id.model)
                        obj_pool.write(cr, uid, [write_id], res)

                elif action.write_id:
                    obj_pool = self.pool.get(action.srcmodel_id.model)
                    rec = self.pool.get(action.model_id.model).browse(cr, uid, context.get('active_id'))
                    id = eval(action.write_id, {'object': rec})
                    try:
                        id = int(id)
                    except:
                        raise osv.except_osv(_('Error'), _("Problem in configuration `Record Id` in Server Action!"))

                    if type(id) != type(1):
                        raise osv.except_osv(_('Error'), _("Problem in configuration `Record Id` in Server Action!"))
                    write_id = id
                    obj_pool.write(cr, uid, [write_id], res)

            if action.state == 'object_create':
                res = {}
                for exp in action.fields_lines:
                    euq = exp.value
                    if exp.type == 'equation':
                        expr = eval(euq, cxt)
                    else:
                        expr = exp.value
                    res[exp.col1.name] = expr

                obj_pool = None
                res_id = False
                obj_pool = self.pool.get(action.srcmodel_id.model)
                res_id = obj_pool.create(cr, uid, res)
                if action.record_id:
                    self.pool.get(action.model_id.model).write(cr, uid, [context.get('active_id')], {action.record_id.name:res_id})

            if action.state == 'object_copy':
                res = {}
                for exp in action.fields_lines:
                    euq = exp.value
                    if exp.type == 'equation':
                        expr = eval(euq, cxt)
                    else:
                        expr = exp.value
                    res[exp.col1.name] = expr

                model = action.copy_object.split(',')[0]
                cid = action.copy_object.split(',')[1]
                obj_pool = self.pool.get(model)
                res_id = obj_pool.copy(cr, uid, int(cid), res)

        return False
예제 #22
0
class crm_lead(crm_case, osv.osv):
    """ CRM Lead Case """
    _name = "crm.lead"
    _description = "Lead/Opportunity"
    _order = "priority,date_action,id desc"
    _inherit = ['mail.thread', 'res.partner.address']

    def _read_group_stage_ids(self,
                              cr,
                              uid,
                              ids,
                              domain,
                              read_group_order=None,
                              access_rights_uid=None,
                              context=None):
        access_rights_uid = access_rights_uid or uid
        stage_obj = self.pool.get('crm.case.stage')
        order = stage_obj._order
        if read_group_order == 'stage_id desc':
            # lame hack to allow reverting search, should just work in the trivial case
            order = "%s desc" % order
        stage_ids = stage_obj._search(
            cr,
            uid, ['|', ('id', 'in', ids), ('case_default', '=', 1)],
            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])))
        return result

    _group_by_full = {'stage_id': _read_group_stage_ids}

    # overridden because res.partner.address has an inconvenient name_get,
    # especially if base_contact is installed.
    def name_get(self, cr, user, ids, context=None):
        if isinstance(ids, (int, long)):
            ids = [ids]
        return [(r['id'], tools.ustr(r[self._rec_name]))
                for r in self.read(cr, user, ids, [self._rec_name], context)]

    # overridden because if 'base_contact' is installed - their default_get() will remove
    # 'default_type' from context making it impossible to record an 'opportunity'
    def default_get(self, cr, uid, fields_list, context=None):
        return super(osv.osv, self).default_get(cr,
                                                uid,
                                                fields_list,
                                                context=context)

    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
        """
        cal_obj = self.pool.get('resource.calendar')
        res_obj = self.pool.get('resource.resource')

        res = {}
        for lead in self.browse(cr, uid, ids, context=context):
            for field in fields:
                res[lead.id] = {}
                duration = 0
                ans = False
                if field == 'day_open':
                    if lead.date_open:
                        date_create = datetime.strptime(
                            lead.create_date, "%Y-%m-%d %H:%M:%S")
                        date_open = datetime.strptime(lead.date_open,
                                                      "%Y-%m-%d %H:%M:%S")
                        ans = date_open - date_create
                        date_until = lead.date_open
                elif field == 'day_close':
                    if lead.date_closed:
                        date_create = datetime.strptime(
                            lead.create_date, "%Y-%m-%d %H:%M:%S")
                        date_close = datetime.strptime(lead.date_closed,
                                                       "%Y-%m-%d %H:%M:%S")
                        date_until = lead.date_closed
                        ans = date_close - date_create
                if ans:
                    resource_id = False
                    if lead.user_id:
                        resource_ids = res_obj.search(
                            cr, uid, [('user_id', '=', lead.user_id.id)])
                        if len(resource_ids):
                            resource_id = resource_ids[0]

                    duration = float(ans.days)
                    if lead.section_id and lead.section_id.resource_calendar_id:
                        duration = float(ans.days) * 24
                        new_dates = cal_obj.interval_get(
                            cr,
                            uid,
                            lead.section_id.resource_calendar_id
                            and lead.section_id.resource_calendar_id.id
                            or False,
                            datetime.strptime(lead.create_date,
                                              '%Y-%m-%d %H:%M:%S'),
                            duration,
                            resource=resource_id)
                        no_days = []
                        date_until = datetime.strptime(date_until,
                                                       '%Y-%m-%d %H:%M:%S')
                        for in_time, out_time in new_dates:
                            if in_time.date not in no_days:
                                no_days.append(in_time.date)
                            if out_time > date_until:
                                break
                        duration = len(no_days)
                res[lead.id][field] = abs(int(duration))
        return res

    def _history_search(self, cr, uid, obj, name, args, context=None):
        res = []
        msg_obj = self.pool.get('mail.message')
        message_ids = msg_obj.search(cr,
                                     uid,
                                     [('email_from', '!=', False),
                                      ('subject', args[0][1], args[0][2])],
                                     context=context)
        lead_ids = self.search(cr,
                               uid, [('message_ids', 'in', message_ids)],
                               context=context)

        if lead_ids:
            return [('id', 'in', lead_ids)]
        else:
            return [('id', '=', '0')]

    def _get_email_subject(self, cr, uid, ids, fields, args, context=None):
        res = {}
        for obj in self.browse(cr, uid, ids, context=context):
            res[obj.id] = ''
            for msg in obj.message_ids:
                if msg.email_from:
                    res[obj.id] = msg.subject
                    break
        return res

    _columns = {
        # Overridden from res.partner.address:
        'partner_id': fields.many2one('res.partner', 'Partner', ondelete='set null',
            select=True, help="Optional linked partner, usually after conversion of the lead"),

        'id': fields.integer('ID', readonly=True),
        'name': fields.char('Name', size=64, select=1),
        'active': fields.boolean('Active', required=False),
        'date_action_last': fields.datetime('Last Action', readonly=1),
        'date_action_next': fields.datetime('Next Action', readonly=1),
        'email_from': fields.char('Email', size=128, help="E-mail address of the contact", select=1),
        'section_id': fields.many2one('crm.case.section', 'Sales Team', \
                        select=True, help='When sending mails, the default email address is taken from the sales team.'),
        'create_date': fields.datetime('Creation Date' , readonly=True),
        'email_cc': fields.text('Global CC', size=252 , 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"),
        'description': fields.text('Notes'),
        'write_date': fields.datetime('Update Date' , readonly=True),

        'categ_id': fields.many2one('crm.case.categ', 'Category', \
            domain="['|',('section_id','=',section_id),('section_id','=',False), ('object_id.model', '=', 'crm.lead')]"),
        'type_id': fields.many2one('crm.case.resource.type', 'Campaign', \
            domain="['|',('section_id','=',section_id),('section_id','=',False)]", help="From which campaign (seminar, marketing campaign, mass mailing, ...) did this contact come from?"),
        'channel_id': fields.many2one('crm.case.channel', 'Channel', help="Communication channel (mail, direct, phone, ...)"),
        'contact_name': fields.char('Contact Name', size=64),
        'partner_name': fields.char("Customer Name", size=64,help='The name of the future partner that will be created while converting the lead into opportunity', select=1),
        'optin': fields.boolean('Opt-In', help="If opt-in is checked, this contact has accepted to receive emails."),
        'optout': fields.boolean('Opt-Out', help="If opt-out is checked, this contact has refused to receive emails or unsubscribed to a campaign."),
        'type':fields.selection([ ('lead','Lead'), ('opportunity','Opportunity'), ],'Type', help="Type is used to separate Leads and Opportunities"),
        'priority': fields.selection(crm.AVAILABLE_PRIORITIES, 'Priority', select=True),
        'date_closed': fields.datetime('Closed', readonly=True),
        'stage_id': fields.many2one('crm.case.stage', 'Stage', domain="[('section_ids', '=', section_id)]"),
        'user_id': fields.many2one('res.users', 'Salesman', select=1),
        'referred': fields.char('Referred By', size=64),
        'date_open': fields.datetime('Opened', readonly=True),
        'day_open': fields.function(_compute_day, string='Days to Open', \
                                multi='day_open', type="float", store=True),
        'day_close': fields.function(_compute_day, string='Days to Close', \
                                multi='day_close', type="float", store=True),
        'state': fields.selection(crm.AVAILABLE_STATES, 'State', size=16, readonly=True,
                                  help='The state is set to \'Draft\', when a case is created.\
                                  \nIf the case is in progress the state is set to \'Open\'.\
                                  \nWhen the case is over, the state is set to \'Done\'.\
                                  \nIf the case needs to be reviewed then the state is set to \'Pending\'.'                                                                                                           ),
        'message_ids': fields.one2many('mail.message', 'res_id', 'Messages', domain=[('model','=',_name)]),
        'subjects': fields.function(_get_email_subject, fnct_search=_history_search, string='Subject of Email', type='char', size=64),


        # Only used for type opportunity
        'partner_address_id': fields.many2one('res.partner.address', 'Partner Contact', domain="[('partner_id','=',partner_id)]"),
        'probability': fields.float('Probability (%)',group_operator="avg"),
        'planned_revenue': fields.float('Expected Revenue'),
        'ref': fields.reference('Reference', selection=crm._links_get, size=128),
        'ref2': fields.reference('Reference 2', selection=crm._links_get, size=128),
        'phone': fields.char("Phone", size=64),
        'date_deadline': fields.date('Expected Closing'),
        'date_action': fields.date('Next Action Date', select=True),
        'title_action': fields.char('Next Action', size=64),
        'stage_id': fields.many2one('crm.case.stage', 'Stage', domain="[('section_ids', '=', section_id)]"),
        'color': fields.integer('Color Index'),
        'partner_address_name': fields.related('partner_address_id', 'name', type='char', string='Partner Contact Name', readonly=True),
        'partner_address_email': fields.related('partner_address_id', 'email', type='char', string='Partner Contact Email', readonly=True),
        'company_currency': fields.related('company_id', 'currency_id', 'symbol', type='char', string='Company Currency', readonly=True),
        'user_email': fields.related('user_id', 'user_email', type='char', string='User Email', readonly=True),
        'user_login': fields.related('user_id', 'login', type='char', string='User Login', readonly=True),

    }

    _defaults = {
        'active':
        lambda *a: 1,
        'user_id':
        crm_case._get_default_user,
        'email_from':
        crm_case._get_default_email,
        'state':
        lambda *a: 'draft',
        'type':
        lambda *a: 'lead',
        'section_id':
        crm_case._get_section,
        'company_id':
        lambda s, cr, uid, c: s.pool.get('res.company')._company_default_get(
            cr, uid, 'crm.lead', context=c),
        'priority':
        lambda *a: crm.AVAILABLE_PRIORITIES[2][0],
        'color':
        0,
    }

    def onchange_partner_address_id(self, cr, uid, ids, add, email=False):
        """This function returns value of partner email based on Partner Address
        """
        if not add:
            return {'value': {'email_from': False, 'country_id': False}}
        address = self.pool.get('res.partner.address').browse(cr, uid, add)
        return {
            'value': {
                'email_from': address.email,
                'phone': address.phone,
                'country_id': address.country_id.id
            }
        }

    def on_change_optin(self, cr, uid, ids, optin):
        return {'value': {'optin': optin, 'optout': False}}

    def on_change_optout(self, cr, uid, ids, optout):
        return {'value': {'optout': optout, 'optin': False}}

    def onchange_stage_id(self, cr, uid, ids, stage_id, context={}):
        if not stage_id:
            return {'value': {}}
        stage = self.pool.get('crm.case.stage').browse(cr, uid, stage_id,
                                                       context)
        if not stage.on_change:
            return {'value': {}}
        return {'value': {'probability': stage.probability}}

    def stage_find_percent(self, cr, uid, percent, section_id):
        """ Return the first stage with a probability == percent
        """
        stage_pool = self.pool.get('crm.case.stage')
        if section_id:
            ids = stage_pool.search(cr, uid,
                                    [("probability", '=', percent),
                                     ("section_ids", 'in', [section_id])])
        else:
            ids = stage_pool.search(cr, uid, [("probability", '=', percent)])

        if ids:
            return ids[0]
        return False

    def stage_find_lost(self, cr, uid, section_id):
        return self.stage_find_percent(cr, uid, 0.0, section_id)

    def stage_find_won(self, cr, uid, section_id):
        return self.stage_find_percent(cr, uid, 100.0, section_id)

    def case_open(self, cr, uid, ids, *args):
        for l in self.browse(cr, uid, ids):
            # When coming from draft override date and stage otherwise just set state
            if l.state == 'draft':
                if l.type == 'lead':
                    message = _("The lead '%s' has been opened.") % l.name
                elif l.type == 'opportunity':
                    message = _(
                        "The opportunity '%s' has been opened.") % l.name
                else:
                    message = _("The case '%s' has been opened.") % l.name
                self.log(cr, uid, l.id, message)
                value = {'date_open': time.strftime('%Y-%m-%d %H:%M:%S')}
                self.write(cr, uid, [l.id], value)
                if l.type == 'opportunity' and not l.stage_id:
                    stage_id = self.stage_find(cr, uid, l.section_id.id
                                               or False,
                                               [('sequence', '>', 0)])
                    if stage_id:
                        self.stage_set(cr, uid, [l.id], stage_id)
        res = super(crm_lead, self).case_open(cr, uid, ids, *args)
        return res

    def case_close(self, cr, uid, ids, *args):
        res = super(crm_lead, self).case_close(cr, uid, ids, *args)
        self.write(cr, uid, ids,
                   {'date_closed': time.strftime('%Y-%m-%d %H:%M:%S')})
        for case in self.browse(cr, uid, ids):
            if case.type == 'lead':
                message = _("The lead '%s' has been closed.") % case.name
            else:
                message = _("The case '%s' has been closed.") % case.name
            self.log(cr, uid, case.id, message)
        return res
예제 #23
0
class subscription_subscription(osv.osv):
    _name = "subscription.subscription"
    _description = "Subscription"
    _columns = {
        'name':
        fields.char('Name', size=60, required=True),
        'active':
        fields.boolean(
            'Active',
            help=
            "If the active field is set to False, it will allow you to hide the subscription without removing it."
        ),
        'partner_id':
        fields.many2one('res.partner', 'Partner'),
        'notes':
        fields.text('Notes'),
        'user_id':
        fields.many2one('res.users', 'User', required=True),
        'interval_number':
        fields.integer('Interval Qty'),
        'interval_type':
        fields.selection([('days', 'Days'), ('weeks', 'Weeks'),
                          ('months', 'Months')], 'Interval Unit'),
        'exec_init':
        fields.integer('Number of documents'),
        'date_init':
        fields.datetime('First Date'),
        'state':
        fields.selection([('draft', 'Draft'), ('running', 'Running'),
                          ('done', 'Done')], 'State'),
        'doc_source':
        fields.reference(
            'Source Document',
            required=True,
            selection=_get_document_types,
            size=128,
            help=
            "User can choose the source document on which he wants to create documents"
        ),
        'doc_lines':
        fields.one2many('subscription.subscription.history',
                        'subscription_id',
                        'Documents created',
                        readonly=True),
        'cron_id':
        fields.many2one('ir.cron',
                        'Cron Job',
                        help="Scheduler which runs on subscription"),
        'note':
        fields.text('Notes', help="Description or Summary of Subscription"),
    }
    _defaults = {
        'date_init': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'),
        'user_id': lambda obj, cr, uid, context: uid,
        'active': lambda *a: True,
        'interval_number': lambda *a: 1,
        'interval_type': lambda *a: 'months',
        'doc_source': lambda *a: False,
        'state': lambda *a: 'draft'
    }

    def set_process(self, cr, uid, ids, context=None):
        for row in self.read(cr, uid, ids, context=context):
            mapping = {
                'name': 'name',
                'interval_number': 'interval_number',
                'interval_type': 'interval_type',
                'exec_init': 'numbercall',
                'date_init': 'nextcall'
            }
            res = {
                'model': 'subscription.subscription',
                'args': repr([[row['id']]]),
                'function': 'model_copy',
                'priority': 6,
                'user_id': row['user_id'] and row['user_id'][0]
            }
            for key, value in mapping.items():
                res[value] = row[key]
            id = self.pool.get('ir.cron').create(cr, uid, res)
            self.write(cr, uid, [row['id']], {
                'cron_id': id,
                'state': 'running'
            })
        return True

    def model_copy(self, cr, uid, ids, context=None):
        for row in self.read(cr, uid, ids, context=context):
            if not row.get('cron_id', False):
                continue
            cron_ids = [row['cron_id'][0]]
            remaining = self.pool.get('ir.cron').read(
                cr, uid, cron_ids, ['numbercall'])[0]['numbercall']
            try:
                (model_name, id) = row['doc_source'].split(',')
                id = int(id)
                model = self.pool.get(model_name)
            except:
                raise osv.except_osv(
                    _('Wrong Source Document !'),
                    _('Please provide another source document.\nThis one does not exist !'
                      ))

            default = {'state': 'draft'}
            doc_obj = self.pool.get('subscription.document')
            document_ids = doc_obj.search(cr, uid,
                                          [('model.model', '=', model_name)])
            doc = doc_obj.browse(cr, uid, document_ids)[0]
            for f in doc.field_ids:
                if f.value == 'date':
                    value = time.strftime('%Y-%m-%d')
                else:
                    value = False
                default[f.field.name] = value

            state = 'running'

            # if there was only one remaining document to generate
            # the subscription is over and we mark it as being done
            if remaining == 1:
                state = 'done'
            id = self.pool.get(model_name).copy(cr, uid, id, default, context)
            self.pool.get('subscription.subscription.history').create(
                cr, uid, {
                    'subscription_id': row['id'],
                    'date': time.strftime('%Y-%m-%d %H:%M:%S'),
                    'document_id': model_name + ',' + str(id)
                })
            self.write(cr, uid, [row['id']], {'state': state})
        return True

    def set_done(self, cr, uid, ids, context=None):
        res = self.read(cr, uid, ids, ['cron_id'])
        ids2 = [x['cron_id'][0] for x in res if x['id']]
        self.pool.get('ir.cron').write(cr, uid, ids2, {'active': False})
        self.write(cr, uid, ids, {'state': 'done'})
        return True

    def set_draft(self, cr, uid, ids, context=None):
        self.write(cr, uid, ids, {'state': 'draft'})
        return True
예제 #24
0
class crm_helpdesk(crm.crm_case, osv.osv):
    """ Helpdesk Cases """

    _name = "crm.helpdesk"
    _description = "Helpdesk"
    _order = "id desc"
    _inherit = ['mailgate.thread']
    _columns = {
            'id': fields.integer('ID', readonly=True),
            'name': fields.char('Name', size=128, required=True),
            'active': fields.boolean('Active', required=False),
            'date_action_last': fields.datetime('Last Action', readonly=1),
            'date_action_next': fields.datetime('Next Action', readonly=1),
            'description': fields.text('Description'),
            'create_date': fields.datetime('Creation Date' , readonly=True),
            'write_date': fields.datetime('Update Date' , readonly=True),
            'date_deadline': fields.date('Deadline'),
            'user_id': fields.many2one('res.users', 'Responsible'),
            'section_id': fields.many2one('crm.case.section', 'Sales Team', \
                            select=True, help='Sales team to which Case belongs to.\
                                 Define Responsible user and Email account for mail gateway.'                                                                                             ),
            'company_id': fields.many2one('res.company', 'Company'),
            'date_closed': fields.datetime('Closed', readonly=True),
            'partner_id': fields.many2one('res.partner', 'Partner'),
            'partner_address_id': fields.many2one('res.partner.address', 'Partner Contact', \
                                 domain="[('partner_id','=',partner_id)]"),
            'email_cc': fields.text('Watchers Emails', size=252 , 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"),
            'email_from': fields.char('Email', size=128, help="These people will receive email."),
            'date': fields.datetime('Date'),
            'ref' : fields.reference('Reference', selection=crm._links_get, size=128),
            'ref2' : fields.reference('Reference 2', selection=crm._links_get, size=128),
            'canal_id': fields.many2one('res.partner.canal', 'Channel', \
                            help="The channels represent the different communication \
 modes available with the customer."                                    ),
            'planned_revenue': fields.float('Planned Revenue'),
            'planned_cost': fields.float('Planned Costs'),
            'priority': fields.selection(crm.AVAILABLE_PRIORITIES, 'Priority'),
            'probability': fields.float('Probability (%)'),
            'categ_id': fields.many2one('crm.case.categ', 'Category', \
                            domain="[('section_id','=',section_id),\
                            ('object_id.model', '=', 'crm.helpdesk')]"                                                                      ),
            'duration': fields.float('Duration', states={'done': [('readonly', True)]}),
            'state': fields.selection(crm.AVAILABLE_STATES, 'State', size=16, readonly=True,
                                  help='The state is set to \'Draft\', when a case is created.\
                                  \nIf the case is in progress the state is set to \'Open\'.\
                                  \nWhen the case is over, the state is set to \'Done\'.\
                                  \nIf the case needs to be reviewed then the state is set to \'Pending\'.'                                                                                                           ),
            'message_ids': fields.one2many('mailgate.message', 'res_id', 'Messages', domain=[('model','=',_name)]),
    }

    _defaults = {
        'active':
        lambda *a: 1,
        'user_id':
        crm.crm_case._get_default_user,
        'partner_id':
        crm.crm_case._get_default_partner,
        'partner_address_id':
        crm.crm_case._get_default_partner_address,
        'email_from':
        crm.crm_case._get_default_email,
        'state':
        lambda *a: 'draft',
        'date':
        lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'),
        'section_id':
        crm.crm_case._get_section,
        'company_id':
        lambda s, cr, uid, c: s.pool.get('res.company')._company_default_get(
            cr, uid, 'crm.helpdesk', context=c),
        'priority':
        lambda *a: crm.AVAILABLE_PRIORITIES[2][0],
    }

    def message_new(self, cr, uid, msg, context=None):
        """
        Automatically calls when new email message arrives

        @param self: The object pointer
        @param cr: the current row, from the database cursor,
        @param uid: the current user’s ID for security checks
        """
        mailgate_pool = self.pool.get('email.server.tools')

        subject = msg.get('subject') or _("No Subject")
        body = msg.get('body')
        msg_from = msg.get('from')
        priority = msg.get('priority')

        vals = {
            'name': subject,
            'email_from': msg_from,
            'email_cc': msg.get('cc'),
            'description': body,
            'user_id': False,
        }
        if msg.get('priority', False):
            vals['priority'] = priority

        res = mailgate_pool.get_partner(cr, uid,
                                        msg.get('from') or msg.get_unixfrom())
        if res:
            vals.update(res)

        res = self.create(cr, uid, vals, context)
        attachents = msg.get('attachments', [])
        att_ids = []
        for attactment in attachents or []:
            data_attach = {
                'name': attactment,
                'datas': binascii.b2a_base64(str(attachents.get(attactment))),
                'datas_fname': attactment,
                'description': 'Mail attachment',
                'res_model': self._name,
                'res_id': res,
            }
            att_ids.append(
                self.pool.get('ir.attachment').create(cr, uid, data_attach))

        return res, att_ids

    def message_update(self,
                       cr,
                       uid,
                       ids,
                       vals={},
                       msg="",
                       default_act='pending',
                       context=None):
        """
        @param self: The object pointer
        @param cr: the current row, from the database cursor,
        @param uid: the current user’s ID for security checks,
        @param ids: List of update mail’s IDs 
        """
        if isinstance(ids, (str, int, long)):
            ids = [ids]

        if msg.get('priority') in dict(crm.AVAILABLE_PRIORITIES):
            vals['priority'] = msg.get('priority')

        maps = {
            'cost': 'planned_cost',
            'revenue': 'planned_revenue',
            'probability': 'probability'
        }
        vls = {}
        for line in msg['body'].split('\n'):
            line = line.strip()
            res = tools.misc.command_re.match(line)
            if res and maps.get(res.group(1).lower()):
                key = maps.get(res.group(1).lower())
                vls[key] = res.group(2).lower()
        vals.update(vls)

        # Unfortunately the API is based on lists
        # but we want to update the state based on the
        # previous state, so we have to loop:
        for case in self.browse(cr, uid, ids, context=context):
            values = dict(vals)
            if case.state in CRM_HELPDESK_STATES:
                values.update(state=crm.AVAILABLE_STATES[1][0])  #re-open
            res = self.write(cr, uid, [case.id], values, context=context)
        return res
예제 #25
0
class ir_property(osv.osv):
    _name = 'ir.property'

    def _models_field_get(self, cr, uid, field_key, field_value, context=None):
        get = attrgetter(field_key, field_value)
        obj = self.pool.get('ir.model.fields')
        ids = obj.search(cr, uid, [('view_load', '=', 1)], context=context)
        res = set()
        for o in obj.browse(cr, uid, ids, context=context):
            res.add(get(o))
        return list(res)

    def _models_get(self, cr, uid, context=None):
        return self._models_field_get(cr, uid, 'model', 'model_id.name',
                                      context)

    def _models_get2(self, cr, uid, context=None):
        return self._models_field_get(cr, uid, 'relation', 'relation', context)

    _columns = {
        'name':
        fields.char('Name', size=128, select=1),
        'res_id':
        fields.reference(
            'Resource',
            selection=_models_get,
            size=128,
            help="If not set, acts as a default value for new resources",
            select=1),
        'company_id':
        fields.many2one('res.company', 'Company', select=1),
        'fields_id':
        fields.many2one('ir.model.fields',
                        'Field',
                        ondelete='cascade',
                        required=True,
                        select=1),
        'value_float':
        fields.float('Value'),
        'value_integer':
        fields.integer('Value'),
        'value_text':
        fields.text('Value'),  # will contain (char, text)
        'value_binary':
        fields.binary('Value'),
        'value_reference':
        fields.reference('Value', selection=_models_get2, size=128),
        'value_datetime':
        fields.datetime('Value'),
        'type':
        fields.selection([
            ('char', 'Char'),
            ('float', 'Float'),
            ('boolean', 'Boolean'),
            ('integer', 'Integer'),
            ('text', 'Text'),
            ('binary', 'Binary'),
            ('many2one', 'Many2One'),
            ('date', 'Date'),
            ('datetime', 'DateTime'),
        ],
                         'Type',
                         required=True,
                         select=1),
    }

    _defaults = {
        'type': 'many2one',
    }

    def _update_values(self, cr, uid, ids, values):
        value = values.pop('value', None)
        if not value:
            return values

        prop = None
        type_ = values.get('type')
        if not type_:
            if ids:
                prop = self.browse(cr, uid, ids[0])
                type_ = prop.type
            else:
                type_ = self._defaults['type']

        type2field = {
            'char': 'value_text',
            'float': 'value_float',
            'boolean': 'value_integer',
            'integer': 'value_integer',
            'text': 'value_text',
            'binary': 'value_binary',
            'many2one': 'value_reference',
            'date': 'value_datetime',
            'datetime': 'value_datetime',
        }
        field = type2field.get(type_)
        if not field:
            raise osv.except_osv('Error', 'Invalid type')

        if field == 'value_reference':
            if isinstance(value, osv.orm.browse_record):
                value = '%s,%d' % (value._name, value.id)
            elif isinstance(value, (int, long)):
                field_id = values.get('fields_id')
                if not field_id:
                    if not prop:
                        raise ValueError()
                    field_id = prop.fields_id
                else:
                    field_id = self.pool.get('ir.model.fields').browse(
                        cr, uid, field_id)

                value = '%s,%d' % (field_id.relation, value)

        values[field] = value
        return values

    def write(self, cr, uid, ids, values, context=None):
        return super(ir_property,
                     self).write(cr,
                                 uid,
                                 ids,
                                 self._update_values(cr, uid, ids, values),
                                 context=context)

    def create(self, cr, uid, values, context=None):
        return super(ir_property,
                     self).create(cr,
                                  uid,
                                  self._update_values(cr, uid, None, values),
                                  context=context)

    def get_by_record(self, cr, uid, record, context=None):
        if record.type in ('char', 'text'):
            return record.value_text
        elif record.type == 'float':
            return record.value_float
        elif record.type == 'boolean':
            return bool(record.value_integer)
        elif record.type == 'integer':
            return record.value_integer
        elif record.type == 'binary':
            return record.value_binary
        elif record.type == 'many2one':
            return record.value_reference
        elif record.type == 'datetime':
            return record.value_datetime
        elif record.type == 'date':
            if not record.value_datetime:
                return False
            return time.strftime(
                '%Y-%m-%d',
                time.strptime(record.value_datetime, '%Y-%m-%d %H:%M:%S'))
        return False

    def get(self, cr, uid, name, model, res_id=False, context=None):
        domain = self._get_domain(cr, uid, name, model, context=context)
        if domain is not None:
            domain = [('res_id', '=', res_id)] + domain
            nid = self.search(cr, uid, domain, context=context)
            if not nid: return False
            record = self.browse(cr, uid, nid[0], context=context)
            return self.get_by_record(cr, uid, record, context=context)
        return False

    def _get_domain_default(self, cr, uid, prop_name, model, context=None):
        domain = self._get_domain(cr, uid, prop_name, model, context=context)
        if domain is None:
            return None
        return ['&', ('res_id', '=', False)] + domain

    def _get_domain(self, cr, uid, prop_name, model, context=None):
        context = context or {}
        cr.execute('select id from ir_model_fields where name=%s and model=%s',
                   (prop_name, model))
        res = cr.fetchone()
        if not res:
            return None

        if 'force_company' in context and context['force_company']:
            cid = context['force_company']
        else:
            company = self.pool.get('res.company')
            cid = company._company_default_get(cr,
                                               uid,
                                               model,
                                               res[0],
                                               context=context)

        domain = [
            '&', ('fields_id', '=', res[0]), '|', ('company_id', '=', cid),
            ('company_id', '=', False)
        ]
        return domain
예제 #26
0
class qc_test_template(osv.osv):
    """
    A template is a group of proofs to with the values that make them valid.
    """
    _name = 'qc.test.template'
    _description = 'Test Template'

    # qc.test.template
    def _default_name(self, cr, uid, context=None):
        if context and context.get('reference_model', False):
            ref_id = context.get('reference_id')
            if not ref_id:
                ref_id = context.get('active_id')
            if ref_id:
                source = self.pool.get(context['reference_model']).browse(cr,
                                                                          uid,
                                                                          ref_id,
                                                                          context)
                if hasattr(source, 'name'):
                    return source.name

    # qc.test.template
    def _default_object_id(self, cr, uid, context=None):
        if context and context.get('reference_model', False):
            return '%s,%d' % (context['reference_model'],
                              context['reference_id'])
        else:
            return False

    # qc.test.template
    def _default_type(self, cr, uid, context=None):
        if context and context.get('reference_model'):
            return 'related'
        else:
            return False

    _columns = {
        'active': fields.boolean('Active', select=True),
        'name': fields.char('Name', size=200, required=True, translate=True,
                            select=True),
        'test_template_line_ids': fields.one2many('qc.test.template.line',
                                                  'test_template_id', 'Lines'),
        'object_id': fields.reference('Reference Object', selection=_links_get,
                                      size=128),
        'fill_correct_values': fields.boolean('Fill With Correct Values'),
        'type': fields.selection([
                                     ('generic', 'Generic'),
                                     ('related', 'Related'),
                                 ], 'Type', select=True),
        'category_id': fields.many2one('qc.test.template.category',
                                       'Category'),
        'formula': fields.text('Formula'),
        'company_id': fields.many2one('res.company', 'Company'),
        'uom_id': fields.many2one('product.uom', 'UoM'),
    }

    _defaults = {
        'name': _default_name,
        'active': lambda *a: True,
        'object_id': _default_object_id,
        'type': _default_type,
        'company_id': lambda self, cr, uid, c:
        self.pool.get('res.company')._company_default_get(cr, uid,
                                                          'qc.test.template',
                                                          context=c),
    }
예제 #27
0
class actions_server(osv.osv):
    def _select_signals(self, cr, uid, context={}):
        cr.execute(
            "SELECT distinct w.osv, t.signal FROM wkf w, wkf_activity a, wkf_transition t \
        WHERE w.id = a.wkf_id  AND t.act_from = a.id OR t.act_to = a.id AND t.signal!='' \
        AND t.signal NOT IN (null, NULL)")
        result = cr.fetchall() or []
        res = []
        for rs in result:
            if rs[0] is not None and rs[1] is not None:
                line = rs[0], "%s - (%s)" % (rs[1], rs[0])
                res.append(line)
        return res

    def _select_objects(self, cr, uid, context={}):
        model_pool = self.pool.get('ir.model')
        ids = model_pool.search(cr, uid, [('name', 'not ilike', '.')])
        res = model_pool.read(cr, uid, ids, ['model', 'name'])
        return [(r['model'], r['name']) for r in res] + [('', '')]

    def change_object(self, cr, uid, ids, copy_object, state, context={}):
        if state == 'object_copy':
            model_pool = self.pool.get('ir.model')
            model = copy_object.split(',')[0]
            mid = model_pool.search(cr, uid, [('model', '=', model)])
            return {'value': {'srcmodel_id': mid[0]}, 'context': context}
        else:
            return {}

    _name = 'ir.actions.server'
    _table = 'ir_act_server'
    _sequence = 'ir_actions_id_seq'
    _order = 'sequence'
    _columns = {
        'name':
        fields.char(
            'Action Name',
            required=True,
            size=64,
            help=
            "Easy to Refer action by name e.g. One Sales Order -> Many Invoices",
            translate=True),
        'condition':
        fields.char(
            'Condition',
            size=256,
            required=True,
            help=
            "Condition that is to be tested before action is executed, e.g. object.list_price > object.cost_price"
        ),
        'state':
        fields.selection([
            ('client_action', 'Client Action'),
            ('dummy', 'Dummy'),
            ('loop', 'Iteration'),
            ('code', 'Python Code'),
            ('trigger', 'Trigger'),
            ('email', 'Email'),
            ('sms', 'SMS'),
            ('object_create', 'Create Object'),
            ('object_copy', 'Copy Object'),
            ('object_write', 'Write Object'),
            ('other', 'Multi Actions'),
        ],
                         'Action Type',
                         required=True,
                         size=32,
                         help="Type of the Action that is to be executed"),
        'code':
        fields.text('Python Code', help="Python code to be executed"),
        'sequence':
        fields.integer(
            'Sequence',
            help=
            "Important when you deal with multiple actions, the execution order will be decided based on this, low number is higher priority."
        ),
        'model_id':
        fields.many2one(
            'ir.model',
            'Object',
            required=True,
            help=
            "Select the object on which the action will work (read, write, create)."
        ),
        'action_id':
        fields.many2one(
            'ir.actions.actions',
            'Client Action',
            help="Select the Action Window, Report, Wizard to be executed."),
        'trigger_name':
        fields.selection(
            _select_signals,
            string='Trigger Name',
            size=128,
            help="Select the Signal name that is to be used as the trigger."),
        'wkf_model_id':
        fields.many2one('ir.model',
                        'Workflow On',
                        help="Workflow to be executed on this model."),
        'trigger_obj_id':
        fields.many2one(
            'ir.model.fields',
            'Trigger On',
            help=
            "Select the object from the model on which the workflow will executed."
        ),
        'email':
        fields.char(
            'Email Address',
            size=512,
            help=
            "Provides the fields that will be used to fetch the email address, e.g. when you select the invoice, then `object.invoice_address_id.email` is the field which gives the correct address"
        ),
        'subject':
        fields.char(
            'Subject',
            size=1024,
            translate=True,
            help=
            "Specify the subject. You can use fields from the object, e.g. `Hello [[ object.partner_id.name ]]`"
        ),
        'message':
        fields.text(
            'Message',
            translate=True,
            help=
            "Specify the message. You can use the fields from the object. e.g. `Dear [[ object.partner_id.name ]]`"
        ),
        'mobile':
        fields.char(
            'Mobile No',
            size=512,
            help=
            "Provides fields that be used to fetch the mobile number, e.g. you select the invoice, then `object.invoice_address_id.mobile` is the field which gives the correct mobile number"
        ),
        'sms':
        fields.char('SMS', size=160, translate=True),
        'child_ids':
        fields.many2many('ir.actions.server', 'rel_server_actions',
                         'server_id', 'action_id', 'Other Actions'),
        'usage':
        fields.char('Action Usage', size=32),
        'type':
        fields.char('Action Type', size=32, required=True),
        'srcmodel_id':
        fields.many2one(
            'ir.model',
            'Model',
            help=
            "Object in which you want to create / write the object. If it is empty then refer to the Object field."
        ),
        'fields_lines':
        fields.one2many('ir.server.object.lines', 'server_id',
                        'Field Mappings.'),
        'record_id':
        fields.many2one(
            'ir.model.fields',
            'Create Id',
            help=
            "Provide the field name where the record id is stored after the create operations. If it is empty, you can not track the new record."
        ),
        'write_id':
        fields.char(
            'Write Id',
            size=256,
            help=
            "Provide the field name that the record id refers to for the write operation. If it is empty it will refer to the active id of the object."
        ),
        'loop_action':
        fields.many2one(
            'ir.actions.server',
            'Loop Action',
            help=
            "Select the action that will be executed. Loop action will not be avaliable inside loop."
        ),
        'expression':
        fields.char(
            'Loop Expression',
            size=512,
            help=
            "Enter the field/expression that will return the list. E.g. select the sale order in Object, and you can have loop on the sales order line. Expression = `object.order_line`."
        ),
        'copy_object':
        fields.reference('Copy Of', selection=_select_objects, size=256),
    }
    _defaults = {
        'state':
        lambda *a: 'dummy',
        'condition':
        lambda *a: 'True',
        'type':
        lambda *a: 'ir.actions.server',
        'sequence':
        lambda *a: 5,
        'code':
        lambda *a: """# You can use the following variables
#    - object or obj
#    - time
#    - cr
#    - uid
#    - ids
# If you plan to return an action, assign: action = {...}
""",
    }

    def get_email(self, cr, uid, action, context):
        logger = netsvc.Logger()
        obj_pool = self.pool.get(action.model_id.model)
        id = context.get('active_id')
        obj = obj_pool.browse(cr, uid, id)

        fields = None

        if '/' in action.email.complete_name:
            fields = action.email.complete_name.split('/')
        elif '.' in action.email.complete_name:
            fields = action.email.complete_name.split('.')

        for field in fields:
            try:
                obj = getattr(obj, field)
            except Exception, e:
                logger.notifyChannel('Workflow', netsvc.LOG_ERROR,
                                     'Failed to parse : %s' % (field))

        return obj
예제 #28
0
class qc_test(osv.osv):
    """
    This model contains an instance of a test template.
    """
    _name = 'qc.test'

    # qc.test
    def _success(self, cr, uid, ids, field_name, arg, context=None):
        result = {}
        for test in self.browse(cr, uid, ids, context):
            success = True
            proof = {}
            for line in test.test_line_ids:
                # Check the partner (test method). Check that at least the test
                #     is a test method with some success.
                proof[line.proof_id.id] = (proof.get(line.proof_id.id, False)
                                           or line.success)

            for p in proof:
                if not proof[p]:
                    success = False
                    break

            result[test.id] = success
        return result

    # qc.test
    def _default_object_id(self, cr, uid, context=None):
        if context and context.get('reference_model', False):
            return '%s,%d' % (
                context['reference_model'],
                context['reference_id'])
        else:
            return False

    # qc.test
    def _action_calc_formula(self, cr, uid, ids, field_names, args, context):
        result = {}.fromkeys(ids, 0)
        for test in self.browse(cr, uid, ids, context):
            vals = {}
            for line in test.test_line_ids:
                if line.name and line.proof_type == 'quantitative':
                    vals[line.name] = line.actual_value_qt

            if not test.formula:
                result[test.id] = 0
                continue

            try:
                value = safe_eval(test.formula, vals)
                result[test.id] = value
            except NameError:
                pass
                #raise osv.except_osv( _('Error:'), msg )
        return result

    _columns = {
        'name': fields.char('Number', size=64, required=True, select=True),
        'date': fields.datetime('Date', required=True, readonly=True,
                                select=True, states={
                'draft': [('readonly', False)],
            }),
        'object_id': fields.reference('Reference', selection=_links_get,
                                      size=128, readonly=True, select=True,
                                      states={
                                          'draft': [('readonly', False)],
                                      }),
        'test_template_id': fields.many2one('qc.test.template', 'Test template',
                                            select=True, states={
                'success': [('readonly', True)],
                'failed': [('readonly', True)],
            }),
        'test_line_ids': fields.one2many('qc.test.line', 'test_id',
                                         'Test Lines', states={
                'success': [('readonly', True)],
                'failed': [('readonly', True)],
            }),
        'test_internal_note': fields.text('Internal Note', states={
            'success': [('readonly', True)],
            'failed': [('readonly', True)],
        }),
        'test_external_note': fields.text('External Note', states={
            'success': [('readonly', True)],
            'failed': [('readonly', True)],
        }),
        'state': fields.selection(
            [('draft', 'Draft'), ('waiting', 'Waiting Approval'),
             ('success', 'Quality Success'), ('failed', 'Quality Failed'), ],
            'Status', readonly=True, select=True),
        'success': fields.function(_success, method=True, type='boolean',
                                   string='Success', select=True, store=True,
                                   help='This field will be active if all tests have succeeded.'),
        'formula': fields.text('Formula', readonly=1),
        'formula_result': fields.function(_action_calc_formula, method=True,
                                          string='Formula Value', type='float',
                                          digits_compute=dp.get_precision(
                                              'Quality Control')),
        'uom_id': fields.many2one('product.uom', 'UoM'),
        'company_id': fields.many2one('res.company', 'Company'),
    }

    _defaults = {
        'name': lambda obj, cr, uid, context: \
            obj.pool.get('ir.sequence').get(cr, uid, 'qc.test'),
        'date': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'),
        'state': 'draft',
        'success': False,
        'object_id': _default_object_id,
        'company_id': lambda s, cr, uid, c: s.pool.get('res.company') \
            ._company_default_get(cr, uid, 'qc.test', context=c),
    }

    # qc.test
    def _calc_line_vals_from_template(self, cr, uid, test_id, template_line,
                                      fill_correct_values, context):
        data = {
            'name': template_line.name,
            'test_id': test_id,
            'method_id': template_line.method_id.id,
            'proof_id': template_line.proof_id.id,
            'test_template_line_id': template_line.id,
            'notes': template_line.notes,
            'min_value': template_line.min_value,
            'max_value': template_line.max_value,
            'uom_id': template_line.uom_id.id,
            'test_uom_id': template_line.uom_id.id,
            'proof_type': template_line.proof_id.type,
        }
        if fill_correct_values:
            if template_line.type == 'qualitative':
                # Fill with the first correct value found.
                data['actual_value_ql'] = (len(template_line.valid_value_ids)
                                           and template_line.valid_value_ids[0]
                                           and template_line.valid_value_ids[
                                               0].id
                                           or False)
            else:
                # Fill with value in the range.
                data['actual_value_qt'] = template_line.min_value
                data['test_uom_id'] = template_line.uom_id.id
        return data

    # qc.test
    def set_test_template(self, cr, uid, ids, template_id, force_fill=False,
                          context=None):
        test_line_proxy = self.pool.get('qc.test.line')

        if context is None:
            context = {}
        template = self.pool.get('qc.test.template').browse(cr, uid,
                                                            template_id,
                                                            context=context)
        for test_id in ids:
            self.write(cr, uid, test_id, {
                'test_template_id': template_id,
                'formula': template.formula,
                'uom_id': template.uom_id and template.uom_id.id
            }, context)

            test = self.browse(cr, uid, test_id, context)

            if len(test.test_line_ids) > 0:
                test_line_proxy.unlink(cr, uid,
                                       [x.id for x in test.test_line_ids],
                                       context)

            fill = test.test_template_id.fill_correct_values or False
            for line in test.test_template_id.test_template_line_ids:
                data = self._calc_line_vals_from_template(cr, uid, test_id,
                                                          line,
                                                          fill or force_fill,
                                                          context)

                test_line_id = test_line_proxy.create(cr, uid,
                                                      data, context)
                test_line_proxy.write(cr, uid, [test_line_id], {
                    'valid_value_ids': [
                        (6, 0, [x.id for x in line.valid_value_ids]),
                    ],
                }, context)
                # It writes again the test to force to recalculate 'success' field
            self.write(cr, uid, test_id, {
                'formula': template.formula,
                'uom_id': template.uom_id and template.uom_id.id
            }, context)
        return True

    # qc.test
    def test_state(self, cr, uid, ids, mode, context):
        '''
        Currently not used.
        Probably it will be completed (this code is a fake) when the
        nan_stock_production_lot_quality_control module will be implemented
        '''
        quality_check = False

        if mode == 'failed':
            return not quality_check
        if mode == 'success':
            return quality_check
        return False

    # qc.test
    def action_workflow_draft(self, cr, uid, ids, context=None):
        self.write(cr, uid, ids, {
            'state': 'draft'
        }, context)
        return True

    # qc.test
    def action_workflow_waiting(self, cr, uid, ids, context=None):
        self.write(cr, uid, ids, {
            'state': 'waiting'
        }, context)
        return True

    # qc.test
    def action_workflow_success(self, cr, uid, ids, context=None):
        self.write(cr, uid, ids, {
            'state': 'success'
        }, context)
        return True

    # qc.test
    def action_workflow_failed(self, cr, uid, ids, context=None):
        self.write(cr, uid, ids, {
            'state': 'failed'
        }, context)
        return True

    # qc.test
    def test_workflow_draft(self, cr, uid, ids, context=None):
        # if qc_test.state=='success':
        return True

    # qc.test
    def copy(self, cr, uid, test_id, default=None, context=None):
        if context is None:
            context = {}

        if default is None:
            default = {}

        if not 'name' in default:
            default['name'] = self.pool.get('ir.sequence').get(cr, uid,
                                                               'qc.test')
        if not 'date' in default:
            default['date'] = time.strftime('%Y-%m-%d %H:%M:%S')

        return super(qc_test, self).copy(cr, uid, test_id, default, context)

    # qc.test
    def create(self, cr, uid, datas, context=None):
        if context and context.get('reference_model'):
            datas['object_id'] = context['reference_model'] + "," + \
                                 str(context['reference_id'])
        return super(qc_test, self).create(cr, uid, datas, context=context)
예제 #29
0
class nan_document(osv.osv):
    _name = 'nan.document'
    _columns = {
        'name':
        fields.char('Name', 64),
        'datas':
        fields.binary('Data'),
        'properties':
        fields.one2many('nan.document.property', 'document', 'Properties'),
        'template':
        fields.many2one('nan.template', 'Template'),
        'document':
        fields.reference('Document', selection=attachableDocuments, size=128),
        'task':
        fields.text('Task', readonly=True),
        'state':
        fields.selection([('pending', 'Pending'), ('scanning', 'Scanning'),
                          ('scanned', 'Scanned'), ('verified', 'Verified'),
                          ('processing', 'Processing'),
                          ('processed', 'Processed')],
                         'State',
                         required=True,
                         readonly=True)
    }
    _defaults = {'state': lambda *a: 'pending'}

    def write(self, cr, uid, ids, values, context=None):
        # Scan after writting as it will modify the objects and thus a "modified in
        # the meanwhile" would be thrown, so by now check which of the records
        # we'll want to scan later
        toScan = []
        if 'template' in values:
            for x in self.read(cr, uid, ids, ['state', 'template'], context):
                # We only scan the document if template has changed and the document
                # is in 'scanned' state.
                if x['state'] == 'scanned' and x['template'] != values[
                        'template']:
                    toScan.append({
                        'id': x['id'],
                        'template': values['template']
                    })

        ret = super(nan_document, self).write(cr, uid, ids, values, context)

        for x in toScan:
            self.scanDocumentWithTemplate(cr, uid, x['id'], x['template'])
        return ret

    def scan_document_background(self, cr, uid, imageIds):
        print "Scan document background"
        self.pool.get('ir.cron').create(
            cr, uid, {
                'name': 'Scan document',
                'user_id': uid,
                'model': 'nan.document',
                'function': 'scan_document',
                'args': repr([imageIds, True])
            })
        cr.commit()

    def scan_documents_batch(self, cr, uid, imageIds):
        self.scan_document(cr, uid, imageIds)
        self.pool.get('res.request').create(
            cr, uid, {
                'act_from':
                uid,
                'act_to':
                uid,
                'name':
                'Finished scanning documents',
                'body':
                'The auto_attach system has finished scanning the documents you requested. You can now go to the Scanned Documents queue to verify and process them.',
            })

    # If notify=True sends a request/notification to uid
    def scan_document(self, cr, uid, imageIds, notify=False):
        print "Scan_documentcalled"
        # Load templates into 'templates' list
        templates = self.pool.get('nan.template').getAllTemplates(cr, uid)

        # Initialize Ocr System (Gamera)
        initOcrSystem()
        recognizer = Recognizer()

        # Iterate over all images and try to find the most similar template
        for document in self.browse(cr, uid, imageIds):
            if document.state not in ('pending', 'scanning'):
                continue
            fp, image = tempfile.mkstemp()
            fp = os.fdopen(fp, 'wb+')
            fp.write(base64.decodestring(document.datas))
            fp.close()
            recognizer.recognize(QImage(image))

            result = recognizer.findMatchingTemplateByOffset(templates)
            template = result['template']
            doc = result['document']
            if not template:
                print "No template found for document %s." % document.name
            else:
                print "The best template found for document %s is %s." % (
                    document.name, template.name)

            if template:
                template_id = template.id
            else:
                template_id = False
            self.write(cr, uid, [document.id], {
                'template': template_id,
                'state': 'scanned'
            })
            if doc:
                obj = self.pool.get('nan.document.property')
                for box in doc.boxes:
                    obj.create(
                        cr, uid, {
                            'name': box.templateBox.name,
                            'value': box.text,
                            'document': document.id,
                            'template_box': box.templateBox.id
                        })

            if notify:
                self.pool.get('res.request').create(
                    cr, uid, {
                        'act_from': uid,
                        'act_to': uid,
                        'name': 'Finished scanning document',
                        'body':
                        'The auto_attach system has finished scanning the document you requested. A reference to the document can be found in field Document Ref 1.',
                        'ref_doc1': 'nan.document,%d' % document.id,
                    })

        self.executeAttachs(cr, uid, imageIds)
        self.executeActions(cr, uid, imageIds, True)

        cr.commit()

    def scanDocumentWithTemplate(self, cr, uid, documentId, templateId):

        # Whether templateId is valid or not
        # Remove previous properties
        obj = self.pool.get('nan.document.property')
        ids = obj.search(cr, uid, [('document', '=', documentId)])
        obj.unlink(cr, uid, ids)

        if templateId:
            # Initialize Ocr System (Gamera)
            initOcrSystem()

            template = self.pool.get('nan.template').getTemplateFromId(
                cr, uid, templateId)

            documents = self.read(cr, uid, [documentId])
            if not documents:
                return
            document = documents[0]

            fp, image = tempfile.mkstemp()
            fp = os.fdopen(fp, 'wb+')
            fp.write(base64.decodestring(document['datas']))
            fp.close()

            recognizer = Recognizer()
            recognizer.recognize(QImage(image))
            doc = recognizer.extractWithTemplate(image, template)

            for box in doc.boxes:
                obj.create(
                    cr, uid, {
                        'name': box.templateBox.name,
                        'value': box.text,
                        'document': document['id'],
                        'template_box': box.templateBox.id
                    })
        self.executeAttachs(cr, uid, [documentId])
        self.executeActions(cr, uid, [documentId], True)
        cr.commit()

    def process_document(self, cr, uid, ids):
        self.executeActions(cr, uid, ids, False)
        cr.commit()

    def _parseFunction(self, function, properties):
        expression = re.match('(.*)\((.*)\)', function)
        name = expression.group(1)
        parameters = expression.group(2)
        if name not in dir(self):
            print "Function '%s' not found" % (name)
            return False

        parameters = parameters.split(',')
        newParameters = []
        for p in parameters:
            value = p.strip()
            if value.startswith('#'):
                if value[1:] not in properties:
                    print "Property '%s' not found" % value
                    newParameters.append("''")
                    continue
                value = properties[value[1:]]
            value = "'" + value.replace("'", "\\'") + "'"
            if type(value) != unicode:
                value = unicode(value, errors='ignore')
            newParameters.append(value)
        return (name, newParameters)

    def executeActions(self, cr, uid, ids, explain):
        for document in self.browse(cr, uid, ids):
            print "Executing action on document with state ", document.state
            if not explain and document.state not in ('verified',
                                                      'processing'):
                continue

            print "Yes"
            task = None
            if document.template:
                function = document.template.action_function
                if function:
                    properties = dict([(x.name, unicode(x.value))
                                       for x in document.properties])
                    (name,
                     parameters) = self._parseFunction(function, properties)

                    obj = self.pool.get('nan.document')
                    task = eval('obj.%s(cr, uid, explain, %s)' %
                                (name, ','.join(parameters)))
            if explain:
                self.write(cr, uid, [document.id], {'task': task})
            elif document.document:
                # Attach document to the appropiate reference
                ref = document.document.split(',')
                model = ref[0]
                id = ref[1]
                self.pool.get('ir.attachment').create(
                    cr, uid, {
                        'res_id': id,
                        'res_model': model,
                        'name': document.name,
                        'datas': document.datas,
                        'datas_fname': document.name,
                        'description': 'Document attached automatically'
                    })
                self.write(cr, uid, [document.id], {'state': 'processed'})

    def executeAttachs(self, cr, uid, ids):
        for document in self.browse(cr, uid, ids):
            reference = None
            if document.template:
                function = document.template.attach_function
                if function:
                    properties = dict([(x.name, unicode(x.value, 'latin-1'))
                                       for x in document.properties])

                    (name,
                     parameters) = self._parseFunction(function, properties)
                    obj = self.pool.get('nan.document')
                    #print 'CALLING: obj.%s(cr, uid, %s)' % ( name, u','.join( parameters ) ),
                    reference = eval('obj.%s(cr, uid, %s)' %
                                     (name, u','.join(parameters)))

            if reference:
                self.write(
                    cr, uid, [document.id],
                    {'document': '%s,%s' % (reference[0], reference[1])})
            else:
                self.write(cr, uid, [document.id], {'document': False})

    def actionAddPartner(self, cr, uid, explain, name):
        if explain:
            return "A new partner with name '%s' will be created (if it doesn't exist already)." % name
        else:
            if not self.pool.get('res.partner').search(cr, uid,
                                                       [('name', '=', name)]):
                self.pool.get('res.partner').create(cr, uid, {'name': name})
            return True

    def attachModelByField(self, cr, uid, model, field, name):
        table = self.pool.get(model)._table
        # TODO: Security issues
        cr.execute('SELECT id FROM "' + table + '" ORDER BY similarity("' +
                   field + '",\'%s\') DESC LIMIT 1' % name)
        record = cr.fetchone()
        if not record:
            return False
        return (model, record[0])
예제 #30
0
class event_registration(osv.osv):
    """Event Registration"""
    _name = 'event.registration'
    _description = __doc__
    _inherit = 'mail.thread'

    def _amount_line(self, cr, uid, ids, field_name, arg, context=None):
        cur_obj = self.pool.get('res.currency')
        res = {}
        for line in self.browse(cr, uid, ids, context=context):
            price = line.unit_price * line.nb_register
            pricelist = line.event_id.pricelist_id or line.partner_invoice_id.property_product_pricelist
            cur = pricelist and pricelist.currency_id or False
            res[line.id] = cur and cur_obj.round(cr, uid, cur, price) or price
        return res

    _columns = {
        'id': fields.integer('ID'),
        'name': fields.char('Summary', size=124,  readonly=True, states={'draft': [('readonly', False)]}),
        'email_cc': fields.text('CC', size=252, readonly=False, states={'done': [('readonly', True)]}, 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"),
        'nb_register': fields.integer('Quantity', required=True, readonly=True, states={'draft': [('readonly', False)]}, help="Number of Registrations or Tickets"),
        'event_id': fields.many2one('event.event', 'Event', required=True, readonly=True, states={'draft': [('readonly', False)]}),
        'partner_id': fields.many2one('res.partner', 'Partner', states={'done': [('readonly', True)]}),
        "partner_invoice_id": fields.many2one('res.partner', 'Partner Invoiced', readonly=True, states={'draft': [('readonly', False)]}),
        "contact_id": fields.many2one('res.partner.address', 'Partner Contact', readonly=False, states={'done': [('readonly', True)]}), #TODO: filter only the contacts that have a function into the selected partner_id
        "unit_price": fields.float('Unit Price', required=True, digits_compute=dp.get_precision('Sale Price'), readonly=True, states={'draft': [('readonly', False)]}),
        'price_subtotal': fields.function(_amount_line, string='Subtotal', digits_compute=dp.get_precision('Sale Price'), store=True),
        "badge_ids": fields.one2many('event.registration.badge', 'registration_id', 'Badges', readonly=False, states={'done': [('readonly', True)]}),
        "event_product": fields.char("Invoice Name", size=128, readonly=True, states={'draft': [('readonly', False)]}),
        "tobe_invoiced": fields.boolean("To be Invoiced", readonly=True, states={'draft': [('readonly', False)]}),
        "invoice_id": fields.many2one("account.invoice", "Invoice", readonly=True),
        'date_closed': fields.datetime('Closed', readonly=True),
        'ref': fields.reference('Reference', selection=crm._links_get, size=128),
        'ref2': fields.reference('Reference 2', selection=crm._links_get, size=128),
        'email_from': fields.char('Email', size=128, states={'done': [('readonly', True)]}, help="These people will receive email."),
        'create_date': fields.datetime('Creation Date', readonly=True),
        'write_date': fields.datetime('Write Date', readonly=True),
        'description': fields.text('Description', states={'done': [('readonly', True)]}),
        'message_ids': fields.one2many('mail.message', 'res_id', 'Messages', domain=[('model','=',_name)]),
        'log_ids': fields.one2many('mail.message', 'res_id', 'Logs', domain=[('email_from', '=', False),('model','=',_name)]),
        'date_deadline': fields.related('event_id','date_end', type='datetime', string="End Date", readonly=True),
        'date': fields.related('event_id', 'date_begin', type='datetime', string="Start Date", readonly=True),
        'user_id': fields.many2one('res.users', 'Responsible', states={'done': [('readonly', True)]}),
        'active': fields.boolean('Active'),
        'section_id': fields.related('event_id', 'section_id', type='many2one', relation='crm.case.section', string='Sale Team', store=True, readonly=True),
        'company_id': fields.related('event_id', 'company_id', type='many2one', relation='res.company', string='Company', store=True, readonly=True, states={'draft':[('readonly',False)]}),
        'state': fields.selection([('open', 'Confirmed'),
                                    ('draft', 'Unconfirmed'),
                                    ('cancel', 'Cancelled'),
                                    ('done', 'Done')], 'State', \
                                    size=16, readonly=True)
    }
    _defaults = {
        'nb_register': 1,
        'tobe_invoiced': True,
        'state': 'draft',
        'active': 1,
        'user_id': lambda self, cr, uid, ctx: uid,
    }

    def _make_invoice(self, cr, uid, reg, lines, context=None):
        """ Create Invoice from Invoice lines
        @param reg: Model of Event Registration
        @param lines: Ids of Invoice lines
        """
        if context is None:
            context = {}
        inv_pool = self.pool.get('account.invoice')
        val_invoice = inv_pool.onchange_partner_id(cr, uid, [], 'out_invoice',
                                                   reg.partner_invoice_id.id,
                                                   False, False)
        val_invoice['value'].update({'partner_id': reg.partner_invoice_id.id})
        val_invoice['value'].update({
            'origin':
            reg.event_product,
            'reference':
            False,
            'invoice_line': [(6, 0, lines)],
            'comment':
            "",
            'date_invoice':
            context.get('date_inv', False)
        })
        inv_id = inv_pool.create(cr,
                                 uid,
                                 val_invoice['value'],
                                 context=context)
        inv_pool.button_compute(cr, uid, [inv_id])
        self.message_append(cr, uid, [reg], _('Invoiced'))
        return inv_id

    def copy(self, cr, uid, id, default=None, context=None):
        """ Copy record of Given id
        @param id: Id of Registration record.
        @param context: A standard dictionary for contextual values
        """
        if not default:
            default = {}
        default.update({
            'invoice_id': False,
        })
        return super(event_registration, self).copy(cr,
                                                    uid,
                                                    id,
                                                    default=default,
                                                    context=context)

    def action_invoice_create(self,
                              cr,
                              uid,
                              ids,
                              grouped=False,
                              date_inv=False,
                              context=None):
        """ Action of Create Invoice """
        res = False
        invoices = {}
        tax_ids = []
        new_invoice_ids = []
        inv_lines_pool = self.pool.get('account.invoice.line')
        inv_pool = self.pool.get('account.invoice')
        product_pool = self.pool.get('product.product')
        contact_pool = self.pool.get('res.partner.address')
        if context is None:
            context = {}
        # If date was specified, use it as date invoiced, usefull when invoices are generated this month and put the
        # last day of the last month as invoice date
        if date_inv:
            context['date_inv'] = date_inv

        for reg in self.browse(cr, uid, ids, context=context):
            val_invoice = inv_pool.onchange_partner_id(
                cr, uid, [], 'out_invoice', reg.partner_invoice_id.id, False,
                False)
            val_invoice['value'].update(
                {'partner_id': reg.partner_invoice_id.id})
            partner_address_id = val_invoice['value']['address_invoice_id']
            if not partner_address_id:
                raise osv.except_osv(
                    _('Error !'),
                    _("Registered partner doesn't have an address to make the invoice."
                      ))

            value = inv_lines_pool.product_id_change(
                cr,
                uid, [],
                reg.event_id.product_id.id,
                uom=False,
                partner_id=reg.partner_invoice_id.id,
                fposition_id=reg.partner_invoice_id.property_account_position.
                id)
            product = product_pool.browse(cr,
                                          uid,
                                          reg.event_id.product_id.id,
                                          context=context)
            for tax in product.taxes_id:
                tax_ids.append(tax.id)
            vals = value['value']
            c_name = reg.contact_id and ('-' + contact_pool.name_get(
                cr, uid, [reg.contact_id.id])[0][1]) or ''
            vals.update({
                'name': reg.event_product + '-' + c_name,
                'price_unit': reg.unit_price,
                'quantity': reg.nb_register,
                'product_id': reg.event_id.product_id.id,
                'invoice_line_tax_id': [(6, 0, tax_ids)],
            })
            inv_line_ids = self._create_invoice_lines(cr, uid, [reg.id], vals)
            invoices.setdefault(reg.partner_id.id, []).append(
                (reg, inv_line_ids))
        for val in invoices.values():
            res = False
            if grouped:
                res = self._make_invoice(cr,
                                         uid,
                                         val[0][0], [v for k, v in val],
                                         context=context)

                for k, v in val:
                    self.do_close(cr, uid, [k.id], context={'invoice_id': res})

            else:
                for k, v in val:
                    res = self._make_invoice(cr, uid, k, [v], context=context)
                    self.do_close(cr, uid, [k.id], context={'invoice_id': res})
            if res: new_invoice_ids.append(res)
        return new_invoice_ids

    def do_open(self, cr, uid, ids, context=None):
        """ Open Registration
        """
        res = self.write(cr, uid, ids, {'state': 'open'}, context=context)
        self.mail_user(cr, uid, ids)
        self.message_append(cr, uid, ids, _('Open'))
        return res

    def do_close(self, cr, uid, ids, context=None):
        """ Close Registration
        """
        if context is None:
            context = {}
        invoice_id = context.get('invoice_id', False)
        values = {
            'state': 'done',
            'date_closed': time.strftime('%Y-%m-%d %H:%M:%S')
        }
        msg = _('Done')
        if invoice_id:
            values['invoice_id'] = invoice_id
        res = self.write(cr, uid, ids, values)
        self.message_append(cr, uid, ids, msg)
        return res

    # event uses add_note wizard from crm, which expects case_* methods
    def case_open(self, cr, uid, ids, context=None):
        self.do_open(cr, uid, ids, context)

    # event uses add_note wizard from crm, which expects case_* methods
    def case_close(self, cr, uid, ids, context=None):
        self.do_close(cr, uid, ids, context)

    # event uses add_note wizard from crm, which expects case_* methods
    def case_cancel(self, cr, uid, ids, context=None):
        """ Cancel Registration
        """
        self.message_append(cr, uid, ids, _('Cancel'))
        return self.write(cr, uid, ids, {'state': 'cancel'})

    # event uses add_note wizard from crm, which expects case_* methods
    def case_reset(self, cr, uid, ids, context=None):
        pass

    # event uses add_note wizard from crm, which expects case_* methods
    def case_pending(self, cr, uid, ids, context=None):
        pass

    def check_confirm(self, cr, uid, ids, context=None):
        """This Function Open Event Registration and send email to user.
        @param ids: List of Event registration's IDs
        @param context: A standard dictionary for contextual values
        @return: True
        """
        if type(ids) in (
                int,
                long,
        ):
            ids = [ids]
        data_pool = self.pool.get('ir.model.data')
        unconfirmed_ids = []
        if context is None:
            context = {}
        for registration in self.browse(cr, uid, ids, context=context):
            total_confirmed = registration.event_id.register_current + registration.nb_register
            if total_confirmed <= registration.event_id.register_max or registration.event_id.register_max == 0:
                self.do_open(cr, uid, [registration.id], context=context)
            else:
                unconfirmed_ids.append(registration.id)
        if unconfirmed_ids:
            view_id = data_pool.get_object_reference(
                cr, uid, 'event', 'view_event_confirm_registration')
            view_id = view_id and view_id[1] or False
            context['registration_ids'] = unconfirmed_ids
            return {
                'name': _('Confirm Registration'),
                'context': context,
                'view_type': 'form',
                'view_mode': 'tree,form',
                'res_model': 'event.confirm.registration',
                'views': [(view_id, 'form')],
                'type': 'ir.actions.act_window',
                'target': 'new',
                'context': context,
                'nodestroy': True
            }
        return True

    def button_reg_close(self, cr, uid, ids, context=None):
        """This Function Close Event Registration.
        """
        data_pool = self.pool.get('ir.model.data')
        unclosed_ids = []
        for registration in self.browse(cr, uid, ids, context=context):
            if registration.tobe_invoiced and not registration.invoice_id:
                unclosed_ids.append(registration.id)
            else:
                self.do_close(cr, uid, [registration.id], context=context)
        if unclosed_ids:
            view_id = data_pool.get_object_reference(
                cr, uid, 'event', 'view_event_make_invoice')
            view_id = view_id and view_id[1] or False
            context['active_ids'] = unclosed_ids
            return {
                'name': _('Close Registration'),
                'context': context,
                'view_type': 'form',
                'view_mode': 'tree,form',
                'res_model': 'event.make.invoice',
                'views': [(view_id, 'form')],
                'type': 'ir.actions.act_window',
                'target': 'new',
                'context': context,
                'nodestroy': True
            }
        return True

    def button_reg_cancel(self, cr, uid, ids, context=None, *args):
        return self.case_cancel(cr, uid, ids)

    def mail_user(self, cr, uid, ids, confirm=False, context=None):
        """
        Send email to user
        """
        mail_message = self.pool.get('mail.message')
        for registration in self.browse(cr, uid, ids, context=context):
            src = registration.event_id.reply_to or False
            email_to = []
            email_cc = []
            if registration.email_from:
                email_to = [registration.email_from]
            if registration.email_cc:
                email_cc += [registration.email_cc]
            if not (email_to or email_cc):
                continue
            subject = ""
            body = ""
            if confirm:
                subject = _('Auto Confirmation: [%s] %s') % (registration.id,
                                                             registration.name)
                body = registration.event_id.mail_confirm
            elif registration.event_id.mail_auto_confirm or registration.event_id.mail_auto_registr:
                if registration.event_id.state in [
                        'draft', 'fixed', 'open', 'confirm', 'running'
                ] and registration.event_id.mail_auto_registr:
                    subject = _('Auto Registration: [%s] %s') % (
                        registration.id, registration.name)
                    body = registration.event_id.mail_registr
                if (registration.event_id.state in [
                        'confirm', 'running'
                ]) and registration.event_id.mail_auto_confirm:
                    subject = _('Auto Confirmation: [%s] %s') % (
                        registration.id, registration.name)
                    body = registration.event_id.mail_confirm
            if subject or body:
                mail_message.schedule_with_attach(cr,
                                                  uid,
                                                  src,
                                                  email_to,
                                                  subject,
                                                  body,
                                                  model='event.registration',
                                                  email_cc=email_cc,
                                                  res_id=registration.id)

        return True

    def mail_user_confirm(self, cr, uid, ids, context=None):
        """
        Send email to user
        """
        return self.mail_user(cr, uid, ids, confirm=True, context=context)

    def _create_invoice_lines(self, cr, uid, ids, vals):
        """ Create account Invoice line for Registration Id.
        """
        return self.pool.get('account.invoice.line').create(cr, uid, vals)

    def onchange_contact_id(self, cr, uid, ids, contact, partner):
        """This function returns value of Badge Name, Badge Title based on Partner contact.
        @param self: The object pointer
        @param cr: the current row, from the database cursor,
        @param uid: the current user’s ID for security checks,
        @param ids: List of Registration IDs
        @param contact: Patner Contact IDS
        @param partner: Partner IDS
        """
        data = {}
        if not contact:
            return data
        addr_obj = self.pool.get('res.partner.address')
        data['email_from'] = addr_obj.browse(cr, uid, contact).email
        return {'value': data}

    def onchange_event(self, cr, uid, ids, event_id, partner_invoice_id):
        """This function returns value of Product Name, Unit Price based on Event.
        @param self: The object pointer
        @param cr: the current row, from the database cursor,
        @param uid: the current user’s ID for security checks,
        @param ids: List of Registration IDs
        @param event_id: Event ID
        @param partner_invoice_id: Partner Invoice ID
        """
        context = {}
        if not event_id:
            return {'value': {'unit_price': False, 'event_product': False}}

        event_obj = self.pool.get('event.event')
        prod_obj = self.pool.get('product.product')
        res_obj = self.pool.get('res.partner')

        data_event = event_obj.browse(cr, uid, event_id)
        res = {
            'value': {
                'unit_price':
                False,
                'event_product':
                False,
                'user_id':
                False,
                'date':
                data_event.date_begin,
                'date_deadline':
                data_event.date_end,
                'description':
                data_event.note,
                'name':
                data_event.name,
                'section_id':
                data_event.section_id and data_event.section_id.id or False,
            }
        }
        if data_event.user_id.id:
            res['value'].update({'user_id': data_event.user_id.id})
        if data_event.product_id:
            pricelist_id = data_event.pricelist_id and data_event.pricelist_id.id or False
            if partner_invoice_id:
                partner = res_obj.browse(cr,
                                         uid,
                                         partner_invoice_id,
                                         context=context)
                pricelist_id = pricelist_id or partner.property_product_pricelist.id
            unit_price = prod_obj._product_price(
                cr, uid, [data_event.product_id.id], False, False,
                {'pricelist': pricelist_id})[data_event.product_id.id]
            if not unit_price:
                unit_price = data_event.unit_price
            res['value'].update({
                'unit_price': unit_price,
                'event_product': data_event.product_id.name
            })
        return res

    def onchange_partner_id(self, cr, uid, ids, part, event_id, email=False):
        """This function returns value of Patner Invoice id, Unit Price, badget title based on partner and Event.
        @param self: The object pointer
        @param cr: the current row, from the database cursor,
        @param uid: the current user’s ID for security checks,
        @param ids: List of Registration IDs
        @param event_id: Event ID
        @param partner_invoice_id: Partner Invoice ID
        """
        res_obj = self.pool.get('res.partner')

        data = {}
        data['contact_id'], data['partner_invoice_id'], data['email_from'] = (
            False, False, False)
        if not part:
            return {'value': data}
        data['partner_invoice_id'] = part
        # this calls onchange_partner_invoice_id
        d = self.onchange_partner_invoice_id(cr, uid, ids, event_id, part)
        # this updates the dictionary
        data.update(d['value'])
        addr = res_obj.address_get(cr, uid, [part]).get('default', False)
        if addr:
            d = self.onchange_contact_id(cr, uid, ids, addr, part)
            data.update(d['value'])
        return {'value': data}

    def onchange_partner_invoice_id(self, cr, uid, ids, event_id,
                                    partner_invoice_id):
        """This function returns value of Product unit Price based on Invoiced partner.
        @param self: The object pointer
        @param cr: the current row, from the database cursor,
        @param uid: the current user’s ID for security checks,
        @param ids: List of Registration IDs
        @param event_id: Event ID
        @param partner_invoice_id: Partner Invoice ID
        """
        data = {}
        context = {}
        event_obj = self.pool.get('event.event')
        prod_obj = self.pool.get('product.product')
        res_obj = self.pool.get('res.partner')

        data['unit_price'] = False
        if not event_id:
            return {'value': data}
        data_event = event_obj.browse(cr, uid, event_id, context=context)
        if data_event.product_id:
            data['event_product'] = data_event.product_id.name
            pricelist_id = data_event.pricelist_id and data_event.pricelist_id.id or False
            if partner_invoice_id:
                partner = res_obj.browse(cr,
                                         uid,
                                         partner_invoice_id,
                                         context=context)
                pricelist_id = pricelist_id or partner.property_product_pricelist.id
            unit_price = prod_obj._product_price(
                cr, uid, [data_event.product_id.id], False, False,
                {'pricelist': pricelist_id})[data_event.product_id.id]
            if not unit_price:
                unit_price = data_event.unit_price
            data['unit_price'] = unit_price
        return {'value': data}