asset/models/asset.py
# -*- coding: utf-8 -*-
from datetime import datetime
import odoo.addons.decimal_precision as dp
from odoo import api, fields, models
from odoo.exceptions import UserError, ValidationError
# 字段只读状态
READONLY_STATES = {
'done': [('readonly', True)], # 已确认
'clean': [('readonly', True)], # 已清理
}
class AssetCategory(models.Model):
'''固定资产分类'''
_name = 'asset.category'
_description = u'固定资产分类'
# 字段,命名问题很严重
name = fields.Char(u'名称', required=True)
# 一些带到固定资产上的默认值
account_accumulated_depreciation = fields.Many2one(
'finance.account', u'累计折旧科目', required=True)
account_asset = fields.Many2one(
'finance.account', u'固定资产科目', required=True)
account_depreciation = fields.Many2one(
'finance.account', u'折旧费用科目', required=True)
depreciation_number = fields.Float(u'折旧期间数', required=True)
depreciation_value = fields.Float(u'最终残值率%', required=True)
clean_income = fields.Many2one(
'finance.account', u'固定资产清理收入科目', required=True)
clean_costs = fields.Many2one(
'finance.account', u'固定资产清理成本科目', required=True)
# 用于软删除归档
active = fields.Boolean(u'启用', default=True)
# 未来支持多公司
company_id = fields.Many2one(
'res.company',
string=u'公司',
change_default=True,
default=lambda self: self.env['res.company']._company_default_get())
class Asset(models.Model):
_name = 'asset'
_description = u'固定资产'
_order = "code" # 按资产编号排序
@api.one
@api.depends('date')
def _compute_period_id(self):
''' 根据入账日期获取期间,用于生成凭证 '''
self.period_id = self.env['finance.period'].get_period(self.date)
@api.one
@api.depends('cost', 'tax')
def _get_amount(self):
''' 价税合计 '''
self.amount = self.cost + self.tax
@api.one
@api.depends('cost', 'depreciation_previous')
def _get_surplus_value(self):
''' 计算固定资产原值和残值 '''
# 原值 = 购置成本 - (ERP系统上线前)已提折旧
self.surplus_value = self.cost - self.depreciation_previous
# 残值按固定资产分类上的残值比率计算
self.depreciation_value = self.category_id.depreciation_value * self.cost / 100
@api.one
@api.depends('surplus_value', 'depreciation_value', 'depreciation_number','no_depreciation')
def _get_cost_depreciation(self):
''' 计算每月折旧 '''
if self.no_depreciation == True: # 不提折旧不要算
self.cost_depreciation = 0
else: # 原值减残值减已折旧额,再除以剩余折旧期数
dep_his_count = 0 # 已提期数
dep_his_amount = 0 # 已提折旧
for l in self.line_ids:
dep_his_amount += l.cost_depreciation
dep_his_count += 1
if dep_his_count == self.depreciation_number:
self.cost_depreciation = 0 # 已提完
else:
self.cost_depreciation = (self.surplus_value - self.depreciation_value
- dep_his_amount) \
/ (self.depreciation_number - dep_his_count)
@api.one
@api.depends('surplus_value', 'line_ids','state')
def _get_net_value(self):
''' 计算固定资产净值 '''
if self.state == 'clean': # 已清理的固定资产净值为0
self.net_value = 0
else: # 原值 - 折旧
self.net_value = self.surplus_value - sum(
[l.cost_depreciation for l in self.line_ids] )
# 字段
code = fields.Char(u'编号', required="1", states=READONLY_STATES)
name = fields.Char(u'名称', required=True, states=READONLY_STATES)
category_id = fields.Many2one(
'asset.category', u'固定资产分类', ondelete='restrict', required=True, states=READONLY_STATES)
cost = fields.Float(u'金额', digits=dp.get_precision(
'Amount'), required=True, states=READONLY_STATES)
surplus_value = fields.Float(u'原值', digits=dp.get_precision(
'Amount'), store=True, compute='_get_surplus_value')
net_value = fields.Float(u'净值',digits=dp.get_precision(
'Amount'), store=True, compute='_get_net_value')
no_depreciation = fields.Boolean(u'不折旧')
depreciation_number = fields.Integer(
u'折旧期间数', required=True, states=READONLY_STATES)
depreciation_value = fields.Float(u'最终残值', digits=dp.get_precision(
'Amount'), required=True, states=READONLY_STATES)
cost_depreciation = fields.Float(u'每月折旧额', digits=dp.get_precision(
'Amount'), store=True, compute='_get_cost_depreciation')
state = fields.Selection([('draft', u'草稿'),
('done', u'已确认'),
('clean', u'已清理')], u'状态', default='draft',
index=True,)
period_id = fields.Many2one(
'finance.period',
u'会计期间',
compute='_compute_period_id', ondelete='restrict', store=True)
date = fields.Date(u'记帐日期', required=True, states=READONLY_STATES)
tax = fields.Float(u'税额', digits=dp.get_precision(
'Amount'), required=True, states=READONLY_STATES)
amount = fields.Float(u'价税合计', digits=dp.get_precision(
'Amount'), store=True, compute='_get_amount')
partner_id = fields.Many2one('partner', u'供应商', ondelete='restrict', states=READONLY_STATES,
domain="[('s_category_id', '!=', False)]",
help=u'用于记录采购固定资产时的应付账款,据此生成结算单')
bank_account = fields.Many2one('bank.account', u'结算账户', ondelete='restrict', states=READONLY_STATES,
help=u'用于记录现金采购固定资产时的付款,据此生成其他支出单')
is_init = fields.Boolean(u'初始化资产', states=READONLY_STATES,
help=u'此固定资产在ERP系统启用前就已经有折旧了')
depreciation_previous = fields.Float(u'以前折旧', digits=dp.get_precision(
'Amount'), required=True, states=READONLY_STATES)
account_credit = fields.Many2one(
'finance.account', u'资产贷方科目', required=True, states=READONLY_STATES,
help=u'固定资产入账时:\n 如赊购,此处为应付科目;\n 如现购,此处为资金科目;\n 如自建,此处为在建工程')
account_asset = fields.Many2one(
'finance.account', u'固定资产科目', required=True, states=READONLY_STATES)
account_depreciation = fields.Many2one(
'finance.account', u'折旧费用科目', required=True, states=READONLY_STATES)
account_accumulated_depreciation = fields.Many2one(
'finance.account', u'累计折旧科目', required=True, states=READONLY_STATES)
line_ids = fields.One2many('asset.line', 'order_id', u'折旧明细行',
states=READONLY_STATES, copy=False)
chang_ids = fields.One2many('chang.line', 'order_id', u'变更明细行',
states=READONLY_STATES, copy=False)
# 界面上不可见的字段
voucher_id = fields.Many2one(
'voucher', u'对应凭证', readonly=True, ondelete='restrict', copy=False)
money_invoice = fields.Many2one(
'money.invoice', u'对应结算单', readonly=True, ondelete='restrict', copy=False)
other_money_order = fields.Many2one(
'other.money.order', u'对应其他应付款单', readonly=True, ondelete='restrict', copy=False)
# 未来支持多公司
company_id = fields.Many2one(
'res.company',
string=u'公司',
change_default=True,
default=lambda self: self.env['res.company']._company_default_get())
@api.onchange('category_id')
def onchange_category_id(self):
'''当固定资产分类发生变化时,折旧期间数,固定资产科目,累计折旧科目,最终残值同时变化'''
if self.category_id:
self.depreciation_number = self.category_id.depreciation_number
self.account_asset = self.category_id.account_asset
self.account_accumulated_depreciation = self.category_id.account_accumulated_depreciation
self.account_depreciation = self.category_id.account_depreciation
self.depreciation_value = self.category_id.depreciation_value * self.cost / 100
@api.onchange('cost')
def onchange_cost(self):
'''当固定资产金额发生变化时,最终残值变化'''
if self.cost:
self.depreciation_value = self.category_id.depreciation_value * self.cost / 100
@api.onchange('partner_id')
def onchange_partner_id(self):
'''当合作伙伴发生变化时,固定资产贷方科目变化'''
if self.partner_id:
self.account_credit = self.partner_id.s_category_id.account_id
@api.onchange('bank_account')
def onchange_bank_account(self):
'''当结算帐户发生变化时,固定资产贷方科目变化'''
if self.bank_account:
self.account_credit = self.bank_account.account_id
@api.one
def _wrong_asset_done(self):
''' 固定资产确认入账前的验证 '''
if self.state == 'done':
raise UserError(u'请不要重复确认!')
if self.period_id.is_closed:
raise UserError(u'该会计期间(%s)已结账!不能确认' % self.period_id.name)
if self.cost <= 0:
raise UserError(u'金额必须大于0!\n金额:%s' % self.cost)
if self.tax < 0:
raise UserError(u'税额必须大于0!\n税额:%s' % self.tax)
if self.depreciation_previous < 0:
raise UserError(u'以前折旧必须大于0!\n折旧金额:%s' %
self.depreciation_previous)
@api.one
def _partner_generate_invoice(self):
''' 赊购的方式,选择往来单位时,生成结算单 '''
categ = self.env.ref('asset.asset_expense') # 固定资产采购
# 创建结算单
money_invoice = self.env['money.invoice'].create({
'name': u'固定资产' + self.code,
'partner_id': self.partner_id.id,
'category_id': categ and categ.id,
'date': self.date,
'amount': self.amount,
'reconciled': 0,
'to_reconcile': self.amount,
'date_due': fields.Date.context_today(self),
'state': 'draft',
'tax_amount': self.tax
})
self.write({'money_invoice': money_invoice.id})
''' 因分类上只能设置一个固定资产科目,这里要用当前固定资产的对应科目替换凭证 '''
# 如未自动确认,则确认一下结算单
if money_invoice.state != 'done':
money_invoice.money_invoice_done()
# 找到结算单对应的凭证行并修改科目
chang_account = self.env['voucher.line'].search(
[('voucher_id', '=', money_invoice.voucher_id.id),
('account_id', '=', categ.account_id.id)])
chang_account.write({'account_id': self.account_asset.id})
return money_invoice
@api.one
def _bank_account_generate_other_pay(self):
''' 现金和银行支付的方式,选择结算账户,生成其他支出单 '''
category = self.env.ref('asset.asset') # 借:固定资产
other_money_order = self.with_context(type='other_pay').env['other.money.order'].create({
'state': 'draft',
'partner_id': self.partner_id.id,
'date': self.date,
'bank_id': self.bank_account.id,
})
self.write({'other_money_order': other_money_order.id})
self.env['other.money.order.line'].create({
'other_money_id': other_money_order.id,
'amount': self.cost,
'tax_rate': self.cost and self.tax / self.cost * 100 or 0,
'tax_amount': self.tax,
'category_id': category and category.id
})
return other_money_order
@api.one
def _construction_generate_voucher(self):
''' 贷方科目选择在建工程,直接生成凭证 '''
vals = {}
vouch_obj = self.env['voucher'].create({'date': self.date, 'ref': '%s,%s' % (self._name, self.id)})
self.write({'voucher_id': vouch_obj.id})
vals.update({'vouch_obj_id': vouch_obj.id, 'string': self.name, 'name': u'固定资产',
'amount': self.amount, 'credit_account_id': self.account_credit.id,
'debit_account_id': self.account_asset.id,
'buy_tax_amount': self.tax or 0
})
self.env['money.invoice'].create_voucher_line(vals)
vouch_obj.voucher_done()
return vouch_obj
@api.one
def asset_done(self):
''' 确认固定资产 '''
self._wrong_asset_done()
# 非初始化固定资产生成入账凭证
if not self.is_init:
if self.partner_id and self.partner_id.s_category_id.account_id == self.account_credit:
# 赊购
self._partner_generate_invoice()
elif self.bank_account and self.account_credit == self.bank_account.account_id:
# 现金购入
self._bank_account_generate_other_pay()
else:
# 在建工程转入
self._construction_generate_voucher()
# 初始化的固定资产需要在初始化会计凭证上点击【导入固定资产】按钮
self.state = 'done'
return True
@api.one
def asset_draft(self):
''' 撤销确认固定资产 '''
if self.state == 'draft':
raise UserError(u'请不要重复撤销确认!')
if self.line_ids:
raise UserError(u'已折旧不能撤销确认!')
if self.chang_ids:
raise UserError(u'已变更不能撤销确认!')
if self.period_id.is_closed:
raise UserError(u'该会计期间(%s)已结账!不能撤销确认' % self.period_id.name)
if self.money_invoice.reconciled != 0:
raise UserError(u'固定资产已有核销,请不要撤销')
'''删掉凭证'''
if self.voucher_id:
Voucher, self.voucher_id = self.voucher_id, False
if Voucher.state == 'done':
Voucher.voucher_draft()
Voucher.unlink()
'''删掉其他应付款单'''
if self.other_money_order:
other_money_order, self.other_money_order = self.other_money_order, False
if other_money_order.state == 'done':
other_money_order.other_money_draft()
other_money_order.unlink()
'''删掉结算单'''
if self.money_invoice:
money_invoice, self.money_invoice = self.money_invoice, False
if money_invoice.state == 'done':
money_invoice.money_invoice_draft()
money_invoice.unlink()
self.state = 'draft'
return True
@api.multi
def unlink(self):
for record in self:
if record.state != 'draft':
raise UserError(u'只能删除草稿状态的固定资产')
return super(Asset, self).unlink()
class CreateCleanWizard(models.TransientModel):
'''固定资产清理'''
_name = 'create.clean.wizard'
_description = u'固定资产清理向导'
@api.one
@api.depends('date')
def _compute_period_id(self):
''' 根据清理日期取得期间 '''
self.period_id = self.env['finance.period'].get_period(self.date)
#字段
date = fields.Date(u'清理日期', required=True)
period_id = fields.Many2one(
'finance.period',
u'会计期间',
compute='_compute_period_id', ondelete='restrict', store=True)
clean_cost = fields.Float(u'清理费用', required=True)
residual_income = fields.Float(u'残值收入', required=True)
sell_tax_amount = fields.Float(u'销项税额', required=True)
bank_account = fields.Many2one('bank.account', u'结算账户')
company_id = fields.Many2one(
'res.company',
string=u'公司',
change_default=True,
default=lambda self: self.env['res.company']._company_default_get())
@api.one
def _generate_other_get(self):
'''按发票收入生成收入单'''
get_category = self.env.ref('asset.asset_clean_get')
other_money_order = self.with_context(type='other_get').env['other.money.order'].create({
'state': 'draft',
'partner_id': None,
'date': self.date,
'bank_id': self.bank_account.id,
})
self.env['other.money.order.line'].create({
'other_money_id': other_money_order.id,
'amount': self.residual_income,
'tax_rate': self.residual_income and self.sell_tax_amount / self.residual_income * 100 or 0,
'tax_amount': self.sell_tax_amount,
'category_id': get_category and get_category.id
})
return other_money_order
@api.one
def _clean_cost_generate_other_pay(self, clean_cost):
'''按费用生成支出单'''
pay_category = self.env.ref('asset.asset_clean_pay')
other_money_order = self.with_context(type='other_pay').env['other.money.order'].create({
'state': 'draft',
'partner_id': None,
'date': self.date,
'bank_id': self.bank_account.id,
})
self.env['other.money.order.line'].create({
'other_money_id': other_money_order.id,
'amount': clean_cost,
'category_id': pay_category and pay_category.id
})
@api.one
def _generate_voucher(self, Asset):
''' 生成凭证,并确认 '''
vouch_obj = self.env['voucher'].create({'date': self.date, 'ref': '%s,%s' % (self._name, self.id)})
depreciation2 = sum(line.cost_depreciation for line in Asset.line_ids)
depreciation = Asset.depreciation_previous + depreciation2
income = Asset.cost - depreciation
Asset.write({'voucher_id': vouch_obj.id})
'''借方行'''
self.env['voucher.line'].create({'voucher_id': vouch_obj.id, 'name': u'清理固定资产',
'debit': income, 'account_id': Asset.category_id.clean_costs.id,
})
self.env['voucher.line'].create({'voucher_id': vouch_obj.id, 'name': u'清理固定资产',
'debit': depreciation, 'account_id': Asset.account_accumulated_depreciation.id,
})
'''贷方行'''
self.env['voucher.line'].create({'voucher_id': vouch_obj.id, 'name': u'清理固定资产',
'credit': Asset.cost, 'account_id': Asset.account_asset.id,
})
vouch_obj.voucher_done()
return vouch_obj
@api.one
def create_clean_account(self):
''' 清理固定资产 '''
if not self.env.context.get('active_id'):
return
Asset = self.env['asset'].browse(self.env.context.get('active_id'))
Asset.no_depreciation = 1
Asset.state = 'clean'
# 按发票收入生成收入单
self._generate_other_get()
# 按费用生成支出单
if self.clean_cost:
self._clean_cost_generate_other_pay(self.clean_cost)
# 生成凭证
self._generate_voucher(Asset)
class CreateChangWizard(models.TransientModel):
'''固定资产变更'''
_name = 'create.chang.wizard'
_description = u'固定资产变更向导'
@api.one
@api.depends('chang_date')
def _compute_period_id(self):
''' 根据变更日期取会计期间 '''
self.period_id = self.env['finance.period'].get_period(self.chang_date)
# 字段
chang_date = fields.Date(u'变更日期', required=True)
period_id = fields.Many2one(
'finance.period',
u'会计期间',
compute='_compute_period_id', ondelete='restrict', store=True)
chang_cost = fields.Float(u'增加金额', required=True,
digits=dp.get_precision('Amount'))
chang_depreciation_number = fields.Float(u'变更折旧期间', required=True)
chang_tax = fields.Float(
u'增加税额', digits=dp.get_precision('Amount'), required=True)
chang_partner_id = fields.Many2one(
'partner', u'供应商', ondelete='restrict', required=True)
change_reason = fields.Text(u'变更原因')
company_id = fields.Many2one(
'res.company',
string=u'公司',
change_default=True,
default=lambda self: self.env['res.company']._company_default_get())
@api.one
def create_chang_account(self):
''' 创建变更对应的结算单,确认应付 '''
''' TODO 逻辑似乎不太对,原值和折旧期的变更都会引起每月折旧的金额变化,但是已经提过的折旧差异没有处理 '''
if not self.env.context.get('active_id'):
return
Asset = self.env['asset'].browse(self.env.context.get('active_id'))
if self.chang_cost > 0:
chang_before_cost = Asset.cost
chang_before_depreciation_number = Asset.depreciation_number
Asset.cost = self.chang_cost + Asset.cost # 历史成本
Asset.surplus_value = Asset.cost - Asset.depreciation_previous # 入账价值
Asset.tax = Asset.tax + self.chang_tax # 税
categ = self.env.ref('money.core_category_purchase')
money_invoice = self.env['money.invoice'].create({
'name': u'固定资产变更' + Asset.code,
'partner_id': self.chang_partner_id.id,
'category_id': categ.id,
'date': self.chang_date,
'amount': self.chang_cost + self.chang_tax,
'reconciled': 0,
'to_reconcile': self.chang_cost + self.chang_tax,
'date_due': fields.Date.context_today(self),
'state': 'draft',
'tax_amount': self.chang_tax
})
# 如未自动确认,则确认一下结算单
if money_invoice.state != 'done':
money_invoice.money_invoice_done()
#将分类上的资产科目替换为固定资产上的资产科目
chang_account = self.env['voucher.line'].search(
[('voucher_id', '=',money_invoice.voucher_id.id),
('account_id', '=', categ.account_id.id)])
chang_account.write({'account_id': Asset.account_asset.id})
# 记录变更历史 - 原值变更
self.env['chang.line'].create({'date': self.chang_date, 'period_id': self.period_id.id,
'chang_before': chang_before_cost,
'change_reason': self.change_reason,
'chang_after': Asset.cost, 'chang_name': u'原值变更',
'order_id': Asset.id, 'partner_id': self.chang_partner_id.id
})
Asset.depreciation_number = Asset.depreciation_number + \
self.chang_depreciation_number # 折旧期数
Asset.depreciation_value = Asset.depreciation_value + Asset.category_id.depreciation_value * \
self.chang_cost / 100 # 残值
if self.chang_depreciation_number:
self.env['chang.line'].create({'date': self.chang_date, 'period_id': self.period_id.id,
'chang_before': chang_before_depreciation_number,
'change_reason': self.change_reason,
'chang_after': Asset.depreciation_number, 'chang_name': u'折旧期间变更',
'order_id': Asset.id, 'partner_id': self.chang_partner_id.id
})
return True
class AssetLine(models.Model):
_name = 'asset.line'
_description = u'资产折旧明细'
@api.one
@api.depends('date')
def _compute_period_id(self):
''' 根据记账日期取会计期间 '''
self.period_id = self.env['finance.period'].get_period(self.date)
order_id = fields.Many2one('asset', u'资产', index=True,
required=True, ondelete='restrict')
cost_depreciation = fields.Float(
u'折旧额', required=True, digits=dp.get_precision('Amount'))
no_depreciation = fields.Float(u'未提折旧额')
code = fields.Char(u'编码')
name = fields.Char(u'名称')
date = fields.Date(u'记帐日期', required=True)
period_id = fields.Many2one(
'finance.period',
u'会计期间',
compute='_compute_period_id', ondelete='restrict', store=True)
company_id = fields.Many2one(
'res.company',
string=u'公司',
change_default=True,
default=lambda self: self.env['res.company']._company_default_get())
class CreateDepreciationWizard(models.TransientModel):
"""生成每月折旧的向导 根据输入的期间"""
_name = "create.depreciation.wizard"
_description = u'资产折旧向导'
@api.one
@api.depends('date')
def _compute_period_id(self):
'''根据输入的日期取期间'''
self.period_id = self.env['finance.period'].get_period(self.date)
@api.model
def _get_last_date(self):
''' 取本月的最后一天作为默认折旧日 '''
return self.env['finance.period'].get_period_month_date_range(self.env['finance.period'].get_date_now_period_id())[1]
date = fields.Date(u'记帐日期', required=True, default=_get_last_date)
period_id = fields.Many2one(
'finance.period',
u'会计期间',
compute='_compute_period_id', ondelete='restrict', store=True)
company_id = fields.Many2one(
'res.company',
string=u'公司',
change_default=True,
default=lambda self: self.env['res.company']._company_default_get())
@api.multi
def _get_voucher_line(self, Asset, cost_depreciation, vouch_obj):
''' 借:累计折旧 '''
res = {}
if Asset.account_depreciation.id not in res:
res[Asset.account_depreciation.id] = {'debit': 0}
val = res[Asset.account_depreciation.id]
val.update({'debit': val.get('debit') + cost_depreciation,
'voucher_id': vouch_obj.id,
'account_id': Asset.account_depreciation.id,
'name': u'固定资产折旧',
})
''' 贷:费用科目 '''
if Asset.account_accumulated_depreciation.id not in res:
res[Asset.account_accumulated_depreciation.id] = {'credit': 0}
val = res[Asset.account_accumulated_depreciation.id]
val.update({'credit': val.get('credit') + cost_depreciation,
'voucher_id': vouch_obj.id,
'account_id': Asset.account_accumulated_depreciation.id,
'name': u'固定资产折旧',
})
return res
@api.multi
def _generate_asset_line(self, Asset, cost_depreciation, total):
'''生成折旧明细行'''
AssetLine = self.env['asset.line'].create({
'date': self.date,
'order_id': Asset.id,
'period_id': self.period_id.id,
'cost_depreciation': cost_depreciation,
'name': Asset.name,
'code': Asset.code,
# 未提折旧:原值 - 已提折旧 - 本期折旧
'no_depreciation': Asset.surplus_value - total - cost_depreciation,
})
return AssetLine
@api.multi
def create_depreciation(self):
''' 资产折旧,生成凭证和折旧明细'''
vouch_obj = self.env['voucher'].create({'date': self.date})
res = []
asset_line_id_list = []
for Asset in self.env['asset'].search([('no_depreciation', '=', False), # 提折旧的
('state', '=', 'done'), # 已确认
('period_id', '!=', self.period_id.id)]): # 从入账下月开始
# 本期间没有折旧过,本期间晚于固定资产入账期间
if self.period_id not in [line.period_id for line in Asset.line_ids] and \
self.env['finance.period'].period_compare(self.period_id, Asset.period_id) > 0:
# 本月折旧
cost_depreciation = Asset.cost_depreciation
# 累计折旧
total = sum(
line.cost_depreciation for line in Asset.line_ids) + Asset.depreciation_value
# 最后一次折旧
if Asset.surplus_value <= (total + cost_depreciation):
cost_depreciation = Asset.surplus_value - total
Asset.no_depreciation = 1
# 构造凭证明细行字典
res.append(self._get_voucher_line(
Asset, cost_depreciation, vouch_obj))
# 生成折旧明细行
asset_line_row = self._generate_asset_line(
Asset, cost_depreciation, total)
asset_line_id_list.append(asset_line_row.id)
# 构造凭证明细行字典
debit_line_dict, credit_line_dict = {}, {}
for i in range(len(res)):
for account_id, val in res[i].iteritems():
# 生成借方凭证明细
if 'debit' in val.keys():
if account_id not in debit_line_dict:
debit_line_dict[account_id] = val
else:
debit_line_dict[account_id]['debit'] += val['debit']
# 生成贷方凭证明细
if 'credit' in val.keys():
if account_id not in credit_line_dict:
credit_line_dict[account_id] = val
else:
credit_line_dict[account_id]['credit'] += val['credit']
line_dict = dict(debit_line_dict.items() + credit_line_dict.items())
for account_id, val in line_dict.iteritems():
self.env['voucher.line'].create(dict(val, account_id=account_id)) # 创建凭证行
# 没有凭证行则报错
if not vouch_obj.line_ids:
raise UserError(u'本期没有需要折旧的固定资产。')
vouch_obj.voucher_done()
# 界面转到本月折旧明细
view = self.env.ref('asset.asset_line_tree')
return {
'view_mode': 'tree',
'name': u'资产折旧明细行',
'views': [(view.id, 'tree')],
'res_model': 'asset.line',
'type': 'ir.actions.act_window',
'domain': [('id', 'in', asset_line_id_list)]
}
class ChangLine(models.Model):
_name = 'chang.line'
_description = u'资产变更明细'
@api.one
@api.depends('date')
def _compute_period_id(self):
''' 根据变更日期取会计期间 '''
self.period_id = self.env['finance.period'].get_period(self.date)
# 字段
order_id = fields.Many2one('asset', u'订单编号', index=True,
required=True, ondelete='cascade')
chang_name = fields.Char(u'变更内容', required=True)
date = fields.Date(u'记帐日期', required=True)
period_id = fields.Many2one(
'finance.period',
u'会计期间',
compute='_compute_period_id', ondelete='restrict', store=True)
chang_before = fields.Float(u'变更前')
chang_after = fields.Float(u'变更后')
chang_money_invoice = fields.Many2one(
'money.invoice', u'对应结算单', readonly=True, ondelete='restrict')
partner_id = fields.Many2one('partner', u'供应商')
change_reason = fields.Text(u'变更原因')
company_id = fields.Many2one(
'res.company',
string=u'公司',
change_default=True,
default=lambda self: self.env['res.company']._company_default_get())
class Voucher(models.Model):
''' 在凭证上增加 引入固定资产 按钮逻辑 '''
_inherit = 'voucher'
@api.one
def init_asset(self):
'''删除以前引入的固定资产内容'''
for line in self.line_ids:
if line.init_obj == 'asset':
line.unlink()
'''引入固定资产初始化单据'''
res = {}
if self.env['asset'].search([('is_init', '=', True),
('state', '=', 'draft')]):
raise UserError(u'有未确认的初始化固定资产')
for Asset in self.env['asset'].search([('is_init', '=', True),
('state', '=', 'done')]):
cost = Asset.cost
depreciation_previous = Asset.depreciation_previous
'''固定资产'''
if Asset.account_asset.id not in res:
res[Asset.account_asset.id] = {'credit': 0, 'debit': 0}
val = res[Asset.account_asset.id]
val.update({'debit': val.get('debit') + cost,
'account_id': Asset.account_asset.id,
'voucher_id': self.id,
'init_obj': 'asset',
'name': '固定资产 期初'
})
'''累计折旧'''
if Asset.account_accumulated_depreciation.id not in res:
res[Asset.account_accumulated_depreciation.id] = {
'credit': 0, 'debit': 0}
val = res[Asset.account_accumulated_depreciation.id]
val.update({'credit': val.get('credit') + depreciation_previous,
'account_id': Asset.account_accumulated_depreciation.id,
'voucher_id': self.id,
'init_obj': 'asset',
'name': '固定资产 期初'
})
for account_id, val in res.iteritems():
self.env['voucher.line'].create(dict(val, account_id=account_id),
)