class policy_line_ot(models.Model): _name = 'hr.policy.line.ot' def _tz_list(self, cr, uid, context=None): res = tuple() for name in common_timezones: res += ((name, name),) return res _columns = { 'name': fields.char('Name', size=64, required=True), 'policy_id': fields.many2one('hr.policy.ot', 'Policy'), 'type': fields.selection([('daily', 'Daily'), ('weekly', 'Weekly'), ('restday', 'Rest Day'), ('holiday', 'Public Holiday')], 'Type', required=True), 'weekly_working_days': fields.integer('Weekly Working Days'), 'active_after': fields.integer( 'Active After', help="Minutes after which this policy applies"), 'active_start_time': fields.char( 'Active Start Time', size=5, help="Time in 24 hour time format"), 'active_end_time': fields.char( 'Active End Time', size=5, help="Time in 24 hour time format"), 'tz': fields.selection(_tz_list, 'Time Zone'), 'rate': fields.float( 'Rate', required=True, help='Multiplier of employee wage.'), 'code': fields.char( 'Code', required=True, help="Use this code in the salary rules.") }
class nomor_faktur_pajak(osv.osv): _name = "nomor.faktur.pajak" _description = 'Nomor faktur Pajak' def _nomor_faktur(self, cr, uid, ids, nomorfaktur, arg, context=None): res = {} for nomor in self.browse(cr, uid, ids, context): res[nomor.id] = "%s.%s.%s" % (nomor.nomor_perusahaan, nomor.tahun_penerbit, nomor.nomor_urut) return res _columns = { 'nomor_perusahaan' : fields.char('Nomor Perusahaan', size=3), 'tahun_penerbit': fields.char('Tahun Penerbit', size=2), 'nomor_urut': fields.char('Nomor Urut', size=8), 'name': fields.function(_nomor_faktur, type='char', string="Nomor Faktur", store=True), 'invoice_id': fields.many2one('account.invoice','Invoice No'), 'partner_id' : fields.many2one('res.partner', "Customer"), 'dpp' : fields.float('Untaxed Amount'), 'tax_amount': fields.float("Tax Amount"), 'date_used' : fields.date("Used Date"), 'company_id': fields.many2one('res.company', 'Company'), 'currency_id': fields.many2one('res.currency', 'Currency'), 'type' : fields.selection([('in','Faktur Pajak Masukan'),('out','Faktur Pajak Keluaran')],'Type'), 'status': fields.selection([('1','Used'),('0','Not Used')],'Status'), } _defaults = { 'status': '0', } _sql_constraints = [ ('faktur_unique', 'unique(nomor_perusahaan,tahun_penerbit,nomor_urut)', 'Number Faktur Must Be Unique.'), ]
class ProductTemplate(orm.Model): _inherit = 'product.template' _columns = { 'date_start': fields.date("Start date"), 'date_end': fields.date("End Date"), 'period': fields.selection([('week', 'Week'), ('month', 'Month'), ('year', 'Year')], 'Time Period'), 'analysis_type': fields.selection([('average', 'Average'), ('end_of_period', 'End of period')], 'Type of analysis'), 'stock_graphic': fields.binary("Graph") } _defaults = { 'date_start': lambda *a: (datetime.now() - relativedelta(months=6)).strftime('%Y-%m-%d'), 'date_end': lambda *a: datetime.now().strftime('%Y-%m-%d'), 'period': 'month', 'analysis_type': 'average' }
class barcode_rule(models.Model): _name = 'barcode.rule' _order = 'sequence asc' @api.model def _encoding_selection_list(self): return [ ('any', _('Any')), ('ean13', 'EAN-13'), ('ean8', 'EAN-8'), ('upca', 'UPC-A'), ] @api.model def _get_type_selection(self): return [('alias', _('Alias')), ('product', _('Unit Product'))] _columns = { 'name': fields.char('Rule Name', size=32, required=True, help='An internal identification for this barcode nomenclature rule'), 'barcode_nomenclature_id': fields.many2one('barcode.nomenclature','Barcode Nomenclature'), 'sequence': fields.integer('Sequence', help='Used to order rules such that rules with a smaller sequence match first'), 'encoding': fields.selection('_encoding_selection_list','Encoding',required=True,help='This rule will apply only if the barcode is encoded with the specified encoding'), 'type': fields.selection('_get_type_selection','Type', required=True), 'pattern': fields.char('Barcode Pattern', size=32, help="The barcode matching pattern", required=True), 'alias': fields.char('Alias',size=32,help='The matched pattern will alias to this barcode', required=True), } _defaults = { 'type': 'product', 'pattern': '.*', 'encoding': 'any', 'alias': "0", } @api.one @api.constrains('pattern') def _check_pattern(self): p = self.pattern.replace("\\\\", "X").replace("\{", "X").replace("\}", "X") findall = re.findall("[{]|[}]", p) # p does not contain escaped { or } if len(findall) == 2: if not re.search("[{][N]*[D]*[}]", p): raise ValidationError(_("There is a syntax error in the barcode pattern ") + self.pattern + _(": braces can only contain N's followed by D's.")) elif re.search("[{][}]", p): raise ValidationError(_("There is a syntax error in the barcode pattern ") + self.pattern + _(": empty braces.")) elif len(findall) != 0: raise ValidationError(_("There is a syntax error in the barcode pattern ") + self.pattern + _(": a rule can only contain one pair of braces.")) elif p == '*': raise ValidationError(_(" '*' is not a valid Regex Barcode Pattern. Did you mean '.*' ?"))
class hr_salary_rule_variable(models.Model): _name = 'hr.salary.rule.variable' _description = 'Variables used on salary rules that change over the years' _columns = { 'salary_rule_id': fields.many2one( 'hr.salary.rule', 'Salary Rule', ondelete='cascade', required=True, ), 'date_from': fields.date( 'Date From', required=True, ), 'date_to': fields.date('Date To', ), 'type': fields.selection([('python', 'Python Code'), ('fixed', 'Fixed Amount')], string='Type'), 'python_code': fields.text('Python Code'), 'fixed_amount': fields.float('Fixed Amount'), }
class appointment (osv.osv): _name = "medical.appointment" _inherit = "medical.appointment" def copy(self, cr, uid, id, default=None, context={}): default.update({'validity_status':'tobe'}) return super(appointment,self).copy(cr, uid, id, default, context) def onchange_appointment_date(self, cr, uid, ids, apt_date): if apt_date: validity_date = datetime.datetime.fromtimestamp(time.mktime(time.strptime(apt_date,"%Y-%m-%d %H:%M:%S"))) validity_date = validity_date+datetime.timedelta(days=7) v = {'appointment_validity_date':str(validity_date)} return {'value': v} return {} _columns = { 'no_invoice' : fields.boolean ('Invoice exempt'), 'appointment_validity_date' : fields.datetime ('Validity Date'), 'validity_status' : fields.selection([('invoiced','Invoiced'),('tobe','To be Invoiced')],'Status'), 'consultations' : fields.many2one ('product.product', 'Consultation Service', domain=[('type', '=', "service")], help="Consultation Services", required=True), } _defaults = { 'validity_status': lambda *a: 'tobe', 'no_invoice': lambda *a: True }
class policy_line_presence(models.Model): _name = 'hr.policy.line.presence' _columns = { 'name': fields.char('Name', size=64, required=True), 'policy_id': fields.many2one('hr.policy.presence', 'Policy'), 'code': fields.char('Code', required=True, help="Use this code in the salary rules."), 'rate': fields.float('Rate', required=True, help='Multiplier of employee wage.'), 'type': fields.selection([('normal', 'Normal Working Hours'), ('holiday', 'Holidays'), ('restday', 'Rest Days')], 'Type', required=True), 'active_after': fields.integer( 'Active After', required=True, help='Minutes after first punch of the day in which policy will ' 'take effect.'), 'duration': fields.integer('Duration', required=True, help="In minutes.") } _defaults = { 'rate': 1.0, }
class solt_http_test(osv.osv): _name = 'solt.http.test' _columns = { 'name': fields.char('URL', size=1024), 'method': fields.selection([('post', 'POST'), ('get', 'GET'), ('put', 'PUT'), ('patch', 'PATCH'), ('delete', 'DELETE')], string='HTTP Method'), 'user': fields.char('User', size=64), 'password': fields.char('Password', size=64), 'content': fields.text('Content'), 'response': fields.text('Response'), } def action_request(self, cr, uid, ids, context=None): for test in self.browse(cr, uid, ids, context): auth = None if test.user and test.password: auth = (test.user, test.password) headers = { 'Content-Type': 'application/json', 'Accept': 'application/json' } result = getattr(requests, test.method)(test.name, test.content, auth=auth, headers=headers) test.write({'response': result.text}) return True
class WizardReports(osv.TransientModel): _name = 'wiz.invoices.writeoff' _description = 'PDF Reports for showing all disconnection,reconnection' _columns = { 'date': fields.date('Invoice Date', required=True), 'cheque_no': fields.char('Cheque No', required=True), 'bank_code': fields.selection([ ('FBL', 'FBL'), ('JSBL', 'JSBL'), ], required=True, string='Bank Code'), 'invoice_amount': fields.float('Invoice Amount', required=True), 'received_amount': fields.float('Received Amount', required=True) } def inv_status_changed(self, central, south, north, main): self.env.cr.execute( "UPDATE account_invoice " "SET state='cancel', payment_received=True,courier=True" + ",cheque_no='" + str(self.cheque_no) + "'" + ",comment='Payment has been received against parent invoice therefore user cancelled this invoice' " "FROM res_partner WHERE account_invoice.partner_id = res_partner.id and account_invoice.state='draft' " + "and res_partner.bank_code='" + str(self.bank_code) + "'" + "and account_invoice.invoice_date='" + str(self.date) + "'" + "and account_invoice.amount_total='" + str(self.invoice_amount) + "'" + "and account_invoice.partner_id!='" + str(central) + "'" + "and account_invoice.partner_id != '" + str(south) + "'" + "and account_invoice.partner_id !='" + str(north) + "'" + "and account_invoice.partner_id !=" + str(main)) return True @api.one def inv_status_change_request(self): if self.bank_code == 'FBL': fbl_central = 9464 fbl_south = 9522 fbl_north = 9450 fbl_main = 9572 result = self.inv_status_changed(fbl_central, fbl_south, fbl_north, fbl_main) return result if self.bank_code == 'JSBL': jsbl_central = 11056 jsbl_south = 11057 jsbl_north = 11058 jsbl_main = 3349 result = self.inv_status_changed(jsbl_central, jsbl_south, jsbl_north, jsbl_main) return result raise osv.except_osv("Done........", "Records have been successfully updated")
class hr_warning(models.Model): _name = 'hr.infraction.warning' _description = 'Employee Warning' _columns = { 'name': fields.char( 'Subject', size=256, ), 'date': fields.date( 'Date Issued', ), 'type': fields.selection( [ ('verbal', 'Verbal'), ('written', 'Written'), ], 'Type', required=True, ), 'action_id': fields.many2one( 'hr.infraction.action', 'Action', ondelete='cascade', readonly=True, ), 'infraction_id': fields.related( 'action_id', 'infraction_id', type='many2one', obj='hr.infraction', string='Infraction', readonly=True, ), 'employee_id': fields.related( 'infraction_id', 'employee_id', type='many2one', obj='hr.employee', string='Employee', readonly=True, ), } _defaults = { 'type': 'written', 'date': time.strftime(DEFAULT_SERVER_DATE_FORMAT), } def unlink(self, cr, uid, ids, context=None): for warning in self.browse(cr, uid, ids, context=context): if (warning.action_id and warning.action_id.infraction_id.state != 'draft'): raise models.except_orm( _('Error'), _('Warnings attached to Infractions not in "Draft" state ' 'may not be removed.') ) return super(hr_warning, self).unlink(cr, uid, ids, context=context)
class BmLot(models.Model): _name = "bm.lot" name = fields.Char('Lot #', size=10, required=True) lettable_area = fields.Float('Lettable Area (sqm)', required=True) rental_charge = fields.Float('Rental (/sqm/month)', required=True) service_charge = fields.Float('Service Charge (/sqm/month)', required=True) promotion_levy = fields.Float('Promotion Levy (/sqm/month)', required=True) state = fields.selection(AVAILABLE_STATES, 'Status', required=True, readonly=True)
class generate_faktur_pajak(osv.osv_memory): _name = 'generate.faktur.pajak' _columns = { 'nomor_faktur_awal' : fields.char('Nomor Faktur Awal', size=20), 'nomor_faktur_akhir' : fields.char('Nomor Faktur Akhir', size=20), 'strip' : fields.char('Strip', size=3), 'dot' : fields.char('Dot', size=3), 'strip2' : fields.char('Strip', size=3), 'dot2' : fields.char('Dot', size=3), 'nomor_perusahaan' : fields.char('Nomor Perusahaan', size=3, required=True), 'nomor_awal' : fields.char('Nomor Faktur Awal', size=8, required=True), 'nomor_akhir' : fields.char('Nomor Faktur Akhir', size=8, required=True), 'tahun' : fields.char('Tahun Penerbit', size=2, required=True), 'type' : fields.selection([('in','Faktur Pajak Masukan'),('out','Faktur Pajak Keluaran')],'Type'), } _defaults = { 'nomor_awal': '', 'nomor_akhir': '', 'type': 'out', 'nomor_faktur_awal':'Nomor Faktur Awal:', 'nomor_faktur_akhir':'Nomor Faktur Akhir:', 'strip': '-', 'dot': '.', 'strip2': '-', 'dot2': '.', } def generate_faktur(self, cr, uid, ids, context=None): if not context: context={} wizard = self.browse(cr, uid, ids[0], context) #print "=====wizard.nomor_awal=====",wizard.nomor_awal,int(wizard.nomor_awal) #print "=====wizard.nomor_akhir=====",wizard.nomor_akhir,int(wizard.nomor_akhir) awal = int(wizard.nomor_awal) akhir = int(wizard.nomor_akhir) while (awal <= akhir): value = { 'nomor_perusahaan': wizard.nomor_perusahaan, 'tahun_penerbit': wizard.tahun, 'nomor_urut': '%08d' % awal, 'status': '0', 'type': wizard.type, } self.pool.get('nomor.faktur.pajak').create(cr,uid,value,context=context) awal += 1 return {'type': 'ir.actions.act_window_close'} def onchange_nomor_faktur(self, cr, uid, ids, akhir, context=None): res = {} wizard = self.browse(cr, uid, ids[0], context) if akhir <= wizard.nomor_awal: warning = { 'title': _('Warning'), 'message': _('Wrong Format must 15 digit'), } return {'warning': warning, 'value' : {'nomor_akhir' : False}} return res
class hr_infraction_action(models.Model): _name = 'hr.infraction.action' _description = 'Action Based on Infraction' _columns = { 'infraction_id': fields.many2one( 'hr.infraction', 'Infraction', ondelete='cascade', required=True, readonly=True, ), 'type': fields.selection( ACTION_TYPE_SELECTION, 'Type', required=True, ), 'memo': fields.text( 'Notes', ), 'employee_id': fields.related( 'infraction_id', 'employee_id', type='many2one', store=True, obj='hr.employee', string='Employee', readonly=True, ), 'warning_id': fields.many2one( 'hr.infraction.warning', 'Warning', readonly=True, ), 'transfer_id': fields.many2one( 'hr.department.transfer', 'Transfer', readonly=True, ), } _rec_name = 'type' def unlink(self, cr, uid, ids, context=None): for action in self.browse(cr, uid, ids, context=context): if action.infraction_id.state not in ['draft']: raise models.except_orm( _('Error'), _('Actions belonging to Infractions not in "Draft" state ' 'may not be removed.') ) return super(hr_infraction_action, self).unlink( cr, uid, ids, context=context )
class SaleInherit(osv.Model): _inherit = 'sale.order' _columns = { 'state': fields.selection([('draft', 'Draft Quotation'), ('confirm', 'Quotation Confirmed'), ('sent', 'Quotation Sent'), ('cancel', 'Cancelled'), ('waiting_date', 'Waiting Schedule'), ('waitingapproval', 'Waiting Approval'), ('progress', 'Sales Order'), ('manual', 'Sale to Invoice'), ('shipping_except', 'Shipping Exception'), ('invoice_except', 'Invoice Exception'), ('done', 'Done')], required=True, track_visibility='onchange'), } def action_button_confirm(self, cr, uid, ids, context=None): discnt = 0.0 no_line = 0.0 line_dicnt = 0.0 prod_price = 0.0 conf = self.pool.get('ir.values') sale_obj = self.browse(cr, uid, ids, context) double_valid = conf.get_default(cr, uid, 'sale.config.settings', 'module_sale_discount_approval') if double_valid == 'True': min_disct = conf.get_default(cr, uid, 'sale.config.settings', 'limit_discount') for line in sale_obj.order_line: no_line += 1 discnt += line.discount discnt = (discnt / no_line) if discnt >= min_disct: assert len( ids ) == 1, 'This option should only be used for a single id at a time.' self.signal_workflow(cr, uid, ids, 'order_toapprov') return True else: return super(SaleInherit, self).action_button_confirm( cr, uid, ids, context) else: return super(SaleInherit, self).action_button_confirm(cr, uid, ids, context) ####################################### workflow functions############################################################################# @api.one def wait_approval(self): self.state = 'waitingapproval' return True
class WizardMissingVisits(osv.TransientModel): _name = 'wiz.missing.visits' _description = 'Missing Visits Calculation' _columns = { 'bank_code': fields.selection([('MBL', 'MBL'), ('SAMBA', 'SAMBA'), ('ABL', 'ABL'), ('UBL', 'UBL'), ('NBP', 'NBP'), ('HBL', 'HBL')], 'Bank Code', required=True), } _defaults = {'bank_code': 'MBL'} @api.multi def createvisits(self): self.env.cr.execute( "select bank_code,branch_code,street,city,force_code,rf_id from res_partner where rf_id is not null and bank_code=" + "'" + self.bank_code + "'" + " and rf_id not in (select card_no from mutual_guard_tracking where archive_signal is null and visit_time is not null)" ) missing_branches = self.env.cr.dictfetchall() self.env.cr.execute( "select visit_time,visit_time_two from mutual_guard_tracking where visit_time is null and visit_time_two is null and archive_signal is False and bank_code=" + "'" + self.bank_code + "'") missing_visits_created = self.env.cr.dictfetchall() print ">>>>>>>>>>>>>>>>>>>Missing Visits>>>>>>>>>>>>>>>>>>>>>" print len(missing_visits_created) if (len(missing_branches) > 0): if (len(missing_visits_created) == 0): for branch in missing_branches: self.env['mutual.guard.tracking'].create({ 'bank_code': branch['bank_code'], 'branch_code': branch['branch_code'], 'address': branch['street'], 'city': branch['city'], 'force_code': branch['force_code'], 'card_no': branch['rf_id'] }) else: raise osv.except_osv( 'Alert.......', 'Missing visits has been already created') else: raise osv.except_osv('Alert.......', 'All branches have been first visited')
class labtest (osv.osv): _name = "medical.patient.lab.test" _inherit = "medical.patient.lab.test" _columns = { 'no_invoice' : fields.boolean ('Invoice exempt'), 'invoice_status' : fields.selection([('invoiced','Invoiced'),('tobe','To be Invoiced')],'Invoice Status'), } _defaults={ 'invoice_status': lambda *a: 'tobe', 'no_invoice': lambda *a: True }
class account_bank_statement_line(osv.osv): _inherit = "account.bank.statement.line" _description = "Bank Statement Line" _columns = { 'type': fields.selection([('supplier', 'Supplier'), ('customer', 'Customer'), ('general', 'General')], 'Type'), 't_type': fields.selection([('receipt', 'Receipt'), ('payment', 'Payment')], "Transaction Type"), 't_amount': fields.float("Amount", digits=(16, 2)), } _defaults = { 'date': False, } def onchange_trnstyp_amount(self, cr, uid, ids, t_type, t_amount): res = {} if t_amount: sign = (t_type == 'payment') and -1 or 1 res['amount'] = t_amount * sign return {'value': res}
class patient_prescription_order (osv.osv): _name = "medical.prescription.order" _inherit = "medical.prescription.order" _columns = { 'no_invoice' : fields.boolean ('Invoice exempt'), 'invoice_status' : fields.selection([('invoiced','Invoiced'),('tobe','To be Invoiced')],'Invoice Status'), } _defaults = { 'invoice_status': lambda *a: 'tobe', 'no_invoice': lambda *a: True }
class policy_line_absence(models.Model): _name = 'hr.policy.line.absence' _columns = { 'name': fields.char('Name', size=64, required=True), 'code': fields.char('Code', required=True, help="Use this code in the salary rules."), 'holiday_status_id': fields.many2one('hr.holidays.status', 'Leave', required=True), 'policy_id': fields.many2one('hr.policy.absence', 'Policy'), 'type': fields.selection( [('paid', 'Paid'), ('unpaid', 'Unpaid'), ('dock', 'Dock')], 'Type', required=True, help="Determines how the absence will be treated in payroll. " "The 'Dock Salary' type will deduct money (useful for " "salaried employees).", ), 'rate': fields.float('Rate', required=True, help='Multiplier of employee wage.'), 'use_awol': fields.boolean( 'Absent Without Leave', help='Use this policy to record employee time absence not covered ' 'by other leaves.') } def onchange_holiday(self, cr, uid, ids, holiday_status_id, context=None): res = {'value': {'name': False, 'code': False}} if not holiday_status_id: return res data = self.pool.get('hr.holidays.status').read(cr, uid, holiday_status_id, ['name', 'code'], context=context) res['value']['name'] = data['name'] res['value']['code'] = data['code'] return res
class product_product(osv.Model): _inherit = 'product.product' _columns = { 'wk_order_allow': fields.selection(( ('allow', 'Allow Order'), ('deny', 'Deny Orders'), ), 'When Product is out of Stock'), 'wk_in_stock_msg': fields.char('Message'), 'wk_out_of_stock_msg': fields.char('Message'), 'wk_override_default': fields.boolean('Override Default Message') } _defaults = { 'wk_order_allow': 'deny', 'wk_in_stock_msg': 'In Stock', 'wk_out_of_stock_msg': 'This product has gone out of Stock!' }
class surgery(osv.osv): _name = "medical.surgery" _description = "Surgery" _columns = { 'name': fields.many2one( 'medical.procedure', 'Code', help= "Procedure Code, for example ICD-10-PCS Code 7-character string"), 'pathology': fields.many2one('medical.pathology', 'Base condition', help="Base Condition / Reason"), 'classification': fields.selection([ ('o', 'Optional'), ('r', 'Required'), ('u', 'Urgent'), ], 'Surgery Classification', select=True), 'surgeon': fields.many2one('medical.physician', 'Surgeon', help="Surgeon who did the procedure"), 'date': fields.datetime('Date of the surgery'), 'age': fields.char( 'Patient age', size=3, help='Patient age at the moment of the surgery. Can be estimative' ), 'description': fields.char('Description', size=128), 'extra_info': fields.text('Extra Info'), }
class product_pricelist_item(osv.osv): _inherit = 'product.pricelist.item' def _price_field_get(self, cr, uid, context=None): pt = self.pool.get('product.price.type') ids = pt.search(cr, uid, [], context=context) result = [] for line in pt.browse(cr, uid, ids, context=context): result.append((line.id, line.name)) result.append((-1, _('Other Pricelist'))) result.append((-2, _('Supplier Prices on the product form'))) result.append((-3, _('Precio fijo'))) return result _columns = { 'base': fields.selection(_price_field_get, 'Based on', required=True, size=-1, help="Base price for computation."), 'fixed_price': fields.float('Precio Fijo', digits=(9, 2)), 'product_partner_ident': fields.char('Identificacion Cliente', required=True), 'partner_desc': fields.char('Descripcion del Cliente', required=True), # 'o2s_id': fields.integer('O2s sequence'), } def product_id_change(self, cr, uid, ids, product_id, context=None): res = super(product_pricelist_item, self).product_id_change(cr, uid, ids, product_id, context) if 'value' in res and product_id: product = self.pool.get('product.product').browse( cr, uid, product_id) res['value']['partner_desc'] = product.name return res
class restday(models.TransientModel): _name = 'hr.restday.wizard' _description = 'Schedule Template Change Wizard' _columns = { 'employee_id': fields.many2one( 'hr.employee', 'Employee', required=True, ), 'contract_id': fields.related( 'employee_id', 'contract_id', type='many2one', relation='hr.contract', string='Contract', readonly=True, ), 'st_current_id': fields.many2one( 'hr.schedule.template', 'Current Template', readonly=True, ), 'st_new_id': fields.many2one( 'hr.schedule.template', 'New Template', ), 'permanent': fields.boolean('Make Permanent', ), 'temp_restday': fields.boolean( 'Temporary Rest Day Change', help="If selected, change the rest day to the specified day only " "for the selected schedule.", ), 'dayofweek': fields.selection( [('0', 'Monday'), ('1', 'Tuesday'), ('2', 'Wednesday'), ('3', 'Thursday'), ('4', 'Friday'), ('5', 'Saturday'), ('6', 'Sunday')], 'Rest Day', select=True, ), 'temp_week_start': fields.date('Start of Week', ), 'week_start': fields.date('Start of Week', ), } _defaults = { 'temp_restday': False, } def onchange_employee(self, cr, uid, ids, ee_id, context=None): res = {'value': {'st_current_id': False}} if ee_id: ee = self.pool.get('hr.employee').browse(cr, uid, ee_id, context=None) res['value'][ 'st_current_id'] = ee.contract_id.schedule_template_id.id return res def onchange_week(self, cr, uid, ids, newdate): res = {'value': {'week_start': newdate}} if newdate: d = datetime.strptime(newdate, "%Y-%m-%d") if d.weekday() != 0: res['value']['week_start'] = False return res return res def onchange_temp_week(self, cr, uid, ids, newdate): res = {'value': {'temp_week_start': newdate}} if newdate: d = datetime.strptime(newdate, "%Y-%m-%d") if d.weekday() != 0: res['value']['temp_week_start'] = False return res return res def _create_detail(self, cr, uid, schedule, actual_dayofweek, template_dayofweek, week_start, context=None): # First, see if there's a schedule for the actual dayofweek. # If so, use it. # for worktime in schedule.template_id.worktime_ids: if worktime.dayofweek == actual_dayofweek: template_dayofweek = actual_dayofweek prevutcdtStart = False prevDayofWeek = False user = self.pool.get('res.users').browse(cr, uid, uid, context=context) local_tz = timezone(user.tz) dSchedStart = datetime.strptime(schedule.date_start, OE_DFORMAT).date() dWeekStart = schedule.date_start < week_start and datetime.strptime( week_start, OE_DFORMAT).date() or dSchedStart for worktime in schedule.template_id.worktime_ids: if worktime.dayofweek != template_dayofweek: continue hour, sep, minute = worktime.hour_from.partition(':') toHour, toSep, toMin = worktime.hour_to.partition(':') if len(sep) == 0 or len(toSep) == 0: raise models.except_orm( _('Invalid Time Format'), _('The time should be entered as HH:MM')) # TODO - Someone affected by DST should fix this # dtStart = datetime.strptime( dWeekStart.strftime('%Y-%m-%d') + ' ' + hour + ':' + minute + ':00', '%Y-%m-%d %H:%M:%S') locldtStart = local_tz.localize(dtStart, is_dst=False) utcdtStart = locldtStart.astimezone(utc) if actual_dayofweek != '0': utcdtStart = utcdtStart + \ relativedelta(days=+int(actual_dayofweek)) dDay = utcdtStart.astimezone(local_tz).date() # If this worktime is a continuation (i.e - after lunch) set the # start time based on the difference from the previous record # if prevDayofWeek and prevDayofWeek == actual_dayofweek: prevHour = prevutcdtStart.strftime('%H') prevMin = prevutcdtStart.strftime('%M') curHour = utcdtStart.strftime('%H') curMin = utcdtStart.strftime('%M') delta_seconds = ( datetime.strptime(curHour + ':' + curMin, '%H:%M') - datetime.strptime(prevHour + ':' + prevMin, '%H:%M')).seconds utcdtStart = prevutcdtStart + timedelta(seconds=+delta_seconds) dDay = prevutcdtStart.astimezone(local_tz).date() delta_seconds = ( datetime.strptime(toHour + ':' + toMin, '%H:%M') - datetime.strptime(hour + ':' + minute, '%H:%M')).seconds utcdtEnd = utcdtStart + timedelta(seconds=+delta_seconds) val = { 'name': schedule.name, 'dayofweek': actual_dayofweek, 'day': dDay, 'date_start': utcdtStart.strftime('%Y-%m-%d %H:%M:%S'), 'date_end': utcdtEnd.strftime('%Y-%m-%d %H:%M:%S'), 'schedule_id': schedule.id, } self.pool.get('hr.schedule').write(cr, uid, schedule.id, { 'detail_ids': [(0, 0, val)], }, context=context) prevDayofWeek = worktime.dayofweek prevutcdtStart = utcdtStart def _change_restday(self, cr, uid, employee_id, week_start, dayofweek, context=None): sched_obj = self.pool.get('hr.schedule') sched_detail_obj = self.pool.get('hr.schedule.detail') schedule_ids = sched_obj.search(cr, uid, [('employee_id', '=', employee_id), ('date_start', '<=', week_start), ('date_end', '>=', week_start), ('state', 'not in', ['locked'])], context=context) sched = sched_obj.browse(cr, uid, schedule_ids[0], context=context) dtFirstDay = datetime.strptime(sched.detail_ids[0].date_start, OE_DTFORMAT) date_start = (dtFirstDay.strftime(OE_DFORMAT) < week_start and week_start + ' ' + dtFirstDay.strftime('%H:%M:%S') or dtFirstDay.strftime(OE_DTFORMAT)) dtNextWeek = datetime.strptime(date_start, OE_DTFORMAT) + relativedelta(weeks=+1) # First get the current rest days rest_days = sched_obj.get_rest_days_by_id( cr, uid, sched.id, dtFirstDay.strftime(OE_DFORMAT), context=context) # Next, remove the schedule detail for the new rest day for dtl in sched.detail_ids: if (dtl.date_start < week_start or datetime.strptime( dtl.date_start, OE_DTFORMAT) >= dtNextWeek): continue if dtl.dayofweek == dayofweek: sched_detail_obj.unlink(cr, uid, dtl.id, context=context) # Enter the new rest day(s) # sched_obj = self.pool.get('hr.schedule') nrest_days = [dayofweek] + rest_days[1:] dSchedStart = datetime.strptime(sched.date_start, OE_DFORMAT).date() dWeekStart = sched.date_start < week_start and datetime.strptime( week_start, OE_DFORMAT).date() or dSchedStart if dWeekStart == dSchedStart: sched_obj.add_restdays(cr, uid, sched, 'restday_ids1', rest_days=nrest_days, context=context) elif dWeekStart == dSchedStart + relativedelta(days=+7): sched_obj.add_restdays(cr, uid, sched, 'restday_ids2', rest_days=nrest_days, context=context) elif dWeekStart == dSchedStart + relativedelta(days=+14): sched_obj.add_restdays(cr, uid, sched, 'restday_ids3', rest_days=nrest_days, context=context) elif dWeekStart == dSchedStart + relativedelta(days=+21): sched_obj.add_restdays(cr, uid, sched, 'restday_ids4', rest_days=nrest_days, context=context) elif dWeekStart == dSchedStart + relativedelta(days=+28): sched_obj.add_restdays(cr, uid, sched, 'restday_ids5', rest_days=nrest_days, context=context) # Last, add a schedule detail for the first rest day in the week using # the template for the new (temp) rest day # if len(rest_days) > 0: self._create_detail(cr, uid, sched, str(rest_days[0]), dayofweek, week_start, context=context) def _remove_add_schedule(self, cr, uid, schedule_id, week_start, tpl_id, context=None): """Remove the current schedule and add a new one in its place according to the new template. If the week that the change starts in is not at the beginning of a schedule create two new schedules to accommodate the truncated old one and the partial new one. """ sched_obj = self.pool.get('hr.schedule') sched = sched_obj.browse(cr, uid, schedule_id, context=context) vals2 = False vals1 = { 'name': sched.name, 'employee_id': sched.employee_id.id, 'template_id': tpl_id, 'date_start': sched.date_start, 'date_end': sched.date_end, } if week_start > sched.date_start: dWeekStart = datetime.strptime(week_start, '%Y-%m-%d').date() start_day = dWeekStart.strftime('%Y-%m-%d') vals1['template_id'] = sched.template_id.id vals1['date_end'] = (dWeekStart + relativedelta(days=-1)).strftime('%Y-%m-%d') vals2 = { 'name': (sched.employee_id.name + ': ' + start_day + ' Wk ' + str(dWeekStart.isocalendar()[1])), 'employee_id': sched.employee_id.id, 'template_id': tpl_id, 'date_start': start_day, 'date_end': sched.date_end, } sched_obj.unlink(cr, uid, schedule_id, context=context) _l.warning('vals1: %s', vals1) sched_obj.create(cr, uid, vals1, context=context) if vals2: _l.warning('vals2: %s', vals2) sched_obj.create(cr, uid, vals2, context=context) def _change_by_template(self, cr, uid, employee_id, week_start, new_template_id, doall, context=None): sched_obj = self.pool.get('hr.schedule') schedule_ids = sched_obj.search(cr, uid, [('employee_id', '=', employee_id), ('date_start', '<=', week_start), ('date_end', '>=', week_start), ('state', 'not in', ['locked'])], context=context) # Remove the current schedule and add a new one in its place according # to the new template # if len(schedule_ids) > 0: self._remove_add_schedule(cr, uid, schedule_ids[0], week_start, new_template_id, context=context) # Also, change all subsequent schedules if so directed if doall: ids = sched_obj.search(cr, uid, [('employee_id', '=', employee_id), ('date_start', '>', week_start), ('state', 'not in', ['locked'])], context=context) for i in ids: self._remove_add_schedule(cr, uid, i, week_start, new_template_id, context) def change_restday(self, cr, uid, ids, context=None): data = self.read(cr, uid, ids[0], [], context=context) # Change the rest day for only one schedule if (data.get('temp_restday') and data.get('dayofweek') and data.get('temp_week_start')): self._change_restday(cr, uid, data['employee_id'][0], data['temp_week_start'], data['dayofweek'], context=context) # Change entire week's schedule to the chosen schedule template if (not data.get('temp_restday') and data.get('st_new_id') and data.get('week_start')): if data.get('week_start', False): self._change_by_template(cr, uid, data['employee_id'][0], data['week_start'], data['st_new_id'][0], data.get('permanent', False), context=context) # If this change is permanent modify employee's contract to # reflect the new template # if data.get('permanent', False): self.pool.get('hr.contract').write( cr, uid, data['contract_id'][0], { 'schedule_template_id': data['st_new_id'][0], }, context=context) return { 'name': 'Change Schedule Template', 'view_type': 'form', 'view_mode': 'form', 'res_model': 'hr.restday.wizard', 'type': 'ir.actions.act_window', 'target': 'new', 'context': context }
class product_product(osv.osv): _inherit = "product.product" @api.one @api.onchange('lst_price') # if these fields are changed, call method def check_change_price(self): #import pdb;pdb.set_trace(); pricelists = self.env['product.pricelist'].search([]) pricelist = pricelists[0] return {} def product_meli_get_products( self, cr, uid, context=None ): user_obj = self.pool.get('res.users').browse(cr, uid, uid) company = user_obj.company_id product_obj = self.pool.get('product.product') #product = product_obj.browse(cr, uid, ids[0]) CLIENT_ID = company.mercadolibre_client_id CLIENT_SECRET = company.mercadolibre_secret_key ACCESS_TOKEN = company.mercadolibre_access_token REFRESH_TOKEN = company.mercadolibre_refresh_token meli = Meli(client_id=CLIENT_ID,client_secret=CLIENT_SECRET, access_token=ACCESS_TOKEN, refresh_token=REFRESH_TOKEN) url_login_meli = meli.auth_url(redirect_URI=REDIRECT_URI) #url_login_oerp = "/meli_login" response = meli.get("/users/"+company.mercadolibre_seller_id+"/items/search", {'access_token':meli.access_token}) print "product_meli_get_products: " + response.content rjson = response.json() if 'error' in rjson: if rjson['message']=='invalid_token' or rjson['message']=='expired_token': ACCESS_TOKEN = '' REFRESH_TOKEN = '' company.write({'mercadolibre_access_token': ACCESS_TOKEN, 'mercadolibre_refresh_token': REFRESH_TOKEN, 'mercadolibre_code': '' } ) return { "type": "ir.actions.act_url", "url": url_login_meli, "target": "new", } results = rjson['results'] if (results): for item_id in results: print item_id posting_id = self.pool.get('product.product').search(cr,uid,[('meli_id','=',item_id)]) response = meli.get("/items/"+item_id, {'access_token':meli.access_token}) rjson = response.json() if (posting_id): print "Item already in database: " + str(posting_id[0]) else: idcreated = self.pool.get('product.product').create(cr,uid,{ 'name': rjson['title'], 'meli_id': rjson['id'] }) if (idcreated): product = product_obj.browse(cr, uid, idcreated) product_obj.product_meli_get_product( cr, uid, [idcreated] ) return {} def product_meli_get_product( self, cr, uid, ids, context=None ): user_obj = self.pool.get('res.users').browse(cr, uid, uid) company = user_obj.company_id product_obj = self.pool.get('product.product') product = product_obj.browse(cr, uid, ids[0]) product_template_obj = self.pool.get('product.template') product_template = product_template_obj.browse(cr, uid, product.product_tmpl_id.id) CLIENT_ID = company.mercadolibre_client_id CLIENT_SECRET = company.mercadolibre_secret_key ACCESS_TOKEN = company.mercadolibre_access_token REFRESH_TOKEN = company.mercadolibre_refresh_token meli = Meli(client_id=CLIENT_ID,client_secret=CLIENT_SECRET, access_token=ACCESS_TOKEN, refresh_token=REFRESH_TOKEN) response = meli.get("/items/"+product.meli_id, {'access_token':meli.access_token}) print "product_meli_get_product: " + response.content rjson = response.json() des = '' desplain = '' vid = '' if 'error' in rjson: return {} #TODO: traer la descripcion: con #https://api.mercadolibre.com/items/{ITEM_ID}/description?access_token=$ACCESS_TOKEN if rjson['descriptions']: response2 = meli.get("/items/"+product.meli_id+"/description", {'access_token':meli.access_token}) rjson2 = response2.json() des = rjson2['text'] desplain = rjson2['plain_text'] if (len(des)>0): desplain = des #TODO: verificar q es un video if rjson['video_id']: vid = '' #TODO: traer las imagenes #TODO: pictures = rjson['pictures'] if pictures and len(pictures): thumbnail_url = pictures[0]['url'] image = urllib2.urlopen(thumbnail_url).read() image_base64 = base64.encodestring(image) product.image_medium = image_base64 #if (len(pictures)>1): #complete product images: #delete all images... #categories mlcatid = "" if ('category_id' in rjson): category_id = rjson['category_id'] ml_cat_id = self.pool.get('mercadolibre.category').search(cr,uid,[('meli_category_id','=',category_id)]) if (ml_cat_id): print "category exists!" + str(ml_cat_id) mlcatid = ml_cat_id[0] else: print "Creating category: " + str(category_id) #https://api.mercadolibre.com/categories/MLA1743 response_cat = meli.get("/categories/"+str(category_id), {'access_token':meli.access_token}) rjson_cat = response_cat.json() print "category:" + str(rjson_cat) fullname = "" if ("path_from_root" in rjson_cat): path_from_root = rjson_cat["path_from_root"] for path in path_from_root: fullname = fullname + "/" + path["name"] #fullname = fullname + "/" + rjson_cat['name'] print "category fullname:" + fullname cat_fields = { 'name': fullname, 'meli_category_id': ''+str(category_id), } ml_cat_id = self.pool.get('mercadolibre.category').create(cr,uid,(cat_fields)) if (ml_cat_id): mlcatid = ml_cat_id imagen_id = '' if (len(rjson['pictures'])>0): imagen_id = rjson['pictures'][0]['id'] meli_fields = { 'name': str(rjson['title']), 'meli_imagen_id': imagen_id, 'meli_post_required': True, 'meli_id': rjson['id'], 'meli_permalink': rjson['permalink'], 'meli_title': rjson['title'], 'meli_description': desplain, # 'meli_description_banner_id': , 'meli_category': mlcatid, 'meli_listing_type': rjson['listing_type_id'], 'meli_buying_mode':rjson['buying_mode'], 'meli_price': str(rjson['price']), 'meli_price_fixed': True, 'meli_currency': rjson['currency_id'], 'meli_condition': rjson['condition'], 'meli_available_quantity': rjson['available_quantity'], 'meli_warranty': rjson['warranty'], ## 'meli_imagen_logo': fields.char(string='Imagen Logo', size=256), ## 'meli_imagen_id': fields.char(string='Imagen Id', size=256), 'meli_imagen_link': rjson['thumbnail'], ## 'meli_multi_imagen_id': fields.char(string='Multi Imagen Ids', size=512), 'meli_video': str(vid) } tmpl_fields = { 'name': str(rjson['title']) } product.write( meli_fields ) product_template.write( tmpl_fields ) #{"id":"MLA639109219","site_id":"MLA","title":"Disco Vinilo Queen - Rock - A Kind Of Magic","subtitle":null,"seller_id":171329758,"category_id":"MLA2038","official_store_id":null,"price":31,"base_price":31,"original_price":null,"currency_id":"ARS","initial_quantity":5,"available_quantity":5,"sold_quantity":0,"buying_mode":"buy_it_now","listing_type_id":"free","start_time":"2016-10-17T20:36:22.000Z","stop_time":"2016-12-16T20:36:22.000Z","end_time":"2016-12-16T20:36:22.000Z","expiration_time":null,"condition":"used","permalink":"http://articulo.mercadolibre.com.ar/MLA-639109219-disco-vinilo-queen-rock-a-kind-of-magic-_JM","thumbnail":"http://mla-s1-p.mlstatic.com/256905-MLA25108641321_102016-I.jpg","secure_thumbnail":"https://mla-s1-p.mlstatic.com/256905-MLA25108641321_102016-I.jpg","pictures":[{"id":"256905-MLA25108641321_102016","url":"http://mla-s1-p.mlstatic.com/256905-MLA25108641321_102016-O.jpg","secure_url":"https://mla-s1-p.mlstatic.com/256905-MLA25108641321_102016-O.jpg","size":"500x400","max_size":"960x768","quality":""},{"id":"185215-MLA25150338489_112016","url":"http://www.mercadolibre.com/jm/img?s=STC&v=O&f=proccesing_image_es.jpg","secure_url":"https://www.mercadolibre.com/jm/img?s=STC&v=O&f=proccesing_image_es.jpg","size":"500x500","max_size":"500x500","quality":""}],"video_id":null,"descriptions":[{"id":"MLA639109219-1196717922"}],"accepts_mercadopago":true,"non_mercado_pago_payment_methods":[],"shipping":{"mode":"not_specified","local_pick_up":false,"free_shipping":false,"methods":[],"dimensions":null,"tags":[]},"international_delivery_mode":"none","seller_address":{"id":193196973,"comment":"3B","address_line":"Billinghurst 1711","zip_code":"1425","city":{"id":"TUxBQlBBTDI1MTVa","name":"Palermo"},"state":{"id":"AR-C","name":"Capital Federal"},"country":{"id":"AR","name":"Argentina"},"latitude":-34.5906131,"longitude":-58.4101982,"search_location":{"neighborhood":{"id":"TUxBQlBBTDI1MTVa","name":"Palermo"},"city":{"id":"TUxBQ0NBUGZlZG1sYQ","name":"Capital Federal"},"state":{"id":"TUxBUENBUGw3M2E1","name":"Capital Federal"}}},"seller_contact":null,"location":{},"geolocation":{"latitude":-34.5906131,"longitude":-58.4101982},"coverage_areas":[],"attributes":[],"warnings":[],"listing_source":"","variations":[],"status":"active","sub_status":[],"tags":[],"warranty":null,"catalog_product_id":null,"domain_id":null,"seller_custom_field":null,"parent_item_id":null,"differential_pricing":null,"deal_ids":[],"automatic_relist":false,"date_created":"2016-10-17T20:36:22.000Z","last_updated":"2016-11-07T21:38:10.000Z"} return {} def product_meli_login(self, cr, uid, ids, context=None ): user_obj = self.pool.get('res.users').browse(cr, uid, uid) company = user_obj.company_id REDIRECT_URI = company.mercadolibre_redirect_uri CLIENT_ID = company.mercadolibre_client_id CLIENT_SECRET = company.mercadolibre_secret_key meli = Meli(client_id=CLIENT_ID,client_secret=CLIENT_SECRET) url_login_meli = meli.auth_url(redirect_URI=REDIRECT_URI) #url_login_oerp = "/meli_login" return { "type": "ir.actions.act_url", "url": url_login_meli, "target": "new", } def product_get_meli_loginstate( self, cr, uid, ids, field_name, attributes, context=None ): # recoger el estado y devolver True o False (meli) #False if logged ok #True if need login user_obj = self.pool.get('res.users').browse(cr, uid, uid) company = user_obj.company_id CLIENT_ID = company.mercadolibre_client_id CLIENT_SECRET = company.mercadolibre_secret_key ACCESS_TOKEN = company.mercadolibre_access_token REFRESH_TOKEN = company.mercadolibre_refresh_token meli = Meli(client_id=CLIENT_ID,client_secret=CLIENT_SECRET, access_token=ACCESS_TOKEN, refresh_token=REFRESH_TOKEN) ML_state = False if ACCESS_TOKEN=='': ML_state = True else: response = meli.get("/users/me/", {'access_token':meli.access_token} ) rjson = response.json() if 'error' in rjson: if rjson['message']=='invalid_token' or rjson['message']=='expired_token': ACCESS_TOKEN = '' REFRESH_TOKEN = '' company.write({'mercadolibre_access_token': ACCESS_TOKEN, 'mercadolibre_refresh_token': REFRESH_TOKEN, 'mercadolibre_code': '' } ) ML_state = True #raise osv.except_osv( _('MELI WARNING'), _('INVALID TOKEN (must login, go to Edit Company and login): error: %s, message: %s, status: %s') % ( rjson["error"], rjson["message"],rjson["status"],)) res = {} for product in self.browse(cr,uid,ids): res[product.id] = ML_state return res def product_meli_status_close( self, cr, uid, ids, context=None ): user_obj = self.pool.get('res.users').browse(cr, uid, uid) company = user_obj.company_id product_obj = self.pool.get('product.product') product = product_obj.browse(cr, uid, ids[0]) CLIENT_ID = company.mercadolibre_client_id CLIENT_SECRET = company.mercadolibre_secret_key ACCESS_TOKEN = company.mercadolibre_access_token REFRESH_TOKEN = company.mercadolibre_refresh_token meli = Meli(client_id=CLIENT_ID,client_secret=CLIENT_SECRET, access_token=ACCESS_TOKEN, refresh_token=REFRESH_TOKEN) response = meli.put("/items/"+product.meli_id, { 'status': 'closed' }, {'access_token':meli.access_token}) #print "product_meli_status_close: " + response.content return {} def product_meli_status_pause( self, cr, uid, ids, context=None ): user_obj = self.pool.get('res.users').browse(cr, uid, uid) company = user_obj.company_id product_obj = self.pool.get('product.product') product = product_obj.browse(cr, uid, ids[0]) CLIENT_ID = company.mercadolibre_client_id CLIENT_SECRET = company.mercadolibre_secret_key ACCESS_TOKEN = company.mercadolibre_access_token REFRESH_TOKEN = company.mercadolibre_refresh_token meli = Meli(client_id=CLIENT_ID,client_secret=CLIENT_SECRET, access_token=ACCESS_TOKEN, refresh_token=REFRESH_TOKEN) response = meli.put("/items/"+product.meli_id, { 'status': 'paused' }, {'access_token':meli.access_token}) #print "product_meli_status_pause: " + response.content return {} def product_meli_status_active( self, cr, uid, ids, context=None ): user_obj = self.pool.get('res.users').browse(cr, uid, uid) company = user_obj.company_id product_obj = self.pool.get('product.product') product = product_obj.browse(cr, uid, ids[0]) CLIENT_ID = company.mercadolibre_client_id CLIENT_SECRET = company.mercadolibre_secret_key ACCESS_TOKEN = company.mercadolibre_access_token REFRESH_TOKEN = company.mercadolibre_refresh_token meli = Meli(client_id=CLIENT_ID,client_secret=CLIENT_SECRET, access_token=ACCESS_TOKEN, refresh_token=REFRESH_TOKEN) response = meli.put("/items/"+product.meli_id, { 'status': 'active' }, {'access_token':meli.access_token}) #print "product_meli_status_active: " + response.content return {} def product_meli_delete( self, cr, uid, ids, context=None ): user_obj = self.pool.get('res.users').browse(cr, uid, uid) company = user_obj.company_id product_obj = self.pool.get('product.product') product = product_obj.browse(cr, uid, ids[0]) if product.meli_status!='closed': self.product_meli_status_close( cr, uid, ids, context ) CLIENT_ID = company.mercadolibre_client_id CLIENT_SECRET = company.mercadolibre_secret_key ACCESS_TOKEN = company.mercadolibre_access_token REFRESH_TOKEN = company.mercadolibre_refresh_token meli = Meli(client_id=CLIENT_ID,client_secret=CLIENT_SECRET, access_token=ACCESS_TOKEN, refresh_token=REFRESH_TOKEN) response = meli.put("/items/"+product.meli_id, { 'deleted': 'true' }, {'access_token':meli.access_token}) #print "product_meli_delete: " + response.content rjson = response.json() ML_status = rjson["status"] if "error" in rjson: ML_status = rjson["error"] if "sub_status" in rjson: if len(rjson["sub_status"]) and rjson["sub_status"][0]=='deleted': product.write({ 'meli_id': '' }) return {} def product_meli_upload_image( self, cr, uid, ids, context=None ): user_obj = self.pool.get('res.users').browse(cr, uid, uid) company = user_obj.company_id product_obj = self.pool.get('product.product') product = product_obj.browse(cr, uid, ids[0]) CLIENT_ID = company.mercadolibre_client_id CLIENT_SECRET = company.mercadolibre_secret_key ACCESS_TOKEN = company.mercadolibre_access_token REFRESH_TOKEN = company.mercadolibre_refresh_token # meli = Meli(client_id=CLIENT_ID,client_secret=CLIENT_SECRET, access_token=ACCESS_TOKEN, refresh_token=REFRESH_TOKEN) if product.image==None or product.image==False: return { 'status': 'error', 'message': 'no image to upload' } # print "product_meli_upload_image" #print "product_meli_upload_image: " + response.content imagebin = base64.b64decode(product.image) imageb64 = product.image # print "data:image/png;base64,"+imageb64 # files = [ ('images', ('image_medium', imagebin, "image/png")) ] files = { 'file': ('image.jpg', imagebin, "image/jpeg"), } #print files response = meli.upload("/pictures", files, { 'access_token': meli.access_token } ) # print response.content rjson = response.json() if ("error" in rjson): raise osv.except_osv( _('MELI WARNING'), _('No se pudo cargar la imagen en MELI! Error: %s , Mensaje: %s, Status: %s') % ( rjson["error"], rjson["message"],rjson["status"],)) return { 'status': 'error', 'message': 'not uploaded'} _logger.info( rjson ) if ("id" in rjson): #guardar id product.write( { "meli_imagen_id": rjson["id"], "meli_imagen_link": rjson["variations"][0]["url"] }) #asociar imagen a producto if product.meli_id: response = meli.post("/items/"+product.meli_id+"/pictures", { 'id': rjson["id"] }, { 'access_token': meli.access_token } ) else: return { 'status': 'warning', 'message': 'uploaded but not assigned' } return { 'status': 'success', 'message': 'uploaded and assigned' } def product_meli_upload_multi_images( self, cr, uid, ids, context=None ): user_obj = self.pool.get('res.users').browse(cr, uid, uid) company = user_obj.company_id product_obj = self.pool.get('product.product') product = product_obj.browse(cr, uid, ids[0]) CLIENT_ID = company.mercadolibre_client_id CLIENT_SECRET = company.mercadolibre_secret_key ACCESS_TOKEN = company.mercadolibre_access_token REFRESH_TOKEN = company.mercadolibre_refresh_token # meli = Meli(client_id=CLIENT_ID,client_secret=CLIENT_SECRET, access_token=ACCESS_TOKEN, refresh_token=REFRESH_TOKEN) if product.images==None: return { 'status': 'error', 'message': 'no images to upload' } image_ids = [] c = 0 #loop over images for product_image in product.images: if (product_image.image): print "product_image.image:" + str(product_image.image) imagebin = base64.b64decode( product_image.image ) #files = { 'file': ('image.png', imagebin, "image/png"), } files = { 'file': ('image.jpg', imagebin, "image/jpeg"), } response = meli.upload("/pictures", files, { 'access_token': meli.access_token } ) print "meli upload:" + response.content rjson = response.json() if ("error" in rjson): raise osv.except_osv( _('MELI WARNING'), _('No se pudo cargar la imagen en MELI! Error: %s , Mensaje: %s, Status: %s') % ( rjson["error"], rjson["message"],rjson["status"],)) #return { 'status': 'error', 'message': 'not uploaded'} else: image_ids+= [ { 'id': rjson['id'] }] c = c + 1 print "image_ids:" + str(image_ids) product.write( { "meli_multi_imagen_id": "%s" % (image_ids) } ) return image_ids def product_on_change_meli_banner(self, cr, uid, ids, banner_id ): banner_obj = self.pool.get('mercadolibre.banner') #solo para saber si ya habia una descripcion completada product_obj = self.pool.get('product.product') if len(ids): product = product_obj.browse(cr, uid, ids[0]) else: product = product_obj.browse(cr, uid, ids) banner = banner_obj.browse( cr, uid, banner_id ) #banner.description _logger.info( banner.description ) result = "" if (banner.description!="" and banner.description!=False and product.meli_imagen_link!=""): imgtag = "<img style='width: 420px; height: auto;' src='%s'/>" % ( product.meli_imagen_link ) result = banner.description.replace( "[IMAGEN_PRODUCTO]", imgtag ) if (result): _logger.info( "result: %s" % (result) ) else: result = banner.description return { 'value': { 'meli_description' : result } } def product_get_meli_status( self, cr, uid, ids, field_name, attributes, context=None ): user_obj = self.pool.get('res.users').browse(cr, uid, uid) company = user_obj.company_id warningobj = self.pool.get('warning') product_obj = self.pool.get('product.product') product = product_obj.browse(cr, uid, ids[0]) CLIENT_ID = company.mercadolibre_client_id CLIENT_SECRET = company.mercadolibre_secret_key ACCESS_TOKEN = company.mercadolibre_access_token REFRESH_TOKEN = company.mercadolibre_refresh_token ML_status = "unknown" if ACCESS_TOKEN=='': ML_status = "unknown" else: meli = Meli(client_id=CLIENT_ID,client_secret=CLIENT_SECRET, access_token=ACCESS_TOKEN, refresh_token=REFRESH_TOKEN) if product.meli_id: response = meli.get("/items/"+product.meli_id, {'access_token':meli.access_token} ) rjson = response.json() ML_status = rjson["status"] if "error" in rjson: ML_status = rjson["error"] if "sub_status" in rjson: if len(rjson["sub_status"]) and rjson["sub_status"][0]=='deleted': product.write({ 'meli_id': '' }) res = {} for product in self.browse(cr,uid,ids): res[product.id] = ML_status return res def product_get_permalink( self, cr, uid, ids, field_name, attributes, context=None ): ML_permalink = '' user_obj = self.pool.get('res.users').browse(cr, uid, uid) company = user_obj.company_id product_obj = self.pool.get('product.product') product = product_obj.browse(cr, uid, ids[0]) CLIENT_ID = company.mercadolibre_client_id CLIENT_SECRET = company.mercadolibre_secret_key ACCESS_TOKEN = company.mercadolibre_access_token REFRESH_TOKEN = company.mercadolibre_refresh_token ML_permalink = "" if ACCESS_TOKEN=='': ML_permalink = "" else: meli = Meli(client_id=CLIENT_ID,client_secret=CLIENT_SECRET, access_token=ACCESS_TOKEN, refresh_token=REFRESH_TOKEN) if product.meli_id: response = meli.get("/items/"+product.meli_id, {'access_token':meli.access_token} ) rjson = response.json() if "permalink" in rjson: ML_permalink = rjson["permalink"] if "error" in rjson: ML_permalink = "" #if "sub_status" in rjson: #if len(rjson["sub_status"]) and rjson["sub_status"][0]=='deleted': # product.write({ 'meli_id': '' }) res = {} for product in self.browse(cr,uid,ids): res[product.id] = ML_permalink return res def product_post(self, cr, uid, ids, context=None): import pdb;pdb.set_trace(); # product_ids = context['active_ids'] product_ids = ids product_obj = self.pool.get('product.product') user_obj = self.pool.get('res.users').browse(cr, uid, uid) #user_obj.company_id.meli_login() company = user_obj.company_id warningobj = self.pool.get('warning') #company = self.pool.get('res.company').browse(cr,uid,1) REDIRECT_URI = company.mercadolibre_redirect_uri CLIENT_ID = company.mercadolibre_client_id CLIENT_SECRET = company.mercadolibre_secret_key ACCESS_TOKEN = company.mercadolibre_access_token REFRESH_TOKEN = company.mercadolibre_refresh_token meli = Meli(client_id=CLIENT_ID,client_secret=CLIENT_SECRET, access_token=ACCESS_TOKEN, refresh_token=REFRESH_TOKEN) if ACCESS_TOKEN=='': meli = Meli(client_id=CLIENT_ID,client_secret=CLIENT_SECRET) url_login_meli = meli.auth_url(redirect_URI=REDIRECT_URI) return { "type": "ir.actions.act_url", "url": url_login_meli, "target": "new", } for product_id in product_ids: product = product_obj.browse(cr,uid,product_id) if (product.meli_id): response = meli.get("/items/%s" % product.meli_id, {'access_token':meli.access_token}) # print product.meli_category.meli_category_id if product.meli_title==False: # print 'Assigning title: product.meli_title: %s name: %s' % (product.meli_title, product.name) product.meli_title = product.name if product.meli_price==False: # print 'Assigning price: product.meli_price: %s standard_price: %s' % (product.meli_price, product.standard_price) product.meli_price = product.standard_price body = { "title": product.meli_title or '', "description": product.meli_description or '', "category_id": product.meli_category.meli_category_id or '0', "listing_type_id": product.meli_listing_type or '0', "buying_mode": product.meli_buying_mode or '', "price": product.meli_price or '0', "currency_id": product.meli_currency or '0', "condition": product.meli_condition or '', "available_quantity": product.meli_available_quantity or '0', "warranty": product.meli_warranty or '', #"pictures": [ { 'source': product.meli_imagen_logo} ] , "video_id": product.meli_video or '', } # print body assign_img = False and product.meli_id #publicando imagen cargada en OpenERP if product.image==None: return warningobj.info(cr, uid, title='MELI WARNING', message="Debe cargar una imagen de base en el producto.", message_html="" ) elif product.meli_imagen_id==False: # print "try uploading image..." resim = product.product_meli_upload_image() if "status" in resim: if (resim["status"]=="error" or resim["status"]=="warning"): error_msg = 'MELI: mensaje de error: ', resim _logger.error(error_msg) else: assign_img = True and product.meli_imagen_id #modificando datos si ya existe el producto en MLA if (product.meli_id): body = { "title": product.meli_title or '', #"description": product.meli_description or '', #"category_id": product.meli_category.meli_category_id, #"listing_type_id": product.meli_listing_type, "buying_mode": product.meli_buying_mode or '', "price": product.meli_price or '0', #"currency_id": product.meli_currency, "condition": product.meli_condition or '', "available_quantity": product.meli_available_quantity or '0', "warranty": product.meli_warranty or '', "pictures": [], #"pictures": [ { 'source': product.meli_imagen_logo} ] , "video_id": product.meli_video or '', } #publicando multiples imagenes multi_images_ids = {} if (product.images): # print 'website_multi_images presente: ', product.images #recorrer las imagenes y publicarlas multi_images_ids = product.product_meli_upload_multi_images() #asignando imagen de logo (por source) if product.meli_imagen_logo: if product.meli_imagen_id: if 'pictures' in body.keys(): body["pictures"]+= [ { 'id': product.meli_imagen_id } ] else: body["pictures"] = [ { 'id': product.meli_imagen_id } ] if (multi_images_ids): if 'pictures' in body.keys(): body["pictures"]+= multi_images_ids else: body["pictures"] = multi_images_ids if 'pictures' in body.keys(): body["pictures"]+= [ { 'source': product.meli_imagen_logo} ] else: body["pictures"]+= [ { 'source': product.meli_imagen_logo} ] else: imagen_producto = "" if (product.meli_description!="" and product.meli_description!=False and product.meli_imagen_link!=""): imgtag = "<img style='width: 420px; height: auto;' src='%s'/>" % ( product.meli_imagen_link ) result = product.meli_description.replace( "[IMAGEN_PRODUCTO]", imgtag ) if (result): _logger.info( "result: %s" % (result) ) product.meli_description = result else: result = product.meli_description else: return warningobj.info(cr, uid, title='MELI WARNING', message="Debe completar el campo 'Imagen_Logo' con el url: http://www.nuevohorizonte-sa.com.ar/images/logo1.png", message_html="") #check fields if product.meli_description==False: return warningobj.info(cr, uid, title='MELI WARNING', message="Debe completar el campo 'description' (en html)", message_html="") #put for editing, post for creating if product.meli_id: response = meli.put("/items/"+product.meli_id, body, {'access_token':meli.access_token}) else: assign_img = True and product.meli_imagen_id response = meli.post("/items", body, {'access_token':meli.access_token}) #check response # print response.content rjson = response.json() #check error if "error" in rjson: #print "Error received: %s " % rjson["error"] error_msg = 'MELI: mensaje de error: %s , mensaje: %s, status: %s, cause: %s ' % (rjson["error"], rjson["message"], rjson["status"], rjson["cause"]) _logger.error(error_msg) missing_fields = error_msg #expired token if "message" in rjson and (rjson["message"]=='invalid_token' or rjson["message"]=="expired_token"): meli = Meli(client_id=CLIENT_ID,client_secret=CLIENT_SECRET) url_login_meli = meli.auth_url(redirect_URI=REDIRECT_URI) #print "url_login_meli:", url_login_meli #raise osv.except_osv( _('MELI WARNING'), _('INVALID TOKEN or EXPIRED TOKEN (must login, go to Edit Company and login): error: %s, message: %s, status: %s') % ( rjson["error"], rjson["message"],rjson["status"],)) return warningobj.info(cr, uid, title='MELI WARNING', message="Debe iniciar sesión en MELI. ", message_html="") else: #Any other errors return warningobj.info(cr, uid, title='MELI WARNING', message="Completar todos los campos! ", message_html="<br><br>"+missing_fields ) #last modifications if response is OK if "id" in rjson: product.write( { 'meli_id': rjson["id"]} ) posting_fields = {'posting_date': str(datetime.now()),'meli_id':rjson['id'],'product_id':product.id,'name': 'Post: ' + product.meli_title } posting_id = self.pool.get('mercadolibre.posting').search(cr,uid,[('meli_id','=',rjson['id'])]) if not posting_id: posting_id = self.pool.get('mercadolibre.posting').create(cr,uid,(posting_fields)) return {} _columns = { 'meli_imagen_id': fields.char(string='Imagen Id', size=256), 'meli_post_required': fields.boolean(string='Este producto es publicable en Mercado Libre'), 'meli_id': fields.char( string='Id del item asignado por Meli', size=256), 'meli_permalink': fields.function( product_get_permalink, method=True, type='char', size=256, string='PermaLink in MercadoLibre' ), 'meli_title': fields.char(string='Nombre del producto en Mercado Libre',size=256), 'meli_description': fields.html(string='Descripción'), 'meli_description_banner_id': fields.many2one("mercadolibre.banner","Banner"), 'meli_category': fields.many2one("mercadolibre.category","Categoría de MercadoLibre"), 'meli_listing_type': fields.selection([("free","Libre"),("bronze","Bronce"),("silver","Plata"),("gold","Oro"),("gold_premium","Gold Premium"),("gold_special","Gold Special"),("gold_pro","Oro Pro")], string='Tipo de lista'), 'meli_buying_mode': fields.selection( [("buy_it_now","Compre ahora"),("classified","Clasificado")], string='Método de compra'), 'meli_price': fields.char(string='Precio de venta', size=128), 'meli_price_fixed': fields.boolean(string='Price is fixed'), 'meli_currency': fields.selection([("ARS","Peso Argentino (ARS)")],string='Moneda (ARS)'), 'meli_condition': fields.selection([ ("new", "Nuevo"), ("used", "Usado"), ("not_specified","No especificado")],'Condición del producto'), 'meli_available_quantity': fields.integer(string='Cantidad disponible'), 'meli_warranty': fields.char(string='Garantía', size=256), 'meli_imagen_logo': fields.char(string='Imagen Logo', size=256), 'meli_imagen_id': fields.char(string='Imagen Id', size=256), 'meli_imagen_link': fields.char(string='Imagen Link', size=256), 'meli_multi_imagen_id': fields.char(string='Multi Imagen Ids', size=512), 'meli_video': fields.char( string='Video (id de youtube)', size=256), 'meli_state': fields.function( product_get_meli_loginstate, method=True, type='boolean', string="Inicio de sesión requerida", store=False ), 'meli_status': fields.function( product_get_meli_status, method=True, type='char', size=128, string="Estado del producto en MLA", store=False ), ### Agregar imagen/archivo uno o mas, y la descripcion en HTML... # TODO Agregar el banner } _defaults = { 'meli_imagen_logo': 'None', 'meli_video': '' }
class xls_report(osv.osv_memory): _name = 'xls.report' _columns = { 'partner_ids': fields.one2many('multi.partners','name','Partner IDs'), 'region_id': fields.many2one('res.region', string="Region"), 'type': fields.selection([('IncomeTax Report', 'IncomeTax Report'), ('Purchase Register', 'Purchase Register'), ('Sales Register', 'Sales Register'), ('Annex C', 'Annex C'), ('Collection Report', 'Collection Report'), ('Individual Aging', 'Individual Aging'), ('Monthly or Weekly Progress', 'Monthly or Weekly Progress'), ('/', '/')], 'Report Type', required=True), 'date_from': fields.date('From', required=True), 'date_to': fields.date('To', required=True), 'company_id': fields.many2one('res.company', 'Company'), 'partner_id': fields.many2one('res.partner', 'Customer', domain=[('customer','=','True')]), } _defaults = { 'date_from': lambda *a: datetime.now().strftime('%Y-%m-%d'), 'date_to': lambda *a: datetime.now().strftime('%Y-%m-%d'), 'type': '/' } def check_dates(self, cr, uid, ids, context=None): wizard = self.browse(cr, uid, ids, context=context)[0] if wizard.date_from: if wizard.date_from > wizard.date_to: return False if wizard.date_to > fields.date.today(): return False return True _constraints = [(check_dates, 'Error: Invalid Dates\nDate From must be less than Date To\nDate To must not be greater than todays date.', ['date_from', 'date_to']), ] def report_data(self, data,account_head): res = {} for rec in data: partner_id = self.env['res.partner'].search([['id', '=', rec['partner_id']],]) res = { 'customer': partner_id.name, 'account_head': account_head, 'entry': rec['ref'], 'particulars': rec['name'], 'date': rec['date'], 'amount': rec['debit'], } return res def collection_report(self): self.env.cr.execute("""select account_move_line.date,account_move.name as number, account_account.name as account_head, res_partner.name as customer, account_move_line.debit,account_move_line.ref from account_move inner join account_move_line on account_move.id = account_move_line.move_id inner join account_account on account_move_line.account_id = account_account.id inner join res_partner on account_move_line.partner_id=res_partner.id where account_account.type ='liquidity' and account_move.state='posted' and account_move_line.debit>0 and account_move_line.date between '%s' and '%s' and account_account.company_id=%s order by account_move_line.date asc """%(self.date_from,self.date_to,self.company_id.id)) result= self.env.cr.dictfetchall() return result def collection_report_region_wise(self): self.env.cr.execute("""select account_move_line.date,account_move.name as number, account_account.name as account_head, res_partner.name as customer,res_region.name as region, account_move_line.debit,account_move_line.ref from account_move inner join account_move_line on account_move.id = account_move_line.move_id inner join account_account on account_move_line.account_id = account_account.id inner join res_partner on account_move_line.partner_id=res_partner.id inner join res_region on res_partner.region_id = res_region.id where account_account.type ='liquidity' and account_move.state='posted' and res_partner.region_id=%s and account_move_line.debit>0 and account_move_line.date between '%s' and '%s' and account_account.company_id=%s order by account_move_line.date asc """ % (self.region_id.id,self.date_from, self.date_to, self.company_id.id)) result = self.env.cr.dictfetchall() return result def cal_aging_brackets(self,data): _list = [] date_format = "%Y-%m-%d" for rec in data: a = datetime.strptime(rec['date_invoice'], date_format) b = datetime.strptime(datetime.now().strftime('%Y-%m-%d'), date_format) delta = b - a rec['days'] = delta.days _list.append(rec) return _list def individual_aging_report(self): if self.partner_id: self.env.cr.execute( "select account_invoice.number,account_invoice.partner_id,account_invoice.date_invoice,account_invoice.residual as amount_total from account_invoice where account_invoice.date_invoice between'" + str( self.date_from) + "'" + " and '" + str( self.date_to) + "'" + "and state='open'" + "and account_invoice.company_id=" + str( self.company_id.id) + "and account_invoice.partner_id="+str(self.partner_id.id)+"and type='out_invoice'order by account_invoice.date_invoice") data = self.env.cr.dictfetchall() res = self.cal_aging_brackets(data) return res else: res = [] for partner in self.partner_ids: self.env.cr.execute( "select account_invoice.number,account_invoice.partner_id,account_invoice.date_invoice,account_invoice.residual as amount_total from account_invoice where account_invoice.date_invoice between'" + str( self.date_from) + "'" + " and '" + str( self.date_to) + "'" + "and state='open'" + "and account_invoice.company_id=" + str( self.company_id.id) + "and account_invoice.partner_id=" + str( partner.partner_id.id) + "and type='out_invoice'order by account_invoice.date_invoice") data = self.env.cr.dictfetchall() result = self.cal_aging_brackets(data) res.append({'customer':partner.partner_id.name,'details':result}) return res def collection_report_(self, mw_id): collection_amount = 0 self.env.cr.execute("""select account_move_line.date,account_move.name as number, account_account.name as account_head, res_partner.name as customer, account_move_line.debit,account_move_line.ref from account_move inner join account_move_line on account_move.id = account_move_line.move_id inner join account_account on account_move_line.account_id = account_account.id inner join res_partner on account_move_line.partner_id=res_partner.id where account_account.type ='liquidity' and account_move.state='posted' and account_move_line.partner_id=%s and account_move_line.debit>0 and account_move_line.date between '%s' and '%s' and account_account.company_id=%s order by account_move_line.date asc """ % (mw_id,self.date_from, self.date_to, self.company_id.id)) result = self.env.cr.dictfetchall() for res in result: collection_amount += res['debit'] return collection_amount def mw_progress_report(self): mw_report = [] final_res = [] new = [] _res = [] result = [] self.env.cr.execute('select id from res_partner where res_partner.customer=True') customers = self.env.cr.dictfetchall() for customer in customers: if self.company_id.name == 'Sara Automobiles': self.env.cr.execute("select sum(account_move_line.debit) - sum(account_move_line.credit) as opening from account_move_line inner join account_move on account_move_line.move_id = account_move.id where account_move_line.date < '"+str(self.date_from)+"'"+"and account_move_line.partner_id="+str(customer['id'])+"and account_move.state='posted'and account_move_line.company_id=1 and(account_move_line.account_id=8 or account_move_line.account_id=13)") data = self.env.cr.dictfetchall() if data[0]['opening']!=None: data[0]['partner_id']=customer['id'] result.append(data) else: data[0]['opening'] = 0 data[0]['partner_id'] = customer['id'] result.append(data) for records in result: for rec in records: collection = self.collection_report_(rec['partner_id']) rec['collection'] = collection _res.append(rec) for rec in _res: self.env.cr.execute("select rp.name as customer,ai.partner_id,sum(ai.amount_total) as amount_total from account_invoice as ai inner join res_partner as rp on ai.partner_id = rp.id where ai.date_invoice between'"+self.date_from+"'"+"and'"+self.date_to+"'"+"and ai.partner_id="+str(rec['partner_id'])+"group by rp.name,ai.partner_id") data = self.env.cr.dictfetchall() customer = self.env['res.partner'].search([['id', '=', rec['partner_id']], ]) if len(data)>0: rec['sale_amount'] = data[0]['amount_total'] rec['customer'] = customer.name new.append(rec) else: rec['sale_amount'] = 0 rec['customer'] = customer.name new.append(rec) for i in new: if int(i['opening'])>0 or int(i['collection'])>0 or int(i['sale_amount'])>0: final_res.append(i) for i in final_res: print(i['partner_id']) self.env.cr.execute(""" select sum(av.amount_total) as sales_return from account_invoice as av where av.type='out_refund' and av.partner_id=%s group by av.amount_total"""%(i['partner_id'])) data = self.env.cr.dictfetchall() print(data) if len(data) > 0: i['sales_return'] = data[0]['sales_return'] mw_report.append(i) else: i['sales_return'] = 0 mw_report.append(i) return mw_report def print_report(self, cr, uid, ids, data, context=None): obj = self.browse(cr, uid, ids[0], context=context) if obj.type == 'Collection Report': if obj.region_id: return { 'type': 'ir.actions.report.xml', 'name': 'custom_inventory.collection_region_wise', 'report_name': 'custom_inventory.collection_region_wise' } else: return { 'type': 'ir.actions.report.xml', 'name': 'custom_inventory.collection_report', 'report_name': 'custom_inventory.collection_report' } elif obj.type == 'Individual Aging': if obj.partner_id: return { 'type': 'ir.actions.report.xml', 'name': 'custom_inventory.wiz_individual_aging_report', 'report_name': 'custom_inventory.wiz_individual_aging_report' } else: return { 'type': 'ir.actions.report.xml', 'name': 'custom_inventory.individual_aging_multiple_customers', 'report_name': 'custom_inventory.individual_aging_multiple_customers' } elif obj.type == 'Monthly or Weekly Progress': return { 'type': 'ir.actions.report.xml', 'name': 'custom_inventory.wiz_mw_progress_report', 'report_name': 'custom_inventory.wiz_mw_progress_report' } def sales_register_report(self, cr, uid, ids, context=None): obj = self.browse(cr, uid, ids[0], context=context) cr.execute( "select sales_register.ntn,sales_register.nic,custom_dummy_invoice.partner_id,custom_dummy_invoice.amount_total,sales_register.products,sales_register.engine_number,sales_register.chassis_number," "sales_register.sara_inv_number,sales_register.date,sales_register.excl_val,sales_register.further_tax,sales_register.sales_tax," "sales_register.price_subtotal from custom_dummy_invoice_line as sales_register inner join custom_dummy_invoice on sales_register.name = custom_dummy_invoice.id where sales_register.date between'" + str( obj.date_from) + "'" + " and '" + str( obj.date_to) + "'" + "order by sales_register.date") data = cr.dictfetchall() return data def annex_c_report(self, cr, uid, ids, context=None): obj = self.browse(cr, uid, ids[0], context=context) cr.execute( "select rp.ntn,rp.nic,rp.name,rp.taxation,cdi.amount_untaxed,cdi.type,cdi.date_invoice,cdi.sara_inv_serial,cdi.amount_tax,cdi.amount_total,cdi.further_tax from custom_dummy_invoice as cdi inner join res_partner as rp on cdi.dealer_id = rp.id where cdi.date_invoice between'" + str( obj.date_from) + "'" + " and '" + str( obj.date_to) + "'" + "order by cdi.date_invoice asc") data = cr.dictfetchall() return data def income_tax_report(self,cr, uid, ids, context=None): obj = self.browse(cr, uid, ids[0], context=context) cr.execute( """ select rp.ntn,rp.name,rp.street,rp.city,aml.date,aml.ref,aml.move_id,aml.credit from account_move_line as aml inner join account_move as am on aml.move_id=am.id inner join account_account as aa on aml.account_id = aa.id inner join res_partner as rp on aml.partner_id = rp.id inner join account_account_type as aat on aa.user_type=aat.id where aat.name = 'Income Tax' and aml.date between '%s' and '%s' """%(obj.date_from, obj.date_to)) data = cr.dictfetchall() return data def purchase_register_report(self,cr, uid, ids, context=None): obj = self.browse(cr, uid, ids[0], context=context) cr.execute( "select rp.ntn,rp.name,rp.street,rp.city,av.date_invoice,av.amount_tax,av.number,av.amount_total,av.amount_untaxed,avl.name as description,avl.quantity,avl.price_unit from account_invoice as av inner join res_partner as rp on av.partner_id = rp.id " "inner join account_invoice_line as avl on av.id = avl.invoice_id where av.date_invoice between'" + str( obj.date_from) + "'" + " and '" + str( obj.date_to) + "'" + "and av.type='in_invoice' order by date_invoice asc") data = cr.dictfetchall() return data def report_xls(self, cr, uid, ids, context=None): date_format = "%d-%m-%Y" date_format_new = "%Y-%m-%d" if self.check_dates(cr, uid, ids, context=None): obj = self.browse(cr, uid, ids[0], context=context) fl = StringIO.StringIO() if context is None: context = {} wb = xlwt.Workbook() ws = wb.add_sheet('Report') font = xlwt.Font() font.bold = True borders = xlwt.Borders() bold_style = xlwt.XFStyle() bold_style.font = font new_style7 = xlwt.easyxf('font:height 210; font:name Calibri; align:wrap No;') borders.bottom = xlwt.Borders.THICK # ws.col(1).width = 500 * 12 # ws.row(5).height = 70 * 5 if obj.type == 'Sales Register': for i in range(len(sales_register)): ws.write(0, i,sales_register[i], new_style7) data = self.sales_register_report(cr,uid,ids,context=context) rows = len(data) if rows >0: for i in range(len(data)): ws.write(i+1, 0, i+1, new_style7) ws.write(i+1, 1, data[i]['ntn'], new_style7) ws.write(i+1, 2, data[i]['nic'], new_style7) ws.write(i+1, 3, data[i]['partner_id'], new_style7) ws.write(i+1, 4, data[i]['products'], new_style7) ws.write(i+1, 5, data[i]['engine_number'], new_style7) ws.write(i+1, 6, data[i]['chassis_number'], new_style7) ws.write(i+1, 7, data[i]['sara_inv_number'], new_style7) ws.write(i+1, 8, datetime.strftime(datetime.strptime(data[i]['date'],date_format_new),date_format), new_style7) ws.write(i+1, 9, data[i]['excl_val'], new_style7) ws.write(i+1, 10, data[i]['further_tax'], new_style7) ws.write(i+1, 11, data[i]['sales_tax'], new_style7) ws.write(i+1, 12, data[i]['amount_total'], new_style7) elif obj.type == 'Purchase Register': for i in range(len(purchase_register)): ws.write(0, i, purchase_register[i], new_style7) data = self.purchase_register_report(cr, uid, ids, context=context) rows = len(data) if rows > 0: for i in range(len(data)): ws.write(i + 1, 0, i + 1, new_style7) ws.write(i + 1, 1, data[i]['ntn'], new_style7) ws.write(i + 1, 2, data[i]['name'], new_style7) ws.write(i + 1, 3, str(data[i]['street']) + str(data[i]['city']), new_style7) ws.write(i + 1, 4, data[i]['description'], new_style7) ws.write(i + 1, 5, data[i]['number'],new_style7) ws.write(i + 1, 6, datetime.strftime(datetime.strptime(data[i]['date_invoice'],date_format_new),date_format), new_style7) ws.write(i + 1, 7, data[i]['quantity'], new_style7) ws.write(i + 1, 8, data[i]['price_unit'], new_style7) ws.write(i + 1, 9, data[i]['amount_untaxed'], new_style7) ws.write(i + 1, 10, data[i]['amount_tax'], new_style7) ws.write(i + 1, 11, data[i]['amount_total'], new_style7) ws.write(i + 1, 12, '', new_style7) elif obj.type == 'IncomeTax Report': for i in range(len(income_tax)): ws.write(0, i, income_tax[i], new_style7) data = self.income_tax_report(cr, uid, ids, context=context) rows = len(data) if rows >0: for i in range(len(data)): ws.write(i+1, 0, i+1, new_style7) ws.write(i+1, 1, data[i]['ntn'], new_style7) ws.write(i+1, 2, data[i]['name'], new_style7) ws.write(i+1, 3, str(data[i]['street'])+str(data[i]['city']), new_style7) ws.write(i+1, 4, '', new_style7) ws.write(i+1, 5, '', new_style7) ws.write(i+1, 6, datetime.strftime(datetime.strptime(data[i]['date'],date_format_new),date_format), new_style7) ws.write(i+1, 7, data[i]['ref'], new_style7) ws.write(i + 1, 8, '', new_style7) ws.write(i + 1, 9, '', new_style7) ws.write(i+1, 10, '', new_style7) ws.write(i+1, 11, data[i]['credit'], new_style7) ws.write(i+1, 12, '', new_style7) elif obj.type == 'Annex C': for i in range(len(annex_c)): ws.write(0, i, annex_c[i], new_style7) data = self.annex_c_report(cr,uid,ids,context=context) rows = len(data) if rows >0: for i in range(len(data)): ws.write(i+1, 0, i+1, new_style7) ws.write(i+1, 1, data[i]['ntn'], new_style7) ws.write(i+1, 2, data[i]['nic'], new_style7) ws.write(i+1, 3, data[i]['name'], new_style7) ws.write(i+1, 4, data[i]['taxation'], new_style7) ws.write(i+1, 5, '', new_style7) ws.write(i+1, 6, 'SI', new_style7) ws.write(i+1, 7, data[i]['sara_inv_serial'], new_style7) ws.write(i+1, 8, datetime.strftime(datetime.strptime(data[i]['date_invoice'],date_format_new),date_format), new_style7) ws.write(i+1, 9, '', new_style7) if data[i]['type'] == 'Unregistered': ws.write(i+1, 10, data[i]['type'],new_style7) else: ws.write(i + 1, 10,'Registered',new_style7) ws.write(i+1, 11, '', new_style7) ws.write(i+1, 12, '', new_style7) ws.write(i+1, 13, '', new_style7) ws.write(i+1, 14, '', new_style7) ws.write(i+1, 15, data[i]['amount_untaxed'], new_style7) ws.write(i+1, 16, data[i]['amount_tax'], new_style7) ws.write(i+1, 17, '', new_style7) ws.write(i+1, 18, '', new_style7) ws.write(i+1, 19, '', new_style7) ws.write(i+1, 20, '', new_style7) ws.write(i+1, 21, data[i]['further_tax'], new_style7) ws.write(i+1, 22, data[i]['amount_total'], new_style7) wb.save(fl) fl.seek(0) buf = base64.encodestring(fl.read()) ctx = dict(context) ctx.update({'file': buf}) if context is None: context = {} data = {} res = self.read(cr, uid, ids, [], context=context) res = res and res[0] or {} data['form'] = res try: form_id = \ self.pool.get('ir.model.data').get_object_reference(cr, uid, 'report_xls', 'view_xls_file_form_view')[1] except ValueError: form_id = False return { 'type': 'ir.actions.act_window', 'view_type': 'form', 'view_mode': 'form', 'res_model': 'demo.xls.report.file', 'views': [(form_id, 'form')], 'view_id': form_id, 'targer': 'new', 'context': ctx }
class wage_increment_run(models.Model): _name = 'hr.contract.wage.increment.run' _description = 'Wage Increment Batches' _inherit = ['ir.needaction_mixin'] _columns = { 'name': fields.char( 'Name', size=64, required=True, readonly=True, states={'draft': [('readonly', False)]}, ), 'effective_date': fields.date( 'Effective Date', required=True, readonly=True, states={'draft': [('readonly', False)]}, ), 'type': fields.selection( [ ('fixed', 'Fixed Amount'), ('percent', 'Percentage'), ('final', 'Final Amount'), ('manual', 'Manual'), ], 'Type', required=True, readonly=True, states={'draft': [('readonly', False)]}, ), 'adjustment_amount': fields.float( 'Adjustment Amount', digits_compute=dp.get_precision('Payroll'), required=True, readonly=True, states={'draft': [('readonly', False)]}, ), 'increment_ids': fields.one2many( 'hr.contract.wage.increment', 'run_id', 'Adjustments', required=False, readonly=False, states={ 'confirm': [('readonly', False)], 'approve': [('readonly', True)], 'decline': [('readonly', True)], }, ), 'state': fields.selection([('draft', 'Draft'), ('confirm', 'Confirmed'), ('approve', 'Approved'), ('decline', 'Declined')], 'State', readonly=True), } _defaults = { 'state': 'draft', } def _needaction_domain_get(self, cr, uid, context=None): users_obj = self.pool.get('res.users') domain = [] if users_obj.has_group(cr, uid, 'hr_security.group_hr_director'): domain = [('state', 'in', ['confirm'])] return domain return False def unlink(self, cr, uid, ids, context=None): if isinstance(ids, (int, long)): ids = [ids] for run in self.browse(cr, uid, ids, context=context): if run.state in ['approve']: raise models.except_orm( _('The adjustment run cannot be deleted!'), _('You may not delete a wage adjustment that is in the ' '%s state.') % run.state) return super(wage_increment_run, self).unlink(cr, uid, ids, context=context) def _state(self, cr, uid, ids, signal, state, context=None): wkf = netsvc.LocalService('workflow') for run in self.browse(cr, uid, ids, context=context): [ wkf.trg_validate(uid, 'hr.contract.wage.increment', incr.id, signal, cr) for incr in run.increment_ids ] self.write(cr, uid, run.id, {'state': state}, context=context) return True def state_confirm(self, cr, uid, ids, context=None): return self._state(cr, uid, ids, 'signal_confirm', 'confirm', context) def state_approve(self, cr, uid, ids, context=None): return self._state(cr, uid, ids, 'signal_approve', 'approve', context) def state_decline(self, cr, uid, ids, context=None): return self._state(cr, uid, ids, 'signal_decline', 'decline', context)
class wage_increment(models.Model): _name = 'hr.contract.wage.increment' _description = 'HR Contract Wage Adjustment' def _calculate_difference(self, cr, uid, ids, field_name, args, context=None): res = dict.fromkeys(ids) for incr in self.browse(cr, uid, ids, context=context): if incr.wage >= incr.contract_id.wage: percent = ((incr.wage / incr.contract_id.wage) - 1.0) * 100.0 else: percent = (1.0 - (incr.wage / incr.contract_id.wage)) * -100.0 res[incr.id] = { 'wage_difference': incr.wage - incr.current_wage, 'wage_difference_percent': percent, } return res def _get_department(self, cr, uid, ids, field_name, arg, context=None): res = dict.fromkeys(ids, False) for incr in self.browse(cr, uid, ids, context=context): res[incr.id] = incr.employee_id.department_id.id, return res _columns = { 'effective_date': fields.date( 'Effective Date', required=True, readonly=True, states={'draft': [('readonly', False)]}, ), 'wage': fields.float( 'New Wage', digits_compute=dp.get_precision('Payroll'), required=True, readonly=True, states={'draft': [('readonly', False)]}, ), 'new_contract_id': fields.many2one( 'hr.contract', 'New Contract', readonly=True, ), 'contract_id': fields.many2one( 'hr.contract', 'Contract', readonly=True, ), 'current_wage': fields.related( 'contract_id', 'wage', type='float', string='Current Wage', store=True, readonly=True, ), 'wage_difference': fields.function( _calculate_difference, type='float', method=True, string='Difference', multi='diff', readonly=True, ), 'wage_difference_percent': fields.function( _calculate_difference, type='float', method=True, string='Percentage', multi='diff', readonly=True, ), 'employee_id': fields.related( 'contract_id', 'employee_id', relation='hr.employee', type='many2one', string='Employee', store=True, readonly=True, ), 'job_id': fields.related( 'contract_id', 'job_id', relation='hr.job', type='many2one', string='Job', store=True, readonly=True, ), 'department_id': fields.related( 'employee_id', 'department_id', relation='hr.department', type='many2one', string='Department', store=True, readonly=True, ), 'state': fields.selection( [('draft', 'Draft'), ('confirm', 'Confirmed'), ('approve', 'Approved'), ('decline', 'Declined')], 'State', readonly=True, ), 'run_id': fields.many2one( 'hr.contract.wage.increment.run', 'Batch Run', readonly=True, ondelete='cascade', ), } def _get_contract_data(self, cr, uid, field_list, context=None): if context is None: context = {} employee_id = self._get_employee(cr, uid, context=context) ee_data = self.pool.get('hr.employee').read(cr, uid, employee_id, ['contract_id'], context=context) contract_id = ee_data.get('contract_id', False)[0] if not contract_id: return False data = self.pool.get('hr.contract').read(cr, uid, contract_id, field_list, context=context) return data def _get_contract_id(self, cr, uid, context=None): data = self._get_contract_data(cr, uid, ['id'], context) return data.get('id', False) def _get_employee(self, cr, uid, context=None): if context is None: context = {} employee_id = context.get('active_id', False) return employee_id def _get_effective_date(self, cr, uid, context=None): contract_id = self._get_contract_id(cr, uid, context=context) if not contract_id: return False contract = self.pool.get('hr.contract').browse(cr, uid, contract_id, context=context) if contract.pps_id: first_day = 1 if contract.pps_id.type == 'monthly': first_day = contract.pps_id.mo_firstday date_format = '%Y-%m-' + first_day dThisMonth = datetime.now().strftime(date_format).strptime( DEFAULT_SERVER_DATE_FORMAT).date() dNextMonth = (datetime.now() + relativedelta(months=+1)).strftime( date_format).strptime(DEFAULT_SERVER_DATE_FORMAT).date() if dThisMonth < datetime.now().date(): return dNextMonth.strftime(DEFAULT_SERVER_DATE_FORMAT) else: return dThisMonth.strftime(DEFAULT_SERVER_DATE_FORMAT) return False _defaults = { 'contract_id': _get_contract_id, 'employee_id': _get_employee, 'effective_date': _get_effective_date, 'state': 'draft', } _rec_name = 'effective_date' def _check_state(self, cr, uid, wage_incr, context=None): wage_incr_ids = self.search( cr, uid, [ ('contract_id', '=', wage_incr.contract_id.id), ('state', 'in', ['draft', 'confirm', 'approved']), ('id', '!=', wage_incr.id), ], context=context) if len(wage_incr_ids) > 0: data = self.pool.get('hr.contract').read(cr, uid, wage_incr.contract_id.id, ['name'], context=context) raise models.except_orm( _('Warning'), _('There is already another wage adjustment in progress for ' 'this contract: %s.') % (data['name'])) contract_obj = self.pool.get('hr.contract') data = contract_obj.read(cr, uid, wage_incr.contract_id.id, ['state', 'date_end'], context=context) if data['state'] in ['draft', 'done']: data = self.pool.get('hr.contract').read(cr, uid, wage_incr.contract_id.id, ['name'], context=context) raise models.except_orm( _('Warning!'), _('The current state of the contract does not permit a wage ' 'change: %s') % (data['name'])) if data.get('date_end', False) and data['date_end'] != '': dContractEnd = datetime.strptime(data['date_end'], DEFAULT_SERVER_DATE_FORMAT) dEffective = datetime.strptime(wage_incr.effective_date, DEFAULT_SERVER_DATE_FORMAT) if dEffective >= dContractEnd: data = self.pool.get('hr.contract').read( cr, uid, wage_incr.contract_id.id, ['name'], context=context) raise models.except_orm( _('Warning!'), _('The contract end date is on or before the effective ' 'date of the adjustment: %s') % (data['name'])) return True def action_wage_increment(self, cr, uid, ids, context=None): hr_obj = self.pool.get('hr.contract') if isinstance(ids, (int, long)): ids = [ids] # Copy the contract and adjust start/end dates and wage accordingly. # for wi in self.browse(cr, uid, ids, context=context): if -0.01 < wi.wage_difference < 0.01: continue self._check_state(cr, uid, wi, context=context) default = { 'wage': wi.wage, 'date_start': wi.effective_date, 'name': False, 'state': False, 'message_ids': False, 'trial_date_start': False, 'trial_date_end': False, } data = hr_obj.copy_data(cr, uid, wi.contract_id.id, default=default, context=context) notes = data.get('notes', False) if not notes: notes = '' notes = notes + \ _('\nSuperceedes (because of wage adjustment) previous ' 'contract: ') + wi.contract_id.name data['notes'] = notes c_id = hr_obj.create(cr, uid, data, context=context) if c_id: if wi.contract_id.notes: notes = wi.contract_id.notes else: notes = '' notes = notes + \ _('\nSuperceeded (for wage adjustment) by contract: ') + \ wi.contract_id.name vals = {'notes': notes, 'date_end': False} wkf = netsvc.LocalService('workflow') # Set the new contract to the appropriate state wkf.trg_validate(uid, 'hr.contract', c_id, 'signal_confirm', cr) # Terminate the current contract (and trigger appropriate state # change) vals['date_end'] = datetime.strptime( wi.effective_date, '%Y-%m-%d').date() + \ relativedelta(days=-1) hr_obj.write(cr, uid, wi.contract_id.id, vals, context=context) wkf.trg_validate(uid, 'hr.contract', wi.contract_id.id, 'signal_done', cr) return def create(self, cr, uid, vals, context=None): contract_id = vals.get('contract_id', False) if not contract_id: if context is not None: contract_id = context.get('active_id') data = self.pool.get('hr.contract').read(cr, uid, contract_id, ['name', 'date_start'], context=context) # Check that the contract start date is before the effective date if vals['effective_date'] <= data['date_start']: raise models.except_orm( _('Error'), _('The effective date of the adjustment must be after the ' 'contract start date. Contract: %s.') % (data['name'])) wage_incr_ids = self.search( cr, uid, [ ('contract_id', '=', contract_id), ('state', 'in', ['draft', 'confirm', 'approved']), ], context=context) if len(wage_incr_ids) > 0: raise models.except_orm( _('Warning'), _('There is already another wage adjustment in progress for ' 'this contract: %s.') % (data['name'])) return super(wage_increment, self).create(cr, uid, vals, context=context) def do_signal_confirm(self, cr, uid, ids, context=None): for wi in self.browse(cr, uid, ids, context=context): self._check_state(cr, uid, wi, context=context) self.write(cr, uid, wi.id, {'state': 'confirm'}, context=context) def do_signal_approve(self, cr, uid, ids, context=None): for i in ids: self.action_wage_increment(cr, uid, [i], context=context) self.write(cr, uid, i, {'state': 'approve'}, context=context) def unlink(self, cr, uid, ids, context=None): for incr in self.browse(cr, uid, ids, context=context): if incr.state in ['approve']: raise models.except_orm( _('The record cannot be deleted!'), _("""\ You may not delete a record that is in a %s state: Employee: %s""") % (incr.state, incr.employee_id.name)) return super(wage_increment, self).unlink(cr, uid, ids, context=context)
class SaleQuickInvoiceConfirmLine(osv.TransientModel): _name = 'sale.quick.invoice.confirm.line' def _get_order_line_info(self, cr, uid, ids, field_name, arg, context=None): down_payment_id = self.pool['ir.values'].get_default( cr, uid, 'sale.config.settings', 'deposit_product_id_setting') res = dict(map(lambda x: (x, 0), ids)) for line in self.browse(cr, uid, ids, context): if line.sale_order_line: sol = line.sale_order_line if field_name == 'product_id': res[line.id] = sol.product_id.name if field_name == 'sequence': res[line.id] = sol.sequence if field_name == 'price_unit': res[line.id] = sol.price_unit if field_name == 'price_total': if line.identification != 'discount': res[line.id] = sol.price_unit if ( sol.product_id.id == down_payment_id) else sol.price_total else: res[line.id] = sol.price_total if field_name == 'product_uom_qty': res[line.id] = sol.product_uom_qty if field_name == 'qty_invoiced' and line.identification == 'commodity': res[line.id] = sol.qty_invoiced if field_name == 'balance': invoice_total = 0.0 for invoice in sol.invoice_lines: if line.identification == 'discount': invoice_total += -invoice.price_subtotal else: invoice_total += invoice.price_subtotal res[line.id] = ( line.price_total - invoice_total ) if line.identification == 'discount' else ( line.price_total - invoice_total) return res _columns = { 'quick_invoice_line': fields.many2one('quick.invoice.confirm', required=True, ondelete='cascade'), 'sale_order_line': fields.many2one('sale.order.line', string='订单行ID', required=True, ondelete='cascade'), 'product_id': fields.function(_get_order_line_info, string='产品', type='char'), 'sequence': fields.function(_get_order_line_info, string='序号', type='integer'), 'price_unit': fields.function(_get_order_line_info, string='单价', type='float'), 'price_total': fields.function(_get_order_line_info, string='小计', type='float'), 'product_uom_qty': fields.function(_get_order_line_info, string='数量', type='float'), 'qty_invoiced': fields.function(_get_order_line_info, string='收款次数', type='float'), 'balance': fields.function(_get_order_line_info, string='余款', type='float'), 'amount': fields.float(string='本次收款'), 'comment': fields.text(string='说明'), 'invoice_number': fields.char(string='收据号'), 'date_invoice': fields.date(string='收款日期'), 'identification': fields.selection([('down_payment', '预付'), ('discount', '优惠'), ('commodity', '产品')], string='类型'), } @api.multi def create_new_invoice(self): imd = self.env['ir.model.data'] action = imd.xmlid_to_object( 'account_expend.act_sale_quick_invoice_confirm') form_view_id = imd.xmlid_to_res_id( 'account_expend.view_sale_quick_invoice_confirm_line_from') result = { 'res_id': self.id, 'name': '收款信息', 'type': action.type, 'view_type': 'form', 'view_model': 'form', 'res_model': action.res_model, 'views': [(form_view_id, 'form')], 'views_id': form_view_id, 'target': 'new', } return result @api.multi def confirm_cancel(self): qid = self.quick_invoice_line.id return self.env['sale.order'].confirm_cancel(qid) # 覆盖sale_make_invoice_advance的发票创建方法 @api.multi def action_invoice_create(self, order_ids, order_line_id, grouped=False, final=False): inv_obj = self.env['account.invoice'] precision = self.env['decimal.precision'].precision_get( 'Product Unit of Measure') orders = self.env['sale.order'].browse(order_ids) invoices = {} for order in orders: group_key = order.id if grouped else (order.partner_invoice_id.id, order.currency_id.id) line = self.env['sale.order.line'].browse(order_line_id) if line: # if float_is_zero(line.qty_to_invoice, precision_digits=precision): # continue if group_key not in invoices: inv_data = order._prepare_invoice() if self.invoice_number: inv_data['invoice_number'] = self.invoice_number if self.date_invoice: inv_data['date_invoice'] = self.date_invoice if self.comment: inv_data['comment'] = self.comment # 如果产品为优惠,那么建立退款收据 if line.product_id.name == u'价格优惠': inv_data['type'] = 'out_refund' invoice = inv_obj.create(inv_data) invoices[group_key] = invoice elif group_key in invoices: vals = {} if order.name not in invoices[group_key].origin.split( ', '): vals['origin'] = invoices[ group_key].origin + ', ' + order.name if order.client_order_ref and order.client_order_ref not in invoices[ group_key].name.split(', '): vals['name'] = invoices[ group_key].name + ', ' + order.client_order_ref invoices[group_key].write(vals) # if not float_is_zero(qty, precision_digits=precision): vals = self._prepare_invoice_line(qty=line.product_uom_qty) vals.update({ 'invoice_id': invoices[group_key].id, 'sale_line_ids': [(6, 0, [line.id])] }) self.env['account.invoice.line'].create(vals) if not invoices: raise UserError(_('There is no invoicable line.')) for invoice in invoices.values(): if not invoice.invoice_line_ids: raise UserError(_('There is no invoicable line.')) if invoice.amount_untaxed < 0: invoice.type = 'out_refund' for line in invoice.invoice_line_ids: line.quantity = line.quantity for line in invoice.invoice_line_ids: line._set_additional_fields(invoice) invoice.compute_taxes() # 调用验证按钮的工作流 if invoice.state not in ('draft', 'proforma', 'proforma2'): pass invoice.signal_workflow('invoice_open') return [inv.id for inv in invoices.values()] @api.multi def _prepare_invoice_line(self, qty): sol = self.sale_order_line product = sol.product_id order_id = sol.order_id res = {} account = product.property_account_income_id or product.categ_id.property_account_income_categ_id if not account: raise UserError(_('Please define income account for this product: "%s" (id:%d) - or for its category: "%s".') % \ (product.name, product.id, product.categ_id.name)) fpos = order_id.fiscal_position_id or order_id.partner_id.property_account_position_id if fpos: account = fpos.map_account(account) # 因为收款改为手写,当出现数量大于1时,一定有计算的必要,变为计算单价的方式 res = { 'name': sol.name, 'sequence': sol.sequence, 'origin': sol.order_id.name, 'account_id': account.id, 'price_unit': self.amount / qty, 'quantity': qty, 'price_subtotal': self.amount, 'discount': sol.discount, 'uom_id': sol.product_uom.id, 'product_id': product.id or False, 'invoice_line_tax_ids': [(6, 0, sol.tax_id.ids)], 'account_analytic_id': sol.order_id.project_id.id, } return res @api.multi def create_invoice(self): if self.identification == 'commodity': self.amount = abs(self.amount) if self.amount <= 0.0: raise ValidationError(u'收款不能小于或等于0.0') if self.identification != 'discount' and self.amount > self.balance: raise ValidationError(u'收款不能大于余款') new_invoices = self.action_invoice_create( [self.sale_order_line.order_id.id], self.sale_order_line.id, grouped=True) invoices = [] for new_invoice in new_invoices: self.env['account.quick.invoice.confirm.line'].create({ 'quick_invoice_line': self.quick_invoice_line.id, 'invoice_id': new_invoice }) return self.confirm_cancel()
class AccountQuickInvoiceConfirmLine(osv.TransientModel): _name = 'account.quick.invoice.confirm.line' def _get_invoice_info(self, cr, uid, ids, field_name, arg, context=None): res = dict(map(lambda x: (x, 0), ids)) for line in self.browse(cr, uid, ids, context): if line.invoice_id: if field_name == 'invoice_line_ids': invoice_text = '' for invoice_line in line.invoice_id.invoice_line_ids: invoice_text += invoice_line.product_id.name + u';' res[line.id] = invoice_text if field_name == 'total': invoice_total = 0.0 for invoice_line in line.invoice_id.invoice_line_ids: invoice_total += invoice_line.price_subtotal res[line.id] = invoice_total if field_name == 'cdate': res[line.id] = line.invoice_id.create_date return res # 实体字段使用constrain获取 @api.constrains('invoice_id') def _get_enity_invoice_field(self): self.write({ 'invoice_number': self.invoice_id.invoice_number, 'date_invoice': self.invoice_id.date_invoice, 'state': self.invoice_id.state }) _columns = { 'quick_invoice_line': fields.many2one('quick.invoice.confirm', required=True, ondelete='cascade', readonly=True), 'invoice_id': fields.many2one('account.invoice', string='付款ID', required=True, ondelete='cascade', readonly=True), 'invoice_line_ids': fields.function(_get_invoice_info, type='html', string='目标产品'), 'total': fields.function(_get_invoice_info, type='float', string='收款'), 'cdate': fields.function(_get_invoice_info, type='datetime', string='创建时间'), 'invoice_number': fields.char(string='收据号'), 'date_invoice': fields.date(string='收款日期'), 'state': fields.selection([('draft', '草稿'), ('proforma', '形式'), ('proforma2', '形式2'), ('open', '确认(待收)'), ('paid', '已收'), ('cancel', '已取消')], string='状态', readonly=True), } @api.multi def confirm_cancel(self): qid = self.quick_invoice_line.id return self.env['sale.order'].confirm_cancel(qid) @api.multi def action_invoice(self): vals = {} if self.invoice_number: vals['invoice_number'] = self.invoice_number if self.date_invoice: vals['date_invoice'] = self.date_invoice self.env['account.invoice'].browse(self.invoice_id.id).write(vals) imd = self.env['ir.model.data'] action = imd.xmlid_to_object('account.action_account_invoice_payment') form_view_id = imd.xmlid_to_res_id( 'account.view_account_payment_invoice_form') result = { 'res_id': False, 'name': '确认', 'type': action.type, 'view_type': 'form', 'view_model': 'form', 'res_model': action.res_model, 'views': [(form_view_id, 'form')], 'views_id': form_view_id, 'context': { 'default_invoice_ids': [(4, self.invoice_id.id, None)] }, 'target': 'new', } return result
class wolftrakglobal_report_606(osv.osv): _name = 'wolftrakglobal.report606' def _toma_default_pagos(self, cr, uid, context=None): return self.pool.get('account.payment').search( cr, uid, []) # retorna una lista (importate) _columns = { 'invoices': fields.many2many('account.invoice', domain=[('type', '=', 'in_invoice'), ('state', '!=', 'draft'), ('company_id', '=', 3)]), 'payments': fields.many2many('account.payment'), 'dt_payments': fields.selection([('default', 'Default'), ('x', 'y'), ('z', 'aa')], string="Fecha Pagos"), 'desde_606': fields.date('Desde:'), 'desde_str': fields.char(compute='_toma_desde'), 'hasta_606': fields.date('Hasta:'), 'hasta_str': fields.char(compute='_toma_hasta'), 'periodo': fields.char(compute='_toma_periodo', string='Periodo', readonly=True), 'cant_reg': fields.integer('Cantidad de registros'), 'total_rtn': fields.float('ITBIS Retenido: '), 'total_cld': fields.float('Total Calculado: '), 'total_tax': fields.float('ITBIS Calculado: ') } _defaults = { 'desde_606': lambda *a: time.strftime('%Y-%m-01'), 'hasta_606': lambda *a: str(datetime.now() + relativedelta.relativedelta( months=+1, day=1, days=-1))[:10], 'payments': _toma_default_pagos } @api.depends('hasta_606') def _toma_periodo(self): month = str(self.hasta_606[5:7]) year = str(self.hasta_606[:4]) self.periodo = year + month @api.depends('desde_606') def _toma_desde(self): year = str(self.desde_606[:4]) month = str(self.desde_606[5:7]) day = str(self.desde_606[8:10]) self.desde_str = year + month + day @api.depends('hasta_606') def _toma_hasta(self): year = str(self.hasta_606[:4]) month = str(self.hasta_606[5:7]) day = str(self.hasta_606[8:10]) self.hasta_str = year + month + day @api.onchange('invoices') def total_calculado(self): self.total_cld = 0.0 self.total_tax = 0.0 self.total_rtn = 0.0 for value in self.invoices: self.total_cld += value.amount_untaxed self.total_tax += value.amount_tax self.total_rtn += float(value.tax_hold) self.cant_reg = len(self.invoices)