def _group(self, items, prefix): """Return an XML chunk which represents a group of fields.""" names = [] for k, v in items: key = '%s\\%s' % (prefix, k) # Mask passwords if 'passw' in k and not self.show_passwords: v = '**********' self._columns[key] = fields.char(k, size=1024) self._conf_defaults[key] = v names.append(key) return ('<group col="2" colspan="4">' + ''.join(['<field name="%s" readonly="1"/>' % _escape(name) for name in names]) + '</group>')
def __init__(self, pool, cr): """ Dynamically add columns.""" super(report_prompt_class, self).__init__(pool, cr) for counter in range(0, MAX_PARAMS): field_name = PARAM_XXX_STRING_VALUE % counter self._columns[field_name] = fields.char('String Value', size=64) field_name = PARAM_XXX_BOOLEAN_VALUE % counter self._columns[field_name] = fields.boolean('Boolean Value') field_name = PARAM_XXX_INTEGER_VALUE % counter self._columns[field_name] = fields.integer('Integer Value') field_name = PARAM_XXX_NUMBER_VALUE % counter self._columns[field_name] = fields.float('Number Value') field_name = PARAM_XXX_DATE_VALUE % counter self._columns[field_name] = fields.date('Date Value') field_name = PARAM_XXX_TIME_VALUE % counter self._columns[field_name] = fields.datetime('Time Value') self.paramfile = False
def __init__(self, pool, cr): """ Dynamically add columns.""" super(report_prompt_class, self).__init__(pool, cr) for counter in range(0, MAX_PARAMS): field_name = PARAM_XXX_STRING_VALUE % counter self._columns[field_name] = fields.char('String Value', size=64) field_name = PARAM_XXX_BOOLEAN_VALUE % counter self._columns[field_name] = fields.boolean('Boolean Value') field_name = PARAM_XXX_INTEGER_VALUE % counter self._columns[field_name] = fields.integer('Integer Value') field_name = PARAM_XXX_NUMBER_VALUE % counter self._columns[field_name] = fields.float('Number Value') field_name = PARAM_XXX_DATE_VALUE % counter self._columns[field_name] = fields.date('Date Value') field_name = PARAM_XXX_TIME_VALUE % counter self._columns[field_name] = fields.datetime('Time Value') field_name = PARAM_XXX_2M_VALUE % counter self._columns[field_name] = fields.function(self._multi_select_values.im_func, arg={"entry_num": counter}, fnct_inv=self._multi_select_values_store.im_func, fnct_inv_arg={"entry_num": counter}, method=False, type='many2many', relation='ir.actions.report.multivalues.promptwizard', string='Multi-Select')
class product_tmalljd(osv.osv): _name = "product.tmalljd" def _get_ean13(self, cr, uid, ids, field_name, arg, context=None): result = {} for line in self.pool.get('product.tmalljd').browse(cr, uid, ids, context=context): if line.erp_product_id : result[line.id] = line.erp_product_id.ean13 or line.erp_product_id.default_code return result def _get_stock(self, cr, uid, ids, field_name, arg, context=None): result = {} domain_products = [('location_id','=',38)] quants = self.pool.get('stock.quant').read_group(cr, uid, domain_products, ['product_id', 'qty'], ['product_id'], context=context) quants = dict(map(lambda x: (x['product_id'][0], x['qty']), quants)) for line in self.pool.get('product.tmalljd').browse(cr, uid, ids, context=context): id = line.id if line.erp_product_id : pid = line.erp_product_id.id result[id] = quants.get(pid, 0.0) else: result[id] = 0 return result _columns = { 'gift_ids': fields.one2many('product.tmalljd.gifts','tmalljd_id','Gift Products'), 'erp_product_set': fields.many2many('product.product', 'product_product_tmalljd_rel', 'tmalljd_id', 'product_id', u'Product Set(套装)'), 'erp_product_id': fields.many2one('product.product','ERP Product Name'), 'erp_ean13': fields.char('ERP_EAN13'), #fields.function(_get_ean13,type='char',string='ERP_EAN13'), 'erp_stock': fields.float('ERPStock'),#fields.function(_get_stock,type='float',string='ERP库存'), 'ec_shop_id': fields.many2one('loewieec.shop', u'店铺'), 'ec_num_iid': fields.char(u'淘宝数字编码'), 'ec_sku_id': fields.char(u'淘宝SKU_ID'), 'ec_title':fields.char(u'商品标题'), 'ec_price':fields.float(u'售价'), 'ec_color':fields.char(u'颜色'), 'ec_ean13': fields.char(u'条形码'), 'ec_brand': fields.char(u'品牌'), 'ec_qty': fields.integer(u'EC数量'), 'ec_outer_code': fields.char(u'商家外部编码'), 'ec_product_name': fields.char(u'产品名称'), 'ec_product_id': fields.char(u'EC产品ID'), 'ec_num_custom':fields.char(u'海关代码'), }
def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False): result = super(product_search_ept, self).fields_view_get(cr, uid, view_id, view_type, context, toolbar,submenu) if context is None: context={} self._columns = {} self._columns['product_ids'] = fields.text('Product IDS') if view_type != 'form': return result _moves_arch_lst = """ <form string="Stone Search" version="7.0"> <div> """ #_moves_arch_lst += """<group colspan="4" col="10">""" _line_fields = result['fields'] info = [ {'model':None,'_column_name':'product_name','label':'Stone ID','type':'char','name':'name','product_search_type':'char'}, {'model':None,'_column_name':'product_certificate_no','label':'Certificate No.','type':'char','name':'certificate_no','product_search_type':'char'}, {'model':None,'_column_name':'product_weight','label':'Weight','no':3,'type':'float','name':'weight','product_search_type':'char','range':True}, {'model':None,'_column_name':'product_price_caret','label':'PPC','no':1,'type':'float','name':'price_caret','product_search_type':'char','range':True}, {'model':None,'_column_name':'product_discount','label':'Back%','no':1,'type':'float','name':'discount','product_search_type':'char','range':True}, {'model':'product.shape','width':'15%','_column_name':'product_shape','label':'SHP','help':'Shape','type':'many2one','name':'shape_id','product_search_type':'boolean','on_change':'product_shape_change'}, {'model':'product.color','width':'8%','_column_name':'product_color','label':'CLR','help':'Color','type':'many2one','name':'color_id','product_search_type':'boolean','on_change':'product_color_change'}, {'model':'product.clarity','width':'10%','_column_name':'product_clarity','label':'CLRTY','help':'Clarity','type':'many2one','name':'clarity_id','product_search_type':'boolean','on_change':'product_clarity_change'}, {'model':'product.cut','width':'12%','_column_name':'product_cut','label':'CUT','help':'Cut','type':'many2one','name':'cut_id','product_search_type':'boolean','on_change':'product_cut_change'}, {'model':'product.polish','width':'8%','_column_name':'product_polish','label':'POL','help':'Polish','type':'many2one','name':'polish_id','product_search_type':'boolean','on_change':'product_polish_change'}, {'model':'product.symmetry','width':'10%','_column_name':'product_symmetry','label':'SYM','help':'Symmetry','type':'many2one','name':'symmetry_id','product_search_type':'boolean','on_change':'product_symmetry_change'}, {'model':'product.fluorescence.intensity','width':'13%','_column_name':'product_fluorescence_intensity','label':'FLUR','help':'Fluorescence Intensity','type':'many2one','name':'fluorescence_intensity_id','product_search_type':'boolean','on_change':'product_fluorescence_intensity_change'}, {'model':'product.lab','width':'8%','_column_name':'product_lab','label':'LAB','help':'Lab','type':'many2one','name':'lab_id','product_search_type':'boolean','on_change':'product_lab_change'}, {'model':'product.fancy.color','width':'15%','_column_name':'product_fancy_color','label':'FNC CLR','help':'Fancy Color','type':'many2one','name':'fancy_color_id','product_search_type':'boolean','on_change':'product_fancy_color_change'}, {'model':'product.fancy.color.intensity','width':'15%','_column_name':'product1_fancy_color_intensity','label':'FNC CLR INT','help':'Fancy Color Intensity','type':'many2one','name':'fancy_color_intensity','product_search_type':'boolean','on_change':'product1_fancy_color_intensity_change'}, {'model':'product.fancy.color.overtone','width':'15%','_column_name':'product2_fancy_color_overtone','label':'FNC CLR OVR','help':'Fancy Color Overtone','type':'many2one','name':'fancy_color_overtone','product_search_type':'boolean','on_change':'product2_fancy_color_overtone_change'}, {'model':None,'_column_name':'product_status','width':'20%','label':'Status','type':'selection','name':'product_status','product_search_type':'boolean' ,'selection_val':[('available','Available'), ('hold','Hold'), ('sold','Sold'), ('on_approval','On Approval'), ('on_consignment','On Consignment'), ('offline','Offline'), ('repair','Repair'), ('web_sale','Web Sale')]}, {'model':'stock.location','_column_name':'stock_location','width':'15%','label':'Location','type':'many2one','name':'location_id','product_search_type':'boolean' ,'domain':[('usage','=','internal')],}, ] for model_info in info : if model_info['type'] == 'many2one' and model_info['product_search_type'] == 'boolean' : if model_info['model']: ids = self.pool.get(model_info['model']).search(cr,uid,model_info.get('domain',[])) if ids : _moves_arch_lst += """<div style="float:left;width:%s;">"""%(model_info.get('width', '100%')) ''' Header ''' if model_info.get('label', False)=='Location': _moves_arch_lst += """<u><label style="color:rgb(124,123,173);font-weight:bold;" string="%s"/></u>"""%(model_info['label']) if model_info.get('on_change', False): ''' Check box for Select All ''' _moves_arch_lst += """<div><field name="%s" class="oe_inline" nolabel="1" on_change="%s(%s)"/> """%(model_info['on_change'],model_info['on_change'],model_info['on_change']) ''' Label for Select All ''' _moves_arch_lst += """<u><label help='%s' style="color:rgb(124, 123, 173);" string="%s" for="%s" /></u></div>"""%(model_info['help'],model_info['label'],model_info['label']) _line_fields.update({ '%s'%(model_info['on_change']) : { 'string': 'All ?', 'type' : 'boolean', },}) self._columns['%s'%(model_info['on_change'])] = fields.boolean(model_info['on_change']) for obj in self.pool.get(model_info['model']).browse(cr,uid,ids,context=context): name=len(obj.name) > 7 and (obj.name[:7]+'...') or obj.name[:7] _line_fields.update({ '%s%s'%(model_info['_column_name'],obj.id) : { 'string': obj.name, 'type' : 'boolean', 'help' : '%s'%(obj.name) },}) self._columns['%s%s'%(model_info['_column_name'],obj.id)] = fields.boolean(obj.name) ''' Check box and related label ''' _moves_arch_lst += """ <div><field name="%s%s" class="oe_inline" nolabel="1"/> <label string="%s" for="%s%s" /></div> """%(model_info['_column_name'],obj.id,name,model_info['_column_name'],obj.id) _moves_arch_lst += """</div>""" ####################### if model_info['type'] == 'char' and model_info['product_search_type'] == 'char': _moves_arch_lst += """<div style="width:%s;float:left;">""" %('50%') _line_fields.update({ '%s'%(model_info['_column_name']) : { 'string': 'Name', 'type' : 'char', 'help' : '%s'%(model_info['_column_name']), },}) self._columns['%s'%(model_info['_column_name'])] = fields.char(model_info['label'],size=1024) _moves_arch_lst += """ <div> <label style="color:rgb(124, 123, 173);" string="%s" for="%s" /> <field name="%s" style="width: 70%%" nolabel="1"/> </div> </div> """%(model_info['label'],model_info['_column_name'],model_info['_column_name']) ################################ if model_info['type'] == 'selection' and model_info['product_search_type'] == 'boolean' : if model_info['selection_val']: _moves_arch_lst += """<div style="float:left;width:%s">"""%(model_info['width']) _moves_arch_lst += """<u><label style="color:rgb(124, 123, 173);font-weight:bold;" string="%s" /></u><newline/>"""%(model_info['label']) for value in model_info['selection_val']: _line_fields.update({ '%s_%s'%(model_info['_column_name'],value[0]) : { 'string': value[1], 'type' : 'boolean', },}) self._columns['%s_%s'%(model_info['_column_name'],value[0])] = fields.boolean(value[1]) _moves_arch_lst += """ <div><field name="%s_%s" nolabel="1"/> <label string="%s" for="%s_%s" /></div> """%(model_info['_column_name'],value[0],value[1],model_info['_column_name'],value[0]) _moves_arch_lst +="""</div>""" ########################### if model_info.get('range') and model_info['range']: width = '50%' if model_info.get('no') > 1:width = '100%' _moves_arch_lst += """<div style="float:left;width:%s;">"""%(width) _moves_arch_lst += """<div style="float:left;width:%s;"><label style="color:rgb(124, 123, 173);font-weight:bold;" string="%s" /></div>"""%('15%',model_info['label']) if model_info.get('no'): no = model_info.get('no') wid = str(85/int(no)) + '%' while no != 0 : no = no - 1 _line_fields.update({'%s_from_%s'%(model_info['_column_name'],no) : {'string': model_info['label'],'type':'float'}}) _line_fields.update({'%s_to_%s'%(model_info['_column_name'],no) : {'string': model_info['label'],'type':'float'}}) self._columns['%s_from_%s'%(model_info['_column_name'],no)] = fields.float(model_info['label'],digits=(16,2)) self._columns['%s_to_%s'%(model_info['_column_name'],no)] = fields.float(model_info['label'],digits=(16,2)) _moves_arch_lst += """ <div style="float:left;width:%s;"> <div style="float:left;"><field name="%s_from_%s" placeholder="From" class="oe_inline" nolabel="1"/></div> <div style="float:left;"><b><label style="color:rgb(124, 123, 173);" string="--" /></b></div> <div style="float:left;"><field name="%s_to_%s" placeholder="To" class="oe_inline" nolabel="1"/></div> </div> """%(wid,model_info['_column_name'],no,model_info['_column_name'],no) _moves_arch_lst += """</div>""" _moves_arch_lst += """ </div> <footer> <button name="get_product" string="Search" type="object" colspan="2" class="oe_highlight"/> or <button string="Cancel" class="oe_link" special="cancel"/> </footer> </form> """ result['arch'] = _moves_arch_lst result['arch'] = result['arch'].replace('&','&') result['fields'] = _line_fields return result
def _save_file(self, path, b64_file): """Save a file encoded in base 64""" self._check_filestore(path) with open(path, 'w') as ofile: ofile.write(base64.b64decode(b64_file)) return True def _set_image(self, cr, uid, id, name, value, arg, context=None): image = self.browse(cr, uid, id, context=context) full_path = self._image_path(cr, uid, image, context=context) if full_path: return self._save_file(full_path, value) return self.write(cr, uid, id, {'file_db_store' : value}, context=context) _columns = { 'name':fields.char('Image Title', size=100, required=True), 'extention': fields.char('file extention', size=6), 'link':fields.boolean('Link?', help="Images can be linked from files on your file system or remote (Preferred)"), 'file_db_store':fields.binary('Image stored in database'), 'file':fields.function(_get_image, fnct_inv=_set_image, type="binary", filters='*.png,*.jpg,*.gif'), 'url':fields.char('File Location', size=250), 'comments':fields.text('Comments'), 'product_id':fields.many2one('product.product', 'Product') } _defaults = { 'link': lambda *a: False, } _sql_constraints = [('uniq_name_product_id', 'UNIQUE(product_id, name)', _('A product can have only one image with the same name'))]
_logger.debug("Creating new Odoo user \"%s\" from LDAP" % login) user_obj = self.pool['res.users'] values = self.map_ldap_attributes(cr, uid, conf, login, ldap_entry) if conf['user']: values['active'] = True user_id = user_obj.copy(cr, SUPERUSER_ID, conf['user'], default=values) else: user_id = user_obj.create(cr, SUPERUSER_ID, values) return user_id _columns = { 'sequence': fields.integer('Sequence'), 'company': fields.many2one('res.company', 'Company', required=True, ondelete='cascade'), 'ldap_server': fields.char('LDAP Server address', required=True), 'ldap_server_port': fields.integer('LDAP Server port', required=True), 'ldap_binddn': fields.char('LDAP binddn', help=("The user account on the LDAP server that is used to query " "the directory. Leave empty to connect anonymously.")), 'ldap_password': fields.char('LDAP password', help=("The password of the user account on the LDAP server that is " "used to query the directory.")), 'ldap_filter': fields.char('LDAP filter', required=True), 'ldap_base': fields.char('LDAP base', required=True), 'user': fields.many2one('res.users', 'Template User', help="User to copy when creating new users"), 'create_user': fields.boolean('Create user', help="Automatically create local user accounts for new users authenticating via LDAP"), 'ldap_tls': fields.boolean('Use TLS', help="Request secure TLS/SSL encryption when connecting to the LDAP server. "
for record in self.browse(cr, uid, ids, context=context): if record.res_model != 'ir.ui.view' or not record.datas: continue try: result[record.id] = openerp.tools.image_resize_image_big(record.datas) except Exception,ex: # ignore any f*****g exceptions pass return result _columns = { 'datas_checksum': fields.function(_datas_checksum, size=40, string="Datas checksum", type='char', store=True, select=True), 'website_url': fields.function(_website_url_get, string="Attachment URL", type='char'), 'datas_big': fields.function (_datas_big, type='binary', store=True, string="Resized file content"), 'mimetype': fields.char('Mime Type', readonly=True), } def _add_mimetype_if_needed(self, values): if values.get('datas_fname'): values['mimetype'] = mimetypes.guess_type(values.get('datas_fname'))[0] or 'application/octet-stream' def create(self, cr, uid, values, context=None): chk = self._compute_checksum(values) if chk: match = self.search(cr, uid, [('datas_checksum', '=', chk)], context=context) if match: return match[0] self._add_mimetype_if_needed(values) return super(ir_attachment, self).create( cr, uid, values, context=context)
class sale_order(osv.osv): _name = "sale.order" _inherit = "sale.order" _columns = { 'express_ids': fields.related('order_line', 'express_id', type='many2one', relation='sale.coe', string=u'TMI_JDI收货人'), 'tmi_jdi_nos': fields.related('order_line', 'tmi_jdi_no', type='char', string='TMI_JDI_NO'), 'is_set_seq': fields.boolean('Set Sequence',default=False, readonly=True), 'selected': fields.boolean('Selected'), 'shop_id': fields.many2one('loewieec.shop', string=u"EC店铺名", readonly=True), 'sale_code': fields.char(u'EC单号', readonly=True), 'order_state': fields.selection([ ('WAIT_SELLER_SEND_GOODS', u'等待卖家发货'), ('WAIT_BUYER_CONFIRM_GOODS', u'等待买家确认收货'), ('TRADE_FINISHED', u'交易成功'), ('TRADE_CLOSED', u'交易关闭'), ], u'订单状态'), } def update_orders_seller_memo(self, cr, uid, ids, context=None): sale_order_obj = self.pool.get('sale.order').browse(cr,uid,ids[0],context=context) shop = sale_order_obj.shop_id if not shop : return False if shop.code == 'JDI' : raise osv.except_osv(u'错误',u'''JDI京东国际订单无需更新备注''') return False statement = "select tmi_jdi_no from sale_order_line where order_id=%d group by tmi_jdi_no" % ids[0] cr.execute(statement) tids = [item[0] for item in cr.fetchall()] if not tids : return False return shop.update_orders_seller_memo(context=context, tids=tids) def delete_lines_of_tmijdi_no(self, cr, uid, ids, context=None): # 完整删除 天猫京东 订单的 行 sale_order_obj = self.pool.get('sale.order').browse(cr,uid,ids[0],context=context) note = sale_order_obj.note or '' tmijdi_nos = note.strip().split(',') tmijdi_no_list = [] for tmijdi_no in tmijdi_nos: if tmijdi_no.strip() != '': tmijdi_no_list.append( tmijdi_no.strip() ) statement = "delete from sale_order_line where order_id=%d and tmi_jdi_no in (%s)" % ( ids[0], ("'" + """','""".join(tmijdi_no_list) + "'") ) cr.execute(statement) val = val1 = 0.0 cur = sale_order_obj.pricelist_id.currency_id for line in sale_order_obj.order_line: val1 += line.price_subtotal val += self._amount_line_tax(cr, uid, line, context=context) cur_obj = self.pool.get('res.currency') amount_tax = cur_obj.round(cr, uid, cur, val) amount_untaxed = cur_obj.round(cr, uid, cur, val1) amount_total = amount_untaxed + amount_tax sale_order_obj.write({'amount_tax':amount_tax, 'amount_untaxed': amount_untaxed,'amount_total':amount_total}) def update_waybill_no(self, cr, uid, ids, context=None): sale_order_obj = self.pool.get('sale.order').browse(cr,uid,ids[0],context=context) shop = sale_order_obj.shop_id if not shop : return False if shop.code == 'JDI' : return shop.jdi_order_delivery(salesorder=sale_order_obj, context=context) return shop.update_tmall_waybill(context=context, salesorder=sale_order_obj) def string_refactor(self, name): if not name: return False name = name.replace("/","%") name = name.replace("|","%") ll = name.split("-") ll = [l.strip() for l in ll] ll = "%".join(ll) return ll.replace(" ","%") def get_express_data(self, cr, uid, ids, context=None): sale_coe_obj = self.pool.get('sale.coe') express_ids = sale_coe_obj.search(cr,uid,[('sale_id','=',ids[0])],context=context) if len(express_ids)<1: return False note = "" for express in sale_coe_obj.browse(cr,uid,express_ids,context=context): if not express.name : continue name = express.name express_no = express.express_no or 'none' expresser = express.expresser and express.expresser.name or 'none' tmp_str = name + "," + expresser + "," + express_no + chr(10) note += tmp_str sale_order_obj = self.pool.get('sale.order').browse(cr,uid,ids[0],context=context) note_tmp = sale_order_obj.note or '.' sale_order_obj.note = note + note_tmp return True def view_express_data(self, cr, uid, ids, context=None): sale_order_obj = self.pool.get('sale.order').browse(cr,uid,ids[0],context=context) if not sale_order_obj : raise osv.except_osv(u'Sale order 错误',u'''请先保存销售单草稿''') return False #express_ids = sale_coe_obj.search(cr,uid,[('sale_id','=',ids[0])],context=context) sale_order_line_ids = self.pool.get('sale.order.line').search(cr,uid,[('order_id','=',ids[0])],context=context) if len(sale_order_line_ids)< 1: return False eids = self.pool.get('sale.order.line').read(cr,uid,sale_order_line_ids,['express_id'],context=context) #if len(eids) < 1: return False express_ids = [ eid['express_id'] and eid['express_id'][0] for eid in eids ] customer_id = sale_order_obj.partner_id.id sale_coe_obj = self.pool.get('sale.coe') if len(express_ids)>0: for express_obj in sale_coe_obj.browse(cr,uid,express_ids,context=context): express_obj.sale_id = ids[0] express_obj.customer = customer_id mod_obj = self.pool.get('ir.model.data') act_obj = self.pool.get('ir.actions.act_window') result = mod_obj.get_object_reference(cr, uid, 'loewieec_sync_sz', 'action_loewieec_salecoe') id = result and result[1] or False result = act_obj.read(cr, uid, [id], context=context)[0] result['domain'] = [('id','in',express_ids)] result['res_id'] = express_ids result['context'] = {'default_sale_id':ids[0],'default_customer':customer_id} return result def import_orders_from_note(self, cr, uid, ids, context=None): sale_order_obj = self.pool.get('sale.order').browse(cr,uid,ids[0],context=context) if sale_order_obj.shop_id or sale_order_obj.partner_id.name in [u'TMI天猫国际', u'天猫乐易成人用品专营店'] : return self.import_tmall_csv_file(cr, uid, ids, context=context) # 2边ERP统一收货人信息 的 导入方式 为 从附件导入 #return self.import_tmall_consignee_from_note(cr, uid, ids, context=context, order=sale_order_obj) if not sale_order_obj : raise osv.except_osv(u'Sale order 错误',u'''请先保存销售单草稿''') return False customer_id = sale_order_obj.partner_id.id carrier_obj = self.pool.get('loewie.carrier') coe_obj = self.pool.get('sale.coe') note = sale_order_obj.note.strip() lines = [ o.split(u',') for o in note.split(chr(10))] express_ids = [] pay_way = {'we_pay':u'包邮' , 'customer_pay': u'到付', 'cash_pay': u'现付'} for line in lines: if len(line) < 4 : continue if len(line) != 6 or not line[3].strip().isdigit() or line[2].strip().isdigit(): raise osv.except_osv(u'格式错误',','.join(line) + chr(10) + chr(10) + u"正确格式例子:姓名,手机号码,地址,邮编,韵达,现付" ) vals = { 'sale_id': ids[0], 'customer': customer_id, 'name':line[0].strip(), 'mobile':line[1].strip(), 'address':line[2].strip(), 'zip':line[3].strip(), 'price':6, } express_id = coe_obj.search(cr, uid, [('name','=',vals["name"]),('mobile','=',vals['mobile']),('sale_id','=',ids[0])], context=context) express_id = express_id and express_id[0] or 0 if not express_id : way = len(line)>5 and line[5] or '' way = way.strip() way_erp = '' for key in pay_way.keys(): if pay_way[key] == way : way_erp = key if way_erp in pay_way.keys(): vals.update({'pay_way':way_erp}) expresser = line[4] or '' carrier_id = carrier_obj.search(cr,uid,[('name','=',expresser.strip())],context=context) carrier_id = carrier_id and carrier_id[0] or 0 if carrier_id : vals.update({'expresser':carrier_id}) express_id = coe_obj.create(cr, uid, vals, context=context) express_ids.append(express_id) if len(express_ids) != 1: return True for product in sale_order_obj.order_line: product.express_id = express_ids[0] return True def import_tmall_consignee_from_note(self, cr, uid, ids, context=None,order=None): sale_order_obj = order if not sale_order_obj : raise osv.except_osv(u'Sale order 错误',u'''请先保存销售单草稿''') customer_id = sale_order_obj.partner_id.id carrier_obj = self.pool.get('loewie.carrier') coe_obj = self.pool.get('sale.coe') lines = [ o.split(chr(9)) for o in sale_order_obj.note.split(chr(10))] statement = "select tmi_jdi_no from sale_order_line where order_id=%d group by tmi_jdi_no" % ids[0] cr.execute(statement) tids = [item[0] for item in cr.fetchall()] lost_tids = [] express_ids = {} pay_way = {'we_pay':u'包邮' , 'customer_pay': u'到付', 'cash_pay': u'现付'} for line in lines: if len(line) < 4 : continue tmino = line[0].strip() if len(line) != 4 or not tmino.isdigit() or line[1].strip().isdigit() or line[2].strip().isdigit(): raise osv.except_osv(u'格式错误',','.join(line) + chr(10) + chr(10) + u'正确格式:订单编号,收件人姓名,收件地址,收件人手机号码') if tmino not in tids : # 如果销售订单行中 天猫单号不在 lost_tids.append(tmino) continue vals = { 'sale_id': ids[0], 'customer': customer_id, 'tmi_jdi_no': tmino, 'name':line[1].strip(), 'mobile':line[3].strip(), 'address':line[2].strip(), #'zip':line[4].strip(), 'expresser':3, 'pay_way':'cash_pay', 'price':6, } express_id = coe_obj.search(cr, uid, [('name','=',vals["name"]),('mobile','=',vals['mobile']),('sale_id','=',ids[0])], context=context) express_id = express_id and express_id[0] or 0 if not express_id : express_id = coe_obj.create(cr, uid, vals, context=context) express_ids[vals['tmi_jdi_no']] = express_id for product in sale_order_obj.order_line: tmi_no = product.tmi_jdi_no.strip() if tmi_no in express_ids.keys(): product.express_id = express_ids[tmi_no] if lost_tids : note = sale_order_obj.note or '-' note_tmp = u"销售单中不存在以下电商单号:" + ",".join(lost_tids) + chr(10) sale_order_obj.note = note_tmp + note return True def set_line_express_id(self, cr, uid, ids, context=None): sale_order_obj = self.pool.get('sale.order').browse(cr,uid,ids[0],context=context) express_ids = self.pool.get('sale.coe').search(cr,uid,[('sale_id','=',ids[0])],context=context) express_id = len(express_ids)==1 and express_ids[0] or 0 if not express_id : return False for product in sale_order_obj.order_line: product.express_id = express_id return True def split_address(self, address): assert address != None addr_list = address.split(" ",2) if len(addr_list) < 3: return None length = len( addr_list[2] ) for i in range( length-1, 0, -1 ): if addr_list[2][i] == '(': break addr = addr_list[2][0:i] zip = addr_list[2][i+1: length-1] return {'province':addr_list[0],'city':addr_list[1],'address':addr,'zip':zip} def get_full_path(self, cr, uid, path): # sanitize ath path = re.sub('[.]', '', path) path = path.strip('/\\') return os.path.join(tools.config.filestore(cr.dbname), path) def import_tmall_csv_file(self, cr, uid, ids, context=None): attachment_obj = self.pool.get('ir.attachment') shop_attach_id = context.get('res_id') shop_attach_id = shop_attach_id or ids[0] attachment_id = attachment_obj.search(cr,uid,[('res_id', '=', shop_attach_id)], context=context) if len(attachment_id)<1: return False attach = attachment_obj.browse(cr,uid,attachment_id[0],context=context) fname = attach.store_fname display_name = attach.name if not fname : return False fname = self.get_full_path(cr, uid, fname) csvfile = file(fname, 'rb') coe_obj = self.pool.get('sale.coe') tmi_no = {} no_coe_list = [] statement = 'select tmi_jdi_no from sale_order_line where order_id=%d group by tmi_jdi_no' % ids[0] cr.execute(statement) tmi_jdi_no_list = [ str(item[0]).strip() for item in cr.fetchall() ] sale_id = ids[0] #for line in reader: for cols in csvfile.readlines(): cols = cols.decode('gbk') cols = cols.split(",") line = [ col.replace('"','').strip() for col in cols ] line[0] = line[0].replace('=','').strip() if line[0] == u'订单编号' and line[1] == u'买家会员名' or line[0] not in tmi_jdi_no_list : continue #coeids = coe_obj.search(cr,uid,[('name','=',line[12]),('address','=',addr and addr2 or line[13]),('tel','=',phone)],context=context) coeids = coe_obj.search(cr,uid,[('tmi_jdi_no','=',line[0])],context=context) coeid = coeids and coeids[0] or 0 if not coeid : addr = self.split_address(line[13]) addr2 = addr['province'] + ',' + addr['city'] + ',' + addr['address'] phone = line[16].replace("'","") phone = phone.strip() if addr : coe_info = {'tmi_jdi_no':line[0], 'name':line[12], 'receive_name':line[12], 'mobile':phone, 'tel':phone, 'address':addr2, 'province':addr['province'], 'city':addr['city'], 'zip':addr['zip']} else: coe_info = {'tmi_jdi_no':line[0], 'name':line[12], 'receive_name':line[12], 'mobile':phone, 'tel':phone, 'address':line[13]} coeid = coe_obj.create( cr, uid, coe_info, context=context ) tmi_no[line[0]] = coeid sale_order = self.pool.get('sale.order').browse(cr,uid,ids[0],context=context) coe_in_sale = [] for line in sale_order.order_line: tmi_jdi_no = line.tmi_jdi_no and line.tmi_jdi_no.strip() or '' if not tmi_jdi_no : continue if tmi_jdi_no in tmi_no.keys(): line.write( {'express_id': tmi_no[tmi_jdi_no]} ) # 深圳ERP中为 line.express_id 而香港ERP为 line.coe_no coe_in_sale.append(tmi_jdi_no) #_logger.info( "Jimmy: have such a order:%s, and coeid:%d " % ( tmi_jdi_no, tmi_no[tmi_jdi_no]) ) #tmi_no[tmi_jdi_no] = 0 # 这里有问题, 如果一个 电商订单有几个产品,则只有第一个产品行 会被添加 coe 条目id else: no_coe_list.append(tmi_jdi_no) if no_coe_list : log = sale_order.note or '' sale_order.note = u'以下销售订单行的TMI_NO在CSV文件中不存在:' + chr(10) + ",".join(no_coe_list) + chr(10) + log not_in_tmi_no = [] for key in tmi_no.keys(): if key not in coe_in_sale: not_in_tmi_no.append(key) if not_in_tmi_no : log = sale_order.note or '' sale_order.note = u"以下CSV内的 '订单编号' 无法匹配到 销售订单行:" + chr(10) + ",".join( not_in_tmi_no ) # + chr(10) + log # #_logger.info( "Jimmy: OK....") return True
class crea8s_repair(osv.osv): _name = "crea8s.repair" _inherit = ['mail.thread', 'ir.needaction_mixin'] def compute_total(self, cr, uid, ids, field_names, arg=None, context=None, query='', query_params=()): result = 0 res = {} for record in self.browse(cr, uid, ids): result = record.labor_charge + record.trans_charge + sum([x.amount for x in record.repair_line]) res[record.id] = result return res def onchange_customer(self,cr, uid, ids, customer_id): partner_obj = self.pool.get('res.partner.repair') partner_br = partner_obj.browse(cr, uid, customer_id) return {'value': {'unit_no': partner_br.unit_no and partner_br.unit_no or '', 'pos_code': partner_br.postal_code and partner_br.postal_code or '', 'block': partner_br.name and partner_br.name or '',}} _columns = { 'name': fields.char('Job Number', size=128), 'customer_id': fields.many2one('res.partner', 'Customer'), 'cus_repair_id': fields.many2one('res.partner.repair', 'Customer'), 'block': fields.char('Block and Street', size=256), #related('cus_repair_id','block', type='char', store=True, string='Block'), 'pos_code': fields.char('Postal Code', size=128), 'unit_no': fields.char('Unit No', size=128), #related('cus_repair_id','postal_code', type='char', store=True, string='Postal Code'), 'dealer_id': fields.char('Dealer', size=256), 'telephone1': fields.related('cus_repair_id','telephone1', type='char', string='Telephone', store=True), 'telephone2': fields.related('cus_repair_id','telephone2', type='char', string='2'), 'telephone3': fields.related('cus_repair_id','telephone3', type='char', string='3'), 'date': fields.date('Date'), 'appointment_date': fields.datetime('Appointment Date'), 'tech_person': fields.many2one('crea8s.repair.user', 'Technician'), 'model_no': fields.char('Model No', size=256), 'purchase_date': fields.char('Purchase Date', size=128), 'attend_by': fields.many2one('crea8s.repair.user', 'Attend By'), 'type': fields.selection([('INSTALLING', 'INSTALLING'), ('SERVICING', 'SERVICING')], 'Type'), 'description': fields.text('Description'), 'remark': fields.text('Remark'), 'trans_charge': fields.float('Transport Charge', digits=(16,2)), 'labor_charge': fields.float('Labour Charge', digits=(16,2)), 'subtotal_charge': fields.float('Sub-Total Charge', digits=(16,2)), #fields.function(compute_total, digits_compute=dp.get_precision('Account'), store=True, string='Sub-Total Charge'), 'state': fields.selection([('draft', 'Draft'), ('open', 'Open'), ('confirm', 'Confirm')], 'State'), 'repair_line': fields.one2many('crea8s.repair.line', 'repair_id', 'Repair Line'), 'is_cash': fields.boolean('CASH'), 'is_cheque': fields.boolean('CHEQUE'), 'cheque_num': fields.char('Cheque Number'), 'hide_remark': fields.text('Internal Remark'), 'amount_total': fields.function(compute_total, digits_compute=dp.get_precision('Account'), string='Total'), } def default_name(self, cr, uid, context={}): return self.pool.get('ir.sequence').get(cr, uid, 'crea8s.repair') or '/' _defaults = { 'date': lambda *a: time.strftime('%Y-%m-%d'), 'state': 'draft', 'name': '/', } def insert_telephone(self, cr, uid, ids, partner_id, telephone): partner_obj = self.pool.get('res.partner.repair') return partner_obj.write(cr, uid, partner_id, {'telephone1': telephone}) def get_partner(self, cr, uid, ids, partner_name, partner_unitno, telephone): partner_obj = self.pool.get('res.partner.repair') partner_id = partner_obj.search(cr, uid, [('name', '=',partner_name), ('unit_no', '=', partner_unitno)]) partner_id = partner_id and partner_id[0] or 0 if not partner_id: partner_id = partner_obj.search(cr, uid, [('name', '=',partner_name), ('telephone1', '=', telephone)]) partner_id = partner_id and partner_id[0] or 0 return partner_id def get_user(self, cr, uid, ids, user_name): user_obj = self.pool.get('crea8s.repair.user') user_id = user_obj.search(cr, uid, [('name', '=', user_name)]) user_id = user_id and user_id[0] or 0 if not user_id: user_id = user_obj.create(cr, uid, {'name': user_name}) return user_id def get_date(self, date_or): result = datetime.date(int(date_or[:4]), int(date_or[5:7]), int(date_or[8:10])) return result def get_date_time(self, date_or): result = datetime.datetime(int(date_or[:4]), int(date_or[5:7]), int(date_or[8:10]), int(date_or[11:13]), int(date_or[14:16]), int(date_or[17:19])) return result def get_state(self, cr, uid, ids, state): result = '' if state == 'Draft': result = 'draft' elif state == 'Open': result = 'open' else: result = 'confirm' return result def import_csv_file(self, cr, uid, ids, context={}): user_obj = self.pool.get('crea8s.repair.user') partner_obj = self.pool.get('res.partner.repair') for record in self.browse(cr, uid, ids): ifile = open('C:\\Users\\tri\\Desktop\\import\\July15\\import_fanco.csv', 'rb') reader = csv.reader(ifile) a = 0 for row in reader: a += 1 if a > 1: if 2>1: # try: cus_id = self.get_partner(cr, uid, ids, row[2], row[5], row[23]) attend_id = self.get_user(cr, uid, ids, row[1]) tech_id = self.get_user(cr, uid, ids, row[3]) vals_re = { 'name': row[4], 'cus_repair_id': cus_id, 'block': row[9], 'pos_code': row[19], 'unit_no': row[5], 'dealer_id': row[14], 'tech_person': tech_id, 'model_no': row[18], 'purchase_date': row[20], 'attend_by': attend_id, 'type': row[6], 'description': row[15], 'remark': row[21], 'trans_charge': row[24] and float(row[24]) or 0, 'labor_charge': row[17] and float(row[17]) or 0, 'subtotal_charge': row[22] and float(row[22]) or 0, 'state': self.get_state(cr, uid, ids, row[7]), 'is_cash': row[10], 'is_cheque': row[11], 'cheque_num': row[12], 'hide_remark': row[16],} if row[13]: vals_re.update({'date': self.get_date(row[13]),}) if row[8]: vals_re.update({'appointment_date': self.get_date_time(row[8])}) self.create(cr, uid, vals_re) # except: # print row[4], ' ', row[2], ' ', row[5], ' ', row[23] return 1 def create(self, cr, uid, vals, context={}): if vals.get('name', False) == '/': vals['name'] = self.default_name(cr, uid, context) return super(crea8s_repair, self).create(cr, uid, vals, context) def action_open(self, cr, uid, ids, context={}): self.write(cr, uid, ids, {'state': 'open'}) #print self.pool.get('res.partner.repair').search(cr, uid, []) return 1 def action_confirm(self, cr, uid, ids, context={}): self.write(cr, uid, ids, {'state': 'confirm'}) return 1 def action_cancel(self, cr, uid, ids, context={}): self.write(cr, uid, ids, {'state': 'draft'}) return 1 def button_dummy(self,cr, uid, ids, context={}): return 1
)[0] report = self.pool.get("ir.actions.report.xml").browse(cr, uid, rep_id, context=context) return report.report_name def print_invoice(self, cr, uid, ids, context=None): """ Method called by button print report in wizard, to print report in pdf @param self: The object pointer. @param cr: A database cursor @param uid: ID of the user currently logged in @param ids: Ids to invoice's to print ticket @param context: A standard dictionary @return : retrun report pdf generated """ if context is None: context = {} if len(context.get("active_ids", [])) > 1: return {} return { "type": "ir.actions.report.xml", "report_name": self._get_report_name(cr, uid, context=context), "datas": {"ids": context["active_ids"]}, } _columns = { "journal": fields.char("Journal", 64, readonly=True, requied=True), "report_format": fields.binary("Report", readonly=True, required=True), } _defaults = {"journal": _get_journal, "report_format": _get_report}
class crea8s_warranty(osv.osv): _name = "crea8s.warranty" _inherit = ['mail.thread', 'ir.needaction_mixin'] def compute_total(self, cr, uid, ids, field_names, arg=None, context=None, query='', query_params=()): result = 0 res = {} for record in self.browse(cr, uid, ids): result = record.labor_charge + record.trans_charge res[record.id] = result return res _columns = { 'name': fields.char('Warranty No', size=128), 'cus_war_id': fields.many2one('res.partner.repair', 'customer'), 'cus_name': fields.related('cus_war_id','type', type='char', string='''Customer's Name'''), 'block': fields.char('Block and Street', size=256), 'pos_code': fields.related('cus_war_id','postal_code', type='char', string='Postal Code'), 'street': fields.related('cus_war_id','name', type='char', string='Street Name'), 'unit_no': fields.related('cus_war_id','unit_no', type='char', string='Unit No.'), 'telephone': fields.related('cus_war_id','telephone1', type='char', string='Telephone'), 'telephone2': fields.related('cus_war_id','telephone2', type='char', string='2'), 'pur_inv_no': fields.char('Purchase Invoice No', size=256), 'model_no': fields.char('Model No.', size=256), 'purchase_date': fields.date('Date of Purchase'), 'install_date': fields.date('Date of Installation'), 'install_by': fields.char('Installed By', size=256), 'dealer_id': fields.many2one('res.partner', '''Dealer's Name'''), 'contact_no1': fields.char('Contact No.1', size=256), 'contact_no2': fields.char('Contact No.2', size=256), 'contact_no3': fields.char('Contact No.3', size=256), 'email': fields.related('cus_war_id','email', type='char', string='Email'), 'state': fields.selection([('draft', 'Draft'), ('open', 'Open'), ('confirm', 'Confirm')], 'State'), 'remark': fields.text('Remark'), } def default_name(self, cr, uid, context={}): return self.pool.get('ir.sequence').get(cr, uid, 'crea8s.warranty') or '/' _defaults = { 'purchase_date': lambda *a: time.strftime('%Y-%m-%d'), 'state': 'draft', 'name': '/', } def create(self, cr, uid, vals, context={}): if vals.get('name', False) == '/': vals['name'] = self.default_name(cr, uid, context) return super(crea8s_warranty, self).create(cr, uid, vals, context) def action_open(self, cr, uid, ids, context={}): self.write(cr, uid, ids, {'state': 'open'}) return 1 def action_confirm(self, cr, uid, ids, context={}): self.write(cr, uid, ids, {'state': 'confirm'}) return 1 def action_cancel(self, cr, uid, ids, context={}): self.write(cr, uid, ids, {'state': 'draft'}) return 1 def button_dummy(self,cr, uid, ids, context={}): return 1
class crea8s_repair_user(osv.osv): _name = "crea8s.repair.user" _columns = { 'name': fields.char('Name', size=256), }
class tms_expense_loan(osv.osv): _name = 'tms.expense.loan' _inherit = ['mail.thread', 'ir.needaction_mixin'] _description = 'TMS Driver Loan Mgmnt' def _balance(self, cr, uid, ids, field_name, args, context=None): res = {} for record in self.browse(cr, uid, ids, context=context): cr.execute('select sum(coalesce(price_total, 0.0))::float from tms_expense_line where loan_id = %s' % (record.id)) data = filter(None, map(lambda x:x[0], cr.fetchall())) or [0.0] res[record.id] = { 'balance' : record.amount + data[0], 'paid' : not (record.amount + data[0]) > 0, } return res def _get_loan_discounts_from_expense_lines(self, cr, uid, ids, context=None): expense_line = {} for line in self.pool.get('tms.expense.line').browse(cr, uid, ids, context=context): expense_line[line.loan_id.id] = True expense_line_ids = [] if expense_line: expense_line_ids = self.pool.get('tms.expense.loan').search(cr, uid, [('id','in',expense_line.keys())], context=context) return expense_line_ids _columns = { 'name' : fields.char('Name', size=64, select=True, readonly=True), 'description' : fields.char('Description', size=128, select=True, required=True, readonly=True, states={'draft':[('readonly',False)], 'approved':[('readonly',False)]}), 'date' : fields.date('Date', required=True, select=True, readonly=True, states={'draft':[('readonly',False)], 'approved':[('readonly',False)]}), 'employee_id' : fields.many2one('hr.employee', 'Driver', required=True, domain=[('tms_category', '=', 'driver')] , readonly=True, states={'draft':[('readonly',False)], 'approved':[('readonly',False)]}), 'expense_line_ids' : fields.one2many('tms.expense.line', 'loan_id', 'Expense Line', readonly=True), 'state' : fields.selection([ ('draft', 'Draft'), ('approved', 'Approved'), ('confirmed', 'Confirmed'), ('closed', 'Closed'), ('cancel', 'Cancelled') ], 'State', readonly=True, help="State of the Driver Loan. ", select=True), 'discount_method' : fields.selection([ ('each', 'Each Travel Expense Record'), ('weekly', 'Weekly'), ('fortnightly', 'Fortnightly'), ('monthly', 'Monthly'), ], 'Discount Method', readonly=True, states={'draft':[('readonly',False)], 'approved':[('readonly',False)]}, help="""Select Loan Recovery Method: - Weekly: Discount will be applied every week, considering only 4 weeks in each month - Fortnightly: Discount will be applied forthnightly, considering only 2 discounts in each month, applied the 14th and 28th day of the month. - Monthy: Discount will be applied only once a month, applied the 28th day of the month. . """, select=True, required=True), 'discount_type' : fields.selection([ ('fixed', 'Fixed'), ('percent', 'Loan Percentage'), ], 'Discount Type', readonly=True, states={'draft':[('readonly',False)], 'approved':[('readonly',False)]}, required=True, help="""Select Loan Recovery Type: - Fixed: Discount will a fixed amount - Percent: Discount will be a percentage of total Loan Amount """, select=True), 'notes' : fields.text('Notes'), 'origin' : fields.char('Source Document', size=64, help="Reference of the document that generated this Expense Record", readonly=True, states={'draft':[('readonly',False)], 'approved':[('readonly',False)]}), 'amount' : fields.float('Amount', digits_compute=dp.get_precision('Sale Price'), required=True, readonly=True, states={'draft':[('readonly',False)], 'approved':[('readonly',False)]}), 'percent_discount' : fields.float('Percent (%)', digits_compute=dp.get_precision('Sale Price'), required=False, help="Please set percent as 10.00%", readonly=True, states={'draft':[('readonly',False)], 'approved':[('readonly',False)]}), 'fixed_discount' : fields.float('Fixed Discount', digits_compute=dp.get_precision('Sale Price'), required=False, readonly=True, states={'draft':[('readonly',False)], 'approved':[('readonly',False)]}), 'balance' : fields.function(_balance, method=True, digits_compute=dp.get_precision('Sale Price'), string='Balance', type='float', multi=True, store={ 'tms.expense.loan': (lambda self, cr, uid, ids, c={}: ids, ['notes', 'amount','state','expense_line_ids'], 10), 'tms.expense.line': (_get_loan_discounts_from_expense_lines, ['product_uom_qty', 'price_unit'], 10), }), #store = {'tms.expense.line': (_get_loan_discounts_from_expense_lines, None, 50)}), 'paid' : fields.function(_balance, method=True, string='Paid', type='boolean', multi=True, store={ 'tms.expense.loan': (lambda self, cr, uid, ids, c={}: ids, ['notes','amount','state','expense_line_ids'], 10), 'tms.expense.line': (_get_loan_discounts_from_expense_lines, ['product_uom_qty', 'price_unit'], 10), }), #store = {'tms.expense.line': (_get_loan_discounts_from_expense_lines, None, 50)}), 'product_id' : fields.many2one('product.product', 'Discount Product', readonly=True, states={'draft':[('readonly',False)], 'approved':[('readonly',False)]}, required=True, domain=[('tms_category', '=', ('salary_discount'))], ondelete='restrict'), 'shop_id' : fields.related('employee_id', 'shop_id', type='many2one', relation='sale.shop', string='Shop', store=True, readonly=True), 'company_id' : fields.related('shop_id', 'company_id', type='many2one', relation='res.company', string='Company', store=True, readonly=True), 'create_uid' : fields.many2one('res.users', 'Created by', readonly=True), 'create_date' : fields.datetime('Creation Date', readonly=True, select=True), 'cancelled_by' : fields.many2one('res.users', 'Cancelled by', readonly=True), 'date_cancelled': fields.datetime('Date Cancelled', readonly=True), 'approved_by' : fields.many2one('res.users', 'Approved by', readonly=True), 'date_approved' : fields.datetime('Date Approved', readonly=True), 'confirmed_by' : fields.many2one('res.users', 'Confirmed by', readonly=True), 'date_confirmed': fields.datetime('Date Confirmed', readonly=True), 'closed_by' : fields.many2one('res.users', 'Closed by', readonly=True), 'date_closed' : fields.datetime('Date Closed', readonly=True), } _defaults = { 'date' : lambda *a: time.strftime(DEFAULT_SERVER_DATE_FORMAT), 'state' : lambda *a: 'draft', } _sql_constraints = [ ('name_uniq', 'unique(name)', 'Loan record must be unique !'), ] def create(self, cr, uid, vals, context=None): values = vals if 'employee_id' in vals and vals['employee_id']: employee = self.pool.get('hr.employee').browse(cr, uid, [vals['employee_id']])[0] seq_id = employee.shop_id.tms_loan_seq.id if seq_id: seq_number = self.pool.get('ir.sequence').get_id(cr, uid, seq_id) values['name'] = seq_number else: raise osv.except_osv(_('Loan Sequence Error !'), _('You have not defined Loan Sequence for shop ' + employee.shop_id.name)) return super(tms_expense_loan, self).create(cr, uid, values, context=context) def action_approve(self, cr, uid, ids, context=None): for rec in self.browse(cr, uid, ids, context=context): if rec.amount <= 0.0: raise osv.except_osv( _('Could not approve Loan !'), _('Amount must be greater than zero.')) self.write(cr, uid, ids, {'state':'approved', 'approved_by' : uid, 'date_approved':time.strftime(DEFAULT_SERVER_DATETIME_FORMAT)}) for (id,name) in self.name_get(cr, uid, ids): message = _("Loan '%s' is set to Approved.") % name self.log(cr, uid, id, message) return True def action_confirm(self, cr, uid, ids, context=None): for rec in self.browse(cr, uid, ids, context=context): self.write(cr, uid, ids, {'state':'confirmed', 'confirmed_by' : uid, 'date_confirmed':time.strftime(DEFAULT_SERVER_DATETIME_FORMAT)}) for (id,name) in self.name_get(cr, uid, ids): message = _("Loan '%s' is set to Confirmed.") % name self.log(cr, uid, id, message) return True def action_cancel(self, cr, uid, ids, context=None): for rec in self.browse(cr, uid, ids, context=context): self.write(cr, uid, ids, {'state':'cancel', 'cancelled_by' : uid, 'date_cancelled':time.strftime(DEFAULT_SERVER_DATETIME_FORMAT)}) for (id,name) in self.name_get(cr, uid, ids): message = _("Loan '%s' is set to Cancel.") % name self.log(cr, uid, id, message) return True def action_close(self, cr, uid, ids, context=None): for rec in self.browse(cr, uid, ids, context=context): self.write(cr, uid, ids, {'state':'closed', 'closed_by' : uid, 'date_closed':time.strftime(DEFAULT_SERVER_DATETIME_FORMAT)}) for (id,name) in self.name_get(cr, uid, ids): message = _("Loan '%s' is set to Closed even when it is not paid.") % name if rec.balance > 0.0 else _("Loan '%s' is set to Closed.") % name self.log(cr, uid, id, message) return True def get_loan_discounts(self, cr, uid, employee_id, expense_id, context=None): expense_line_obj = self.pool.get('tms.expense.line') expense_obj = self.pool.get('tms.expense') res = expense_line_obj.search(cr, uid, [('expense_id', '=', expense_id),('control','=', 1),('loan_id','!=',False)]) #print "res: ", res if len(res): loan_ids = [] expense_line_ids = [] for x in expense_obj.browse(cr, uid, [expense_id])[0].expense_line: if x.loan_id.id: loan_ids.append(x.loan_id.id) expense_line_ids.append(x.id) if len(loan_ids): expense_line_obj.unlink(cr, uid, expense_line_ids) self.write(cr, uid,loan_ids, {'state':'confirmed', 'closed_by' : False, 'date_closed':False} ) prod_obj = self.pool.get('product.product') loan_ids = self.search(cr, uid, [('employee_id', '=', employee_id),('state','=','confirmed'),('balance', '>', 0.0)]) flag_each = True fecha_liq = expense_obj.read(cr, uid, [expense_id], ['date'])[0]['date'] for rec in self.browse(cr, uid, loan_ids, context=context): if rec.discount_method in ('weekly','fortnightly','monthy'): cr.execute('select date from tms_expense_line where loan_id = %s order by date desc limit 1' % (rec.id)) data = filter(None, map(lambda x:x[0], cr.fetchall())) date = data[0] if data else rec.date #print "fecha_liq: ", fecha_liq dur = datetime.strptime(fecha_liq, '%Y-%m-%d') - datetime.strptime(date, '%Y-%m-%d') product = prod_obj.browse(cr, uid, [rec.product_id.id])[0] xfactor = 7 if rec.discount_method == 'weekly' else 14.0 if rec.discount_method == 'fortnightly' else 28.0 rango = 1 if not int(dur.days / xfactor) else int(dur.days / xfactor) + 1 balance = rec.balance while rango and balance: rango -= 1 discount = rec.fixed_discount if rec.discount_type == 'fixed' else rec.amount * rec.percent_discount / 100.0 discount = balance if discount > balance else discount balance -= discount xline = { 'expense_id' : expense_id, 'line_type' : product.tms_category, 'name' : product.name + ' - ' + rec.name, 'sequence' : 100, 'product_id' : product.id, 'product_uom' : product.uom_id.id, 'product_uom_qty' : 1, 'price_unit' : discount * -1.0, 'control' : True, 'loan_id' : rec.id, #'operation_id' : travel.operation_id.id, #'tax_id' : [(6, 0, [x.id for x in product.supplier_taxes_id])], } res = expense_line_obj.create(cr, uid, xline) if discount >= rec.balance: self.write(cr, uid, [rec.id], {'state':'closed', 'closed_by' : uid, 'date_closed':time.strftime(DEFAULT_SERVER_DATETIME_FORMAT)}) for (id,name) in self.name_get(cr, uid, [rec.id]): message = _("Loan '%s' has been Closed.") % rec.name self.log(cr, uid, id, message) elif rec.discount_method == 'each' and flag_each: # Buscaoms el ultimo descuento de prestamo de tipo "En cada liquidacion" cr.execute("""select date from tms_expense_line where loan_id in (select id from tms_expense_loan where employee_id=%s and discount_method='each' and state in ('closed','confirmed')) order by date desc limit 1; """ % (rec.employee_id.id)) data = filter(None, map(lambda x:x[0], cr.fetchall())) date = data and data[0] or rec.date if date >= fecha_liq: continue flag_each = False cr.execute('select date from tms_expense_line where loan_id = %s order by date desc limit 1' % (rec.id)) data = filter(None, map(lambda x:x[0], cr.fetchall())) date = data[0] if data else rec.date #print "fecha_liq: ", fecha_liq dur = datetime.strptime(fecha_liq, '%Y-%m-%d') - datetime.strptime(date, '%Y-%m-%d') product = prod_obj.browse(cr, uid, [rec.product_id.id])[0] balance = rec.balance discount = rec.fixed_discount if rec.discount_type == 'fixed' else rec.amount * rec.percent_discount / 100.0 discount = balance if discount > balance else discount balance -= discount xline = { 'expense_id' : expense_id, 'line_type' : product.tms_category, 'name' : product.name + ' - ' + rec.name, 'sequence' : 100, 'product_id' : product.id, 'product_uom' : product.uom_id.id, 'product_uom_qty' : 1, 'price_unit' : discount * -1.0, 'control' : True, 'loan_id' : rec.id, #'operation_id' : travel.operation_id.id, #'tax_id' : [(6, 0, [x.id for x in product.supplier_taxes_id])], } res = expense_line_obj.create(cr, uid, xline) if discount >= rec.balance: self.write(cr, uid, [rec.id], {'state':'closed', 'closed_by' : uid, 'date_closed':time.strftime(DEFAULT_SERVER_DATETIME_FORMAT)}) for (id,name) in self.name_get(cr, uid, [rec.id]): message = _("Loan '%s' has been Closed.") % rec.name self.log(cr, uid, id, message) return
class crm_stage(osv.Model): """ Model for case stages. This models the main stages of a document management flow. Main CRM objects (leads, opportunities, project issues, ...) will now use only stages, instead of state and stages. Stages are for example used to display the kanban view of records. """ _name = "crm.stage" _description = "Stage of case" _rec_name = 'name' _order = "sequence" _columns = { 'name': fields.char('Stage Name', required=True, translate=True), 'sequence': fields.integer('Sequence', help="Used to order stages. Lower is better."), 'probability': fields.float( 'Probability (%)', required=True, help= "This percentage depicts the default/average probability of the Case for this stage to be a success" ), 'on_change': fields.boolean( 'Change Probability Automatically', help= "Setting this stage will change the probability automatically on the opportunity." ), 'requirements': fields.text('Requirements'), 'team_ids': fields.many2many( 'crm.team', 'crm_team_stage_rel', 'stage_id', 'team_id', string='Teams', help= "Link between stages and sales teams. When set, this limitate the current stage to the selected sales teams." ), 'case_default': fields.boolean( 'Default to New Sales Team', help= "If you check this field, this stage will be proposed by default on each sales team. It will not assign this stage to existing teams." ), 'legend_priority': fields.text( 'Priority Management Explanation', translate=True, help= 'Explanation text to help users using the star and priority mechanism on stages or issues that are in this stage.' ), 'fold': fields.boolean('Folded in Kanban View', help='This stage is folded in the kanban view when' 'there are no records in that stage to display.'), 'type': fields.selection( [('lead', 'Lead'), ('opportunity', 'Opportunity'), ('both', 'Both')], string='Type', required=True, help= "This field is used to distinguish stages related to Leads from stages related to Opportunities, or to specify stages available for both types." ), } _defaults = { 'sequence': 1, 'probability': 0.0, 'on_change': True, 'fold': False, 'type': 'both', 'case_default': True, }
class contract_init(orm.Model): _name = 'hr.contract.init' _description = 'Initial Contract Settings' _inherit = 'ir.needaction_mixin' _columns = { 'name': fields.char( 'Name', size=64, required=True, readonly=True, states={'draft': [('readonly', False)]}, ), 'date': fields.date( 'Effective Date', required=True, readonly=True, states={'draft': [('readonly', False)]}, ), 'wage_ids': fields.one2many( 'hr.contract.init.wage', 'contract_init_id', 'Starting Wages', readonly=True, states={'draft': [('readonly', False)]}, ), 'struct_id': fields.many2one( 'hr.payroll.structure', 'Payroll Structure', readonly=True, states={'draft': [('readonly', False)]}, ), 'trial_period': fields.integer( 'Trial Period', readonly=True, states={'draft': [('readonly', False)]}, help="Length of Trial Period, in days", ), 'active': fields.boolean('Active', ), 'state': fields.selection( [ ('draft', 'Draft'), ('approve', 'Approved'), ('decline', 'Declined'), ], 'State', readonly=True, ), } _defaults = { 'trial_period': 0, 'active': True, 'state': 'draft', } # Return records with latest date first _order = 'date desc' def _needaction_domain_get(self, cr, uid, context=None): users_obj = self.pool.get('res.users') if users_obj.has_group(cr, uid, 'base.group_hr_director'): domain = [('state', 'in', ['draft'])] return domain return False def unlink(self, cr, uid, ids, context=None): if isinstance(ids, (int, long)): ids = [ids] data = self.read(cr, uid, ids, ['state'], context=context) for d in data: if d['state'] in ['approve', 'decline']: raise orm.except_orm( _('Error'), _('You may not a delete a record that is not in a ' '"Draft" state')) return super(contract_init, self).unlink(cr, uid, ids, context=context) def set_to_draft(self, cr, uid, ids, context=None): self.write(cr, uid, ids, { 'state': 'draft', }, context=context) wf_service = netsvc.LocalService("workflow") for i in ids: wf_service.trg_delete(uid, 'hr.contract.init', i, cr) wf_service.trg_create(uid, 'hr.contract.init', i, cr) return True def state_approve(self, cr, uid, ids, context=None): self.write(cr, uid, ids, {'state': 'approve'}, context=context) return True def state_decline(self, cr, uid, ids, context=None): self.write(cr, uid, ids, {'state': 'decline'}, context=context) return True
try: file_data = image_file.read() self._logo_image = base64.encodestring(file_data) return self._logo_image finally: image_file.close() else: self._logo_image = base64.encodestring(im.read()) return self._logo_image def _get_image_fn(self, cr, uid, ids, name, args, context=None): image = self._get_image(cr, uid, context) return dict.fromkeys(ids, image) # ok to use .fromkeys() as the image is same for all _columns = { 'soffice': fields.char('Path to LibreOffice executable', size=256, required=True), 'dir_tmp': fields.char('Temp directory', size=256, required=True), 'state': fields.selection([ ('init', 'Init'), ('error', 'Error'), ('done', 'Done') ], 'State', select=True, readonly=True), 'msg': fields.text('Message', readonly=True), 'error_details': fields.text('Error Details', readonly=True), 'config_logo': fields.function(_get_image_fn, string='Image', type='binary', method=True) } def default_get(self, cr, uid, fields, context=None): values = super(AerooConfigInstaller, self).default_get(cr, uid, fields, context=context) if platform == "linux" or platform == "linux2": # linux
class hr_timesheet_sheet(osv.osv): _name = "hr_timesheet_sheet.sheet" _inherit = "mail.thread" _table = 'hr_timesheet_sheet_sheet' _order = "id desc" _description="Timesheet" def _total(self, cr, uid, ids, name, args, context=None): """ Compute the attendances, analytic lines timesheets and differences between them for all the days of a timesheet and the current day """ res = {} for sheet in self.browse(cr, uid, ids, context=context or {}): res.setdefault(sheet.id, { 'total_attendance': 0.0, 'total_timesheet': 0.0, 'total_difference': 0.0, }) for period in sheet.period_ids: res[sheet.id]['total_attendance'] += period.total_attendance res[sheet.id]['total_timesheet'] += period.total_timesheet res[sheet.id]['total_difference'] += period.total_attendance - period.total_timesheet return res def check_employee_attendance_state(self, cr, uid, sheet_id, context=None): ids_signin = self.pool.get('hr.attendance').search(cr,uid,[('sheet_id', '=', sheet_id),('action','=','sign_in')]) ids_signout = self.pool.get('hr.attendance').search(cr,uid,[('sheet_id', '=', sheet_id),('action','=','sign_out')]) if len(ids_signin) != len(ids_signout): raise osv.except_osv(('Warning!'),_('The timesheet cannot be validated as it does not contain an equal number of sign ins and sign outs.')) return True def copy(self, cr, uid, ids, *args, **argv): raise osv.except_osv(_('Error!'), _('You cannot duplicate a timesheet.')) def create(self, cr, uid, vals, *args, **argv): if 'employee_id' in vals: if not self.pool.get('hr.employee').browse(cr, uid, vals['employee_id']).user_id: raise osv.except_osv(_('Error!'), _('In order to create a timesheet for this employee, you must link him/her to a user.')) if not self.pool.get('hr.employee').browse(cr, uid, vals['employee_id']).product_id: raise osv.except_osv(_('Error!'), _('In order to create a timesheet for this employee, you must link the employee to a product, like \'Consultant\'.')) if not self.pool.get('hr.employee').browse(cr, uid, vals['employee_id']).journal_id: raise osv.except_osv(_('Configuration Error!'), _('In order to create a timesheet for this employee, you must assign an analytic journal to the employee, like \'Timesheet Journal\'.')) return super(hr_timesheet_sheet, self).create(cr, uid, vals, *args, **argv) def write(self, cr, uid, ids, vals, *args, **argv): if 'employee_id' in vals: new_user_id = self.pool.get('hr.employee').browse(cr, uid, vals['employee_id']).user_id.id or False if not new_user_id: raise osv.except_osv(_('Error!'), _('In order to create a timesheet for this employee, you must link him/her to a user.')) if not self._sheet_date(cr, uid, ids, forced_user_id=new_user_id): raise osv.except_osv(_('Error!'), _('You cannot have 2 timesheets that overlap!\nYou should use the menu \'My Timesheet\' to avoid this problem.')) if not self.pool.get('hr.employee').browse(cr, uid, vals['employee_id']).product_id: raise osv.except_osv(_('Error!'), _('In order to create a timesheet for this employee, you must link the employee to a product.')) if not self.pool.get('hr.employee').browse(cr, uid, vals['employee_id']).journal_id: raise osv.except_osv(_('Configuration Error!'), _('In order to create a timesheet for this employee, you must assign an analytic journal to the employee, like \'Timesheet Journal\'.')) return super(hr_timesheet_sheet, self).write(cr, uid, ids, vals, *args, **argv) def button_confirm(self, cr, uid, ids, context=None): for sheet in self.browse(cr, uid, ids, context=context): if sheet.employee_id and sheet.employee_id.parent_id and sheet.employee_id.parent_id.user_id: self.message_subscribe_users(cr, uid, [sheet.id], user_ids=[sheet.employee_id.parent_id.user_id.id], context=context) self.check_employee_attendance_state(cr, uid, sheet.id, context=context) di = sheet.user_id.company_id.timesheet_max_difference if (abs(sheet.total_difference) < di) or not di: self.signal_confirm(cr, uid, [sheet.id]) else: raise osv.except_osv(_('Warning!'), _('Please verify that the total difference of the sheet is lower than %.2f.') %(di,)) return True def attendance_action_change(self, cr, uid, ids, context=None): hr_employee = self.pool.get('hr.employee') employee_ids = [] for sheet in self.browse(cr, uid, ids, context=context): if sheet.employee_id.id not in employee_ids: employee_ids.append(sheet.employee_id.id) return hr_employee.attendance_action_change(cr, uid, employee_ids, context=context) _columns = { 'name': fields.char('Note', size=64, select=1, states={'confirm':[('readonly', True)], 'done':[('readonly', True)]}), 'employee_id': fields.many2one('hr.employee', 'Employee', required=True), 'user_id': fields.related('employee_id', 'user_id', type="many2one", relation="res.users", store=True, string="User", required=False, readonly=True),#fields.many2one('res.users', 'User', required=True, select=1, states={'confirm':[('readonly', True)], 'done':[('readonly', True)]}), 'date_from': fields.date('Date from', required=True, select=1, readonly=True, states={'new':[('readonly', False)]}), 'date_to': fields.date('Date to', required=True, select=1, readonly=True, states={'new':[('readonly', False)]}), 'timesheet_ids' : fields.one2many('hr.analytic.timesheet', 'sheet_id', 'Timesheet lines', readonly=True, states={ 'draft': [('readonly', False)], 'new': [('readonly', False)]} ), 'attendances_ids' : fields.one2many('hr.attendance', 'sheet_id', 'Attendances'), 'state' : fields.selection([ ('new', 'New'), ('draft','Open'), ('confirm','Waiting Approval'), ('done','Approved')], 'Status', select=True, required=True, readonly=True, help=' * The \'Draft\' status is used when a user is encoding a new and unconfirmed timesheet. \ \n* The \'Confirmed\' status is used for to confirm the timesheet by user. \ \n* The \'Done\' status is used when users timesheet is accepted by his/her senior.'), 'state_attendance' : fields.related('employee_id', 'state', type='selection', selection=[('absent', 'Absent'), ('present', 'Present')], string='Current Status', readonly=True), 'total_attendance': fields.function(_total, method=True, string='Total Attendance', multi="_total"), 'total_timesheet': fields.function(_total, method=True, string='Total Timesheet', multi="_total"), 'total_difference': fields.function(_total, method=True, string='Difference', multi="_total"), 'period_ids': fields.one2many('hr_timesheet_sheet.sheet.day', 'sheet_id', 'Period', readonly=True), 'account_ids': fields.one2many('hr_timesheet_sheet.sheet.account', 'sheet_id', 'Analytic accounts', readonly=True), 'company_id': fields.many2one('res.company', 'Company'), 'department_id':fields.many2one('hr.department','Department'), } def _default_date_from(self, cr, uid, context=None): user = self.pool.get('res.users').browse(cr, uid, uid, context=context) r = user.company_id and user.company_id.timesheet_range or 'month' if r=='month': return time.strftime('%Y-%m-01') elif r=='week': return (datetime.today() + relativedelta(weekday=0, days=-6)).strftime('%Y-%m-%d') elif r=='year': return time.strftime('%Y-01-01') return time.strftime('%Y-%m-%d') def _default_date_to(self, cr, uid, context=None): user = self.pool.get('res.users').browse(cr, uid, uid, context=context) r = user.company_id and user.company_id.timesheet_range or 'month' if r=='month': return (datetime.today() + relativedelta(months=+1,day=1,days=-1)).strftime('%Y-%m-%d') elif r=='week': return (datetime.today() + relativedelta(weekday=6)).strftime('%Y-%m-%d') elif r=='year': return time.strftime('%Y-12-31') return time.strftime('%Y-%m-%d') def _default_employee(self, cr, uid, context=None): emp_ids = self.pool.get('hr.employee').search(cr, uid, [('user_id','=',uid)], context=context) return emp_ids and emp_ids[0] or False _defaults = { 'date_from' : _default_date_from, 'date_to' : _default_date_to, 'state': 'new', 'employee_id': _default_employee, 'company_id': lambda self, cr, uid, c: self.pool.get('res.company')._company_default_get(cr, uid, 'hr_timesheet_sheet.sheet', context=c) } def _sheet_date(self, cr, uid, ids, forced_user_id=False, context=None): for sheet in self.browse(cr, uid, ids, context=context): new_user_id = forced_user_id or sheet.user_id and sheet.user_id.id if new_user_id: cr.execute('SELECT id \ FROM hr_timesheet_sheet_sheet \ WHERE (date_from <= %s and %s <= date_to) \ AND user_id=%s \ AND id <> %s',(sheet.date_to, sheet.date_from, new_user_id, sheet.id)) if cr.fetchall(): return False return True _constraints = [ (_sheet_date, 'You cannot have 2 timesheets that overlap!\nPlease use the menu \'My Current Timesheet\' to avoid this problem.', ['date_from','date_to']), ] def action_set_to_draft(self, cr, uid, ids, *args): self.write(cr, uid, ids, {'state': 'draft'}) self.create_workflow(cr, uid, ids) return True def name_get(self, cr, uid, ids, context=None): if not ids: return [] if isinstance(ids, (long, int)): ids = [ids] return [(r['id'], _('Week ')+datetime.strptime(r['date_from'], '%Y-%m-%d').strftime('%U')) \ for r in self.read(cr, uid, ids, ['date_from'], context=context, load='_classic_write')] def unlink(self, cr, uid, ids, context=None): sheets = self.read(cr, uid, ids, ['state','total_attendance'], context=context) for sheet in sheets: if sheet['state'] in ('confirm', 'done'): raise osv.except_osv(_('Invalid Action!'), _('You cannot delete a timesheet which is already confirmed.')) elif sheet['total_attendance'] <> 0.00: raise osv.except_osv(_('Invalid Action!'), _('You cannot delete a timesheet which have attendance entries.')) return super(hr_timesheet_sheet, self).unlink(cr, uid, ids, context=context) def onchange_employee_id(self, cr, uid, ids, employee_id, context=None): department_id = False user_id = False if employee_id: empl_id = self.pool.get('hr.employee').browse(cr, uid, employee_id, context=context) department_id = empl_id.department_id.id user_id = empl_id.user_id.id return {'value': {'department_id': department_id, 'user_id': user_id,}} # ------------------------------------------------ # OpenChatter methods and notifications # ------------------------------------------------ def _needaction_domain_get(self, cr, uid, context=None): emp_obj = self.pool.get('hr.employee') empids = emp_obj.search(cr, uid, [('parent_id.user_id', '=', uid)], context=context) if not empids: return False dom = ['&', ('state', '=', 'confirm'), ('employee_id', 'in', empids)] return dom
class wizard(osv.TransientModel): """ A wizard to manage the modification of protocol object """ _name = 'protocollo.modify.wizard' _description = 'Modify Protocollo Management' def set_before(self, before, label, value): if not value: value = '' before += label + ': ' + value + '\n' return before def set_after(self, after, label, value): after += label + ': ' + value + '\n' return after def _get_write_date(self, cr, uid, context): protocollo = self.pool.get('protocollo.protocollo').browse( cr, uid, context['active_id']) return protocollo.write_date def on_change_typology(self, cr, uid, ids, typology_id, context=None): values = {'pec': False, 'sharedmail': False, 'email_error': ''} if typology_id: typology_obj = self.pool.get('protocollo.typology') typology = typology_obj.browse(cr, uid, typology_id) protocollo_obj = self.pool.get('protocollo.protocollo') protocollo = protocollo_obj.browse(cr, uid, context['active_id'], {'skip_check': True}) if typology.pec: values['pec'] = True values['sharedmail'] = False if protocollo.type == 'out': for sender_receiver in protocollo.sender_receivers: if not sender_receiver.pec_mail: values[ 'email_error'] = "Attenzione!\nIl mezzo di trasmissione 'PEC' non può essere usato perchè ci sono dei destinatari privi di email PEC!" break if typology.sharedmail: values['pec'] = False values['sharedmail'] = True if protocollo.type == 'out': for sender_receiver in protocollo.sender_receivers: if not sender_receiver.email: values[ 'email_error'] = "Attenzione!\nIl mezzo di trasmissione 'Email' non può essere usato perchè ci sono dei destinatari privi di email!" break if protocollo.typology.id != typology.id: if protocollo.typology.pec: values[ 'email_error'] = "Attenzione!\nIl mezzo di trasmissione 'PEC' non può essere modificato!" elif typology.pec: values[ 'email_error'] = "Attenzione!\nIl mezzo di trasmissione 'PEC' non può essere inserito in questa fase!" return {'value': values} _columns = { 'name': fields.char('Numero Protocollo', size=256, required=True, readonly=True), 'registration_date': fields.datetime('Data Registrazione', readonly=True), 'type': fields.selection( [('out', 'Uscita'), ('in', 'Ingresso')], 'Tipo', size=32, required=True, readonly=True, ), 'typology': fields.many2one('protocollo.typology', 'Mezzo di Trasmissione', help="Mezzo di Trasmissione: \ Raccomandata, Fax, PEC, etc. \ si possono inserire nuove tipologie \ dal menu Tipologie."), 'pec': fields.related('typology', 'pec', type='boolean', string='PEC', readonly=False, store=False), 'sharedmail': fields.related('typology', 'sharedmail', type='boolean', string='Sharedmail', readonly=False, store=False), 'receiving_date': fields.datetime( 'Data Ricezione', required=False, ), 'subject': fields.text('Oggetto', required=True), 'email_pec_sending_mode': fields.selection( [('all_receivers', 'Un messaggio per tutti i destinatari')], 'Modalità Invio', size=32), 'body': fields.html('Corpo della mail'), 'classification': fields.many2one( 'protocollo.classification', 'Titolario di Classificazione', required=False, ), 'sender_protocol': fields.char( 'Protocollo Mittente', required=False, ), 'server_sharedmail_id': fields.many2one( 'fetchmail.server', 'Account Email', domain= "[('sharedmail', '=', True),('user_sharedmail_ids', 'in', uid),('state','=','done')]" ), 'server_pec_id': fields.many2one( 'fetchmail.server', 'Account PEC', domain= "[('pec', '=', True),('user_ids', 'in', uid),('state','=','done')]" ), 'dossier_ids': fields.many2many('protocollo.dossier', 'dossier_protocollo_pec_rel', 'wizard_id', 'dossier_id', 'Fascicoli'), 'notes': fields.text('Note'), 'cause': fields.text('Motivo della Modifica', required=True), 'last_write_date': fields.datetime('Ultimo salvataggio', required=True), 'email_error': fields.text('Errore', readonly=True), } def _default_name(self, cr, uid, context): protocollo = self.pool.get('protocollo.protocollo').browse( cr, uid, context['active_id'], {'skip_check': True}) return protocollo.name def _default_registration_date(self, cr, uid, context): protocollo = self.pool.get('protocollo.protocollo').browse( cr, uid, context['active_id'], {'skip_check': True}) return protocollo.registration_date def _default_type(self, cr, uid, context): protocollo = self.pool.get('protocollo.protocollo').browse( cr, uid, context['active_id'], {'skip_check': True}) return protocollo.type def _default_typology(self, cr, uid, context): protocollo = self.pool.get('protocollo.protocollo').browse( cr, uid, context['active_id'], {'skip_check': True}) return protocollo.typology.id def _default_receiving_date(self, cr, uid, context): protocollo = self.pool.get('protocollo.protocollo').browse( cr, uid, context['active_id'], {'skip_check': True}) return protocollo.receiving_date def _default_subject(self, cr, uid, context): protocollo = self.pool.get('protocollo.protocollo').browse( cr, uid, context['active_id'], {'skip_check': True}) return protocollo.subject def _default_body(self, cr, uid, context): protocollo = self.pool.get('protocollo.protocollo').browse( cr, uid, context['active_id'], {'skip_check': True}) return protocollo.body def _default_email_pec_sending_mode(self, cr, uid, context): protocollo = self.pool.get('protocollo.protocollo').browse( cr, uid, context['active_id'], {'skip_check': True}) return protocollo.email_pec_sending_mode def _default_classification(self, cr, uid, context): protocollo = self.pool.get('protocollo.protocollo').browse( cr, uid, context['active_id'], {'skip_check': True}) return protocollo.classification.id def _default_sender_protocol(self, cr, uid, context): protocollo = self.pool.get('protocollo.protocollo').browse( cr, uid, context['active_id'], {'skip_check': True}) return protocollo.sender_protocol def _default_dossier_ids(self, cr, uid, context): protocollo = self.pool.get('protocollo.protocollo').browse( cr, uid, context['active_id'], {'skip_check': True}) dossier_ids = [] for dossier_id in protocollo.dossier_ids: dossier_ids.append(dossier_id.id) return [(6, 0, dossier_ids)] def _default_notes(self, cr, uid, context): protocollo = self.pool.get('protocollo.protocollo').browse( cr, uid, context['active_id'], {'skip_check': True}) return protocollo.notes def _default_last_write_date(self, cr, uid, context): protocollo = self.pool.get('protocollo.protocollo').browse( cr, uid, context['active_id'], {'skip_check': True}) return protocollo.write_date def _default_server_sharedmail_id(self, cr, uid, context): protocollo = self.pool.get('protocollo.protocollo').browse( cr, uid, context['active_id'], {'skip_check': True}) return protocollo.server_sharedmail_id def _default_server_pec_id(self, cr, uid, context): protocollo = self.pool.get('protocollo.protocollo').browse( cr, uid, context['active_id'], {'skip_check': True}) return protocollo.server_pec_id _defaults = { 'name': _default_name, 'registration_date': _default_registration_date, 'type': _default_type, 'typology': _default_typology, 'receiving_date': _default_receiving_date, 'subject': _default_subject, 'body': _default_body, 'email_pec_sending_mode': _default_email_pec_sending_mode, 'classification': _default_classification, 'sender_protocol': _default_sender_protocol, 'dossier_ids': _default_dossier_ids, 'notes': _default_notes, 'last_write_date': _default_last_write_date, 'server_sharedmail_id': _default_server_sharedmail_id, 'server_pec_id': _default_server_pec_id, 'email_error': '' } def action_save(self, cr, uid, ids, context=None): vals = {} wizard = self.browse(cr, uid, ids[0], context) protocollo_obj = self.pool.get('protocollo.protocollo') protocollo = protocollo_obj.browse(cr, uid, context['active_id'], {'skip_check': True}) if wizard.last_write_date != protocollo.write_date: raise osv.except_osv( _('Attenzione!'), _('Il protocollo corrente e\' stato modificato di recente da un altro utente.\nAggiornare la pagina prima di modificare il protocollo.' )) vals['typology'] = wizard.typology.id if wizard.typology.id != protocollo.typology.id: if protocollo.typology.pec: raise orm.except_orm( _('Attenzione!'), _('Il metodo di spedizione PEC' ' non puo\' essere modificato.')) elif wizard.typology.pec: raise orm.except_orm( _('Attenzione!'), _('Il metodo di spedizione PEC' ' non puo\' essere inserito in questa fase.')) if wizard.server_sharedmail_id.id != protocollo.server_sharedmail_id.id: vals['server_sharedmail_id'] = wizard.server_sharedmail_id.id if wizard.server_pec_id.id != protocollo.server_pec_id.id: vals['server_pec_id'] = wizard.server_pec_id.id if wizard.subject != protocollo.subject: vals['subject'] = wizard.subject if wizard.email_pec_sending_mode != protocollo.email_pec_sending_mode: vals['email_pec_sending_mode'] = wizard.email_pec_sending_mode if wizard.body != protocollo.body: vals['body'] = wizard.body if protocollo.receiving_date != wizard.receiving_date: vals['receiving_date'] = wizard.receiving_date protocollo_obj.write(cr, uid, [context['active_id']], vals, {'cause': wizard.cause}) if vals and \ ('subject' in vals or 'server_sharedmail_id' in vals or 'server_pec_id' in vals) and \ protocollo.registration_date: protocollo_obj.aggiorna_segnatura_xml(cr, uid, [protocollo.id], force=True, log=False, commit=False, context=context) return { 'name': 'Protocollo', 'view_type': 'form', 'view_mode': 'form,tree', 'res_model': 'protocollo.protocollo', 'res_id': context['active_id'], 'context': context, 'type': 'ir.actions.act_window', 'flags': { 'initial_mode': 'edit' } }
class account_invoice(orm.Model): _inherit = 'account.invoice' # def _get_sale_order(self, cr, uid, ids, field_name, model_name, context=None): # result = {} # crm_lead_obj = self.pool['crm.lead'] # sale_order_obj = self.pool['sale.order'] # # for crm_lead in crm_lead_obj.browse(cr, uid, ids, context): # partner_id = crm_lead.partner_id.id # contact_id = crm_lead.partner_address_id.id # if contact_id: # result[crm_lead.id] = sale_order_obj.search(cr, uid, [('partner_id', '=', partner_id), ('partner_order_id', '=', contact_id)]) # else: # result[crm_lead.id] = sale_order_obj.search(cr, uid, [('partner_id', '=', partner_id)]) # return result def name_get(self, cr, uid, ids, context=None): context = context or self.pool['res.users'].context_get(cr, uid) if not ids: return [] if isinstance(ids, (int, long)): ids = [ids] return [(x['id'], unicode(x.type in ['in_invoice', 'in_refund'] and x.supplier_invoice_number or x.number or x.name)) for x in self.browse(cr, uid, ids, context=context)] def _get_stock_picking(self, cr, uid, ids, field_name, model_name, context=None): context = context or self.pool['res.users'].context_get(cr, uid) result = {} stock_picking_obj = self.pool['stock.picking'] for invoice in self.browse(cr, uid, ids, context): origins = {} for line in invoice.invoice_line: line_origin = line.origin or False if line_origin not in origins: origins[line_origin] = invoice.id if invoice.origin: for invoice_origin in invoice.origin.split(', '): if invoice_origin not in origins: origins[invoice_origin] = invoice.id picking_ids = [] for origin in origins: if origin: # OUTxxx:SOyy if len(origin.split(':')) == 2: pickings_name = origin.split(':')[0] else: pickings_name = origin picking_ids += stock_picking_obj.search(cr, uid, [('name', '=', pickings_name)], context=context) print picking_ids result[invoice.id] = picking_ids return result _columns = { 'supplier_invoice_number': fields.char('Supplier invoice nr', size=32), # 'sale_order_ids': fields.function(_get_sale_order, 'Sale Order', type='one2many', relation="sale.order", readonly=True, method=True), 'stock_picking_ids': fields.function(_get_stock_picking, 'Stock Picking', type='one2many', relation="stock.picking", readonly=True, method=True), 'sale_order_ids': fields.many2many( 'sale.order', 'sale_order_invoice_rel', 'invoice_id', 'order_id', 'Sale orders' ) } def copy(self, cr, uid, order_id, default, context=None): context = context or self.pool['res.users'].context_get(cr, uid) if not default: default = {} default['user_id'] = uid return super(account_invoice, self).copy(cr, uid, order_id, default, context) def invoice_validate_check(self, cr, uid, ids, context=None): context = context or self.pool['res.users'].context_get(cr, uid) for invoice in self.browse(cr, uid, ids, context): if invoice.type == 'out_invoice' and invoice.fiscal_position and invoice.fiscal_position.sale_journal_id and invoice.fiscal_position.sale_journal_id != invoice.journal_id: raise orm.except_orm(_('Fattura Cliente'), _('Impossibile to valide invoice of {partner} because journal on invoive \'{invoice_journal}\' is different from journal \'{fiscal_position_journal}\' set on fiscal position \'{invoice_fiscal_position}\'').format( partner=invoice.partner_id.name, invoice_journal=invoice.journal_id.name, fiscal_position_journal=invoice.fiscal_position.sale_journal_id.name, invoice_fiscal_position=invoice.fiscal_position.name)) return False return True def invoice_cancel_check(self, cr, uid, ids, context=None): context = context or self.pool['res.users'].context_get(cr, uid) return True def invoice_proforma_check(self, cr, uid, ids, context=None): context = context or self.pool['res.users'].context_get(cr, uid) return True def onchange_fiscal_position(self, cr, uid, ids, journal_id, fiscal_position, ttype, context=None): context = context or self.pool['res.users'].context_get(cr, uid) if not fiscal_position: return False fpos_obj = self.pool['account.fiscal.position'] new_fiscal_position = fpos_obj.browse(cr, uid, fiscal_position, context) if ttype in ['out_invoice']: journal_id = new_fiscal_position.sale_journal_id and new_fiscal_position.sale_journal_id.id or journal_id elif ttype in ['in_invoice']: journal_id = new_fiscal_position.purchase_journal_id and new_fiscal_position.purchase_journal_id.id or journal_id # if is an exiting invoice, also change tax inside line to new fiscal position warning = {} for inv in self.browse(cr, uid, ids, context): if inv.fiscal_position != new_fiscal_position: for line in inv.invoice_line: if line.product_id: result = {} if inv.type in ('out_invoice', 'out_refund'): account_id = line.product_id.product_tmpl_id.property_account_income.id if not account_id: account_id = line.product_id.categ_id.property_account_income_categ.id else: account_id = line.product_id.product_tmpl_id.property_account_expense.id if not account_id: account_id = line.product_id.categ_id.property_account_expense_categ.id account_id = fpos_obj.map_account(cr, uid, new_fiscal_position, account_id) if inv.type in ('out_invoice', 'out_refund'): taxes = line.product_id.taxes_id and line.product_id.taxes_id or ( account_id and self.pool['account.account'].browse(cr, uid, account_id, context=context).tax_ids or False) else: taxes = line.product_id.supplier_taxes_id and line.product_id.supplier_taxes_id or ( account_id and self.pool['account.account'].browse(cr, uid, account_id, context=context).tax_ids or False) new_taxes = fpos_obj.map_tax(cr, uid, new_fiscal_position, taxes) if new_taxes: result['invoice_line_tax_id'] = [(6, 0, new_taxes)] result['account_id'] = fpos_obj.map_account(cr, uid, new_fiscal_position, account_id, context=None) self.pool['account.invoice.line'].write(cr, uid, line.id, result, context=context) inv.button_reset_taxes() warning = { 'title': _('Fiscal Position'), 'message': _('Is Change from \n{old_fiscal_position} to \n{new_fiscal_position}: \nPlease Press Button for recalculate tax').format( old_fiscal_position=inv.fiscal_position and inv.fiscal_position.name or _('None'), new_fiscal_position=new_fiscal_position.name) } return {'value': {'journal_id': journal_id}, 'warning': warning} def _invoice_adaptative_function(self, invoice, vals): partner_vals = {} if set(vals.keys()).intersection(['fiscal_position', 'carriage_condition_id', 'goods_description_id', 'payment_term']): if not invoice.partner_id.carriage_condition_id and vals.get('carriage_condition_id', False): partner_vals['carriage_condition_id'] = vals.get('carriage_condition_id') if not invoice.partner_id.goods_description_id and vals.get('goods_description_id', False): partner_vals['goods_description_id'] = vals.get('goods_description_id') if not invoice.partner_id.property_payment_term and vals.get('payment_term', False): partner_vals['property_payment_term'] = vals.get('payment_term') if not invoice.partner_id.property_account_position and vals.get('fiscal_position', False): partner_vals['property_account_position'] = vals.get('fiscal_position') if 'company_bank_id' in invoice.partner_id._table._columns and not invoice.partner_id.company_bank_id and vals.get('partner_bank_id', False): partner_vals['company_bank_id'] = vals.get('partner_bank_id') if partner_vals: invoice.partner_id.write(partner_vals) return True def create(self, cr, uid, vals, context=None): context = context or self.pool['res.users'].context_get(cr, uid) # adaptative function: the system learn invoice_id = super(account_invoice, self).create(cr, uid, vals, context=context) # create function return only 1 id invoice = self.browse(cr, uid, invoice_id, context) self._invoice_adaptative_function(invoice, vals) return invoice_id def write(self, cr, uid, ids, vals, context=None): context = context or self.pool['res.users'].context_get(cr, uid) if not ids: return True if isinstance(ids, (int, long)): ids = [ids] res = super(account_invoice, self).write(cr, uid, ids, vals, context=context) for invoice in self.browse(cr, uid, ids, context=context): # adaptative function: the system learn self._invoice_adaptative_function(invoice, vals) return res # def button_change_fiscal_position(self, cr, uid, ids, context=None): # if context is None: # context = self.pool['res.users'].context_get(cr, uid) # # fpos_obj = self.pool['account.fiscal.position'] # # for inv in self.browse(cr, uid, ids, context): # for line in inv.invoice_line: # if line.product_id: # new_taxes = fpos_obj.map_tax(cr, uid, inv.fiscal_position, line.product_id.taxes_id) # line.write({'invoice_line_tax_id': [(6, 0, new_taxes)]}) # inv.button_reset_taxes() # # return True # override to group product_id too def inv_line_characteristic_hashcode(self, invoice, invoice_line): """Overridable hashcode generation for invoice lines. Lines having the same hashcode will be grouped together if the journal has the 'group line' option. Of course a module can add fields to invoice lines that would need to be tested too before merging lines or not.""" return "%s-%s-%s-%s"%( invoice_line['account_id'], invoice_line.get('tax_code_id', "False"), # invoice_line.get('product_id',"False"), invoice_line.get('analytic_account_id', "False"), invoice_line.get('date_maturity', "False")) # override to merge description (after will be trunked to x character everyway) def group_lines(self, cr, uid, iml, line, inv): """Merge account move lines (and hence analytic lines) if invoice line hashcodes are equals""" if inv.journal_id.group_invoice_lines: line2 = {} for x, y, l in line: tmp = self.inv_line_characteristic_hashcode(inv, l) if tmp in line2: am = line2[tmp]['debit'] - line2[tmp]['credit'] + (l['debit'] - l['credit']) line2[tmp]['debit'] = (am > 0) and am or 0.0 line2[tmp]['credit'] = (am < 0) and -am or 0.0 line2[tmp]['tax_amount'] += l['tax_amount'] line2[tmp]['analytic_lines'] += l['analytic_lines'] line2[tmp]['amount_currency'] += l['amount_currency'] line2[tmp]['quantity'] += l['quantity'] line2[tmp]['name'] += l['name'] else: line2[tmp] = l line = [] for key, val in line2.items(): line.append((0, 0, val)) return line def unlink(self, cr, uid, ids, context=None): context = context or self.pool['res.users'].context_get(cr, uid) if not isinstance(ids, (list, tuple)): ids = [ids] # account_invoice_line_obj = self.pool['account.invoice.line'] stock_picking_obj = self.pool['stock.picking'] origins = {} for invoice in self.browse(cr, uid, ids, context): for line in invoice.invoice_line: if line.origin_document and line.origin_document._name == 'sale.order.line': # the invoice line is create directly form sale order.line if self.pool['account.invoice.line'].unlink(cr, uid, line.id, context): continue line_origin = line.origin or False if line_origin not in origins: origins[line_origin] = invoice.id if invoice.origin: for invoice_origin in invoice.origin.split(', '): if invoice_origin not in origins: origins[invoice_origin] = invoice.id # now on origins i have all the origin and invoice.id for origin in origins: if origin: # OUTxxx:SOyy if len(origin.split(':')) == 2: pickings_name = origin.split(':')[0] else: pickings_name = origin picking_id = stock_picking_obj.search(cr, uid, [('name', '=', pickings_name)], context=context) if super(account_invoice, self).unlink(cr, uid, [origins[origin]], context=context): if picking_id: stock_picking_obj.write(cr, uid, [picking_id[0]], {'invoice_state': '2binvoiced'}, context=context) # now i need to eliminate other ids if origins[origin] in ids: del ids[ids.index(origins[origin])] return super(account_invoice, self).unlink(cr, uid, ids, context=context)
raise osv.except_osv( _('Wrong Certificate file format'), _('Be sure you have BEGIN CERTIFICATE string in' ' your first line.')) else: raise osv.except_osv( _('Unknown error'), _('X509 return this message:\n %s') % e[0]) wz.wsafip_request_id.write({'state': 'confirmed'}) _name = 'l10n_ar_wsafip.loadcert_config' _inherit = 'res.config' _columns = { 'wsafip_request_id': fields.many2one( 'crypto.certificate', 'Certificate Request', required=True), 'wsafip_request_file': fields.binary( 'Download Signed Certificate Request', readonly=True), 'wsafip_request_filename': fields.char( 'Filename', readonly=True), 'wsafip_response_file': fields.binary( 'Upload Certificate', required=True), } _defaults = { 'wsafip_request_filename': 'request.csr', } l10n_ar_wsafip_loadcert_config() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
class AccountReportBudgetWizard(osv.osv_memory): _inherit = "account.report.budget" _columns = { 'summary': fields.boolean('Summary'), 'closure': fields.char('Closure', ), 'unit_type': fields.selection([('ministry', 'ministry'), ('locality', 'locality'), ('other', 'other')], "Type"), } def _get_analytic_account(self, cr, uid, context=None): """ Method to return the root analytic account in logged in user @return: int root analytic account id or False """ analytic_obj = self.pool.get('account.analytic.account') company = self.pool.get('res.users').browse( cr, uid, uid, context=context).company_id.id analytic_account = self.pool.get('account.analytic.account').search( cr, uid, [('parent_id', '=', False), ('company_id', '=', company)], context=context, limit=1) #Use this code for none Accounting user if not self.pool.get('res.users').has_group( cr, uid, 'account.group_account_user'): analytic_account = self.pool.get( 'account.analytic.account').search(cr, uid, [('type', '=', 'normal')], context=context) temp_analytic = [] cr.execute( "SELECT gid as group_id FROM res_groups_users_rel WHERE uid='%s'" % (str(uid), )) #group_ids = list(cr.fetchall()) user_group_ids = [x for x, in cr.fetchall()] for analytic in analytic_obj.browse(cr, uid, analytic_account, context=context): if set([group.id for group in analytic.group_ids ]) & set(user_group_ids): temp_analytic.append(analytic.id) analytic_account = temp_analytic return analytic_account and analytic_account[0] or False _defaults = { 'summary': 0, 'report_type': '1', 'date_from': time.strftime('%Y-01-01'), 'date_to': time.strftime('%Y-%m-%d'), 'chart_analytic_account_id': _get_analytic_account, } def onchange_fiscalyear_id(self, cr, uid, ids, fiscalyear_id=False, context=None): """ Inherit method to update date_from, date_to values @param fiscalyear_id: fiscalyear_id @return: dictionary of values """ fiscalyear = self.pool.get('account.fiscalyear').browse( cr, uid, fiscalyear_id, context=context) analytic_obj = self.pool.get('account.analytic.account') analytic_domain = [('type', 'in', ('normal', 'view'))] #Use this code for none Accounting user if not self.pool.get('res.users').has_group( cr, uid, 'account.group_account_user'): analytic_account = self.pool.get( 'account.analytic.account').search(cr, uid, [('type', '=', ('normal', 'view'))], context=context) temp_analytic = [] cr.execute( "SELECT gid as group_id FROM res_groups_users_rel WHERE uid='%s'" % (str(uid), )) #group_ids = list(cr.fetchall()) user_group_ids = [x for x, in cr.fetchall()] for analytic in analytic_obj.browse(cr, uid, analytic_account, context=context): if set([group.id for group in analytic.group_ids ]) & set(user_group_ids): temp_analytic.append(analytic.id) analytic_domain = [('id', 'in', temp_analytic)] res = {'domain': {'chart_analytic_account_id': analytic_domain}} if fiscalyear_id: res.update({ 'value': { 'date_from': fiscalyear.date_start, 'date_to': fiscalyear.date_stop, } }) return res def print_report(self, cr, uid, ids, context=None): """ Method to send wizards fields value to the report @return: dictionary call the report service """ res = super(AccountReportBudgetWizard, self).print_report(cr, uid, ids, context) #Mudathir : Get analytic_account From Wizard to set it in report res['datas']['form'].update({ 'chart_analytic_account_report': self.read(cr, uid, ids, [], context)[0]['chart_analytic_account_id'][1] }) summary = res['datas']['form']['summary'] if summary and res['datas']['form']['type_selection'] == 'detail': res['report_name'] = 'account.budget.summary' if summary and res['datas']['form']['type_selection'] == 'consol': res['report_name'] = 'account.budget.consol' if summary and res['datas']['form']['type_selection'] == 'dept': res['report_name'] = 'account.budget.dep' if summary and res['datas']['form']['type_selection'] == 'unit': res['report_name'] = 'account.budget.unit' return res '''
user_id = res[0] elif conf["create_user"]: _logger.debug('Creating new OpenERP user "%s" from LDAP' % login) user_obj = self.pool.get("res.users") values = self.map_ldap_attributes(cr, uid, conf, login, ldap_entry) if conf["user"]: user_id = user_obj.copy(cr, SUPERUSER_ID, conf["user"], default={"active": True}) user_obj.write(cr, SUPERUSER_ID, user_id, values) else: user_id = user_obj.create(cr, SUPERUSER_ID, values) return user_id _columns = { "sequence": fields.integer("Sequence"), "company": fields.many2one("res.company", "Company", required=True, ondelete="cascade"), "ldap_server": fields.char("LDAP Server address", size=64, required=True), "ldap_server_port": fields.integer("LDAP Server port", required=True), "ldap_binddn": fields.char( "LDAP binddn", size=64, help=( "The user account on the LDAP server that is used to query " "the directory. Leave empty to connect anonymously." ), ), "ldap_password": fields.char( "LDAP password", size=64, help=("The password of the user account on the LDAP server that is " "used to query the directory."), ), "ldap_filter": fields.char("LDAP filter", size=256, required=True),
class crm_segmentation_line(osv.osv): """ Segmentation line """ _name = "crm.segmentation.line" _description = "Segmentation line" _columns = { 'name': fields.char('Rule Name', size=64, required=True), 'segmentation_id': fields.many2one('crm.segmentation', 'Segmentation'), 'expr_name': fields.selection([('sale','Sale Amount'), ('purchase','Purchase Amount')], 'Control Variable', size=64, required=True), 'expr_operator': fields.selection([('<','<'),('=','='),('>','>')], 'Operator', required=True), 'expr_value': fields.float('Value', required=True), 'operator': fields.selection([('and','Mandatory Expression'),\ ('or','Optional Expression')],'Mandatory / Optional', required=True), } _defaults = { 'expr_name': lambda *a: 'sale', 'expr_operator': lambda *a: '>', 'operator': lambda *a: 'and' } def test(self, cr, uid, ids, partner_id): """ @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 Test’s IDs """ expression = { '<': lambda x, y: x < y, '=': lambda x, y: x == y, '>': lambda x, y: x > y } ok = False lst = self.read(cr, uid, ids) for l in lst: cr.execute( 'select * from ir_module_module where name=%s and state=%s', ('account', 'installed')) if cr.fetchone(): if l['expr_name'] == 'sale': cr.execute('SELECT SUM(l.price_unit * l.quantity) ' \ 'FROM account_invoice_line l, account_invoice i ' \ 'WHERE (l.invoice_id = i.id) ' \ 'AND i.partner_id = %s '\ 'AND i.type = \'out_invoice\'', (partner_id,)) value = cr.fetchone()[0] or 0.0 cr.execute('SELECT SUM(l.price_unit * l.quantity) ' \ 'FROM account_invoice_line l, account_invoice i ' \ 'WHERE (l.invoice_id = i.id) ' \ 'AND i.partner_id = %s '\ 'AND i.type = \'out_refund\'', (partner_id,)) value -= cr.fetchone()[0] or 0.0 elif l['expr_name'] == 'purchase': cr.execute('SELECT SUM(l.price_unit * l.quantity) ' \ 'FROM account_invoice_line l, account_invoice i ' \ 'WHERE (l.invoice_id = i.id) ' \ 'AND i.partner_id = %s '\ 'AND i.type = \'in_invoice\'', (partner_id,)) value = cr.fetchone()[0] or 0.0 cr.execute('SELECT SUM(l.price_unit * l.quantity) ' \ 'FROM account_invoice_line l, account_invoice i ' \ 'WHERE (l.invoice_id = i.id) ' \ 'AND i.partner_id = %s '\ 'AND i.type = \'in_refund\'', (partner_id,)) value -= cr.fetchone()[0] or 0.0 res = expression[l['expr_operator']](value, l['expr_value']) if (not res) and (l['operator'] == 'and'): return False if res: return True return True
def _default_location(self, cr, uid, ids, context=None): try: loc_model, location_id = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'stock', 'stock_location_stock') except ValueError, e: return False return location_id or False _columns = { 'location_id': fields.many2one('stock.location', 'Location', required=True), 'import_file': fields.binary('File', filters="*.xls"), #to consider the product current inventory or not, if yes then add the current inventory to the upload excel quantity as the quantity to do physical inventory 'consider_inventory': fields.boolean('Consider Current Inventory', select=True), 'all_done': fields.boolean('All Data Imported', readonly=True, select=True), 'result_line': fields.one2many('stock.import.inventory.result', 'import_id', 'Importing Result', readonly=True), 'file_template': fields.binary('Template File', readonly=True), 'file_template_name': fields.char('Template File Name'), } def _get_template(self, cr, uid, context): cur_path = os.path.split(os.path.realpath(__file__))[0] path = os.path.join(cur_path,'stock_import_template.xls') data = open(path,'rb').read().encode('base64') # data = os.path.getsize(path) return data _defaults = { 'location_id': _default_location, 'file_template': _get_template, 'file_template_name': 'stock_import_template.xls' }
class crm_segmentation(osv.osv): ''' A segmentation is a tool to automatically assign categories on partners. These assignations are based on criterions. ''' _name = "crm.segmentation" _description = "Partner Segmentation" _columns = { 'name': fields.char('Name', size=64, required=True, help='The name of the segmentation.'), 'description': fields.text('Description'), 'categ_id': fields.many2one('res.partner.category', 'Partner Category',\ required=True, help='The partner category that will be \ added to partners that match the segmentation criterions after computation.' ), 'exclusif': fields.boolean('Exclusive', help='Check if the category is limited to partners that match the segmentation criterions.\ \nIf checked, remove the category from partners that doesn\'t match segmentation criterions' ), 'state': fields.selection([('not running','Not Running'),\ ('running','Running')], 'Execution Status', readonly=True), 'partner_id': fields.integer('Max Partner ID processed'), 'segmentation_line': fields.one2many('crm.segmentation.line', \ 'segmentation_id', 'Criteria', required=True), 'sales_purchase_active': fields.boolean('Use The Sales Purchase Rules', help='Check if you want to use this tab as part of the segmentation rule. If not checked, the criteria beneath will be ignored') } _defaults = { 'partner_id': lambda *a: 0, 'state': lambda *a: 'not running', } def process_continue(self, cr, uid, ids, start=False): """ @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 Process continue’s IDs""" partner_obj = self.pool.get('res.partner') categs = self.read(cr, uid, ids, ['categ_id', 'exclusif', 'partner_id',\ 'sales_purchase_active', 'profiling_active']) for categ in categs: if start: if categ['exclusif']: cr.execute( 'delete from res_partner_res_partner_category_rel \ where category_id=%s', (categ['categ_id'][0], )) id = categ['id'] cr.execute('select id from res_partner order by id ') partners = [x[0] for x in cr.fetchall()] if categ['sales_purchase_active']: to_remove_list = [] cr.execute( 'select id from crm_segmentation_line where segmentation_id=%s', (id, )) line_ids = [x[0] for x in cr.fetchall()] for pid in partners: if (not self.pool.get('crm.segmentation.line').test( cr, uid, line_ids, pid)): to_remove_list.append(pid) for pid in to_remove_list: partners.remove(pid) for partner in partner_obj.browse(cr, uid, partners): category_ids = [ categ_id.id for categ_id in partner.category_id ] if categ['categ_id'][0] not in category_ids: cr.execute( 'insert into res_partner_res_partner_category_rel (category_id,partner_id) \ values (%s,%s)', (categ['categ_id'][0], partner.id)) self.write(cr, uid, [id], { 'state': 'not running', 'partner_id': 0 }) return True def process_stop(self, cr, uid, ids, *args): """ @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 Process stop’s IDs""" return self.write(cr, uid, ids, { 'state': 'not running', 'partner_id': 0 }) def process_start(self, cr, uid, ids, *args): """ @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 Process start’s IDs """ self.write(cr, uid, ids, {'state': 'running', 'partner_id': 0}) return self.process_continue(cr, uid, ids, start=True)
def _get_extras(self, cr, uid, ids, *args, **kwargs): result = [] if _aeroo_ooo_test(cr): result.append('aeroo_ooo') ##### Check deferred_processing module ##### cr.execute("SELECT id, state FROM ir_module_module WHERE name='deferred_processing'") deferred_proc_module = cr.dictfetchone() if deferred_proc_module and deferred_proc_module['state'] in ('installed', 'to upgrade'): result.append('deferred_processing') ############################################ return dict.fromkeys(ids, ','.join(result)) _columns = { 'charset':fields.selection(_get_encodings, string='Charset', required=True), 'content_fname': fields.char('Override Extension',size=64, help='Here you can override output file extension'), 'styles_mode': fields.selection([ ('default','Not used'), ('global', 'Global'), ('specified', 'Specified'), ], string='Stylesheet'), 'stylesheet_id':fields.many2one('report.stylesheets', 'Template Stylesheet'), 'preload_mode':fields.selection([ ('static',_('Static')), ('preload',_('Preload')), ],'Preload Mode'), 'tml_source':fields.selection([ ('database','Database'), ('file','File'), ('parser','Parser'), ],'Template source', select=True),
class sav(osv.osv): _inherit = 'crm.claim' def create(self, cr, user, vals, context=None): if ('n_reclamation' not in vals) or (vals.get('n_reclamation') == '/'): vals['n_reclamation'] = self.pool.get('ir.sequence').get( cr, user, 'crm.claim') return super(sav, self).create(cr, user, vals, context) _columns = { 'n_reclamation': fields.char('N reclamation', required=True, readonly=True), 'company_id1': fields.many2one('res.company', 'Societe Client'), 'partner_id': fields.many2one('res.partner', u'Partner', required=True), 'partner_id1': fields.many2one('res.partner', u'Client', required=True, domain=[('customer', '=', True)]), 'email_from1': fields.char('Email client', size=128, help="Destination email for email gateway."), 'partner_phone1': fields.char('Phone client', size=32), 'street01': fields.char('Address client', size=128), 'city1': fields.char('Ville client', size=128), 'company_id2': fields.many2one('res.company', 'Societe Distributeur'), 'partner_id2': fields.many2one('res.partner', 'Distributeur', domain=[('supplier', '=', True)]), 'email_from2': fields.char('Email Distributeur', size=128, help="Destination email for email gateway."), 'partner_phone2': fields.char('Phone Distributeur', size=32), 'company_id3': fields.many2one('res.company', 'Societe Revendeur'), 'partner_id3': fields.many2one('res.partner', 'Revendeur'), 'email_from3': fields.char('Email Revendeur', size=128, help="Destination email for email gateway."), 'partner_phone3': fields.char('Phone Revendeur', size=32), 'produit': fields.many2one('product.product', 'Prouduit'), 'Modele': fields.char('Model Produit', size=64), 'date_achat': fields.datetime('Date Achat'), 'Desc': fields.text('description pane '), 'Marque': fields.many2one('product.marque', u'Marque', domain="[('partner_id2','=',partner_id2)]"), 'Serial': fields.char('N de serie', size=64), 'File_upload': fields.binary("Bonne d'achat"), 'follow_ids': fields.one2many('claim.follow', 'follow', u'Suivi'), 'product_ids': fields.many2many('product.product', 'product_equipment_rel', 'product_id', 'equipment_id', 'Piece of change'), 'num_facture': fields.char(u'N facture'), 'selection': fields.boolean(u'Selection'), 'cde_piece': fields.boolean(u'Commande piece'), 'administratif': fields.boolean(u'Administratif'), 'reference': fields.char(u'Réference'), 'klm': fields.integer(u'Kilometrage'), } _defaults = { 'n_reclamation': lambda self, cr, uid, context: 'Num auto', } def onchange_partner_id1(self, cr, uid, ids, part, context={}): data = {} if part: data_sav_model = self.pool.get('res.partner').read( cr, uid, part, ['phone', 'street', 'city']) if data_sav_model: data['partner_phone1'] = data_sav_model['phone'] data['street01'] = data_sav_model['street'] data['city1'] = data_sav_model['city'] return {'value': data} def onchange_partner_id2(self, cr, uid, ids, part, context={}): data = {} if part: data_sav_model = self.pool.get('res.partner').read( cr, uid, part, ['email', 'phone']) if data_sav_model: data['email_from2'] = data_sav_model['email'] data['partner_phone2'] = data_sav_model['phone'] return {'value': data} def onchange_partner3(self, cr, uid, ids, part, context={}): data = {} if part: data_sav_model = self.pool.get('res.partner').read( cr, uid, part, ['email', 'phone']) if data_sav_model: data['email_from3'] = data_sav_model['email'] data['partner_phone3'] = data_sav_model['phone'] return {'value': data}
move_line_obj.create(cr, uid, credit_values, context) asset_lines_obj.write(cr, uid, asset_line.get('id'), {'move_check': True, 'move_id': created_id}) logging.getLogger(self._name).info("""account.move.line created for {0}""".format(asset_name)) except: logging.getLogger('account.asset.asset').error( """ERROR creating the entries of account move from {0}.""".format(__name__)) raise orm.except_orm('Error', 'Failure creating the' ' account move lines.') else: logging.getLogger(self._name).info("Este activo ya esta asentado!") _columns = { 'asset_code': fields.char('Codigo', size=32, required=False, readonly=False), 'category_id': fields.many2one('account.asset.category', 'Asset Category', required=True, change_default=True, readonly=True, states={'draft':[('readonly',False)]}, domain=[('type','=','normal')]), 'category_parent_id': fields.many2one("account.asset.category", string="Categoria Padre del Activo", required=False, readonly=True, states={'draft':[('readonly',False)]}, domain=[('type','=','view')] ), 'account_analytic_id': fields.many2one("account.analytic.account", string="Cuenta analitica", required=True, domain=[('type','=','normal')]), 'asset_move_ids': fields.one2many('account.asset.move', 'asset_id','Movimientos'), #'asset_move_ids': fields.one2many('account.asset.move', 'asset_id', 'Movements') } _defaults = { 'asset_code': lambda obj, cr, uid, context: obj.pool.get('ir.sequence').get(cr, uid, 'asset.number')
class ir_mail_server(osv.osv): """Represents an SMTP server, able to send outgoing emails, with SSL and TLS capabilities.""" _name = "ir.mail_server" NO_VALID_RECIPIENT = ("At least one valid recipient address should be " "specified for outgoing emails (To/Cc/Bcc)") _columns = { 'name': fields.char('Description', required=True, select=True), 'smtp_host': fields.char('SMTP Server', required=True, help="Hostname or IP of SMTP server"), 'smtp_port': fields.integer( 'SMTP Port', size=5, required=True, help= "SMTP Port. Usually 465 for SSL, and 25 or 587 for other cases."), 'smtp_user': fields.char('Username', size=64, help="Optional username for SMTP authentication"), 'smtp_pass': fields.char('Password', size=64, help="Optional password for SMTP authentication"), 'smtp_encryption': fields.selection( [('none', 'None'), ('starttls', 'TLS (STARTTLS)'), ('ssl', 'SSL/TLS')], string='Connection Security', required=True, help="Choose the connection encryption scheme:\n" "- None: SMTP sessions are done in cleartext.\n" "- TLS (STARTTLS): TLS encryption is requested at start of SMTP session (Recommended)\n" "- SSL/TLS: SMTP sessions are encrypted with SSL/TLS through a dedicated port (default: 465)" ), 'smtp_debug': fields.boolean( 'Debugging', help="If enabled, the full output of SMTP sessions will " "be written to the server log at DEBUG level" "(this is very verbose and may include confidential info!)"), 'sequence': fields.integer( 'Priority', help= "When no specific mail server is requested for a mail, the highest priority one " "is used. Default priority is 10 (smaller number = higher priority)" ), 'active': fields.boolean('Active') } _defaults = { 'smtp_port': 25, 'active': True, 'sequence': 10, 'smtp_encryption': 'none', } def __init__(self, *args, **kwargs): # Make sure we pipe the smtplib outputs to our own DEBUG logger if not isinstance(smtplib.stderr, WriteToLogger): logpiper = WriteToLogger(_logger) smtplib.stderr = logpiper smtplib.stdout = logpiper super(ir_mail_server, self).__init__(*args, **kwargs) def name_get(self, cr, uid, ids, context=None): return [(a["id"], "(%s)" % (a['name'])) for a in self.read(cr, uid, ids, ['name'], context=context)] def test_smtp_connection(self, cr, uid, ids, context=None): for smtp_server in self.browse(cr, uid, ids, context=context): smtp = False try: smtp = self.connect(smtp_server.smtp_host, smtp_server.smtp_port, user=smtp_server.smtp_user, password=smtp_server.smtp_pass, encryption=smtp_server.smtp_encryption, smtp_debug=smtp_server.smtp_debug) except Exception, e: raise osv.except_osv( _("Connection Test Failed!"), _("Here is what we got instead:\n %s") % tools.ustr(e)) finally:
def _save_file(self, path, b64_file): """Save a file encoded in base 64""" self._check_filestore(path) with open(path, 'w') as ofile: ofile.write(base64.b64decode(b64_file)) return True def _set_image(self, cr, uid, id, name, value, arg, context=None): image = self.browse(cr, uid, id, context=context) full_path = self._image_path(cr, uid, image, context=context) if full_path: return self._save_file(full_path, value) return self.write(cr, uid, id, {'file_db_store': value}, context=context) _columns = { 'name': fields.char('Image Title', required=True), 'extension': fields.char('file extension', oldname='extention'), 'link': fields.boolean('Link?', help="Images can be linked from files on " "your file system or remote (Preferred)"), 'file_db_store': fields.binary('Image stored in database'), 'file': fields.function(_get_image, fnct_inv=_set_image, type="binary", string="File", filters='*.png,*.jpg,*.gif'), 'url': fields.char('File Location'), 'comments': fields.text('Comments'), 'product_id': fields.many2one('product.product', 'Product') }
res[user1.id] = user1.host_name.lower() + '.'+ user1.server.server_addres +':' + user1.server.rpc_port else : res[user1.id] = user1.server.server_addres +':' + user1.server.rpc_port+'/web?db='+ user1.host_name.lower() return res def get_counter(self,cr,uid,context=None): myids = self.search(cr, uid, [], context=context) for user in self.browse(cr,uid,myids,context=context): res = user.counter +1; isTrue = self.write(cr, uid, user.id, {'counter': res}, context=context) return isTrue _name = "saas.user.info" _description = "saas.user.info" _columns = { 'name': fields.char('Note', required=False,track_visibility='always', help=""), 'user': fields.many2one('res.partner', 'partner', help=""), 'host_name': fields.char('host_name',required=True, help=""), 'host_type': fields.char('host_type',required=False , help=""), 'server': fields.many2one('saas.server', 'server',required=True, help=""), 'url_addres': fields.function(_get_full_url, type='char',string='url_addres'), 'start_date': fields.datetime('start_date',required=False, help=""), 'end_date': fields.function(_compute_exp_date, type = 'datetime',string='end_date'), 'product_id':fields.many2one('product.product','product_id',required = False,help=''), 'state': fields.function(_get_server_state, type='char', string='state'), 'counter': fields.integer('counter',required=False , help=""), } _defaults = { 'start_date': fields.datetime.now, } _sql_constraints = [
# return {'value':{'cc_charge':False, 'cc_p_authorize':True } } # return {'value':{'cc_charge':True, 'cc_p_authorize':False } } # # def onchange_cc_charge(self, cr, uid, ids, cc_charge, context={}): # if cc_charge: # return {'value':{'cc_charge':True, 'cc_p_authorize':False } } # return {'value':{'cc_charge':False, 'cc_p_authorize':True } } def onchange_amount(self, cr, uid, ids, amount, rate, partner_id, journal_id, currency_id, ttype, date, payment_rate_currency_id, company_id, context=None): res = super(account_voucher, self).onchange_amount(cr, uid, ids, amount, rate, partner_id, journal_id, currency_id, ttype, date, payment_rate_currency_id, company_id, context=context) res['value'].update({'cc_order_amt':amount, 'cc_refund_amt':amount}) return res _inherit = 'account.voucher' _columns = { 'cc_name':fields.char("Card Holder's Name", size=32,), 'cc_b_addr_1':fields.char('Billing Address1', size=32,), 'cc_b_addr_2':fields.char('Billing Address2', size=32,), 'cc_city': fields.char('City', size=32,), 'cc_state':fields.char('State', size=32,), 'cc_zip':fields.char('Postal/Zip', size=32,), 'cc_country':fields.char('Country', size=32,), 'cc_order_date':fields.date('Order Date',), <<<<<<< HEAD 'cc_order_amt':fields.float('Order Amt'), ======= 'cc_order_amt':fields.float('Order Amt',required=True), >>>>>>> c1979f64b3360c86d60e00c92be0271d89f97f2d 'cc_number':fields.char('Credit Card Number', size=256), 'cc_v':fields.char('Card Code Verification', size=3), 'cc_e_d_month':fields.char('Expiration Date MM', size=32),
if new_passphrase == old_passphrase: raise osv.except_osv(_('Error'), _('Old passphrase and new passphrase cannot be same')) ### Use Endicia API try: request = endicia.ChangePasswordRequest(ship_endicia.requester_id, ship_endicia.account_id, old_passphrase, new_passphrase, ship_endicia.test) response = request.send() change_passphrase_resp = response._get_value() except Exception, e: raise osv.except_osv(_('Error'), _('Error changing passphrase')) if change_passphrase_resp['status'] != '0': raise osv.except_osv(_('Error'), _('Error changing passphrase')) res = ship_endicia_obj.write_passphrase(cr,uid,new_passphrase) if res: message = _('Passphrase Changed successfully') self.log(cr, uid, ids[0], message) else: message = _('Error changing passphrase') self.log(cr, uid, ids[0], message) return {'type': 'ir.actions.act_window_close'} _columns = { 'name': fields.char('New Passphrase', size=100, required=True), } change_passphrase()
class account_analytic_account_summary_month(osv.osv): _name = "account_analytic_analysis.summary.month" _description = "Hours summary by month" _auto = False _rec_name = 'month' _columns = { 'account_id': fields.many2one('account.analytic.account', 'Analytic Account', readonly=True), 'unit_amount': fields.float('Total Time'), 'month': fields.char('Month', size=32, readonly=True), } def init(self, cr): openerp.tools.sql.drop_view_if_exists( cr, 'account_analytic_analysis_summary_month') cr.execute('CREATE VIEW account_analytic_analysis_summary_month AS (' \ 'SELECT ' \ '(TO_NUMBER(TO_CHAR(d.month, \'YYYYMM\'), \'999999\') + (d.account_id * 1000000::bigint))::bigint AS id, ' \ 'd.account_id AS account_id, ' \ 'TO_CHAR(d.month, \'Mon YYYY\') AS month, ' \ 'TO_NUMBER(TO_CHAR(d.month, \'YYYYMM\'), \'999999\') AS month_id, ' \ 'COALESCE(SUM(l.unit_amount), 0.0) AS unit_amount ' \ 'FROM ' \ '(SELECT ' \ 'd2.account_id, ' \ 'd2.month ' \ 'FROM ' \ '(SELECT ' \ 'a.id AS account_id, ' \ 'l.month AS month ' \ 'FROM ' \ '(SELECT ' \ 'DATE_TRUNC(\'month\', l.date) AS month ' \ 'FROM account_analytic_line AS l, ' \ 'account_analytic_journal AS j ' \ 'WHERE j.type = \'general\' ' \ 'GROUP BY DATE_TRUNC(\'month\', l.date) ' \ ') AS l, ' \ 'account_analytic_account AS a ' \ 'GROUP BY l.month, a.id ' \ ') AS d2 ' \ 'GROUP BY d2.account_id, d2.month ' \ ') AS d ' \ 'LEFT JOIN ' \ '(SELECT ' \ 'l.account_id AS account_id, ' \ 'DATE_TRUNC(\'month\', l.date) AS month, ' \ 'SUM(l.unit_amount) AS unit_amount ' \ 'FROM account_analytic_line AS l, ' \ 'account_analytic_journal AS j ' \ 'WHERE (j.type = \'general\') and (j.id=l.journal_id) ' \ 'GROUP BY l.account_id, DATE_TRUNC(\'month\', l.date) ' \ ') AS l ' 'ON (' \ 'd.account_id = l.account_id ' \ 'AND d.month = l.month' \ ') ' \ 'GROUP BY d.month, d.account_id ' \ ')')
class loewieec_shop(osv.osv): _name = 'loewieec.shop' _description = u"电商店铺" _columns = { 'tmall_time': fields.datetime(string='TMall Time'), 'name': fields.char(u'店铺名称', size=16, required=True), 'code': fields.char(u'店铺前缀', size=8, required=True, help=u"系统会自动给该店铺的订单编号.客户昵称加上此前缀.通常同一个平台的店铺前缀设置成一样"), 'platform': fields.selection([ ('tb', u'淘宝天猫'), ('sb', u'淘宝沙箱'), ], string=u'电商平台', required=True, help=u"淘宝、京东等电商平台"), #'categ_id': fields.many2one('product.category', string=u"商品默认分类", required=True), 'location_id': fields.many2one('stock.location', string=u"店铺库位", required=True), 'journal_id': fields.many2one('account.journal', string=u"默认销售账簿", required=True), 'post_product_id': fields.many2one('product.product', string=u"邮费"), #'coupon_product_id': fields.many2one('product.product', string=u"优惠减款", required=True), 'gift_product_id': fields.many2one( 'product.product', string=u"赠品", ), 'partner_id': fields.many2one('res.partner', string='Partner'), 'pricelist_id': fields.many2one('product.pricelist', string='Price List'), 'warehouse_id': fields.many2one('stock.warehouse', string='Warehouse'), 'appkey': fields.char(u'App Key', ), 'appsecret': fields.char(u'App Secret', ), 'sessionkey': fields.char(u'Session Key', ), 'apiurl': fields.char(u'API URL', ), 'authurl': fields.char(u'Auth URL', ), 'tokenurl': fields.char(u'Token URL', ), 'products': fields.one2many('product.tmalljd', 'ec_shop_id', string="Products"), 'orders': fields.one2many('sale.order', 'shop_id', string="Orders"), 'start_modified': fields.datetime(string='Start Modified'), 'end_modified': fields.datetime(string='End Modified'), } def get_full_path(self, cr, uid, path): # sanitize ath path = re.sub('[.]', '', path) path = path.strip('/\\') return os.path.join(tools.config.filestore(cr.dbname), path) def create_order_from_excel(self, cr, uid, ids, trade, context=None): order_obj = self.pool.get('sale.order') shop = self.browse(cr, uid, ids[0], context=context) partner_id = shop.partner_id.id #{"no":order_no, "coe":coe, "name":name, "tel":tel, "address":address, "city":city, "state":state, "zip":zip, "products":[line]} shipping_id = self.create_shipping_address( cr, uid, partner_id, { 'name': trade["name"], 'phone': trade["tel"], 'street': trade["address"], 'city': trade["city"], 'state': trade["state"], 'zip': trade["zip"] }, context=context) note = u"COE:%s, 姓名:%s, 电话:%s, 省份:%s, 城市%s, 收货地址:%s, 邮编:%s." % ( trade["coe"], trade["name"], trade["tel"], trade["state"], trade["city"], trade["address"], trade["zip"]) order_val = { 'name': "%s_%s" % (shop.code, trade.get('no')), 'shop_id': shop.id, 'date_order': datetime.now(), #订单支付时间 #'create_date': datetime.now(), #订单创建时间 'partner_id': partner_id, 'partner_invoice_id': partner_id, 'partner_shipping_id': shipping_id, 'warehouse_id': shop.warehouse_id.id, 'pricelist_id': shop.pricelist_id.id, 'company_id': 1, 'all_discounts': 0, 'picking_policy': 'one', 'state': 'draft', 'user_id': uid, 'order_policy': 'picking', 'client_order_ref': "COE: %s" % trade["coe"], 'order_line': [], 'note': note, } post_vals = { 'product_uos_qty': 1, 'product_id': 1, 'product_uom': 1, 'price_unit': 1, 'product_uom_qty': 1, 'name': '.', 'delay': 7, 'discount': 0, } products = trade.get('products', []) for o in products: line_vals = { 'product_uos_qty': o.get('qty', 0), 'product_id': 1, 'product_uom': 1, 'price_unit': o.get('price', 0), 'product_uom_qty': o.get('qty', 0), 'name': '.', 'delay': 7, 'discount': 0, } product_name = o.get('product', "").strip() product_ids = self.pool.get('product.product').search( cr, uid, [('name_template', '=', product_name)], context=context) if not product_ids: name = self.string_refactor(product_name) product_ids = self.pool.get('product.product').search( cr, uid, [('name_template', 'like', name)], context=context) if product_ids: line_vals.update({'name': u"产品名未能精确匹配"}) #如果没有匹配到产品,报同步异常 if not product_ids: raise osv.except_osv( u'Excel产品名错误', u'''无法再ERP中找到 - %s. \r\n请检查名字 并纠正如下情况:\r\n 1. 125 ml -> 125ml. \r\n 2. Eros - Eros Warming - 150ml -> Eros - Warming - 150ml''' % product_name) #syncerr = u"订单导入错误: 匹配不到商品。tid=%s, 商品【%s】, outer_iid=%s, num_iid=%s, outer_sku_id=%s, sku_id=%s " % ( trade.get('tid'), o.get('title', ''), o.get('outer_iid', ''), o.get('num_iid', ''), o.get('outer_sku_id', ''), o.get('sku_id', '') ) #self.pool.get('loewieec.error').create(cr, uid, {'name':syncerr, 'shop_id':shop.id }, context = context ) return False #添加订单明细行 line_vals.update({'product_id': product_ids[0]}) order_val['order_line'].append((0, 0, line_vals)) post_vals.update({ 'product_id': shop.gift_product_id.id, 'price_unit': 0, 'product_uos_qty': 1, 'product_uom_qty': 1, 'product_uom': 1 }) order_val['order_line'].append((0, 0, post_vals)) order_id = order_obj.create(cr, uid, order_val, context=context) return order_id def string_refactor(self, name): if not name: return False name = name.replace("/", "%") name = name.replace("|", "%") ll = name.split("-") ll = [l.strip() for l in ll] return "%".join(ll) def import_orders_from_excel(self, cr, uid, ids, context=None): attachment_obj = self.pool.get('ir.attachment') attachment_id = attachment_obj.search(cr, uid, [('res_id', '=', ids[0])], context=context) if len(attachment_id) < 1: return False attach = attachment_obj.browse(cr, uid, attachment_id[0], context=context) fname = attach.store_fname display_name = attach.name if not fname: return False fname = self.get_full_path(cr, uid, fname) wb = load_workbook(filename=fname) #ws = wb.get_sheet_by_name("Sheet1") ws = wb.get_sheet_by_name(wb.get_sheet_names()[0]) highest_row = ws.get_highest_row() highest_col = ws.get_highest_column() title_order = ws.cell(row=1, column=1).value title_product = ws.cell(row=1, column=2).value title_qty = ws.cell(row=1, column=3).value title_coe = ws.cell(row=1, column=5).value if highest_col < 12 or title_order != u"订单編號" or title_product != u"产品名称" or title_coe != u"COE": attach.unlink() raise osv.except_osv(u'Excel错误', u'''文件:%s 格式不正确.''' % display_name) row_start = 2 orders = {} last_order_no = None while row_start <= highest_row and ws.cell(row=row_start, column=2).value: line = {} col_start = 1 line["product"] = ws.cell(row=row_start, column=2).value line["qty"] = ws.cell(row=row_start, column=3).value cell_price = ws.cell(row=row_start, column=4) line["price"] = cell_price.get_original_value() order_no = ws.cell(row=row_start, column=1).value if order_no: coe = ws.cell(row=row_start, column=5).value name = ws.cell(row=row_start, column=6).value tel = ws.cell(row=row_start, column=7).value address = ws.cell(row=row_start, column=8).value city = ws.cell(row=row_start, column=9).value state = ws.cell(row=row_start, column=10).value zip = str(ws.cell(row=row_start, column=11).value) last_order_no = order_no = str(order_no) orders[last_order_no] = { "no": order_no, "coe": coe, "name": name, "tel": tel, "address": address, "city": city, "state": state, "zip": zip, "products": [line] } else: orders[last_order_no]["products"].append(line) row_start += 1 order_ids = [] for key in orders.keys(): order_id = self.create_order_from_excel(cr, uid, ids, orders[key], context=context) order_ids.append(order_id) attach.unlink() return order_ids def b_sync_stock_qty(self, cr, uid, ids, context=None): port = 80 shop = self.browse(cr, uid, ids[0], context=context) setDefaultAppInfo(shop.appkey, shop.appsecret) req = ProductsSearchRequest(shop.apiurl, port) req.fields = "name, sale_props, binds, product_id, outer_id, barcode_str" #resp= req.getResponse(shop.sessionkey) #skus = resp.get('items_inventory_get_response',False).get('items',False).get('item', False) req.page_no = 1 req.page_size = 100 req.q = "Fun Factory" total_get = 0 total_results = 100 res = [] while total_get < total_results: resp = req.getResponse(shop.sessionkey) total_results = resp.get('products_search_response').get( 'total_results') if total_results > 0: res += resp.get('products_search_response').get( 'products').get('product') total_get += req.page_size req.page_no = req.page_no + 1 return res def a_sync_stock_qty(self, cr, uid, ids, context=None): port = 80 shop = self.browse(cr, uid, ids[0], context=context) setDefaultAppInfo(shop.appkey, shop.appsecret) req = ItemsInventoryGetRequest(shop.apiurl, port) req.fields = "skus, num_iid, title, type, product_id, props_name, outer_id, barcode, sub_title, shop_type, price" #resp= req.getResponse(shop.sessionkey) #skus = resp.get('items_inventory_get_response',False).get('items',False).get('item', False) req.page_no = 1 req.page_size = 100 #req.is_ex = "true" req.is_taobao = "true" total_get = 0 total_results = 100 res = [] while total_get < total_results: resp = req.getResponse(shop.sessionkey) total_results = resp.get('items_inventory_get_response').get( 'total_results') if total_results > 0: res += resp.get('items_inventory_get_response').get( 'items').get('item') total_get += req.page_size req.page_no = req.page_no + 1 return res def bad_sync_stock_qty(self, cr, uid, ids, context=None): """ 同步本条记录的库存数量到 电商店铺 """ port = 80 shop = self.pool.get('loewieec.shop').browse(cr, uid, ids[0], context=context) for product in shop.products: qty = product.erp_stock if qty < 1: continue setDefaultAppInfo(shop.appkey, shop.appsecret) req = SkusQuantityUpdateRequest(shop.apiurl, port) req.num_iid = long(product.ec_num_iid) req.skuid_quantities = "%s:%d" % (product.ec_sku_id, int(qty)) req.type = 1 resp = req.getResponse(shop.sessionkey) return True def _sync_stock_qty(self, cr, uid, ids, context=None): """ 同步本条记录的库存数量到 电商店铺 """ port = 80 shop = self.pool.get('loewieec.shop').browse(cr, uid, ids[0], context=context) for product in shop.products: qty = product.erp_stock if qty < 1: continue setDefaultAppInfo(shop.appkey, shop.appsecret) req = ItemQuantityUpdateRequest(shop.apiurl, port) req.num_iid = long(product.ec_num_iid) req.sku_id = product.ec_sku_id if qty < 0: qty = 0 req.quantity = int(qty) req.type = 1 resp = req.getResponse(shop.sessionkey) return True def search_product_sku(self, cr, uid, ids, num_iids=None, context=None): port = 80 shop = self.browse(cr, uid, ids[0], context=context) setDefaultAppInfo(shop.appkey, shop.appsecret) req = ItemSkusGetRequest(shop.apiurl, port) req.fields = "sku_id, num_iid, properties, price, status, memo, properties_name, outer_id,quantity,barcode,change_prop,sku_spec_id,extra_id" if not num_iids: req.num_iids = shop.tokenurl else: req.num_iids = num_iids resp = req.getResponse(shop.sessionkey) skus = resp.get('item_skus_get_response').get('skus', False).get('sku', False) return skus def search_product(self, cr, uid, ids, context=None): this = self.browse(cr, uid, ids, context=context)[0] res = self._search_product(cr, uid, ids, product_name=None, start_modified=this.start_modified, end_modified=this.end_modified, context=context) if len(res) < 1: return product_tmalljd_objs = self.pool.get('product.tmalljd') num_iids = [str(o['num_iid']) for o in res] titles = {} for item in res: titles[item.get('num_iid')] = item.get('title') skus_list = [] interval = 39 start = end = 0 final_end = len(num_iids) - 1 while start <= final_end: if start + interval > final_end: end = final_end else: end = start + interval sub_num_iids = ",".join(num_iids[start:end]) skus_list += self.search_product_sku(cr, uid, ids, num_iids=sub_num_iids, context=context) start = end + 1 for sku in skus_list: product_vals = { 'ec_shop_id': this.id, 'ec_price': float(sku['price']), 'ec_qty': sku['quantity'], 'ec_outer_code': sku['outer_id'], 'ec_sku_id': str(sku['sku_id']), 'ec_ean13': sku['barcode'] } num_iid = sku['num_iid'] product_vals['ec_num_iid'] = str(num_iid) product_vals['ec_title'] = titles[num_iid] pids = product_tmalljd_objs.search( cr, uid, [('ec_sku_id', '=', str(sku['sku_id'])), ('ec_shop_id', '=', this.id)], context=context) if len(pids) > 0: product_tmalljd_objs.write(cr, uid, pids[0], product_vals) else: product_tmalljd_objs.create(cr, uid, product_vals) return True def _search_product(self, cr, uid, ids, product_name=None, start_modified=None, end_modified=None, context=None): """ 1) 按商品名称,商品修改时间搜索店铺商品 2) start_modified、end_modified 都是UTC时间,需要加上8小时传给电商平台 """ shop_id = self.browse(cr, uid, ids[0], context=context) setDefaultAppInfo(shop_id.appkey, shop_id.appsecret) req = ItemsOnsaleGetRequest(shop_id.apiurl, 80) #req.fields="approve_status,num_iid,title,nick,outer_id,modified,num,type,price" req.fields = "approve_status,num_iid,title,nick,type,num,list_time,price,modified,delist_time,outer_id" if product_name: req.q = product_name #if start_modified: # start_modified = (datetime.strptime(str(start_modified),'%Y-%m-%d %H:%M:%S',) + timedelta(hours=8)).strftime('%Y-%m-%d %H:%M:%S') # req.start_modified = start_modified #if end_modified: # end_modified = (datetime.strptime(str(end_modified),'%Y-%m-%d %H:%M:%S',) + timedelta(hours=8)).strftime('%Y-%m-%d %H:%M:%S') # req.end_modified = end_modified req.page_no = 1 req.page_size = 100 total_get = 0 total_results = 100 res = [] while total_get < total_results: resp = req.getResponse(shop_id.sessionkey) total_results = resp.get('items_onsale_get_response').get( 'total_results') #_logger.info("Jimmy total_results :%d" % total_results) if total_results > 0: res += resp.get('items_onsale_get_response').get('items').get( 'item') total_get += req.page_size #_logger.info("Jimmy page_size :%d" % req.page_size) #_logger.info("Jimmy total_get :%d" % total_get) req.page_no = req.page_no + 1 # # 时间需要减去8小时 for r in res: r['modified'] = (datetime.strptime( r['modified'], '%Y-%m-%d %H:%M:%S', ) - timedelta(hours=8)).strftime('%Y-%m-%d %H:%M:%S') return res def create_shipping_address(self, cr, uid, partner_id, vals, context=None): partner_objs = self.pool.get('res.partner') #state_objs = self.pool.get('res.country.state') state_id = 0 if vals.get('state', False): state_id = self.pool.get('res.country.state').search( cr, uid, [('name', 'like', vals.get('state'))]) if not partner_id: return 0 partner_vals = { 'parent_id': partner_id, 'name': vals.get('name'), 'phone': vals.get('phone'), 'street': vals.get('street'), 'mobile': vals.get('mobile'), 'city': vals.get('city'), 'zip': vals.get('zip'), 'type': 'delivery', 'is_company': False, 'customer': False, 'supplier': False, } if state_id: partner_vals.update({'state': state_id[0]}) id = partner_objs.create(cr, uid, partner_vals, context=context) return id or 0 def remove_duplicate_orders(self, cr, uid, orders, context=None): sale_obj = self.pool.get('sale.order') submitted_references = [o['sale_code'] for o in orders] existing_order_ids = sale_obj.search( cr, uid, [('name', 'in', submitted_references)], context=context) existing_orders = sale_obj.read(cr, uid, existing_order_ids, ['name'], context=context) existing_references = set([o['name'] for o in existing_orders]) orders_to_save = [ o for o in orders if o['sale_code'] not in existing_references ] return orders_to_save def search_orders_by_modified_time(self, cr, uid, ids, status='WAIT_SELLER_SEND_GOODS', date_start=None, date_end=None, context=None): port = 80 shop = self.browse(cr, uid, ids[0], context=context) partner_id = shop.partner_id.id setDefaultAppInfo(shop.appkey, shop.appsecret) req = TradesSoldIncrementGetRequest(shop.apiurl, port) req.fields = "type,seller_nick,buyer_nick,created,sid,tid,status,buyer_memo,seller_memo,payment,discount_fee,adjust_fee,post_fee,total_fee, pay_time,end_time,modified,received_payment,price,alipay_id,receiver_name,receiver_state,receiver_city,receiver_district,receiver_address, receiver_zip,receiver_mobile,receiver_phone,orders.price,orders.num,orders.iid,orders.num_iid,orders.sku_id,orders.refund_status,orders.status,orders.oid, orders.total_fee,orders.payment,orders.discount_fee,orders.adjust_fee,orders.sku_properties_name,orders.outer_iid,orders.outer_sku_id" #req.status = status req.type = "instant_trade,auto_delivery,guarantee_trade,tmall_i18n" if shop.start_modified: #date_start = (datetime.strptime( shop.start_modified, '%Y-%m-%d %H:%M:%S',) + timedelta(hours=8)).strftime('%Y-%m-%d %H:%M:%S') #req.start_modified = date_start req.start_modified = shop.start_modified if shop.end_modified: #date_end = (datetime.strptime( shop.end_modified, '%Y-%m-%d %H:%M:%S',) + timedelta(hours=8)).strftime('%Y-%m-%d %H:%M:%S') #req.end_modified = date_end req.end_modified = shop.end_modified res = [] req.page_no = 1 req.page_size = 100 total_get = 0 total_results = 100 while total_get < total_results: resp = req.getResponse(shop.sessionkey) trades = resp.get('trades_sold_increment_get_response').get( 'trades', False) total_results = resp.get('trades_sold_increment_get_response').get( 'total_results') _logger.info("Jimmy total_results :%d" % total_results) if total_results > 0: res += trades.get('trade') total_get += req.page_size req.page_no = req.page_no + 1 _logger.info("Jimmy page_size :%d" % req.page_size) _logger.info("Jimmy total_get :%d" % total_get) # 时间需要减去8小时 # 单号加上店铺前缀 order_ids = [] for trade in res: trade['created'] = (datetime.strptime( trade['created'], '%Y-%m-%d %H:%M:%S', ) - timedelta(hours=8)).strftime('%Y-%m-%d %H:%M:%S') trade['pay_time'] = (datetime.strptime( trade.get('pay_time'), '%Y-%m-%d %H:%M:%S', ) - timedelta(hours=8)).strftime('%Y-%m-%d %H:%M:%S') trade['sale_code'] = '%s_%s' % (shop.code, trade.get('tid')) orders = self.remove_duplicate_orders(cr, uid, res, context=context) #orders = res for trade in orders: #try: # #_logger.info("Jimmy before create_order") #order_id = self.create_order(cr, uid, ids, trade, context = context ) order_id = self.create_order(cr, uid, ids, trade, context=context) # _logger.info("Jimmy after create_order") # order_ids.append(order_id) #except Exception, e: # syncerr = u"店铺[%s]订单[%s]同步错误: %s" % (shop.name, trade['tid'], e) # self.pool.get('loewieec.error').create(cr, uid, {'name':syncerr, 'shop_id': shop.id}, context = context ) # continue return order_ids def create_order(self, cr, uid, ids, trade, context=None): order_obj = self.pool.get('sale.order') shop = self.browse(cr, uid, ids[0], context=context) partner_id = shop.partner_id.id shipping_id = self.create_shipping_address( cr, uid, partner_id, { 'name': trade.get('receiver_name'), 'phone': trade.get('receiver_phone'), 'street': address, 'mobile': trade.get('receiver_mobile') }, context=context) #_logger.info("Jimmy create_shipping_address : %d" % shipping_id ) order_val = { 'name': "%s_%s" % (shop.code, trade.get('tid')), 'shop_id': shop.id, 'date_order': trade.get('pay_time') or datetime.now(), #订单支付时间 'create_date': trade.get('created'), #订单创建时间 'partner_id': partner_id, 'partner_invoice_id': partner_id, 'partner_shipping_id': shipping_id, 'warehouse_id': shop.warehouse_id.id, 'pricelist_id': shop.pricelist_id.id, 'company_id': 1, 'all_discounts': 0, 'picking_policy': 'one', 'state': 'draft', 'user_id': uid, 'order_policy': 'picking', 'client_order_ref': u'Loewieec_sync Generated', 'order_line': [], } post_vals = { 'product_uos_qty': 1, 'product_id': 1, 'product_uom': 1, 'price_unit': 1, 'product_uom_qty': 1, 'name': '.', 'delay': 7, 'discount': 0, } orders = trade.get('orders', {}).get('order', []) for o in orders: line_vals = { 'product_uos_qty': 1, 'product_id': 1, 'product_uom': 1, 'price_unit': 1, 'product_uom_qty': 1, 'name': '.', 'delay': 7, 'discount': 0, } product_tmalljd_ids = self.pool.get('product.tmalljd').search( cr, uid, [('ec_sku_id', '=', o.get('sku_id'))], context=context) #_logger.info("Jimmy num_iid : %s" % o.get('num_iid') ) #如果没有匹配到产品,报同步异常 if not product_tmalljd_ids: syncerr = u"订单导入错误: 匹配不到商品。tid=%s, 商品【%s】, outer_iid=%s, num_iid=%s, outer_sku_id=%s, sku_id=%s " % ( trade.get('tid'), o.get('title', ''), o.get( 'outer_iid', ''), o.get('num_iid', ''), o.get('outer_sku_id', ''), o.get('sku_id', '')) self.pool.get('loewieec.error').create(cr, uid, { 'name': syncerr, 'shop_id': shop.id }, context=context) return False product_tmalljd_obj = self.pool.get('product.tmalljd').browse( cr, uid, product_tmalljd_ids[0], context=context) product_id = product_tmalljd_obj.erp_product_id.id uom_id = product_tmalljd_obj.erp_product_id.uom_id.id #添加订单明细行 price_unit = float(o.get('payment', 0)) / o.get('num') or float( o.get('total_fee', 0)) / o.get('num') line_vals.update({ 'product_id': product_id, 'price_unit': price_unit, 'product_uos_qty': o.get('num'), 'product_uom_qty': o.get('num'), 'product_uom': uom_id }) order_val['order_line'].append((0, 0, line_vals)) post_vals.update({ 'product_id': shop.gift_product_id.id, 'price_unit': 0, 'product_uos_qty': 1, 'product_uom_qty': 1, 'product_uom': 1 }) order_val['order_line'].append((0, 0, post_vals)) order_id = order_obj.create(cr, uid, order_val, context=context) return order_id def get_tmall_time(self, cr, uid, ids, context=None): shop = self.browse(cr, uid, ids[0], context=context) setDefaultAppInfo(shop.appkey, shop.appsecret) req = TimeGetRequest(shop.apiurl, 80) resp = req.getResponse(shop.sessionkey) ttime = resp.get('time_get_response').get('time', False) if ttime: shop.tmall_time = ttime return True def search_orders_by_created_time(self, cr, uid, ids, status='WAIT_SELLER_SEND_GOODS', date_start=None, date_end=None, context=None): port = 80 shop = self.browse(cr, uid, ids[0], context=context) partner_id = shop.partner_id.id setDefaultAppInfo(shop.appkey, shop.appsecret) req = TradesSoldGetRequest(shop.apiurl, port) req.fields = "type,seller_nick,buyer_nick,created,sid,tid,status,buyer_memo,seller_memo,payment,discount_fee,adjust_fee,post_fee,total_fee, pay_time,end_time,modified,received_payment,price,alipay_id,receiver_name,receiver_state,receiver_city,receiver_district,receiver_address, receiver_zip,receiver_mobile,receiver_phone,orders.price,orders.num,orders.iid,orders.num_iid,orders.sku_id,orders.refund_status,orders.status,orders.oid, orders.total_fee,orders.payment,orders.discount_fee,orders.adjust_fee,orders.sku_properties_name,orders.outer_iid,orders.outer_sku_id" #req.status = status req.type = "instant_trade,auto_delivery,guarantee_trade,tmall_i18n" #if shop.start_modified: #date_start = (datetime.strptime( shop.start_modified, '%Y-%m-%d %H:%M:%S',) + timedelta(hours=8)).strftime('%Y-%m-%d %H:%M:%S') #req.start_modified = date_start #req.start_created = shop.start_modified #req.start_created = (datetime.now()- timedelta(hours=64)).strftime('%Y-%m-%d %H:%M:%S') req.start_created = datetime.now().strftime('%Y-%m-%d %H:%M:%S') #if shop.end_modified: #date_end = (datetime.strptime( shop.end_modified, '%Y-%m-%d %H:%M:%S',) + timedelta(hours=8)).strftime('%Y-%m-%d %H:%M:%S') #req.end_modified = date_end #req.end_created = shop.end_modified req.end_created = (datetime.now() + timedelta(hours=8)).strftime('%Y-%m-%d %H:%M:%S') res = [] req.page_no = 1 req.page_size = 100 total_get = 0 total_results = 100 while total_get < total_results: resp = req.getResponse(shop.sessionkey) trades = resp.get('trades_sold_get_response').get('trades', False) total_results = resp.get('trades_sold_get_response').get( 'total_results') _logger.info("Jimmy total_results :%d" % total_results) if total_results > 0: res += trades.get('trade') total_get += req.page_size req.page_no = req.page_no + 1 _logger.info("Jimmy page_size :%d" % req.page_size) _logger.info("Jimmy total_get :%d" % total_get) # 时间需要减去8小时 # 单号加上店铺前缀 order_ids = [] for trade in res: trade['created'] = (datetime.strptime( trade.get('created'), '%Y-%m-%d %H:%M:%S', ) - timedelta(hours=8)).strftime('%Y-%m-%d %H:%M:%S') trade['pay_time'] = (datetime.strptime( (trade.get('pay_time', False) or '2016-01-01 00:00:01'), '%Y-%m-%d %H:%M:%S', ) - timedelta(hours=8)).strftime('%Y-%m-%d %H:%M:%S') trade['sale_code'] = '%s_%s' % (shop.code, trade.get('tid')) orders = self.remove_duplicate_orders(cr, uid, res, context=context) #orders = res for trade in orders: #try: # #_logger.info("Jimmy before create_order") #order_id = self.create_order(cr, uid, ids, trade, context = context ) order_id = self.create_order(cr, uid, ids, trade, context=context) # _logger.info("Jimmy after create_order") # order_ids.append(order_id) #except Exception, e: # syncerr = u"店铺[%s]订单[%s]同步错误: %s" % (shop.name, trade['tid'], e) # self.pool.get('loewieec.error').create(cr, uid, {'name':syncerr, 'shop_id': shop.id}, context = context ) # continue return order_ids def search_orders_by_tid(self, cr, uid, ids, context=None): port = 80 shop = self.browse(cr, uid, ids[0], context=context) partner_id = shop.partner_id.id setDefaultAppInfo(shop.appkey, shop.appsecret) req = TradeFullinfoGetRequest(shop.apiurl, port) #req.fields="type,seller_nick,buyer_nick,created,sid,tid,status,buyer_memo,seller_memo,payment,discount_fee,adjust_fee,post_fee,total_fee, pay_time,end_time,modified,received_payment,price,alipay_id,receiver_name,receiver_state,receiver_city,receiver_district,receiver_address, receiver_zip,receiver_mobile,receiver_phone,orders.price,orders.num,orders.iid,orders.num_iid,orders.sku_id,orders.refund_status,orders.status,orders.oid, orders.total_fee,orders.payment,orders.discount_fee,orders.adjust_fee,orders.sku_properties_name,orders.outer_iid,orders.outer_sku_id" req.fields = "type,receiver_name,receiver_state,receiver_city,receiver_district,receiver_address, receiver_zip,receiver_mobile,receiver_phone" req.tid = shop.authurl resp = req.getResponse(shop.sessionkey) trade = resp.get('trade_fullinfo_get_response').get('trade', False) _logger.info("Jimmy type :%s" % trade.get('type')) _logger.info("Jimmy receiver_name :%s" % trade.get('receiver_name')) _logger.info("Jimmy receiver_address :%s" % trade.get('receiver_address')) _logger.info("Jimmy receiver_mobile :%s" % trade.get('receiver_mobile')) _logger.info("Jimmy receiver_phone :%s" % trade.get('receiver_phone')) return True
logger.debug('Trying to get connection to SERVER %s, PORT %s, USER %s, PWD %s, DRIVER %s' % (tk_pyodbc.server, tk_pyodbc.port, tk_pyodbc.user, tk_pyodbc.pwd, tk_pyodbc.driver)) logger.debug("DRIVER=%s;SERVER=%s;UID=%s;PWD=%s;PORT=%s;%s" % (tk_pyodbc.driver, tk_pyodbc.server, tk_pyodbc.user, tk_pyodbc.pwd, tk_pyodbc.port, tk_pyodbc.optional_params)) conn = pyodbc.connect("DRIVER=%s;SERVER=%s;UID=%s;PWD=%s;PORT=%s;%s" % (tk_pyodbc.driver, tk_pyodbc.server, tk_pyodbc.user, tk_pyodbc.pwd, tk_pyodbc.port, tk_pyodbc.optional_params), timeout=timeout or 0) logger.debug("Connection acquired") return conn except Exception, e: raise orm.except_orm(_('Error !'), _('Could not get a valid connection. %s') % e) def check_download_connection(self, cr, uid, ids, context=None): """ checks the connection to the sql server """ conn = self.get_connection(cr, uid, ids, context) conn.close() raise orm.except_orm(_('Success'), _('Connection to Oscar was successful!')) _columns = { 'name': fields.char('Name', size=64, required=True), 'database_type': fields.selection(__database_types, 'Database Type'), 'server': fields.char('Server address', size=256, required=False), 'database': fields.char('Database name', size=256, required=False), 'port': fields.integer('Database port'), 'user': fields.char('Username', size=256, required=False), 'pwd': fields.char('Password', size=256, required=False), 'driver': fields.char('Driver location', size=256), 'optional_params': fields.char('Optional parameters', size=256), } tk_pyodbc()
class wkf_activity(osv.osv): _name = "workflow.activity" _table = "wkf_activity" _order = "name" _columns = { 'name': fields.char('Name', required=True), 'wkf_id': fields.many2one('workflow', 'Workflow', required=True, select=True, ondelete='cascade'), 'split_mode': fields.selection([('XOR', 'Xor'), ('OR', 'Or'), ('AND', 'And')], 'Split Mode', size=3, required=True), 'join_mode': fields.selection([('XOR', 'Xor'), ('AND', 'And')], 'Join Mode', size=3, required=True), 'kind': fields.selection([('dummy', 'Dummy'), ('function', 'Function'), ('subflow', 'Subflow'), ('stopall', 'Stop All')], 'Kind', required=True), 'action': fields.text('Python Action'), 'action_id': fields.many2one('ir.actions.server', 'Server Action', ondelete='set null'), 'flow_start': fields.boolean('Flow Start'), 'flow_stop': fields.boolean('Flow Stop'), 'subflow_id': fields.many2one('workflow', 'Subflow'), 'signal_send': fields.char('Signal (subflow.*)'), 'out_transitions': fields.one2many('workflow.transition', 'act_from', 'Outgoing Transitions'), 'in_transitions': fields.one2many('workflow.transition', 'act_to', 'Incoming Transitions'), } _defaults = { 'kind': lambda *a: 'dummy', 'join_mode': lambda *a: 'XOR', 'split_mode': lambda *a: 'XOR', } def unlink(self, cr, uid, ids, context=None): if context is None: context = {} if not context.get('_force_unlink') and self.pool.get( 'workflow.workitem').search(cr, uid, [('act_id', 'in', ids)]): raise osv.except_osv( _('Operation Forbidden'), _('Please make sure no workitems refer to an activity before deleting it!' )) super(wkf_activity, self).unlink(cr, uid, ids, context=context)
except Exception, e: cr.rollback() logger.log(logging.WARNING, str(e)) def get(self): return self.__connection def set(self, connection): self.__connection = connection def remove(self): self.__connection = None _columns = { 'host':fields.char('Host', size=128, required=True), 'port': fields.integer('Port', required=True), 'ooo_restart_cmd': fields.char('OOO restart command', size=256, \ help='Enter the shell command that will be executed to restart the LibreOffice/OpenOffice background process. '+ \ 'The command will be executed as the user of the OpenERP server process,'+ \ 'so you may need to prefix it with sudo and configure your sudoers file to have this command executed without password.'), } class report_xml(osv.osv): _name = 'ir.actions.report.xml' _inherit = 'ir.actions.report.xml' _columns = { 'process_sep':fields.boolean('Process Separately'),
class im_livechat_channel(osv.Model): _name = 'im_livechat.channel' def _get_default_image(self, cr, uid, context=None): image_path = openerp.modules.get_module_resource( 'im_livechat', 'static/src/img', 'default.png') return tools.image_resize_image_big( open(image_path, 'rb').read().encode('base64')) def _get_image(self, cr, uid, ids, name, args, context=None): result = dict.fromkeys(ids, False) for obj in self.browse(cr, uid, ids, context=context): result[obj.id] = tools.image_get_resized_images(obj.image) return result def _set_image(self, cr, uid, id, name, value, args, context=None): return self.write(cr, uid, [id], {'image': tools.image_resize_image_big(value)}, context=context) def _are_you_inside(self, cr, uid, ids, name, arg, context=None): res = {} for record in self.browse(cr, uid, ids, context=context): res[record.id] = False for user in record.user_ids: if user.id == uid: res[record.id] = True break return res def _script_external(self, cr, uid, ids, name, arg, context=None): values = { "url": self.pool.get('ir.config_parameter').get_param( cr, openerp.SUPERUSER_ID, 'web.base.url'), "dbname": cr.dbname } res = {} for record in self.browse(cr, uid, ids, context=context): values["channel"] = record.id res[record.id] = self.pool['ir.ui.view'].render( cr, uid, 'im_livechat.external_loader', values, context=context) return res def _script_internal(self, cr, uid, ids, name, arg, context=None): values = { "url": self.pool.get('ir.config_parameter').get_param( cr, openerp.SUPERUSER_ID, 'web.base.url'), "dbname": cr.dbname } res = {} for record in self.browse(cr, uid, ids, context=context): values["channel"] = record.id res[record.id] = self.pool['ir.ui.view'].render( cr, uid, 'im_livechat.internal_loader', values, context=context) return res def _web_page(self, cr, uid, ids, name, arg, context=None): res = {} for record in self.browse(cr, uid, ids, context=context): res[record.id] = self.pool.get('ir.config_parameter').get_param(cr, openerp.SUPERUSER_ID, 'web.base.url') + \ "/im_livechat/support/%s/%i" % (cr.dbname, record.id) return res _columns = { 'name': fields.char(string="Channel Name", size=200, required=True), 'user_ids': fields.many2many('res.users', 'im_livechat_channel_im_user', 'channel_id', 'user_id', string="Users"), 'are_you_inside': fields.function(_are_you_inside, type='boolean', string='Are you inside the matrix?', store=False), 'script_internal': fields.function(_script_internal, type='text', string='Script (internal)', store=False), 'script_external': fields.function(_script_external, type='text', string='Script (external)', store=False), 'web_page': fields.function(_web_page, type='char', string='Web Page', store=False), 'button_text': fields.char(string="Text of the Button"), 'input_placeholder': fields.char(string="Chat Input Placeholder"), 'default_message': fields.char(string="Welcome Message", help="This is an automated 'welcome' message that your visitor will see when they initiate a new chat session."), # image: all image fields are base64 encoded and PIL-supported 'image': fields.binary("Photo", help="This field holds the image used as photo for the group, limited to 1024x1024px."), 'image_medium': fields.function(_get_image, fnct_inv=_set_image, string="Medium-sized photo", type="binary", multi="_get_image", store={ 'im_livechat.channel': (lambda self, cr, uid, ids, c={}: ids, ['image'], 10), }, help="Medium-sized photo of the group. It is automatically "\ "resized as a 128x128px image, with aspect ratio preserved. "\ "Use this field in form views or some kanban views."), 'image_small': fields.function(_get_image, fnct_inv=_set_image, string="Small-sized photo", type="binary", multi="_get_image", store={ 'im_livechat.channel': (lambda self, cr, uid, ids, c={}: ids, ['image'], 10), }, help="Small-sized photo of the group. It is automatically "\ "resized as a 64x64px image, with aspect ratio preserved. "\ "Use this field anywhere a small image is required."), } def _default_user_ids(self, cr, uid, context=None): return [(6, 0, [uid])] _defaults = { 'button_text': "Have a Question? Chat with us.", 'input_placeholder': "How may I help you?", 'default_message': '', 'user_ids': _default_user_ids, 'image': _get_default_image, } def get_available_users(self, cr, uid, channel_id, context=None): """ get available user of a given channel """ channel = self.browse(cr, uid, channel_id, context=context) users = [] for user_id in channel.user_ids: if (user_id.im_status == 'online'): users.append(user_id) return users def get_channel_session(self, cr, uid, channel_id, anonymous_name, context=None): """ return a session given a channel : create on with a registered user, or return false otherwise """ # get the avalable user of the channel users = self.get_available_users(cr, uid, channel_id, context=context) if len(users) == 0: return False user_id = random.choice(users).id # create the session, and add the link with the given channel Session = self.pool["im_chat.session"] newid = Session.create(cr, uid, { 'user_ids': [(4, user_id)], 'channel_id': channel_id, 'anonymous_name': anonymous_name }, context=context) return Session.session_info(cr, uid, [newid], context=context) def test_channel(self, cr, uid, channel, context=None): if not channel: return {} return { 'url': self.browse(cr, uid, channel[0], context=context or {}).web_page, 'type': 'ir.actions.act_url' } def get_info_for_chat_src(self, cr, uid, channel, context=None): url = self.pool.get('ir.config_parameter').get_param( cr, uid, 'web.base.url') chan = self.browse(cr, uid, channel, context=context) return { "url": url, 'buttonText': chan.button_text, 'inputPlaceholder': chan.input_placeholder, 'defaultMessage': chan.default_message, "channelName": chan.name, } def join(self, cr, uid, ids, context=None): self.write(cr, uid, ids, {'user_ids': [(4, uid)]}) return True def quit(self, cr, uid, ids, context=None): self.write(cr, uid, ids, {'user_ids': [(3, uid)]}) return True
try: file_data = image_file.read() self._logo_image = base64.encodestring(file_data) return self._logo_image finally: image_file.close() else: self._logo_image = base64.encodestring(im.read()) return self._logo_image def _get_image_fn(self, cr, uid, ids, name, args, context=None): image = self._get_image(cr, uid, context) return dict.fromkeys(ids, image) # ok to use .fromkeys() as the image is same for all _columns = { 'host':fields.char('Host', size=64, required=True), 'port':fields.integer('Port', required=True), 'ooo_restart_cmd': fields.char('OOO restart command', size=256, \ help='Enter the shell command that will be executed to restart the LibreOffice/OpenOffice background process.'+ \ 'The command will be executed as the user of the OpenERP server process,'+ \ 'so you may need to prefix it with sudo and configure your sudoers file to have this command executed without password.'), 'state':fields.selection([ ('init','Init'), ('error','Error'), ('done','Done'), ],'State', select=True, readonly=True), 'msg': fields.text('Message', readonly=True), 'error_details': fields.text('Error Details', readonly=True), 'link':fields.char('Installation Manual', size=128, help='Installation (Dependencies and Base system setup)', readonly=True), 'config_logo': fields.function(_get_image_fn, string='Image', type='binary', method=True),
class formulir_1111_a2(osv.osv): _name = 'pajak.formulir_1111_a2' _description = 'Formulir 1111 A2' _inherit = ['mail.thread'] def default_state(self, cr, uid, context={}): return 'draft' def default_name(self, cr, uid, context={}): return '/' def default_created_time(self, cr, uid, context={}): #TODO: Ticket #47 return datetime.now().strftime('%Y-%m-%d %H:%M:%S') def default_created_user_id(self, cr, uid, context={}): return uid def function_amount_all(self, cr, uid, ids, name, args, context=None): #TODO: Ticket #48 res = {} for formulir in self.browse(cr, uid, ids): total_dpp = 0.0 total_ppn = 0.0 total_ppnbm = 0.0 if formulir.detail_ids: for detail in formulir.detail_ids: total_dpp += detail.dpp total_ppn += detail.ppn total_ppnbm += detail.ppnbm res[id] = { 'total_dpp': total_dpp, 'total_ppn': total_ppn, 'total_ppnbm': total_ppnbm } return res _columns = { 'name': fields.char(string='# Dokumen', size=30, required=True, readonly=True), 'company_id': fields.many2one(string='Perusahaan', obj='res.company', required=True, readonly=True, states={'draft': [('readonly', False)]}), #TODO: Ticket #54 'nama_pkp': fields.char(string='Nama PKP', size=255, required=True, readonly=True, states={'draft': [('readonly', False)]}), #TODO: Ticket #54 'npwp': fields.char(string='NPWP', size=50, required=True, readonly=True, states={'draft': [('readonly', False)]}), #TODO: Ticket #54 'masa_pajak_id': fields.many2one(string='Masa Pajak', obj='pajak.masa_pajak', required=True, readonly=True, states={'draft': [('readonly', False)]}), #TODO: Ticket #54 'pembetulan_ke': fields.integer(string='Pembetulan Ke-', required=True, readonly=True, states={'draft': [('readonly', False)]}), #TODO: Ticket #54 'detail_ids': fields.one2many(string='Detail', obj='pajak.detail_formulir_1111_a2', fields_id='formulir_id', readonly=True, states={'draft': [('readonly', False)]}), #TODO: Ticket #54 'total_dpp': fields.function(fnct=function_amount_all, string='Total DPP', type='float', digits_compute=dp.get_precision('Account'), method=True, store=True, multi='all'), 'total_ppn': fields.function(fnct=function_amount_all, string='Total PPN', type='float', digits_compute=dp.get_precision('Account'), method=True, store=True, multi='all'), 'total_ppnbm': fields.function(fnct=function_amount_all, string='Total PPnBM', type='float', digits_compute=dp.get_precision('Account'), method=True, store=True, multi='all'), 'note': fields.text(string='Note'), 'state': fields.selection([('draft', 'Draft'), ('confirm', 'Waiting For Approval'), ('approve', 'Ready To Process'), ('done', 'Done'), ('cancel', 'Cancel')], 'Status', readonly=True), 'created_time': fields.datetime(string='Created Time', readonly=True), 'created_user_id': fields.many2one(string='Created By', obj='res.users', readonly=True), 'confirmed_time': fields.datetime(string='Confirmed Time', readonly=True), 'confirmed_user_id': fields.many2one(string='Confirmed By', obj='res.users', readonly=True), 'approved_time': fields.datetime(string='Approved Time', readonly=True), 'approved_user_id': fields.many2one(string='Approved By', obj='res.users', readonly=True), 'processed_time': fields.datetime(string='Processed Time', readonly=True), 'processed_user_id': fields.many2one(string='Process By', obj='res.users', readonly=True), 'cancelled_time': fields.datetime(string='Processed Time', readonly=True), 'cancelled_user_id': fields.many2one(string='Process By', obj='res.users', readonly=True), 'cancelled_reason': fields.text(string='Cancelled Reason', readonly=True), } _defaults = { 'name': default_name, 'state': default_state, 'created_time': default_created_time, 'created_user_id': default_created_user_id, } def workflow_action_confirm(self, cr, uid, ids, context={}): for id in ids: if not self.create_seqence(cr, uid, id): return False if not self.log_audit_trail(cr, uid, id, 'confirmed'): return False return True def workflow_action_approve(self, cr, uid, ids, context={}): for id in ids: if not self.log_audit_trail(cr, uid, id, 'approved'): return False return True def workflow_action_done(self, cr, uid, ids, context={}): for id in ids: if not self.log_audit_trail(cr, uid, id, 'processed'): return False return True def workflow_action_cancel(self, cr, uid, ids, context={}): for id in ids: if not self.log_audit_trail(cr, uid, id, 'cancelled'): return False return True def button_action_set_to_draft(self, cr, uid, ids, context={}): for id in ids: if not self.delete_workflow_instance(cr, uid, id): return False if not self.create_workflow_instance(cr, uid, id): return False if not self.clear_log_audit(cr, uid, id): return False if not self.log_audit_trail(cr, uid, 'created'): return False return True def button_action_cancel(self, cr, uid, ids, context={}): wkf_service = netsvc.LocalService('workflow') for id in ids: if not self.delete_workflow_instance(cr, uid, id): return False if not self.create_workflow_instance(cr, uid, id): return False wkf_service.trg_validate(uid, 'pajak.formulir_1111_a2', id, 'button_cancel', cr) return True def write_cancel_descriprion(self, cr, uid, reason): self.write(cr, uid, [id], {'cancelled_descriprion': reason}) return True def log_audit_trail(self, cr, uid, id, state): #TODO: Ticket #50 if state not in [ 'created', 'confirmed', 'approved', 'processed', 'cancelled' ]: raise osv.except_osv(_('Peringatan!'), _('Error pada method log_audit')) return False state_dict = { 'created': 'draft', 'confirmed': 'confirm', 'approved': 'approve', 'processed': 'done', 'cancelled': 'cancel' } val = { '%s_user_id' % (state): uid, '%s_time' % (state): datetime.now().strftime('%Y-%m-%d %H:%M:%S'), 'state': state_dict.get(state, False), } self.write(cr, uid, [id], val) return True def delete_workflow_instance(self, cr, uid, id): #TODO: Ticket #51 wkf_service = netsvc.LocalService('workflow') wkf_service.trg_delete(uid, 'pajak.formulir_1111_a2', id, cr) return True def create_workflow_instance(self, cr, uid, id): #TODO: Ticket #52 wkf_service = netsvc.LocalService('workflow') wkf_service.trg_create(uid, 'pajak.formulir_1111_a2', id, cr) return True def onchange_company_id(self, cr, uid, ids, comapny_id): #TODO: Ticket #53 obj_res_company = self.pool.get('res.company') value = {} domain = {} warning = {} if company_id: npwp = obj_res_company.browse(cr, uid, company_id).partner_id.npwp value.update({'npwp': npwp}) return {'value': value, 'domain': domain, 'warning': warning} def create_sequence(cr, uid, id): #TODO: Ticket #49 obj_sequence = self.pool.get('ir.sequence') obj_company = self.pool.get('res.company') formulir = self.browse(cr, uid, [id])[0] if formulir.name == '/': if formulir.company_id.sequence_formulir_1111_a2.id: sequence = obj_sequence.next_by_id( cr, uid, formulir.company_id.sequence_formulir_1111_a2.id) self.write(cr, uid, [id], {'name': sequence}) else: raise osv.except_osv( _('Peringatan'), _('Sequence Formulir 1111 A2 Belum Di-Set')) return False return True
'remarks': kail.remarks } kail.asset_id.write({'asset_usage_ids':[(0,0, create_data)]}) kail.write({'state':'done'}) except Exception, e: kail.write({'reason':e}) done = False if done: kai.write({'state':'done'}) pass IMPORT_TYPE = (('lq','Liquidation'),('usage','Usage'),('spec','Specification')) _columns={ 'name':fields.date("Import Date", states={'done':[('readonly',True)]}, required=True), 'remarks':fields.char('Remarks',size=256, states={'done':[('readonly',True)]}), 'state':fields.selection((('draft','Draft'),('done','Completed')),'State',readonly=True), 'detail_ids':fields.one2many('kderp.import.asset.detail','import_id','Details',states={'done':[('readonly',True)]}), 'detail_spec_ids':fields.one2many('kderp.import.asset.detail','import_id','Details',states={'done':[('readonly',True)]}), 'detail_usage_ids':fields.one2many('kderp.import.asset.detail','import_id','Details',states={'done':[('readonly',True)]}), 'import_type':fields.selection(IMPORT_TYPE,'Import type',states={'done':[('readonly',True)]}), } _defaults={ 'name':lambda *a: time.strftime('%Y-%m-%d'), 'state':lambda *a: 'draft' } kderp_asset_import()
class module(osv.osv): _name = "ir.module.module" _rec_name = "shortdesc" _description = "Module" def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False): res = super(module, self).fields_view_get(cr, uid, view_id=view_id, view_type=view_type, context=context, toolbar=toolbar, submenu=False) result = self.pool.get('ir.model.data').get_object_reference( cr, uid, 'base', 'action_server_module_immediate_install')[1] if view_type == 'form': if res.get('toolbar', False): list = [ rec for rec in res['toolbar']['action'] if rec.get('id', False) != result ] res['toolbar'] = {'action': list} return res @classmethod def get_module_info(cls, name): info = {} try: info = modules.load_information_from_description_file(name) except Exception: _logger.debug( 'Error when trying to fetch information for ' 'module %s', name, exc_info=True) return info def _get_desc(self, cr, uid, ids, field_name=None, arg=None, context=None): res = dict.fromkeys(ids, '') for module in self.browse(cr, uid, ids, context=context): path = get_module_resource(module.name, 'static/description/index.html') if path: with tools.file_open(path, 'rb') as desc_file: doc = desc_file.read() html = lxml.html.document_fromstring(doc) for element, attribute, link, pos in html.iterlinks(): if element.get('src') and not '//' in element.get( 'src') and not 'static/' in element.get('src'): element.set( 'src', "/%s/static/description/%s" % (module.name, element.get('src'))) res[module.id] = html_sanitize(lxml.html.tostring(html)) else: overrides = { 'embed_stylesheet': False, 'doctitle_xform': False, 'output_encoding': 'unicode', 'xml_declaration': False, } output = publish_string(source=module.description or '', settings_overrides=overrides, writer=MyWriter()) res[module.id] = html_sanitize(output) return res def _get_latest_version(self, cr, uid, ids, field_name=None, arg=None, context=None): default_version = modules.adapt_version('1.0') res = dict.fromkeys(ids, default_version) for m in self.browse(cr, uid, ids): res[m.id] = self.get_module_info(m.name).get( 'version', default_version) return res def _get_views(self, cr, uid, ids, field_name=None, arg=None, context=None): res = {} model_data_obj = self.pool.get('ir.model.data') dmodels = [] if field_name is None or 'views_by_module' in field_name: dmodels.append('ir.ui.view') if field_name is None or 'reports_by_module' in field_name: dmodels.append('ir.actions.report.xml') if field_name is None or 'menus_by_module' in field_name: dmodels.append('ir.ui.menu') assert dmodels, "no models for %s" % field_name for module_rec in self.browse(cr, uid, ids, context=context): res_mod_dic = res[module_rec.id] = { 'menus_by_module': [], 'reports_by_module': [], 'views_by_module': [] } # Skip uninstalled modules below, no data to find anyway. if module_rec.state not in ('installed', 'to upgrade', 'to remove'): continue # then, search and group ir.model.data records imd_models = dict([(m, []) for m in dmodels]) imd_ids = model_data_obj.search(cr, uid, [('module', '=', module_rec.name), ('model', 'in', tuple(dmodels))]) for imd_res in model_data_obj.read(cr, uid, imd_ids, ['model', 'res_id'], context=context): imd_models[imd_res['model']].append(imd_res['res_id']) def browse(model): M = self.pool[model] # as this method is called before the module update, some xmlid may be invalid at this stage # explictly filter records before reading them ids = M.exists(cr, uid, imd_models.get(model, []), context) return M.browse(cr, uid, ids, context) def format_view(v): aa = v.inherit_id and '* INHERIT ' or '' return '%s%s (%s)' % (aa, v.name, v.type) res_mod_dic['views_by_module'] = map(format_view, browse('ir.ui.view')) res_mod_dic['reports_by_module'] = map( attrgetter('name'), browse('ir.actions.report.xml')) res_mod_dic['menus_by_module'] = map(attrgetter('complete_name'), browse('ir.ui.menu')) for key in res.iterkeys(): for k, v in res[key].iteritems(): res[key][k] = "\n".join(sorted(v)) return res def _get_icon_image(self, cr, uid, ids, field_name=None, arg=None, context=None): res = dict.fromkeys(ids, '') for module in self.browse(cr, uid, ids, context=context): path = get_module_resource(module.name, 'static', 'description', 'icon.png') if path: image_file = tools.file_open(path, 'rb') try: res[module.id] = image_file.read().encode('base64') finally: image_file.close() return res _columns = { 'name': fields.char("Technical Name", readonly=True, required=True, select=True), 'category_id': fields.many2one('ir.module.category', 'Category', readonly=True, select=True), 'shortdesc': fields.char('Module Name', readonly=True, translate=True), 'summary': fields.char('Summary', readonly=True, translate=True), 'description': fields.text("Description", readonly=True, translate=True), 'description_html': fields.function(_get_desc, string='Description HTML', type='html', method=True, readonly=True), 'author': fields.char("Author", readonly=True), 'maintainer': fields.char('Maintainer', readonly=True), 'contributors': fields.text('Contributors', readonly=True), 'website': fields.char("Website", readonly=True), # attention: Incorrect field names !! # installed_version refers the latest version (the one on disk) # latest_version refers the installed version (the one in database) # published_version refers the version available on the repository 'installed_version': fields.function(_get_latest_version, string='Latest Version', type='char'), 'latest_version': fields.char('Installed Version', readonly=True), 'published_version': fields.char('Published Version', readonly=True), 'url': fields.char('URL', readonly=True), 'sequence': fields.integer('Sequence'), 'dependencies_id': fields.one2many('ir.module.module.dependency', 'module_id', 'Dependencies', readonly=True), 'auto_install': fields.boolean( 'Automatic Installation', help='An auto-installable module is automatically installed by the ' 'system when all its dependencies are satisfied. ' 'If the module has no dependency, it is always installed.'), 'state': fields.selection([('uninstallable', 'Not Installable'), ('uninstalled', 'Not Installed'), ('installed', 'Installed'), ('to upgrade', 'To be upgraded'), ('to remove', 'To be removed'), ('to install', 'To be installed')], string='Status', readonly=True, select=True), 'demo': fields.boolean('Demo Data', readonly=True), 'license': fields.selection( [('GPL-2', 'GPL Version 2'), ('GPL-2 or any later version', 'GPL-2 or later version'), ('GPL-3', 'GPL Version 3'), ('GPL-3 or any later version', 'GPL-3 or later version'), ('AGPL-3', 'Affero GPL-3'), ('LGPL-3', 'LGPL Version 3'), ('Other OSI approved licence', 'Other OSI Approved Licence'), ('OEEL-1', 'Odoo Enterprise Edition License v1.0'), ('Other proprietary', 'Other Proprietary')], string='License', readonly=True), 'menus_by_module': fields.function(_get_views, string='Menus', type='text', multi="meta", store=True), 'reports_by_module': fields.function(_get_views, string='Reports', type='text', multi="meta", store=True), 'views_by_module': fields.function(_get_views, string='Views', type='text', multi="meta", store=True), 'application': fields.boolean('Application', readonly=True), 'icon': fields.char('Icon URL'), 'icon_image': fields.function(_get_icon_image, string='Icon', type="binary"), } _defaults = { 'state': 'uninstalled', 'sequence': 100, 'demo': False, 'license': 'LGPL-3', } _order = 'sequence,name' def _name_uniq_msg(self, cr, uid, ids, context=None): return _('The name of the module must be unique !') _sql_constraints = [ ('name_uniq', 'UNIQUE (name)', _name_uniq_msg), ] def unlink(self, cr, uid, ids, context=None): if not ids: return True if isinstance(ids, (int, long)): ids = [ids] mod_names = [] for mod in self.read(cr, uid, ids, ['state', 'name'], context): if mod['state'] in ('installed', 'to upgrade', 'to remove', 'to install'): raise UserError( _('You try to remove a module that is installed or will be installed' )) mod_names.append(mod['name']) #Removing the entry from ir_model_data #ids_meta = self.pool.get('ir.model.data').search(cr, uid, [('name', '=', 'module_meta_information'), ('module', 'in', mod_names)]) #if ids_meta: # self.pool.get('ir.model.data').unlink(cr, uid, ids_meta, context) self.clear_caches() return super(module, self).unlink(cr, uid, ids, context=context) @staticmethod def _check_external_dependencies(terp): depends = terp.get('external_dependencies') if not depends: return for pydep in depends.get('python', []): try: importlib.import_module(pydep) except ImportError: raise ImportError('No module named %s' % (pydep, )) for binary in depends.get('bin', []): try: tools.find_in_path(binary) except IOError: raise Exception('Unable to find %r in path' % (binary, )) @classmethod def check_external_dependencies(cls, module_name, newstate='to install'): terp = cls.get_module_info(module_name) try: cls._check_external_dependencies(terp) except Exception, e: if newstate == 'to install': msg = _( 'Unable to install module "%s" because an external dependency is not met: %s' ) elif newstate == 'to upgrade': msg = _( 'Unable to upgrade module "%s" because an external dependency is not met: %s' ) else: msg = _( 'Unable to process module "%s" because an external dependency is not met: %s' ) raise UserError(msg % (module_name, e.args[0]))
#the Free Software Foundation, either version 3 of the License, or # #(at your option) any later version. # # # #This program is distributed in the hope that it will be useful, # #but WITHOUT ANY WARRANTY; without even the implied warranty of # #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # #GNU Affero General Public License for more details. # # # #You should have received a copy of the GNU Affero General Public License # #along with this program. If not, see <http://www.gnu.org/licenses/>. # ############################################################################### from openerp.osv import orm, fields FISCAL_POSITION_COLUMNS = { 'name': fields.char('Fiscal Position', size=128, required=True), 'fiscal_category_id': fields.many2one( 'l10n_br_account.fiscal.category', 'Categoria Fiscal'), 'fiscal_category_fiscal_type': fields.related( 'fiscal_category_id', 'fiscal_type', type='char', readonly=True, relation='l10n_br_account.fiscal.category', store=True, string='Fiscal Type'), 'type': fields.selection([('input', 'Entrada'), ('output', 'Saida')], 'Tipo'), 'type_tax_use': fields.selection( [('sale', 'Sale'), ('purchase', 'Purchase'), ('all', 'All')], 'Tax Application'), 'inv_copy_note': fields.boolean(u'Copiar Observação na Nota Fiscal'), 'asset_operation': fields.boolean(u'Operação de Aquisição de Ativo', help=u"""Caso seja marcada essa opção, será incluido o IPI na base de calculo do ICMS."""),
class mrp_repair(osv.osv): _name = 'mrp.repair' _inherit = 'mail.thread' _description = 'Repair Order' def _amount_untaxed(self, cr, uid, ids, field_name, arg, context=None): """ Calculates untaxed amount. @param self: The object pointer @param cr: The current row, from the database cursor, @param uid: The current user ID for security checks @param ids: List of selected IDs @param field_name: Name of field. @param arg: Argument @param context: A standard dictionary for contextual values @return: Dictionary of values. """ res = {} cur_obj = self.pool.get('res.currency') for repair in self.browse(cr, uid, ids, context=context): res[repair.id] = 0.0 for line in repair.operations: res[repair.id] += line.price_subtotal for line in repair.fees_lines: res[repair.id] += line.price_subtotal cur = repair.pricelist_id.currency_id res[repair.id] = cur_obj.round(cr, uid, cur, res[repair.id]) return res def _amount_tax(self, cr, uid, ids, field_name, arg, context=None): """ Calculates taxed amount. @param field_name: Name of field. @param arg: Argument @return: Dictionary of values. """ res = {} #return {}.fromkeys(ids, 0) cur_obj = self.pool.get('res.currency') tax_obj = self.pool.get('account.tax') for repair in self.browse(cr, uid, ids, context=context): val = 0.0 cur = repair.pricelist_id.currency_id for line in repair.operations: #manage prices with tax included use compute_all instead of compute if line.to_invoice and line.tax_id: tax_calculate = tax_obj.compute_all( cr, uid, line.tax_id, line.price_unit, cur, line.product_uom_qty, line.product_id.id, repair.partner_id.id) for c in tax_calculate['taxes']: val += c['amount'] for line in repair.fees_lines: if line.to_invoice and line.tax_id: tax_calculate = tax_obj.compute_all( cr, uid, line.tax_id, line.price_unit, cur, line.product_uom_qty, line.product_id.id, repair.partner_id.id) for c in tax_calculate['taxes']: val += c['amount'] res[repair.id] = cur_obj.round(cr, uid, cur, val) return res def _amount_total(self, cr, uid, ids, field_name, arg, context=None): """ Calculates total amount. @param field_name: Name of field. @param arg: Argument @return: Dictionary of values. """ res = {} untax = self._amount_untaxed(cr, uid, ids, field_name, arg, context=context) tax = self._amount_tax(cr, uid, ids, field_name, arg, context=context) cur_obj = self.pool.get('res.currency') for id in ids: repair = self.browse(cr, uid, id, context=context) cur = repair.pricelist_id.currency_id res[id] = cur_obj.round(cr, uid, cur, untax.get(id, 0.0) + tax.get(id, 0.0)) return res def _get_default_address(self, cr, uid, ids, field_name, arg, context=None): res = {} partner_obj = self.pool.get('res.partner') for data in self.browse(cr, uid, ids, context=context): adr_id = False if data.partner_id: adr_id = partner_obj.address_get(cr, uid, [data.partner_id.id], ['default'])['default'] res[data.id] = adr_id return res def _get_lines(self, cr, uid, ids, context=None): return self.pool['mrp.repair'].search(cr, uid, [('operations', 'in', ids)], context=context) def _get_fee_lines(self, cr, uid, ids, context=None): return self.pool['mrp.repair'].search(cr, uid, [('fees_lines', 'in', ids)], context=context) _columns = { 'name': fields.char('Repair Reference', required=True, states={'confirmed': [('readonly', True)]}, copy=False), 'product_id': fields.many2one('product.product', string='Product to Repair', required=True, readonly=True, states={'draft': [('readonly', False)]}), 'product_qty': fields.float( 'Product Quantity', digits_compute=dp.get_precision('Product Unit of Measure'), required=True, readonly=True, states={'draft': [('readonly', False)]}), 'product_uom': fields.many2one('product.uom', 'Product Unit of Measure', required=True, readonly=True, states={'draft': [('readonly', False)]}), 'partner_id': fields.many2one( 'res.partner', 'Partner', select=True, help= 'Choose partner for whom the order will be invoiced and delivered.', states={'confirmed': [('readonly', True)]}), 'address_id': fields.many2one('res.partner', 'Delivery Address', domain="[('parent_id','=',partner_id)]", states={'confirmed': [('readonly', True)]}), 'default_address_id': fields.function(_get_default_address, type="many2one", relation="res.partner"), 'state': fields.selection( [('draft', 'Quotation'), ('cancel', 'Cancelled'), ('confirmed', 'Confirmed'), ('under_repair', 'Under Repair'), ('ready', 'Ready to Repair'), ('2binvoiced', 'To be Invoiced'), ('invoice_except', 'Invoice Exception'), ('done', 'Repaired')], 'Status', readonly=True, track_visibility='onchange', copy=False, help= ' * The \'Draft\' status is used when a user is encoding a new and unconfirmed repair order. \ \n* The \'Confirmed\' status is used when a user confirms the repair order. \ \n* The \'Ready to Repair\' status is used to start to repairing, user can start repairing only after repair order is confirmed. \ \n* The \'To be Invoiced\' status is used to generate the invoice before or after repairing done. \ \n* The \'Done\' status is set when repairing is completed.\ \n* The \'Cancelled\' status is used when user cancel repair order.' ), 'location_id': fields.many2one('stock.location', 'Current Location', select=True, required=True, readonly=True, states={ 'draft': [('readonly', False)], 'confirmed': [('readonly', True)] }), 'location_dest_id': fields.many2one('stock.location', 'Delivery Location', readonly=True, required=True, states={ 'draft': [('readonly', False)], 'confirmed': [('readonly', True)] }), 'lot_id': fields.many2one('stock.production.lot', 'Repaired Lot', domain="[('product_id','=', product_id)]", help="Products repaired are all belonging to this lot", oldname="prodlot_id"), 'guarantee_limit': fields.date('Warranty Expiration', states={'confirmed': [('readonly', True)]}), 'operations': fields.one2many('mrp.repair.line', 'repair_id', 'Operation Lines', readonly=True, states={'draft': [('readonly', False)]}, copy=True), 'pricelist_id': fields.many2one('product.pricelist', 'Pricelist', help='Pricelist of the selected partner.'), 'partner_invoice_id': fields.many2one('res.partner', 'Invoicing Address'), 'invoice_method': fields.selection( [("none", "No Invoice"), ("b4repair", "Before Repair"), ("after_repair", "After Repair")], "Invoice Method", select=True, required=True, states={'draft': [('readonly', False)]}, readonly=True, help= 'Selecting \'Before Repair\' or \'After Repair\' will allow you to generate invoice before or after the repair is done respectively. \'No invoice\' means you don\'t want to generate invoice for this repair order.' ), 'invoice_id': fields.many2one('account.invoice', 'Invoice', readonly=True, track_visibility="onchange", copy=False), 'move_id': fields.many2one('stock.move', 'Move', readonly=True, help="Move created by the repair order", track_visibility="onchange", copy=False), 'fees_lines': fields.one2many('mrp.repair.fee', 'repair_id', 'Fees', readonly=True, states={'draft': [('readonly', False)]}, copy=True), 'internal_notes': fields.text('Internal Notes'), 'quotation_notes': fields.text('Quotation Notes'), 'company_id': fields.many2one('res.company', 'Company'), 'invoiced': fields.boolean('Invoiced', readonly=True, copy=False), 'repaired': fields.boolean('Repaired', readonly=True, copy=False), 'amount_untaxed': fields.function(_amount_untaxed, string='Untaxed Amount', store={ 'mrp.repair': (lambda self, cr, uid, ids, c={}: ids, ['operations', 'fees_lines'], 10), 'mrp.repair.line': (_get_lines, [ 'price_unit', 'price_subtotal', 'product_id', 'tax_id', 'product_uom_qty', 'product_uom' ], 10), 'mrp.repair.fee': (_get_fee_lines, [ 'price_unit', 'price_subtotal', 'product_id', 'tax_id', 'product_uom_qty', 'product_uom' ], 10), }), 'amount_tax': fields.function(_amount_tax, string='Taxes', store={ 'mrp.repair': (lambda self, cr, uid, ids, c={}: ids, ['operations', 'fees_lines'], 10), 'mrp.repair.line': (_get_lines, [ 'price_unit', 'price_subtotal', 'product_id', 'tax_id', 'product_uom_qty', 'product_uom' ], 10), 'mrp.repair.fee': (_get_fee_lines, [ 'price_unit', 'price_subtotal', 'product_id', 'tax_id', 'product_uom_qty', 'product_uom' ], 10), }), 'amount_total': fields.function(_amount_total, string='Total', store={ 'mrp.repair': (lambda self, cr, uid, ids, c={}: ids, ['operations', 'fees_lines'], 10), 'mrp.repair.line': (_get_lines, [ 'price_unit', 'price_subtotal', 'product_id', 'tax_id', 'product_uom_qty', 'product_uom' ], 10), 'mrp.repair.fee': (_get_fee_lines, [ 'price_unit', 'price_subtotal', 'product_id', 'tax_id', 'product_uom_qty', 'product_uom' ], 10), }), } def _default_stock_location(self, cr, uid, context=None): try: warehouse = self.pool.get('ir.model.data').get_object( cr, uid, 'stock', 'warehouse0') return warehouse.lot_stock_id.id except: return False _defaults = { 'state': lambda *a: 'draft', 'name': lambda obj, cr, uid, context: obj.pool.get('ir.sequence').next_by_code( cr, uid, 'mrp.repair'), 'invoice_method': lambda *a: 'none', 'company_id': lambda self, cr, uid, context: self.pool.get('res.company'). _company_default_get(cr, uid, 'mrp.repair', context=context), 'pricelist_id': lambda self, cr, uid, context: self.pool.get( 'product.pricelist').search(cr, uid, [('type', '=', 'sale')])[0], 'product_qty': 1.0, 'location_id': _default_stock_location, } _sql_constraints = [ ('name', 'unique (name)', 'The name of the Repair Order must be unique!'), ] def onchange_product_id(self, cr, uid, ids, product_id=None): """ On change of product sets some values. @param product_id: Changed product @return: Dictionary of values. """ product = False if product_id: product = self.pool.get("product.product").browse( cr, uid, product_id) return { 'value': { 'guarantee_limit': False, 'lot_id': False, 'product_uom': product and product.uom_id.id or False, } } def onchange_product_uom(self, cr, uid, ids, product_id, product_uom, context=None): res = {'value': {}} if not product_uom or not product_id: return res product = self.pool.get('product.product').browse(cr, uid, product_id, context=context) uom = self.pool.get('product.uom').browse(cr, uid, product_uom, context=context) if uom.category_id.id != product.uom_id.category_id.id: res['warning'] = { 'title': _('Warning'), 'message': _('The Product Unit of Measure you chose has a different category than in the product form.' ) } res['value'].update({'product_uom': product.uom_id.id}) return res def onchange_location_id(self, cr, uid, ids, location_id=None): """ On change of location """ return {'value': {'location_dest_id': location_id}} def button_dummy(self, cr, uid, ids, context=None): return True def onchange_partner_id(self, cr, uid, ids, part, address_id): """ On change of partner sets the values of partner address, partner invoice address and pricelist. @param part: Changed id of partner. @param address_id: Address id from current record. @return: Dictionary of values. """ part_obj = self.pool.get('res.partner') pricelist_obj = self.pool.get('product.pricelist') if not part: return { 'value': { 'address_id': False, 'partner_invoice_id': False, 'pricelist_id': pricelist_obj.search(cr, uid, [('type', '=', 'sale')])[0] } } addr = part_obj.address_get(cr, uid, [part], ['delivery', 'invoice', 'default']) partner = part_obj.browse(cr, uid, part) pricelist = partner.property_product_pricelist and partner.property_product_pricelist.id or False return { 'value': { 'address_id': addr['delivery'] or addr['default'], 'partner_invoice_id': addr['invoice'], 'pricelist_id': pricelist } } def action_cancel_draft(self, cr, uid, ids, *args): """ Cancels repair order when it is in 'Draft' state. @param *arg: Arguments @return: True """ if not len(ids): return False mrp_line_obj = self.pool.get('mrp.repair.line') for repair in self.browse(cr, uid, ids): mrp_line_obj.write(cr, uid, [l.id for l in repair.operations], {'state': 'draft'}) self.write(cr, uid, ids, {'state': 'draft'}) return self.create_workflow(cr, uid, ids) def action_confirm(self, cr, uid, ids, *args): """ Repair order state is set to 'To be invoiced' when invoice method is 'Before repair' else state becomes 'Confirmed'. @param *arg: Arguments @return: True """ mrp_line_obj = self.pool.get('mrp.repair.line') for o in self.browse(cr, uid, ids): if (o.invoice_method == 'b4repair'): self.write(cr, uid, [o.id], {'state': '2binvoiced'}) else: self.write(cr, uid, [o.id], {'state': 'confirmed'}) for line in o.operations: if line.product_id.track_production: raise UserError( _("Serial number is required for operation line with product '%s'" ) % (line.product_id.name)) mrp_line_obj.write(cr, uid, [l.id for l in o.operations], {'state': 'confirmed'}) return True def action_cancel(self, cr, uid, ids, context=None): """ Cancels repair order. @return: True """ mrp_line_obj = self.pool.get('mrp.repair.line') for repair in self.browse(cr, uid, ids, context=context): if not repair.invoiced: mrp_line_obj.write(cr, uid, [l.id for l in repair.operations], {'state': 'cancel'}, context=context) else: raise UserError(_('Repair order is already invoiced.')) return self.write(cr, uid, ids, {'state': 'cancel'}) def wkf_invoice_create(self, cr, uid, ids, *args): self.action_invoice_create(cr, uid, ids) return True def action_invoice_create(self, cr, uid, ids, group=False, context=None): """ Creates invoice(s) for repair order. @param group: It is set to true when group invoice is to be generated. @return: Invoice Ids. """ res = {} invoices_group = {} inv_line_obj = self.pool.get('account.invoice.line') inv_obj = self.pool.get('account.invoice') repair_line_obj = self.pool.get('mrp.repair.line') repair_fee_obj = self.pool.get('mrp.repair.fee') for repair in self.browse(cr, uid, ids, context=context): res[repair.id] = False if repair.state in ('draft', 'cancel') or repair.invoice_id: continue if not (repair.partner_id.id and repair.partner_invoice_id.id): raise UserError( _('You have to select a Partner Invoice Address in the repair form!' )) comment = repair.quotation_notes if (repair.invoice_method != 'none'): if group and repair.partner_invoice_id.id in invoices_group: inv_id = invoices_group[repair.partner_invoice_id.id] invoice = inv_obj.browse(cr, uid, inv_id) invoice_vals = { 'name': invoice.name + ', ' + repair.name, 'origin': invoice.origin + ', ' + repair.name, 'comment': (comment and (invoice.comment and invoice.comment + "\n" + comment or comment)) or (invoice.comment and invoice.comment or ''), } inv_obj.write(cr, uid, [inv_id], invoice_vals, context=context) else: if not repair.partner_id.property_account_receivable_id: raise UserError( _('No account defined for partner "%s".') % repair.partner_id.name) account_id = repair.partner_id.property_account_receivable_id.id inv = { 'name': repair.name, 'origin': repair.name, 'type': 'out_invoice', 'account_id': account_id, 'partner_id': repair.partner_invoice_id.id or repair.partner_id.id, 'currency_id': repair.pricelist_id.currency_id.id, 'comment': repair.quotation_notes, 'fiscal_position_id': repair.partner_id.property_account_position_id.id } inv_id = inv_obj.create(cr, uid, inv) invoices_group[repair.partner_invoice_id.id] = inv_id self.write(cr, uid, repair.id, { 'invoiced': True, 'invoice_id': inv_id }) for operation in repair.operations: if operation.to_invoice: if group: name = repair.name + '-' + operation.name else: name = operation.name if operation.product_id.property_account_income_id: account_id = operation.product_id.property_account_income_id.id elif operation.product_id.categ_id.property_account_income_categ_id: account_id = operation.product_id.categ_id.property_account_income_categ_id.id else: raise UserError( _('No account defined for product "%s".') % operation.product_id.name) invoice_line_id = inv_line_obj.create( cr, uid, { 'invoice_id': inv_id, 'name': name, 'origin': repair.name, 'account_id': account_id, 'quantity': operation.product_uom_qty, 'invoice_line_tax_ids': [ (6, 0, [x.id for x in operation.tax_id]) ], 'uos_id': operation.product_uom.id, 'price_unit': operation.price_unit, 'price_subtotal': operation.product_uom_qty * operation.price_unit, 'product_id': operation.product_id and operation.product_id.id or False }) repair_line_obj.write( cr, uid, [operation.id], { 'invoiced': True, 'invoice_line_id': invoice_line_id }) for fee in repair.fees_lines: if fee.to_invoice: if group: name = repair.name + '-' + fee.name else: name = fee.name if not fee.product_id: raise UserError(_('No product defined on Fees!')) if fee.product_id.property_account_income_id: account_id = fee.product_id.property_account_income_id.id elif fee.product_id.categ_id.property_account_income_categ_id: account_id = fee.product_id.categ_id.property_account_income_categ_id.id else: raise UserError( _('No account defined for product "%s".') % fee.product_id.name) invoice_fee_id = inv_line_obj.create( cr, uid, { 'invoice_id': inv_id, 'name': name, 'origin': repair.name, 'account_id': account_id, 'quantity': fee.product_uom_qty, 'invoice_line_tax_ids': [(6, 0, [x.id for x in fee.tax_id])], 'uos_id': fee.product_uom.id, 'product_id': fee.product_id and fee.product_id.id or False, 'price_unit': fee.price_unit, 'price_subtotal': fee.product_uom_qty * fee.price_unit }) repair_fee_obj.write(cr, uid, [fee.id], { 'invoiced': True, 'invoice_line_id': invoice_fee_id }) #inv_obj.button_reset_taxes(cr, uid, inv_id, context=context) res[repair.id] = inv_id return res def action_repair_ready(self, cr, uid, ids, context=None): """ Writes repair order state to 'Ready' @return: True """ for repair in self.browse(cr, uid, ids, context=context): self.pool.get('mrp.repair.line').write( cr, uid, [l.id for l in repair.operations], {'state': 'confirmed'}, context=context) self.write(cr, uid, [repair.id], {'state': 'ready'}) return True def action_repair_start(self, cr, uid, ids, context=None): """ Writes repair order state to 'Under Repair' @return: True """ repair_line = self.pool.get('mrp.repair.line') for repair in self.browse(cr, uid, ids, context=context): repair_line.write(cr, uid, [l.id for l in repair.operations], {'state': 'confirmed'}, context=context) repair.write({'state': 'under_repair'}) return True def action_repair_end(self, cr, uid, ids, context=None): """ Writes repair order state to 'To be invoiced' if invoice method is After repair else state is set to 'Ready'. @return: True """ for order in self.browse(cr, uid, ids, context=context): val = {} val['repaired'] = True if (not order.invoiced and order.invoice_method == 'after_repair'): val['state'] = '2binvoiced' elif (not order.invoiced and order.invoice_method == 'b4repair'): val['state'] = 'ready' else: pass self.write(cr, uid, [order.id], val) return True def wkf_repair_done(self, cr, uid, ids, *args): self.action_repair_done(cr, uid, ids) return True def action_repair_done(self, cr, uid, ids, context=None): """ Creates stock move for operation and stock move for final product of repair order. @return: Move ids of final products """ res = {} move_obj = self.pool.get('stock.move') repair_line_obj = self.pool.get('mrp.repair.line') for repair in self.browse(cr, uid, ids, context=context): move_ids = [] for move in repair.operations: move_id = move_obj.create( cr, uid, { 'name': move.name, 'product_id': move.product_id.id, 'restrict_lot_id': move.lot_id.id, 'product_uom_qty': move.product_uom_qty, 'product_uom': move.product_uom.id, 'partner_id': repair.address_id and repair.address_id.id or False, 'location_id': move.location_id.id, 'location_dest_id': move.location_dest_id.id, }) move_ids.append(move_id) repair_line_obj.write(cr, uid, [move.id], { 'move_id': move_id, 'state': 'done' }, context=context) move_id = move_obj.create( cr, uid, { 'name': repair.name, 'product_id': repair.product_id.id, 'product_uom': repair.product_uom.id or repair.product_id.uom_id.id, 'product_uom_qty': repair.product_qty, 'partner_id': repair.address_id and repair.address_id.id or False, 'location_id': repair.location_id.id, 'location_dest_id': repair.location_dest_id.id, 'restrict_lot_id': repair.lot_id.id, }) move_ids.append(move_id) move_obj.action_done(cr, uid, move_ids, context=context) self.write(cr, uid, [repair.id], { 'state': 'done', 'move_id': move_id }, context=context) res[repair.id] = move_id return res
carrier_grid = self.grid_get(cr, uid, [carrier.id], order.partner_shipping_id.id, context) if carrier_grid: try: price = grid_obj.get_price(cr, uid, carrier_grid, order, time.strftime("%Y-%m-%d"), context) available = True except osv.except_osv, e: # no suitable delivery method found, probably configuration error _logger.error("Carrier %s: %s\n%s" % (carrier.name, e.name, e.value)) price = 0.0 else: price = 0.0 res[carrier.id] = {"price": price, "available": available} return res _columns = { "name": fields.char("Delivery Method", required=True), "partner_id": fields.many2one( "res.partner", "Transport Company", required=True, help="The partner that is doing the delivery service." ), "product_id": fields.many2one("product.product", "Delivery Product", required=True), "grids_id": fields.one2many("delivery.grid", "carrier_id", "Delivery Grids"), "available": fields.function( get_price, string="Available", type="boolean", multi="price", help="Is the carrier method possible with the current order.", ), "price": fields.function(get_price, string="Price", multi="price"), "active": fields.boolean( "Active",
class mrp_repair_fee(osv.osv, ProductChangeMixin): _name = 'mrp.repair.fee' _description = 'Repair Fees Line' def _amount_line(self, cr, uid, ids, field_name, arg, context=None): """ Calculates amount. @param field_name: Name of field. @param arg: Argument @return: Dictionary of values. """ res = {} tax_obj = self.pool.get('account.tax') cur_obj = self.pool.get('res.currency') for line in self.browse(cr, uid, ids, context=context): if line.to_invoice: cur = line.repair_id.pricelist_id.currency_id taxes = tax_obj.compute_all(cr, uid, line.tax_id, line.price_unit, cur.id, line.product_uom_qty, line.product_id.id, line.repair_id.partner_id.id) res[line.id] = taxes['total_included'] else: res[line.id] = 0 return res _columns = { 'repair_id': fields.many2one('mrp.repair', 'Repair Order Reference', required=True, ondelete='cascade', select=True), 'name': fields.char('Description', select=True, required=True), 'product_id': fields.many2one('product.product', 'Product'), 'product_uom_qty': fields.float( 'Quantity', digits_compute=dp.get_precision('Product Unit of Measure'), required=True), 'price_unit': fields.float('Unit Price', required=True), 'product_uom': fields.many2one('product.uom', 'Product Unit of Measure', required=True), 'price_subtotal': fields.function(_amount_line, string='Subtotal', digits=0), 'tax_id': fields.many2many('account.tax', 'repair_fee_line_tax', 'repair_fee_line_id', 'tax_id', 'Taxes'), 'invoice_line_id': fields.many2one('account.invoice.line', 'Invoice Line', readonly=True, copy=False), 'to_invoice': fields.boolean('To Invoice'), 'invoiced': fields.boolean('Invoiced', readonly=True, copy=False), } _defaults = { 'to_invoice': lambda *a: True, }
gd_client = gdata.spreadsheet.service.SpreadsheetsService() gd_client.email = username gd_client.password =passwd gd_client.ProgrammaticLogin() q = gdata.spreadsheet.service.DocumentQuery() q['title'] = doc_title q['title-exact'] = 'true' feed = gd_client.GetSpreadsheetsFeed(query=q) spreadsheet_id = feed.entry[0].id.text.rsplit('/',1)[1] feed = gd_client.GetWorksheetsFeed(spreadsheet_id) worksheet_id = feed.entry[0].id.text.rsplit('/',1)[1] rows = gd_client.GetListFeed(spreadsheet_id, worksheet_id).entry row = rows[43] row2 = rows[44] row_key = row.custom.keys()[2] factor =row.custom[row_key].text row2_key = row2.custom.keys()[1] labor_factor = row2.custom[row2_key].text sale_price = float(factor) * float(cost_price) labor_cost = float(labor_factor) * float(time_factor) line.write({'purchase_price': sale_price,'labor_cost':labor_cost, 'calculate': True}) except Exception, e: raise osv.except_osv(_('User Error!'), _('Authenticate with Google Spreadsheet Fail Please see Configuration in Setting/User/Syncronization.')) return True _name = 'calculate.line' _columns = { 'name': fields.char('Name', size=64), } calulate_line()
class mrp_repair_line(osv.osv, ProductChangeMixin): _name = 'mrp.repair.line' _description = 'Repair Line' def _amount_line(self, cr, uid, ids, field_name, arg, context=None): """ Calculates amount. @param field_name: Name of field. @param arg: Argument @return: Dictionary of values. """ res = {} tax_obj = self.pool.get('account.tax') # cur_obj = self.pool.get('res.currency') for line in self.browse(cr, uid, ids, context=context): if line.to_invoice: cur = line.repair_id.pricelist_id.currency_id taxes = tax_obj.compute_all(cr, uid, line.tax_id, line.price_unit, cur.id, line.product_uom_qty, line.product_id.id, line.repair_id.partner_id.id) #res[line.id] = cur_obj.round(cr, uid, cur, taxes['total']) res[line.id] = taxes['total_included'] else: res[line.id] = 0 return res _columns = { 'name': fields.char('Description', required=True), 'repair_id': fields.many2one('mrp.repair', 'Repair Order Reference', ondelete='cascade', select=True), 'type': fields.selection([('add', 'Add'), ('remove', 'Remove')], 'Type', required=True), 'to_invoice': fields.boolean('To Invoice'), 'product_id': fields.many2one('product.product', 'Product', required=True), 'invoiced': fields.boolean('Invoiced', readonly=True, copy=False), 'price_unit': fields.float('Unit Price', required=True, digits_compute=dp.get_precision('Product Price')), 'price_subtotal': fields.function(_amount_line, string='Subtotal', digits=0), 'tax_id': fields.many2many('account.tax', 'repair_operation_line_tax', 'repair_operation_line_id', 'tax_id', 'Taxes'), 'product_uom_qty': fields.float( 'Quantity', digits_compute=dp.get_precision('Product Unit of Measure'), required=True), 'product_uom': fields.many2one('product.uom', 'Product Unit of Measure', required=True), 'invoice_line_id': fields.many2one('account.invoice.line', 'Invoice Line', readonly=True, copy=False), 'location_id': fields.many2one('stock.location', 'Source Location', required=True, select=True), 'location_dest_id': fields.many2one('stock.location', 'Dest. Location', required=True, select=True), 'move_id': fields.many2one('stock.move', 'Inventory Move', readonly=True, copy=False), 'lot_id': fields.many2one('stock.production.lot', 'Lot'), 'state': fields.selection( [('draft', 'Draft'), ('confirmed', 'Confirmed'), ('done', 'Done'), ('cancel', 'Cancelled')], 'Status', required=True, readonly=True, copy=False, help= ' * The \'Draft\' status is set automatically as draft when repair order in draft status. \ \n* The \'Confirmed\' status is set automatically as confirm when repair order in confirm status. \ \n* The \'Done\' status is set automatically when repair order is completed.\ \n* The \'Cancelled\' status is set automatically when user cancel repair order.' ), } _defaults = { 'state': lambda *a: 'draft', 'product_uom_qty': lambda *a: 1, } def onchange_operation_type(self, cr, uid, ids, type, guarantee_limit, company_id=False, context=None): """ On change of operation type it sets source location, destination location and to invoice field. @param product: Changed operation type. @param guarantee_limit: Guarantee limit of current record. @return: Dictionary of values. """ if not type: return {'value': {'location_id': False, 'location_dest_id': False}} location_obj = self.pool.get('stock.location') warehouse_obj = self.pool.get('stock.warehouse') location_id = location_obj.search(cr, uid, [('usage', '=', 'production')], context=context) location_id = location_id and location_id[0] or False if type == 'add': # TOCHECK: Find stock location for user's company warehouse or # repair order's company's warehouse (company_id field is added in fix of lp:831583) args = company_id and [('company_id', '=', company_id)] or [] warehouse_ids = warehouse_obj.search(cr, uid, args, context=context) stock_id = False if warehouse_ids: stock_id = warehouse_obj.browse( cr, uid, warehouse_ids[0], context=context).lot_stock_id.id to_invoice = (guarantee_limit and datetime.strptime( guarantee_limit, '%Y-%m-%d') < datetime.now()) return { 'value': { 'to_invoice': to_invoice, 'location_id': stock_id, 'location_dest_id': location_id } } scrap_location_ids = location_obj.search( cr, uid, [('scrap_location', '=', True)], context=context) return { 'value': { 'to_invoice': False, 'location_id': location_id, 'location_dest_id': scrap_location_ids and scrap_location_ids[0] or False, } }
return list(enumerate(["Corge", "Grault", "Wheee", "Moog"])) def function_fn(model, cr, uid, ids, field_name, arg, context): return dict((id, 3) for id in ids) def function_fn_write(model, cr, uid, id, field_name, field_value, fnct_inv_arg, context): """ just so CreatorCase.export can be used """ pass models = [ ('boolean', fields.boolean()), ('integer', fields.integer()), ('float', fields.float()), ('decimal', fields.float(digits=(16, 3))), ('string.bounded', fields.char('unknown', size=16)), ('string.required', fields.char('unknown', size=None, required=True)), ('string', fields.char('unknown', size=None)), ('date', fields.date()), ('datetime', fields.datetime()), ('text', fields.text()), ('selection', fields.selection([(1, "Foo"), (2, "Bar"), (3, "Qux"), (4, '')])), # here use size=-1 to store the values as integers instead of strings ('selection.function', fields.selection(selection_fn, size=-1)), # just relate to an integer ('many2one', fields.many2one('export.integer')), ('one2many', fields.one2many('export.one2many.child', 'parent_id')), ('many2many', fields.many2many('export.many2many.other')), ('function', fields.function(function_fn, fnct_inv=function_fn_write, type="integer")), # related: specialization of fields.function, should work the same way # TODO: reference
class account_cutoff(orm.Model): _name = 'account.cutoff' _rec_name = 'cutoff_date' _order = 'cutoff_date desc' _inherit = ['mail.thread'] _description = 'Account Cut-off' _track = { 'state': { 'account_cutoff_base.cutoff_done': lambda self, cr, uid, obj, ctx=None: obj['state'] == 'done', } } def copy(self, cr, uid, id, default=None, context=None): if default is None: default = {} default.update({ 'cutoff_date': '%d-12-31' % datetime.today().year, 'move_id': False, 'state': 'draft', 'line_ids': False, }) return super(account_cutoff, self).copy( cr, uid, id, default=default, context=context) def _compute_total_cutoff(self, cr, uid, ids, name, arg, context=None): res = {} for cutoff in self.browse(cr, uid, ids, context=context): res[cutoff.id] = 0 for line in cutoff.line_ids: res[cutoff.id] += line.cutoff_amount return res _columns = { 'cutoff_date': fields.date( 'Cut-off Date', required=True, readonly=True, states={'draft': [('readonly', False)]}, track_visibility='always'), 'type': fields.selection([ ('accrued_revenue', 'Accrued Revenue'), ('accrued_expense', 'Accrued Expense'), ('prepaid_revenue', 'Prepaid Revenue'), ('prepaid_expense', 'Prepaid Expense'), ], 'Type', required=True, readonly=True, states={'draft': [('readonly', False)]}), 'move_id': fields.many2one( 'account.move', 'Cut-off Journal Entry', readonly=True), 'move_label': fields.char( 'Label of the Cut-off Journal Entry', size=64, required=True, readonly=True, states={'draft': [('readonly', False)]}, help="This label will be written in the 'Name' field of the " "Cut-off Account Move Lines and in the 'Reference' field of " "the Cut-off Account Move."), 'cutoff_account_id': fields.many2one( 'account.account', 'Cut-off Account', domain=[('type', '<>', 'view'), ('type', '<>', 'closed')], required=True, readonly=True, states={'draft': [('readonly', False)]}), 'cutoff_journal_id': fields.many2one( 'account.journal', 'Cut-off Account Journal', required=True, readonly=True, states={'draft': [('readonly', False)]}), 'total_cutoff_amount': fields.function( _compute_total_cutoff, type='float', string="Total Cut-off Amount", readonly=True, track_visibility='always'), 'company_id': fields.many2one( 'res.company', 'Company', required=True, readonly=True, states={'draft': [('readonly', False)]}), 'company_currency_id': fields.related( 'company_id', 'currency_id', readonly=True, type='many2one', relation='res.currency', string='Company Currency'), 'line_ids': fields.one2many( 'account.cutoff.line', 'parent_id', 'Cut-off Lines', readonly=True, states={'draft': [('readonly', False)]}), 'state': fields.selection([ ('draft', 'Draft'), ('done', 'Done'), ], 'State', select=True, readonly=True, track_visibility='onchange', help="State of the cutoff. When the Journal Entry is created, " "the state is set to 'Done' and the fields become read-only."), } def _get_default_journal(self, cr, uid, context=None): cur_user = self.pool['res.users'].browse(cr, uid, uid, context=context) return cur_user.company_id.default_cutoff_journal_id.id or None def _default_move_label(self, cr, uid, context=None): if context is None: context = {} type = context.get('type') cutoff_date = context.get('cutoff_date') if cutoff_date: cutoff_date_label = ' dated %s' % cutoff_date else: cutoff_date_label = '' label = '' if type == 'accrued_expense': label = _('Accrued Expense%s') % cutoff_date_label elif type == 'accrued_revenue': label = _('Accrued Revenue%s') % cutoff_date_label elif type == 'prepaid_revenue': label = _('Prepaid Revenue%s') % cutoff_date_label elif type == 'prepaid_expense': label = _('Prepaid Expense%s') % cutoff_date_label return label def _default_type(self, cr, uid, context=None): if context is None: context = {} return context.get('type') def _inherit_default_cutoff_account_id(self, cr, uid, context=None): '''Function designed to be inherited by other cutoff modules''' return None def _default_cutoff_account_id(self, cr, uid, context=None): '''This function can't be inherited, so we use a second function''' return self._inherit_default_cutoff_account_id( cr, uid, context=context) _defaults = { 'state': 'draft', 'company_id': lambda self, cr, uid, context: self.pool['res.users'].browse( cr, uid, uid, context=context).company_id.id, 'cutoff_journal_id': _get_default_journal, 'move_label': _default_move_label, 'type': _default_type, 'cutoff_account_id': _default_cutoff_account_id, } _sql_constraints = [( 'date_type_company_uniq', 'unique(cutoff_date, company_id, type)', 'A cutoff of the same type already exists with this cut-off date !' )] def cutoff_date_onchange( self, cr, uid, ids, type, cutoff_date, move_label): res = {'value': {}} if type and cutoff_date: context = {'type': type, 'cutoff_date': cutoff_date} res['value']['move_label'] = self._default_move_label( cr, uid, context=context) return res def back2draft(self, cr, uid, ids, context=None): assert len(ids) == 1,\ 'This function should only be used for a single id at a time' cur_cutoff = self.browse(cr, uid, ids[0], context=context) if cur_cutoff.move_id: self.pool['account.move'].unlink( cr, uid, [cur_cutoff.move_id.id], context=context) self.write(cr, uid, ids[0], {'state': 'draft'}, context=context) return True def _prepare_move(self, cr, uid, cur_cutoff, to_provision, context=None): if context is None: context = {} movelines_to_create = [] amount_total = 0 move_label = cur_cutoff.move_label for (cutoff_account_id, analytic_account_id), amount in \ to_provision.items(): movelines_to_create.append((0, 0, { 'account_id': cutoff_account_id, 'name': move_label, 'debit': amount < 0 and amount * -1 or 0, 'credit': amount >= 0 and amount or 0, 'analytic_account_id': analytic_account_id, })) amount_total += amount # add contre-partie counterpart_amount = amount_total * -1 movelines_to_create.append((0, 0, { 'account_id': cur_cutoff.cutoff_account_id.id, 'debit': counterpart_amount < 0 and counterpart_amount * -1 or 0, 'credit': counterpart_amount >= 0 and counterpart_amount or 0, 'name': move_label, 'analytic_account_id': False, })) # Select period local_ctx = context.copy() local_ctx['account_period_prefer_normal'] = True period_search = self.pool['account.period'].find( cr, uid, cur_cutoff.cutoff_date, context=local_ctx) if len(period_search) != 1: raise orm.except_orm( 'Error:', "No matching period for date '%s'" % cur_cutoff.cutoff_date) period_id = period_search[0] res = { 'journal_id': cur_cutoff.cutoff_journal_id.id, 'date': cur_cutoff.cutoff_date, 'period_id': period_id, 'ref': move_label, 'line_id': movelines_to_create, } return res def create_move(self, cr, uid, ids, context=None): assert len(ids) == 1, \ 'This function should only be used for a single id at a time' move_obj = self.pool['account.move'] cur_cutoff = self.browse(cr, uid, ids[0], context=context) if cur_cutoff.move_id: raise orm.except_orm( _('Error:'), _("The Cut-off Journal Entry already exists. You should " "delete it before running this function.")) if not cur_cutoff.line_ids: raise orm.except_orm( _('Error:'), _("There are no lines on this Cut-off, so we can't create " "a Journal Entry.")) to_provision = {} # key = (cutoff_account_id, analytic_account_id) # value = amount for line in cur_cutoff.line_ids: # if it is already present if ( line.cutoff_account_id.id, line.analytic_account_id.id or False ) in to_provision: to_provision[( line.cutoff_account_id.id, line.analytic_account_id.id or False )] += line.cutoff_amount else: # if not already present to_provision[( line.cutoff_account_id.id, line.analytic_account_id.id or False )] = line.cutoff_amount # Same for tax lines for tax_line in line.tax_line_ids: if ( tax_line.cutoff_account_id.id, tax_line.analytic_account_id.id or False ) in to_provision: to_provision[( tax_line.cutoff_account_id.id, tax_line.analytic_account_id.id or False )] += tax_line.cutoff_amount else: to_provision[( tax_line.cutoff_account_id.id, tax_line.analytic_account_id.id or False )] = tax_line.cutoff_amount vals = self._prepare_move( cr, uid, cur_cutoff, to_provision, context=context) move_id = move_obj.create(cr, uid, vals, context=context) move_obj.validate(cr, uid, [move_id], context=context) self.write(cr, uid, ids[0], { 'move_id': move_id, 'state': 'done', }, context=context) action = { 'name': 'Cut-off Account Move', 'view_type': 'form', 'view_mode': 'form,tree', 'res_id': move_id, 'view_id': False, 'res_model': 'account.move', 'type': 'ir.actions.act_window', 'nodestroy': False, 'target': 'current', } return action
price=grid_obj.get_price(cr, uid, carrier_grid, order, time.strftime('%Y-%m-%d'), context) available = True except UserError, e: # no suitable delivery method found, probably configuration error _logger.info("Carrier %s: %s", carrier.name, e.name) price = 0.0 else: price = 0.0 res[carrier.id] = { 'price': price, 'available': available } return res _columns = { 'name': fields.char('Delivery Method', required=True, translate=True), 'sequence': fields.integer('Sequence', help="Determine the display order"), 'partner_id': fields.many2one('res.partner', 'Transport Company', required=True, help="The partner that is doing the delivery service."), 'product_id': fields.many2one('product.product', 'Delivery Product', required=True), 'grids_id': fields.one2many('delivery.grid', 'carrier_id', 'Delivery Grids'), 'available' : fields.function(get_price, string='Available',type='boolean', multi='price', help="Is the carrier method possible with the current order."), 'price' : fields.function(get_price, string='Price', multi='price'), 'active': fields.boolean('Active', help="If the active field is set to False, it will allow you to hide the delivery carrier without removing it."), 'normal_price': fields.float('Normal Price', help="Keep empty if the pricing depends on the advanced pricing per destination"), 'free_if_more_than': fields.boolean('Free If Order Total Amount Is More Than', help="If the order is more expensive than a certain amount, the customer can benefit from a free shipping"), 'amount': fields.float('Amount', help="Amount of the order to benefit from a free shipping, expressed in the company currency"), 'use_detailed_pricelist': fields.boolean('Advanced Pricing per Destination', help="Check this box if you want to manage delivery prices that depends on the destination, the weight, the total of the order, etc."), 'pricelist_ids': fields.one2many('delivery.grid', 'carrier_id', 'Advanced Pricing'), }
class MassObject(orm.Model): _name = "mass.object" _columns = { 'name': fields.char("Name", size=64, required=True, select=1), 'model_id': fields.many2one('ir.model', 'Model', required=True, select=1), 'field_ids': fields.many2many('ir.model.fields', 'mass_field_rel', 'mass_id', 'field_id', 'Fields'), 'ref_ir_act_window': fields.many2one( 'ir.actions.act_window', 'Sidebar Action', readonly=True, help="Sidebar action to make this template available on records \ of the related document model"), 'ref_ir_value': fields.many2one('ir.values', 'Sidebar Button', readonly=True, help="Sidebar button to open the sidebar action"), 'model_ids': fields.many2many('ir.model', string='Model List') } _sql_constraints = [ ('name_uniq', 'unique (name)', _('Name must be unique!')), ] def onchange_model(self, cr, uid, ids, model_id, context=None): if context is None: context = {} if not model_id: return {'value': {'model_ids': [(6, 0, [])]}} model_ids = [model_id] model_obj = self.pool['ir.model'] active_model_obj = self.pool.get( model_obj.browse(cr, uid, model_id).model) if active_model_obj._inherits: for key, val in active_model_obj._inherits.items(): found_model_ids = model_obj.search(cr, uid, [('model', '=', key)], context=context) model_ids += found_model_ids return {'value': {'model_ids': [(6, 0, model_ids)]}} def create_action(self, cr, uid, ids, context=None): vals = {} action_obj = self.pool['ir.actions.act_window'] ir_values_obj = self.pool['ir.values'] for data in self.browse(cr, uid, ids, context=context): src_obj = data.model_id.model button_name = _('Mass Editing (%s)') % data.name vals['ref_ir_act_window'] = action_obj.create( cr, SUPERUSER_ID, { 'name': button_name, 'type': 'ir.actions.act_window', 'res_model': 'mass.editing.wizard', 'src_model': src_obj, 'view_type': 'form', 'context': "{'mass_editing_object' : %d}" % (data.id), 'view_mode': 'form,tree', 'target': 'new', 'auto_refresh': 1, }, context) vals['ref_ir_value'] = ir_values_obj.create( cr, SUPERUSER_ID, { 'name': button_name, 'model': src_obj, 'key2': 'client_action_multi', 'value': ("ir.actions.act_window," + str(vals['ref_ir_act_window'])), 'object': True, }, context) self.write( cr, uid, ids, { 'ref_ir_act_window': vals.get('ref_ir_act_window', False), 'ref_ir_value': vals.get('ref_ir_value', False), }, context) return True def unlink_action(self, cr, uid, ids, context=None): for template in self.browse(cr, uid, ids, context=context): try: if template.ref_ir_act_window: act_window_obj = self.pool['ir.actions.act_window'] act_window_obj.unlink(cr, SUPERUSER_ID, [template.ref_ir_act_window.id], context=context) if template.ref_ir_value: ir_values_obj = self.pool['ir.values'] ir_values_obj.unlink(cr, SUPERUSER_ID, template.ref_ir_value.id, context=context) except: raise orm.except_orm( _("Warning"), _("Deletion of the action record failed.")) return True def unlink(self, cr, uid, ids, context=None): self.unlink_action(cr, uid, ids, context=context) return super(MassObject, self).unlink(cr, uid, ids, context=context) def copy(self, cr, uid, record_id, default=None, context=None): if default is None: default = {} default.update({'name': '', 'field_ids': []}) return super(MassObject, self).copy(cr, uid, record_id, default, context=context)
return res def _get_icon_image(self, cr, uid, ids, field_name=None, arg=None, context=None): res = dict.fromkeys(ids, '') for module in self.browse(cr, uid, ids, context=context): path = addons.get_module_resource(module.name, 'static', 'src', 'img', 'icon.png') if path: image_file = tools.file_open(path, 'rb') try: res[module.id] = image_file.read().encode('base64') finally: image_file.close() return res _columns = { 'name': fields.char("Technical Name", size=128, readonly=True, required=True, select=True), 'category_id': fields.many2one('ir.module.category', 'Category', readonly=True, select=True), 'shortdesc': fields.char('Module Name', size=64, readonly=True, translate=True), 'summary': fields.char('Summary', size=64, readonly=True, translate=True), 'description': fields.text("Description", readonly=True, translate=True), 'description_html': fields.function(_get_desc, string='Description HTML', type='html', method=True, readonly=True), 'author': fields.char("Author", size=128, readonly=True), 'maintainer': fields.char('Maintainer', size=128, readonly=True), 'contributors': fields.text('Contributors', readonly=True), 'website': fields.char("Website", size=256, readonly=True), # attention: Incorrect field names !! # installed_version refers the latest version (the one on disk) # latest_version refers the installed version (the one in database) # published_version refers the version available on the repository 'installed_version': fields.function(_get_latest_version, string='Latest Version', type='char'),
class posix_forward(osv.Model): def _get_email(self, cr, uid, ids, field_names, arg, context=None): cr.execute( "SELECT f.id, f.from_name, from_d.complete_name, f.to_name, to_d.complete_name FROM posix_mailforward AS f " " LEFT JOIN posix_domain AS from_d ON from_d.id = f.from_domain_id " " LEFT JOIN posix_domain AS to_d ON to_d.id = f.to_domain_id " " WHERE f.id IN %s", (tuple(ids), )) res = dict.fromkeys(ids) for row in cr.fetchall(): forward_id = row[0] from_name = row[1] from_domain = row[2] to_name = row[3] to_domain = row[4] from_mail = None to_mail = None if from_name and from_domain: from_mail = ("%s@%s" % (from_name, from_domain)) elif not from_name and from_domain: from_mail = ("@%s" % (from_domain, )) if to_name and to_domain: to_mail = ("%s@%s" % (to_name, to_domain)) elif not to_name and to_domain: to_mail = ("@%s" % (to_domain, )) res[forward_id] = {"from_email": from_mail, "to_email": to_mail} return res def _relids_from_domain(self, cr, uid, ids, context=None): forward_obj = self.pool.get("posix.mailforward") res = forward_obj.search(cr, uid, [("from_domain_id", "in", ids)]) return res def _relids_to_domain(self, cr, uid, ids, context=None): forward_obj = self.pool.get("posix.mailforward") res = forward_obj.search(cr, uid, [("to_domain_id", "in", ids)]) return res _name = "posix.mailforward" _description = "Mail Forward" _columns = { "from_name": fields.char("From", size=64, required=False), "from_domain_id": fields.many2one("posix.domain", string="From Domain", required=True, ondelete="restrict"), "from_domain_name": fields.related("from_domain_id", "complete_name", string="From Domain", type="char", size=64, store=True), "to_name": fields.char("To", size=64, required=False), "to_domain_id": fields.many2one("posix.domain", string="To Domain", required=True, ondelete="restrict"), "to_domain_name": fields.related("to_domain_id", "complete_name", string="To Domain", type="char", size=64, store=True), "from_email": fields.function(_get_email, string="From E-Mail", type="char", size=128, readonly=True, select=True, multi="email", store={ "posix.mailforward": (lambda self, cr, uid, ids, context=None: ids, ["from_name", "from_domain_id"], 10), "posix.domain": (_relids_from_domain, ["name", "parent_id"], 11) }), "to_email": fields.function(_get_email, string="To E-Mail", type="char", size=128, readonly=True, select=True, multi="email", store={ "posix.mailforward": (lambda self, cr, uid, ids, context=None: ids, ["to_name", "to_domain_id"], 10), "posix.domain": (_relids_to_domain, ["name", "parent_id"], 11) }) }
ATTR_USE_DOM_PINVOICE = ('i', 'Invoice Address') ATTR_USE_DOM_PSHIPPER = ('s', 'Shipping Address') ATTR_USE_DOM_PRODUCT = ('p', 'Product') ATTR_USE = (ATTR_USE_DOM_COMPANY, ATTR_USE_DOM_PINVOICE, ATTR_USE_DOM_PSHIPPER, ATTR_USE_DOM_PRODUCT) # Thank you! ACC_FISC_ALLOC_RULE_COLS_TMPL = { # Note: This are template style fields. # For nontemplate fields you might add aditional constraints to specific nontemplate fields (eg. company_id). # The chain method from itertools updates fields. Consider using this from within the nontemplate class when adding # new fields. # --- GENERAL SECTION --- 'name': fields.char('Name', required=True), 'description': fields.char('Description'), # This fiscal domain will narrow down the available fiscal attributes / fiscal allocations. # It should help clustering and reducing complexity. Rules are applied *additionally* # preserving the result (reed: taxes applied) of previous iterations. # However it is optional. You can construct more complex "cross-domain" rules leaving it empty. 'fiscal_domain_id': fields.many2one('account.fiscal.domain', 'Fiscal Domain', required=True, select=True), 'is_account_allocation': fields.boolean(u'Account Allocation?'), # --- CRITERION SECTION --- '{0}_country'.format(ATTR_USE_DOM_COMPANY[0]): fields.many2one('res.country', 'Country'), '{0}_state'.format(ATTR_USE_DOM_COMPANY[0]): fields.many2one( 'res.country.state', 'State', domain="[('country_id','=',{0}_country)]".format(ATTR_USE_DOM_COMPANY[0])), 'to_{0}_country'.format(ATTR_USE_DOM_PINVOICE[0]): fields.many2one(
class account_sequence_installer(osv.osv_memory): _name = 'account.sequence.installer' _inherit = 'res.config.installer' _columns = { 'name': fields.char('Name', required=True), 'prefix': fields.char('Prefix', size=64, help="Prefix value of the record for the sequence"), 'suffix': fields.char('Suffix', size=64, help="Suffix value of the record for the sequence"), 'number_next': fields.integer('Next Number', required=True, help="Next number of this sequence"), 'number_increment': fields.integer( 'Increment Number', required=True, help= "The next number of the sequence will be incremented by this number" ), 'padding': fields.integer( 'Number padding', required=True, help= "Odoo will automatically adds some '0' on the left of the 'Next Number' to get the required padding size." ), 'company_id': fields.many2one('res.company', 'Company'), } _defaults = { 'company_id': lambda s, cr, uid, c: s.pool.get('res.company')._company_default_get( cr, uid, 'ir.sequence', context=c), 'number_increment': 1, 'number_next': 1, 'padding': 0, 'name': 'Internal Sequence Journal', } def execute(self, cr, uid, ids, context=None): if context is None: context = {} record = self.browse(cr, uid, ids, context=context)[0] j_ids = [] if record.company_id: company_id = record.company_id.id, search_criteria = [('company_id', '=', company_id)] else: company_id = False search_criteria = [] vals = { 'id': 'internal_sequence_journal', 'code': 'account.journal', 'name': record.name, 'prefix': record.prefix, 'suffix': record.suffix, 'number_next': record.number_next, 'number_increment': record.number_increment, 'padding': record.padding, 'company_id': company_id, } obj_sequence = self.pool.get('ir.sequence') ir_seq = obj_sequence.create(cr, uid, vals, context) res = super(account_sequence_installer, self).execute(cr, uid, ids, context=context) #jou_obj = self.pool.get('account.journal') #journal_ids = jou_obj.search(cr, uid, search_criteria, context=context) #for journal in jou_obj.browse(cr, uid, journal_ids, context=context): # if not journal.internal_sequence_id: # j_ids.append(journal.id) #if j_ids: # jou_obj.write(cr, uid, j_ids, {'internal_sequence_id': ir_seq}) #ir_values_obj = self.pool.get('ir.values') #ir_values_obj.set(cr, uid, key='default', key2=False, name='internal_sequence_id', models =[('account.journal', False)], value=ir_seq) return res
url_medium = name + "medium" + extention url_small = name + "small" + extention return self.write( cr, uid, id, {"url": url, "url_big": url_big, "url_medium": url_medium, "url_small": url_small}, context=context, ) else: return False return self.write(cr, uid, id, {"file_db_store": value}, context=context) _columns = { "name": fields.char("Image Title", size=64), "filename": fields.char("Filename", size=64), "extension": fields.char("file extension", oldname="extention"), "link": fields.boolean( "Link?", help="Images can be linked from files on " "your file system or remote (Preferred)" ), "file_db_store": fields.binary("Image stored in database"), "file": fields.function( _get_image, fnct_inv=_set_image, type="binary", string="File", filters="*.png,*.jpg,*.gif" ), "url": fields.char("File Location"), "url_big": fields.char("File Location Image Size Big"), "url_medium": fields.char("File Location Image Size Medium"), "url_small": fields.char("File Location Image Size Small"), "comments": fields.text("Comments"), "product_id": fields.many2one("product.product", "Product"),
class cuti_kuliah(osv.Model): _name = 'cuti.kuliah' _columns = { 'name': fields.char('Kode Cuti', size=36, required=True), 'partner_id': fields.many2one('res.partner', 'Mahasiswa', required=True, readonly=True, domain="[('status_mahasiswa','=','Mahasiswa')]"), 'from_semester_id': fields.many2one('master.semester', 'Dari Semester', required=True), 'to_semester_id': fields.many2one('master.semester', 'Sampai Semester', required=True), 'kelas_id': fields.many2one('master.kelas', string='Kelas', required=False), 'prodi_id': fields.many2one('master.prodi', 'Program Studi', required=True), # 'jurusan_id':fields.many2one('master.jurusan','Jurusan',required=True,readonly=True, states={'draft': [('readonly', False)]}), 'fakultas_id': fields.many2one('master.fakultas', 'Fakultas', required=True), 'tahun_ajaran_id': fields.many2one('academic.year', 'Angkatan', required=True), 'state': fields.selection([('draft', 'Draft'), ('waiting', 'Waiting Approval'), ('confirm', 'Confirmed'), ('cancel', 'Canceled'), ('refuse', 'Refused'), ('done', 'Done')], 'Status'), 'notes': fields.text('Alasan', required=True), 'user_id': fields.many2one('res.users', 'User', readonly=True), 'date': fields.date('Tanggal Aktif Kembali'), 'automatic_done': fields.boolean('Automatic Done'), } _defaults = { 'state': 'draft', 'user_id': lambda obj, cr, uid, context: uid, 'name': lambda obj, cr, uid, context: obj.pool.get('ir.sequence').get( cr, uid, 'cuti.kuliah'), } _sql_constraints = [('name_uniq', 'unique(name)', 'Kode cuti kuliah tidak boleh sama')] # def onchange_partner(self, cr, uid, ids, tahun_ajaran_id, fakultas_id, jurusan_id, prodi_id, kelas_id, partner_id, context=None): def onchange_partner(self, cr, uid, ids, tahun_ajaran_id, fakultas_id, prodi_id, kelas_id, partner_id, context=None): results = {} if not partner_id: return results par_obj = self.pool.get('res.partner') par_ids = par_obj.search(cr, uid, [('id', '=', partner_id)], context=context) #import pdb;pdb.set_trace() par_id = par_obj.browse(cr, uid, par_ids, context=context)[0] kelas_id = par_id.kelas_id.id tahun_ajaran_id = par_id.tahun_ajaran_id.id fakultas_id = par_id.fakultas_id.id # jurusan_id = par_id.jurusan_id.id prodi_id = par_id.prodi_id.id results = { 'value': { 'kelas_id': kelas_id, 'tahun_ajaran_id': tahun_ajaran_id, 'fakultas_id': fakultas_id, # 'jurusan_id' : jurusan_id, 'prodi_id': prodi_id, } } return results def confirm(self, cr, uid, ids, context=None): for ct in self.browse(cr, uid, ids): self.write(cr, uid, ct.id, {'state': 'waiting'}, context=context) return True def approve(self, cr, uid, ids, context=None): for ct in self.browse(cr, uid, ids): mhs_id = ct.partner_id.id self.pool.get('res.partner').write(cr, uid, mhs_id, {'status_mahasiswa': 'cuti'}, context=context) self.write(cr, uid, ct.id, {'state': 'confirm'}, context=context) return True def cancel(self, cr, uid, ids, context=None): for ct in self.browse(cr, uid, ids): self.write(cr, uid, ct.id, {'state': 'cancel'}, context=context) return True def set_draft(self, cr, uid, ids, context=None): for ct in self.browse(cr, uid, ids): self.write(cr, uid, ct.id, {'state': 'draft'}, context=context) return True def refuse(self, cr, uid, ids, context=None): for ct in self.browse(cr, uid, ids): self.write(cr, uid, ct.id, {'state': 'refuse'}, context=context) return True def done(self, cr, uid, ids, context=None): for ct in self.browse(cr, uid, ids): mhs_id = ct.partner_id.id self.pool.get('res.partner').write( cr, uid, mhs_id, {'status_mahasiswa': 'Mahasiswa'}, context=context) self.write(cr, uid, ct.id, {'state': 'done'}, context=context) return True def unlink(self, cr, uid, ids, context=None): if context is None: context = {} """Allows to delete in draft state""" for rec in self.browse(cr, uid, ids, context=context): if rec.state != 'draft': raise osv.except_osv( _('Error!'), _('Data yang dapat dihapus hanya yang berstatus draft')) return super(cuti_kuliah, self).unlink(cr, uid, ids, context=context) #################################################################################################### # Cron Job untuk activate otomatis mahasiswa yang habis masa cutinya #################################################################################################### def cron_aktivasi_cuti_mahasiswa(self, cr, uid, ids=None, context=None): partner_obj = self.pool.get('res.partner') #import pdb;pdb.set_trace() mahasiswa_cuti = self.search( cr, uid, [('date', '=', time.strftime(DEFAULT_SERVER_DATETIME_FORMAT)[:10]), ('state', '=', 'confirm'), ('automatic_done', '=', True)], context=context) if mahasiswa_cuti: for mhs in self.browse(cr, uid, mahasiswa_cuti): self.write(cr, uid, mhs.id, {'state': 'done'}) partner_obj.write(cr, uid, mhs.partner_id.id, {'status_mahasiswa': 'Mahasiswa'}) return True #################################################################################################### # Cron Job untuk generate cuti jika mahasiswa telat bayar uang ujian (UAS) #################################################################################################### def cron_cuti_mahasiswa_karena_nunggak(self, cr, uid, ids=None, context=None): partner_obj = self.pool.get('res.partner') invoice_obj = self.pool.get('account.invoice') event_obj = self.pool.get('event.event') now = time.strftime(DEFAULT_SERVER_DATETIME_FORMAT) date_now = datetime.strptime(now[:10], "%Y-%m-%d") start_date = date_now.strftime("%Y-%m-%d 00:00:00") start_end = date_now.strftime("%Y-%m-%d 23:59:59") event_exist = event_obj.search(cr, uid, [('date_begin', '>=', start_date), ('date_begin', '<=', start_end), ('state', '=', 'confirm')]) if event_exist: mahasiswa_nunggak = invoice_obj.search( cr, uid, [('date_invoice', '=', now[:10]), ('state', '=', 'open'), ('krs_id', '!=', False)]) if mahasiswa_nunggak: mhs_ids = [] for inv in invoice_obj.browse(cr, uid, mahasiswa_nunggak): if inv.id not in mhs_ids: mhs_ids.append(inv.partner_id.id) self.create( cr, uid, { 'partner_id': inv.partner_id.id, 'tahun_ajaran_id': inv.partner_id.tahun_ajaran_id.id, 'fakultas_id': inv.partner_id.fakultas_id.id, 'prodi_id': inv.partner_id.prodi_id.id, 'kelas_id': inv.partner_id.kelas_id.id or False, 'state': 'confirm', 'notes': 'Ada tunggakan invoice ' + str(inv.number), 'from_semester_id': inv.krs_id.semester_id.id, 'to_semester_id': 8 }) partner_obj.write(cr, uid, inv.partner_id.id, {'status_mahasiswa': 'cuti'}) invoice_obj.write( cr, uid, inv.id, { 'comment': 'Mahasiswa ini sedang dicutikan oleh sistem karena ada keterlambatan pembayaran atas invoice ini' }) return True