def unlink(self): if any(requisition.state not in ('draft', 'cancel') for requisition in self): raise UserError(_('You can only delete draft requisitions.')) # Draft requisitions could have some requisition lines. self.mapped('line_ids').unlink() return super(PurchaseRequisition, self).unlink()
def create_customer_profile(self, partner, opaqueData): """Create a payment and customer profile in the Authorize.net backend. Creates a customer profile for the partner/credit card combination and links a corresponding payment profile to it. Note that a single partner in the Odoo database can have multiple customer profiles in Authorize.net (i.e. a customer profile is created for every res.partner/payment.token couple). :param record partner: the res.partner record of the customer :param str cardnumber: cardnumber in string format (numbers only, no separator) :param str expiration_date: expiration date in 'YYYY-MM' string format :param str card_code: three- or four-digit verification number :return: a dict containing the profile_id and payment_profile_id of the newly created customer profile and payment profile :rtype: dict """ values = { 'createCustomerProfileRequest': { 'merchantAuthentication': { 'name': self.name, 'transactionKey': self.transaction_key }, 'profile': { 'description': ('ODOO-%s-%s' % (partner.id, uuid4().hex[:8]))[:20], 'email': partner.email or '', 'paymentProfiles': { 'customerType': 'business' if partner.is_company else 'individual', 'billTo': { 'firstName': '' if partner.is_company else _partner_split_name(partner.name)[0], 'lastName': _partner_split_name(partner.name)[1], 'address': (partner.street or '' + (partner.street2 if partner.street2 else '')) or None, 'city': partner.city, 'state': partner.state_id.name or None, 'zip': partner.zip or '', 'country': partner.country_id.name or None }, 'payment': { 'opaqueData': { 'dataDescriptor': opaqueData.get('dataDescriptor'), 'dataValue': opaqueData.get('dataValue') } } } }, 'validationMode': 'liveMode' if self.state == 'enabled' else 'testMode' } } response = self._authorize_request(values) if response and response.get('err_code'): raise UserError(_( "Authorize.net Error:\nCode: %s\nMessage: %s" % (response.get('err_code'), response.get('err_msg')) )) return { 'profile_id': response.get('customerProfileId'), 'payment_profile_id': response.get('customerPaymentProfileIdList')[0] }
def button_checkout(self): ''' 月末结账:结账 按钮 ''' for balance in self: if balance.period_id: # 调用 生成科目余额表 向导的 计算上一个会计期间方法,得到 上一个会计期间 last_period = self.env['create.trial.balance.wizard'].compute_last_period_id(balance.period_id) if last_period: if not last_period.is_closed: raise UserError(u'上一个会计期间%s未结账' % last_period.name) if balance.period_id.is_closed: raise UserError(u'本期间%s已结账' % balance.period_id.name) else: voucher_obj = self.env['voucher'] voucher_ids = voucher_obj.search([('period_id', '=', balance.period_id.id)]) draft_voucher_count = 0 # 未审核凭证个数 for voucher_id in voucher_ids: if voucher_id.state != 'done': draft_voucher_count += 1 if draft_voucher_count != 0: raise UserError(u'该期间有%s张凭证未审核' % draft_voucher_count) else: voucher_line = [] # 生成的结账凭证行 account_obj = self.env['finance.account'] company_obj = self.env['res.company'] voucher_line_obj = self.env['voucher.line'] revenue_account_ids = account_obj.search([('costs_types', '=', 'in')]) # 收入类科目 expense_account_ids = account_obj.search([('costs_types', '=', 'out')]) # 费用类科目 revenue_total = 0 # 收入类科目合计 expense_total = 0 # 费用类科目合计 for revenue_account_id in revenue_account_ids: voucher_line_ids = voucher_line_obj.search([ ('account_id', '=', revenue_account_id.id), ('voucher_id.period_id', '=', balance.period_id.id)]) credit_total = 0 for voucher_line_id in voucher_line_ids: credit_total += voucher_line_id.credit - voucher_line_id.debit revenue_total += credit_total if credit_total != 0: # 贷方冲借方 res = { 'name': u'月末结账', 'account_id': revenue_account_id.id, 'debit': credit_total, 'credit': 0, } voucher_line.append(res) for expense_account_id in expense_account_ids: voucher_line_ids = voucher_line_obj.search([ ('account_id', '=', expense_account_id.id), ('voucher_id.period_id', '=', balance.period_id.id)]) debit_total = 0 for voucher_line_id in voucher_line_ids: debit_total += voucher_line_id.debit - voucher_line_id.credit expense_total += debit_total if debit_total != 0: # 借方冲贷方 res = { 'name': u'月末结账', 'account_id': expense_account_id.id, 'debit': 0, 'credit': debit_total, } voucher_line.append(res) # 利润结余 year_profit_account = company_obj.search([])[0].profit_account remain_account = company_obj.search([])[0].remain_account if not year_profit_account: raise UserError(u'公司本年利润科目未配置') if not remain_account: raise UserError(u'公司未分配利润科目未配置') if (revenue_total - expense_total) > 0: res = { 'name': u'利润结余', 'account_id': year_profit_account.id, 'debit': 0, 'credit': revenue_total - expense_total, } voucher_line.append(res) if (revenue_total - expense_total) < 0: res = { 'name': u'利润结余', 'account_id': year_profit_account.id, 'debit': expense_total - revenue_total, 'credit': 0, } voucher_line.append(res) # 生成凭证 if voucher_line: valus = { 'is_checkout': True, 'date': self.date, 'line_ids': [ (0, 0, line) for line in voucher_line], } voucher = voucher_obj.create(valus) voucher.voucher_done() year_account = None if balance.period_id.month == '12': year_profit_ids = voucher_line_obj.search([ ('account_id', '=', year_profit_account.id), ('voucher_id.period_id.year', '=', balance.period_id.year)]) year_total = 0 for year_profit_id in year_profit_ids: year_total += (year_profit_id.credit - year_profit_id.debit) precision = self.env['decimal.precision'].precision_get('Amount') year_total = round(year_total, precision) if year_total != 0: year_line_ids = [{ 'name': u'年度结余', 'account_id': remain_account.id, 'debit': 0, 'credit': year_total, }, { 'name': u'年度结余', 'account_id': year_profit_account.id, 'debit': year_total, 'credit': 0, }] value = {'is_checkout': True, 'date': balance.date, 'line_ids': [ (0, 0, line) for line in year_line_ids], } year_account = voucher_obj.create(value) # 创建结转凭证 year_account.voucher_done() # 凭证审核 # 生成科目余额表 trial_wizard = self.env['create.trial.balance.wizard'].create({ 'period_id': balance.period_id.id, }) trial_wizard.create_trial_balance() # 按用户设置重排结账会计期间凭证号(会计要求凭证号必须连续) self.recreate_voucher_name(balance.period_id) # 关闭会计期间 balance.period_id.is_closed = True self.env['dupont'].fill(balance.period_id) pre_period = last_period while pre_period: self.env['dupont'].fill(pre_period) pre_period = self.env['create.trial.balance.wizard'].compute_last_period_id(pre_period) # 如果下一个会计期间没有,则创建。 next_period = self.env['create.trial.balance.wizard'].compute_next_period_id(balance.period_id) if not next_period: if balance.period_id.month == '12': self.env['finance.period'].create({'year': str(int(balance.period_id.year) + 1), 'month': '1',}) else: self.env['finance.period'].create({'year': balance.period_id.year, 'month': str(int(balance.period_id.month) + 1),}) # 显示凭证 view = self.env.ref('finance.voucher_form') if voucher_line or year_account: # 因重置凭证号,查找最后一张结转凭证 voucher = self.env['voucher'].search( [('is_checkout', '=', True), ('period_id', '=', balance.period_id.id)], order="create_date desc", limit=1) return { 'name': u'月末结账', 'view_type': 'form', 'view_mode': 'form', 'views': [(view.id, 'form')], 'res_model': 'voucher', 'type': 'ir.actions.act_window', 'res_id': voucher.id, }
def recreate_voucher_name(self, period_id): # 取重排凭证设置 # 是否重置凭证号 context = dict(self.env.context or {}) context['call_module'] = "checkout_wizard" auto_reset = self.env['ir.values'].get_default('finance.config.settings', 'default_auto_reset') # 重置凭证间隔:年 月 reset_period = self.env['ir.values'].get_default('finance.config.settings', 'default_reset_period') # 重置后起始数字 reset_init_number = self.env['ir.values'].get_default('finance.config.settings', 'default_reset_init_number') if auto_reset is True: # 取ir.sequence中的会计凭证的参数 force_company = self._context.get('force_company') if not force_company: force_company = self.env.user.company_id.id company_ids = self.env['res.company'].search([]).ids + [False] seq_ids = self.env['ir.sequence'].search(['&', ('code', '=', 'voucher'), ('company_id', 'in', company_ids)]) preferred_sequences = [s for s in seq_ids if s.company_id and s.company_id.id == force_company] seq_id = preferred_sequences[0] if preferred_sequences else seq_ids[0] voucher_obj = self.env['voucher'] # 按年重置 last_period = self.env['create.trial.balance.wizard'].compute_last_period_id(period_id) last_voucher_number = 0 if reset_period == 'year': if last_period: while last_period and last_voucher_number < 1: if not last_period.is_closed: raise UserError(u'上一个期间%s未结账' % last_period.name) if period_id.year != last_period.year: # 按年,而且是第一个会计期间 last_voucher_number = reset_init_number else: # 查找上一期间最后凭证号 last_period_voucher_name = voucher_obj.search([('period_id', '=', last_period.id)], order="create_date desc", limit=1).name # 凭证号转换为数字 if last_period_voucher_name: # 上一期间是否有凭证? last_voucher_number = int(filter(str.isdigit, last_period_voucher_name.encode("utf-8"))) + 1 #else: # raise UserError(u'请核实上一个期间:%s是否有凭证!' % last_period.name) last_period = self.env['create.trial.balance.wizard'].compute_last_period_id(last_period) else: last_voucher_number = reset_init_number voucher_ids = voucher_obj.search([('period_id', '=', period_id.id)], order='create_date') for voucher_id in voucher_ids: # 产生凭证号 next_voucher_name = '%%0%sd' % seq_id.padding % last_voucher_number last_voucher_number += 1 # 更新凭证号 voucher_id.with_context(context).write({'name': next_voucher_name}) # 按月重置 else: last_voucher_number = reset_init_number voucher_ids = voucher_obj.search([('period_id', '=', period_id.id)], order='create_date') for voucher_id in voucher_ids: # 产生凭证号 next_voucher_name = '%%0%sd' % seq_id.padding % last_voucher_number # 更新凭证号,将老号写到变化表中去! if voucher_id.name != next_voucher_name: self.env['change.voucher.name'].create({ 'period_id': self.period_id.id, 'before_voucher_name': voucher_id.name, 'after_voucher_name': next_voucher_name, }) voucher_id.with_context(context).write({'name': next_voucher_name}) last_voucher_number += 1
def compute_refund(self, mode='refund'): inv_obj = self.env['account.invoice'] inv_tax_obj = self.env['account.invoice.tax'] inv_line_obj = self.env['account.invoice.line'] context = dict(self._context or {}) xml_id = False for form in self: created_inv = [] date = False description = False for inv in inv_obj.browse(context.get('active_ids')): if inv.state in ['draft', 'proforma2', 'cancel']: raise UserError( _('Cannot refund draft/proforma/cancelled invoice.')) if inv.reconciled and mode in ('cancel', 'modify'): raise UserError( _('Cannot refund invoice which is already reconciled, invoice should be unreconciled first. You can only refund this invoice.' )) date = form.date or False description = form.description or inv.name refund = inv.refund(form.date_invoice, date, description, inv.journal_id.id) created_inv.append(refund.id) if mode in ('cancel', 'modify'): movelines = inv.move_id.line_ids to_reconcile_ids = {} to_reconcile_lines = self.env['account.move.line'] for line in movelines: if line.account_id.id == inv.account_id.id: to_reconcile_lines += line to_reconcile_ids.setdefault( line.account_id.id, []).append(line.id) if line.reconciled: line.remove_move_reconcile() refund.action_invoice_open() for tmpline in refund.move_id.line_ids: if tmpline.account_id.id == inv.account_id.id: to_reconcile_lines += tmpline to_reconcile_lines.filtered( lambda l: l.reconciled == False).reconcile() if mode == 'modify': invoice = inv.read( inv_obj._get_refund_modify_read_fields()) invoice = invoice[0] del invoice['id'] invoice_lines = inv_line_obj.browse( invoice['invoice_line_ids']) invoice_lines = inv_obj.with_context( mode='modify')._refund_cleanup_lines(invoice_lines) tax_lines = inv_tax_obj.browse(invoice['tax_line_ids']) tax_lines = inv_obj._refund_cleanup_lines(tax_lines) invoice.update({ 'type': inv.type, 'date_invoice': form.date_invoice, 'state': 'draft', 'number': False, 'invoice_line_ids': invoice_lines, 'tax_line_ids': tax_lines, 'date': date, 'origin': inv.origin, 'fiscal_position_id': inv.fiscal_position_id.id, }) for field in inv_obj._get_refund_common_fields(): if inv_obj._fields[field].type == 'many2one': invoice[field] = invoice[field] and invoice[ field][0] else: invoice[field] = invoice[field] or False inv_refund = inv_obj.create(invoice) if inv_refund.payment_term_id.id: inv_refund._onchange_payment_term_date_invoice() created_inv.append(inv_refund.id) xml_id = (inv.type in ['out_refund', 'out_invoice']) and 'action_invoice_tree1' or \ (inv.type in ['in_refund', 'in_invoice']) and 'action_invoice_tree2' # Put the reason in the chatter subject = _("Invoice refund") body = description refund.message_post(body=body, subject=subject) if xml_id: result = self.env.ref('account.%s' % (xml_id)).read()[0] invoice_domain = safe_eval(result['domain']) invoice_domain.append(('id', 'in', created_inv)) result['domain'] = invoice_domain return result return True
def _check_default_fiscal_position(self): if self.default_fiscal_position_id and self.default_fiscal_position_id not in self.fiscal_position_ids: raise UserError(_("The default fiscal position must be included in the available fiscal positions of the point of sale"))
def _check_company_payment(self): if self.env['account.journal'].search_count([('id', 'in', self.journal_ids.ids), ('company_id', '!=', self.company_id.id)]): raise UserError(_("The company of a payment method is different than the one of point of sale"))