You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

306 lines
13 KiB
Python

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# -*- coding: utf-8 -*-
from odoo import api, fields, models
from odoo.exceptions import ValidationError, UserError, MissingError
class AccountLedgerValue(models.Model):
_name = 'account.ledger.value'
_description = '报表取值'
def _default_from_type(self):
if self.report_id and self.report_type == 'cash_flow':
from_type = 'cash_flow'
else:
from_type = 'ledger_line'
return from_type
# 基础字段
name = fields.Char(string='名称', required=True)
from_type = fields.Selection([
('ledger_line', '科目余额表'),
('cash_flow', '现金流量项目'),
('other_value', '其他取值')], string='取值来源', required=True, default=_default_from_type)
# 关系字段
report_id = fields.Many2one('account.ledger.report', string='报表', ondelete='cascade')
ledger_line_ids = fields.One2many('account.ledger.value.line', 'value_id', domain=[('from_type', '=', 'ledger_line')])
cash_flow_ids = fields.One2many('account.ledger.value.line', 'value_id', domain=[('from_type', '=', 'cash_flow')])
other_value_ids = fields.One2many('account.ledger.value.line', 'value_id', domain=[('from_type', '=', 'other_value')])
# 关系字段
report_type = fields.Selection(related='report_id.report_type', string='报表类型')
company_id = fields.Many2one(related='report_id.company_id', string='公司')
# ===================
# 公用方法
# ===================
def get_value(self, data_cache):
"""单实例方法:根据期间年度和期间号获取对应值"""
self.ensure_one()
value = 0
# 直接从缓存获取值
if not data_cache['value_cache'].get(self.id, None) is None:
return data_cache['value_cache'][self.id]
# 从科目余额表取数
if self.from_type == 'ledger_line':
value = round(sum([line.get_value(data_cache) for line in self.ledger_line_ids]), 2)
# 从现金流量项目取数
elif self.from_type == 'cash_flow':
value = round(sum([line.get_value(data_cache) for line in self.cash_flow_ids]), 2)
# 从其他取值取数
elif self.from_type == 'other_value':
value = round(sum([line.get_value(data_cache) for line in self.other_value_ids]), 2)
# 存入缓存
data_cache['value_cache'][self.id] = value
return value
class AccountLedgerValueLine(models.Model):
_name = 'account.ledger.value.line'
_description = '报表取值明细'
# 基础字段
value_sign = fields.Selection([('add', '+'), ('minus', '-')], string='符号', default='add', required=True)
# 关系字段
value_id = fields.Many2one('account.ledger.value', string='报表取值', required=True, ondelete='cascade')
account_id = fields.Many2one('account.account', string='来源科目')
cash_flow_id = fields.Many2one('account.cash.flow', string='现金流量项目')
value_type = fields.Many2one('account.ledger.value.type', string='取值类型')
value_from_id = fields.Many2one('account.ledger.value', string='来源取值')
# 关联字段
report_type = fields.Selection(related='value_id.report_id.report_type', string='报表类型')
from_type = fields.Selection(related='value_id.from_type', string='取值来源')
company_id = fields.Many2one(related='account_id.company_id', string='来源公司')
# ===================
# 公用方法
# ===================
def get_value(self, data_cache):
"""单实例方法:根据期间年度和期间编号获取明细取值"""
self.ensure_one()
value = 0
# 从科目余额表取数
if self.from_type == 'ledger_line' and self.account_id and self.value_type:
value = self._get_ledger_line_value(data_cache)
# 现金流量表取数
elif self.from_type == 'cash_flow' and self.cash_flow_id and self.value_type:
value = self._get_cash_flow_value(data_cache)
# 从其他取值取数
elif self.from_type == 'other_value' and self.value_from_id:
value = self.value_from_id.get_value(data_cache)
# 判断是否取负
if self.value_sign == 'minus':
value = -value
return value
# ===================
# 约束方法
# ===================
@api.constrains('value_id', 'value_from_id', 'value_form_id.line_ids.value_from_id')
def _constraints_value_id(self):
for rec in self:
if rec.value_id == rec.value_from_id:
raise ValidationError('来源报表取值不能为当前报表取值!')
if rec.value_id in rec.value_from_id.other_value_ids.mapped('value_from_id'):
raise ValidationError(f'报表取值{rec.value_from_id.name}存在递归调用{rec.value_id.name}')
# ===================
# 私有方法
# ===================
def _get_ledger_line_value(self, data_cache):
"""单实例方法:从科目余额表获取取值"""
self.ensure_one()
if not self.account_id:
raise ValidationError('取值科目不能为空!')
value = 0
descendant_ids = self.account_id.get_descendant_ids(leaf=True)
# 获取期末借方余额
if self.value_type.code == 'balance_period_end_deb':
if not(data_cache.get('co_accounts', False) and self.account_id in data_cache['co_accounts']):
balance_data_qm = data_cache.get('balance_data_qm', False)
if balance_data_qm is not False:
balance_qm = sum([balance_data_qm[descendant_id] for descendant_id in descendant_ids])
if balance_qm > 0:
value = balance_qm
else:
value = data_cache['balance_data_qm_co'][self.account_id.id]
# 获取期末贷方余额
elif self.value_type.code == 'balance_period_end_cre':
if not(data_cache.get('co_accounts', False) and self.account_id in data_cache['co_accounts']):
balance_data_qm = data_cache.get('balance_data_qm', False)
if balance_data_qm is not False:
balance_qm = sum([balance_data_qm[descendant_id] for descendant_id in descendant_ids])
if balance_qm < 0:
value = - balance_qm
else:
value = - data_cache['balance_data_qm_co'][self.account_id.id]
# 获取期初借方余额
if self.value_type.code == 'balance_period_start_deb':
if not(data_cache.get('co_accounts', False) and self.account_id in data_cache['co_accounts']):
balance_data_qc = data_cache.get('balance_data_qc', False)
if balance_data_qc is not False:
balance_qc = sum([balance_data_qc[descendant_id] for descendant_id in descendant_ids])
if balance_qc > 0:
value = balance_qc
# 获取期初贷方余额
elif self.value_type.code == 'balance_period_start_cre':
if not(data_cache.get('co_accounts', False) and self.account_id in data_cache['co_accounts']):
balance_data_qc = data_cache.get('balance_data_qc', False)
if balance_data_qc is not False:
balance_qc = sum([balance_data_qc[descendant_id] for descendant_id in descendant_ids])
if balance_qc < 0:
value = - balance_qc
# 获取年初借方余额
elif self.value_type.code == 'balance_year_start_deb':
if not(data_cache.get('co_accounts', False) and self.account_id in data_cache['co_accounts']):
balance_data_nc = data_cache.get('balance_data_nc', False)
if balance_data_nc is not False:
balance_nc = sum([balance_data_nc[descendant_id] for descendant_id in descendant_ids])
if balance_nc > 0:
value = balance_nc
else:
value = data_cache['balance_data_nc_co'][self.account_id.id]
# 获取年初贷方余额
elif self.value_type.code == 'balance_year_start_cre':
if not(data_cache.get('co_accounts', False) and self.account_id in data_cache['co_accounts']):
balance_data_nc = data_cache.get('balance_data_nc', False)
if balance_data_nc is not False:
balance_nc = sum([balance_data_nc[descendant_id] for descendant_id in descendant_ids])
if balance_nc < 0:
value = - balance_nc
else:
value = - data_cache['balance_data_nc_co'][self.account_id.id]
# 获取本期借方发生
elif self.value_type.code == 'period_deb':
occur_data_bq = data_cache.get('occur_data_bq', False)
if occur_data_bq is not False:
value = sum([occur_data_bq[descendant_id][0] for descendant_id in descendant_ids])
# 获取本期贷方发生
elif self.value_type.code == 'period_cre':
occur_data_bq = data_cache.get('occur_data_bq', False)
if occur_data_bq is not False:
value = sum([occur_data_bq[descendant_id][1] for descendant_id in descendant_ids])
# 获取本年借方发生
elif self.value_type.code == 'fiscalyear_deb':
occur_data_bn = data_cache.get('occur_data_bn', False)
if occur_data_bn is not False:
value = sum([occur_data_bn[descendant_id][0] for descendant_id in descendant_ids])
# 获取本年贷方发生
elif self.value_type.code == 'fiscalyear_cre':
occur_data_bn = data_cache.get('occur_data_bn', False)
if occur_data_bn is not False:
value = sum([occur_data_bn[descendant_id][1] for descendant_id in descendant_ids])
# return value
return value
def _get_profit_value(self, data_cache):
self.ensure_one()
if not self.account_id:
raise ValidationError('取值科目不能为空!')
value = 0
occur_data_bn = data_cache['occur_data_bn']
occur_data_bq = data_cache['occur_data_bq']
descendant_ids = self.account_id.get_descendant_ids(leaf=True)
# 获取本年借方发生
if self.value_type.code == 'fiscalyear_deb':
value = sum([occur_data_bn[descendant_id][0] for descendant_id in descendant_ids])
# 获取本年贷方发生
elif self.value_type.code == 'fiscalyear_cre':
value = sum([occur_data_bn[descendant_id][1] for descendant_id in descendant_ids])
# 获取本期借方发生
elif self.value_type.code == 'period_deb':
value = sum([occur_data_bq[descendant_id][0] for descendant_id in descendant_ids])
# 获取本期贷方发生
elif self.value_type.code == 'period_cre':
value = sum([occur_data_bq[descendant_id][1] for descendant_id in descendant_ids])
return value
def _get_cash_flow_value(self, data_cache):
"""单实例方法:从现金流量项目计算取值"""
self.ensure_one()
if not self.cash_flow_id:
raise ValidationError('现金流量项目不能为空!')
value = 0
cash_flow_data_bn = data_cache['cash_flow_data_bn']
cash_flow_data_bq = data_cache['cash_flow_data_bq']
# 获取本年借方差额
if self.value_type.code == 'fiscalyear_deb_diff':
value = cash_flow_data_bn[self.cash_flow_id.id][0]
elif self.value_type.code == 'fiscalyear_cre_diff':
value = cash_flow_data_bn[self.cash_flow_id.id][1]
elif self.value_type.code == 'period_deb_diff':
value = cash_flow_data_bq[self.cash_flow_id.id][0]
elif self.value_type.code == 'period_cre_diff':
value = cash_flow_data_bq[self.cash_flow_id.id][1]
return value
class AccountLedgerValueType(models.Model):
_name = 'account.ledger.value.type'
_description = '报表取值类型'
_order = 'sequence'
sequence = fields.Integer(string='序号')
code = fields.Char(string='代码', required=True)
name = fields.Char(string='名称', required=True)
value_type = fields.Selection([
('ledger_line', '科目余额表'),
('cash_flow', '现金流量表项目'),
], string='取值类型', required=True)
class AccountCashFlow(models.Model):
_name = 'account.cash.flow'
_description = '现金流量项目'
name = fields.Char(string='名称')
code = fields.Char(string='代码')
company_id = fields.Many2one('res.company', string='公司', default=lambda self: self.env.user.company_id.id)