|
- # Copyright 2016 上海开阖软件有限公司 (http://www.osbzr.com)
- # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
-
- from odoo.exceptions import UserError
- from odoo import fields, models, api
- from odoo.tools import float_compare
-
-
- class MoneyTransferOrder(models.Model):
- _name = 'money.transfer.order'
- _description = u'资金转账单'
- _inherit = ['mail.thread', 'mail.activity.mixin']
- _order = 'id desc'
-
- state = fields.Selection([
- ('draft', u'草稿'),
- ('done', u'已确认'),
- ('cancel', u'已作废'),
- ], string=u'状态', readonly=True,
- default='draft', copy=False, index=True,
- tracking=True,
- help=u'资金转账单状态标识,新建时状态为草稿;确认后状态为已确认')
- name = fields.Char(string=u'单据编号', copy=False, default='/',
- help=u'单据编号,创建时会自动生成')
- date = fields.Date(string=u'单据日期',
- default=lambda self: fields.Date.context_today(self),
- readonly="state!='draft'",
- help=u'单据创建日期')
- note = fields.Text(string=u'备注', help=u'可以为该单据添加一些需要的标识信息')
- line_ids = fields.One2many('money.transfer.order.line', 'transfer_id',
- string=u'资金转账单行',
- readonly="state!='draft'",
- help=u'资金转账单明细行')
- company_id = fields.Many2one(
- 'res.company',
- string=u'公司',
- change_default=True,
- default=lambda self: self.env.company)
- voucher_id = fields.Many2one('voucher',
- u'对应凭证',
- readonly=True,
- ondelete='restrict',
- help=u'资金转账单确认时生成的对应凭证',
- copy=False)
- transfer_amount = fields.Float(
- compute='_compute_transfer_amount', string='转账总金额')
-
- @api.depends('line_ids', 'line_ids.amount')
- def _compute_transfer_amount(self):
- for mto in self:
- mto.transfer_amount = sum([line.amount for line in mto.line_ids])
-
- def money_transfer_done(self):
- '''转账单的审核按钮'''
- self.ensure_one()
- if not self.line_ids:
- raise UserError('请先输入转账金额')
- decimal_amount = self.env.ref('core.decimal_amount')
- for line in self.line_ids:
- company_currency_id = self.env.user.company_id.currency_id.id
- out_currency_id = \
- line.out_bank_id.currency_id.id or company_currency_id
- in_currency_id = \
- line.in_bank_id.currency_id.id or company_currency_id
-
- if line.out_bank_id == line.in_bank_id:
- raise UserError('转出账户与转入账户不能相同')
- if line.amount <= 0:
- raise UserError('转账金额必须大于0。\n 转账金额:%s' % line.amount)
- if out_currency_id == company_currency_id: # 如果转出账户是公司本位币
- if float_compare(
- line.out_bank_id.balance,
- line.amount,
- decimal_amount.digits) == -1:
- raise UserError('转出账户余额不足。\n转出账户余额:%s 本次转出金额:%s' % (
- line.out_bank_id.balance, line.amount))
- else: # 转出账户余额充足
- line.out_bank_id.balance -= line.amount
- if in_currency_id == company_currency_id: # 如果转入账户是公司本位币
- line.in_bank_id.balance += line.amount
- else: # 如果转入账户是外币
- line.in_bank_id.balance += line.currency_amount
- else: # 如果转出账户是外币
- if float_compare(
- line.out_bank_id.balance,
- line.currency_amount,
- precision_digits=decimal_amount.digits) == -1:
- raise UserError(
- '转出账户余额不足。\n转出账户余额:%s 本次转出外币金额:%s'
- % (line.out_bank_id.balance, line.currency_amount))
- if in_currency_id == company_currency_id: # 如果转入账户是公司本位币
- line.in_bank_id.balance += line.amount
- line.out_bank_id.balance -= line.currency_amount
- elif (in_currency_id != company_currency_id
- and in_currency_id == out_currency_id):
- # 如果转入账户是外币,只支持同种外币互转
- line.in_bank_id.balance += line.currency_amount
- line.out_bank_id.balance -= line.currency_amount
- else:
- raise UserError('系统不支持外币转不同外币')
-
- # 创建凭证并审核
- voucher = self.create_voucher()
- return self.write({
- 'voucher_id': voucher.id,
- 'state': 'done',
- })
-
- def money_transfer_draft(self):
- '''转账单的反审核按钮,外币要考虑是转入还是转出'''
- self.ensure_one()
- decimal_amount = self.env.ref('core.decimal_amount')
- for line in self.line_ids:
- company_currency_id = self.env.user.company_id.currency_id.id
- out_currency_id = \
- line.out_bank_id.currency_id.id or company_currency_id
- in_currency_id = \
- line.in_bank_id.currency_id.id or company_currency_id
- if line.currency_amount > 0:
- if (in_currency_id != company_currency_id
- and out_currency_id == in_currency_id):
- # 转入和转出都是外币
- if float_compare(
- line.in_bank_id.balance,
- line.currency_amount,
- precision_digits=decimal_amount.digits) == -1:
- raise UserError(
- '转入账户余额不足。\n转入账户余额:%s 本次转出外币金额:%s'
- % (line.in_bank_id.balance, line.currency_amount))
- else: # 转入账户余额充足
- line.in_bank_id.balance -= line.currency_amount
- line.out_bank_id.balance += line.currency_amount
- elif (in_currency_id == company_currency_id
- and out_currency_id != company_currency_id):
- # 转入账户为本位币,转出是外币
- if float_compare(
- line.in_bank_id.balance,
- line.amount,
- precision_digits=decimal_amount.digits) == -1:
- raise UserError(
- '转入账户余额不足。\n转入账户余额:%s 本次转出金额:%s'
- % (line.in_bank_id.balance, line.amount))
- else:
- line.in_bank_id.balance -= line.amount
- line.out_bank_id.balance += line.currency_amount
- elif (in_currency_id != company_currency_id
- and out_currency_id == company_currency_id):
- # 转入账户为外币,转出是人民币
- if float_compare(
- line.in_bank_id.balance,
- line.currency_amount,
- precision_digits=decimal_amount.digits) == -1:
- raise UserError(
- '转入账户余额不足。\n转入账户余额:%s 本次转出金额:%s'
- % (line.in_bank_id.balance, line.currency_amount))
- else:
- line.in_bank_id.balance -= line.currency_amount
- line.out_bank_id.balance += line.amount
- else:
- raise UserError('系统不支持外币转不同外币')
- else: # 转入/转出账户都为本位币
- if float_compare(
- line.in_bank_id.balance,
- line.amount,
- precision_digits=decimal_amount.digits) == -1:
- raise UserError('转入账户余额不足。\n转入账户余额:%s 本次转出金额:%s'
- % (line.in_bank_id.balance, line.amount))
- else:
- line.in_bank_id.balance -= line.amount
- line.out_bank_id.balance += line.amount
-
- voucher = self.voucher_id
- self.write({
- 'voucher_id': False,
- 'state': 'draft',
- })
- # 反审核凭证并删除
- if voucher.state == 'done':
- voucher.voucher_draft()
- voucher.unlink()
- return True
-
- def create_voucher(self):
- """创建凭证并审核"""
- vouch_obj = self.env['voucher'].create(
- {'date': self.date, 'ref': '%s,%s' % (self._name, self.id)})
- vals = {}
- for line in self.line_ids:
- out_currency_id = (
- line.out_bank_id.currency_id.id
- or self.env.user.company_id.currency_id.id)
- in_currency_id = (
- line.in_bank_id.currency_id.id
- or self.env.user.company_id.currency_id.id)
- company_currency_id = self.env.user.company_id.currency_id.id
- if (out_currency_id != company_currency_id
- or in_currency_id != company_currency_id) \
- and not line.currency_amount:
- raise UserError('错误, 请请输入外币金额。')
- if (line.currency_amount
- and in_currency_id == company_currency_id
- and out_currency_id != company_currency_id):
- '''结汇'''
- '''借方行'''
- self.env['voucher.line'].create({
- 'name': "%s %s结汇至%s %s" % (
- self.name,
- line.out_bank_id.name,
- line.in_bank_id.name,
- self.note),
- 'account_id': line.in_bank_id.account_id.id,
- 'debit': line.amount,
- 'voucher_id': vouch_obj.id,
- 'partner_id': '',
- 'currency_id': '',
- 'currency_amount': line.currency_amount,
- 'rate_silent': line.amount / line.currency_amount
- })
- '''贷方行'''
- self.env['voucher.line'].create({
- 'name': "%s %s结汇至%s %s" % (
- self.name, line.out_bank_id.name,
- line.in_bank_id.name,
- self.note),
- 'account_id': line.out_bank_id.account_id.id,
- 'credit': line.amount,
- 'voucher_id': vouch_obj.id,
- 'partner_id': '',
- 'currency_id': out_currency_id,
- 'currency_amount': line.currency_amount,
- 'rate_silent': line.amount / line.currency_amount
- })
- elif (line.currency_amount
- and in_currency_id != company_currency_id
- and out_currency_id == company_currency_id):
- '''买汇'''
- '''借方行'''
- self.env['voucher.line'].create({
- 'name': u"%s %s买汇至%s %s" % (
- self.name,
- line.out_bank_id.name,
- line.in_bank_id.name,
- self.note),
- 'account_id': line.in_bank_id.account_id.id,
- 'debit': line.amount,
- 'voucher_id': vouch_obj.id,
- 'partner_id': '',
- 'currency_id': in_currency_id,
- 'currency_amount': line.currency_amount,
- 'rate_silent': line.amount / line.currency_amount
- })
- '''贷方行'''
- self.env['voucher.line'].create({
- 'name': u"%s %s买汇至%s %s" % (
- self.name,
- line.out_bank_id.name,
- line.in_bank_id.name,
- self.note),
- 'account_id': line.out_bank_id.account_id.id,
- 'credit': line.amount,
- 'voucher_id': vouch_obj.id,
- 'partner_id': '',
- 'currency_id': '',
- 'currency_amount': line.currency_amount,
- 'rate_silent': line.amount / line.currency_amount
-
- })
- elif (line.currency_amount
- and in_currency_id == out_currency_id
- and in_currency_id != company_currency_id):
- '''相同外币币别互转'''
- '''借方行'''
- rate_silent = self.env['res.currency'].get_rate_silent(
- self.date, in_currency_id)
- self.env['voucher.line'].create({
- 'name': u"%s %s外币互转至%s %s" % (
- self.name,
- line.out_bank_id.name,
- line.in_bank_id.name,
- self.note),
- 'account_id': line.in_bank_id.account_id.id,
- 'debit': line.currency_amount * rate_silent,
- 'voucher_id': vouch_obj.id,
- 'partner_id': '',
- 'currency_id': in_currency_id,
- 'currency_amount': line.currency_amount,
- 'rate_silent': rate_silent
- })
- '''贷方行'''
- self.env['voucher.line'].create({
- 'name': u"%s %s外币互转至%s %s" % (
- self.name, line.out_bank_id.name,
- line.in_bank_id.name, self.note),
- 'account_id': line.out_bank_id.account_id.id,
- 'credit': line.currency_amount * rate_silent,
- 'voucher_id': vouch_obj.id, 'partner_id': '',
- 'currency_id': out_currency_id,
- 'currency_amount': line.currency_amount,
- 'rate_silent': rate_silent
- })
- else:
- '''人民币间'''
- vals.update({
- 'vouch_obj_id': vouch_obj.id,
- 'name': self.name, 'string': self.note or '',
- 'amount': abs(line.amount),
- 'credit_account_id': line.out_bank_id.account_id.id,
- 'debit_account_id': line.in_bank_id.account_id.id,
- })
- self.env['money.invoice'].create_voucher_line(vals)
-
- vouch_obj.voucher_done()
- return vouch_obj
-
-
- class MoneyTransferOrderLine(models.Model):
- _name = 'money.transfer.order.line'
- _description = u'资金转账单明细'
-
- transfer_id = fields.Many2one('money.transfer.order',
- string=u'资金转账单', ondelete='cascade',
- help=u'资金转账单行对应的资金转账单')
- out_bank_id = fields.Many2one('bank.account', string=u'转出账户',
- required=True, ondelete='restrict',
- help=u'资金转账单行上的转出账户')
- in_bank_id = fields.Many2one('bank.account', string=u'转入账户',
- required=True, ondelete='restrict',
- help=u'资金转账单行上的转入账户')
- currency_amount = fields.Float(string=u'外币金额',
- digits='Amount',
- help=u'转出或转入的外币金额')
- amount = fields.Float(string=u'金额',
- digits='Amount',
- help=u'转出或转入的金额')
- mode_id = fields.Many2one('settle.mode', string=u'结算方式',
- ondelete='restrict',
- help=u'结算方式:支票、信用卡等')
- number = fields.Char(string=u'结算号', help=u'本次结算号')
- note = fields.Char(string=u'备注',
- help=u'可以为该单据添加一些需要的标识信息')
- company_id = fields.Many2one(
- 'res.company',
- string=u'公司',
- change_default=True,
- default=lambda self: self.env.company)
|