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.

209 lines
7.7 KiB
Python

8 months ago
# -*- coding: utf-8 -*-
from collections import defaultdict
from datetime import timedelta
from odoo import api, models, fields
from odoo.exceptions import UserError, MissingError
BALANCE_DIRECTION = [('debit', ''), ('credit', ''), ('balance', '')]
def balance_debit_to_balance_direction(balance_debit):
if balance_debit > 0:
balance = balance_debit
direction = 'debit'
elif balance_debit < 0:
balance = - balance_debit
direction = 'credit'
else:
balance = 0
direction = 'balance'
return balance, direction
class LedgerInquiryWizard(models.TransientModel):
"""总账查询向导"""
_name = 'ledger.inquiry.wizard'
_inherit = 'inquiry.wizard.mixin'
_description = '总账查询向导'
# company_id = fields.Many2one('res.company', string='公司', default=lambda self: self.env.company.id)
def confirm(self):
self.ensure_one()
# 获取总账窗口动作
act_window = self.env['ir.actions.act_window'].for_xml_id('account_ledger', 'AccountLedgerActionList')
act_window['domain'] = eval(act_window['domain'])
act_window['context'] = eval(act_window['context'])
act_window['display_name'] = '总账:'
periods = self.env['fr.account.period'].search(
[('date_start', '>=', self.period_from.date_start), ('date_start', '<=', self.period_to.date_start)])
# 添加会计期间筛选
if self.period_from and self.period_to:
act_window['domain'] += [('period_id', 'in', periods.ids)]
act_window['display_name'] = f'总账:{self.period_from.name} - {self.period_to.name}'
# 添加会计科目筛选
if len(self.account_ids) > 0:
act_window['domain'] += [('account_id', 'in', self.account_ids.ids)]
return act_window
def confirm(self):
self.ensure_one()
# 获取要打印的科目
if self.account_ids:
account_ids = self.account_ids
else:
account_ids = self.env['account.account'].search([('state', '=', 'on_use')])
periods = self.env['fr.account.period'].search(
[('date_start', '>=', self.period_from.date_start), ('date_start', '<=', self.period_to.date_start)])
date_start = self.period_from.date_start
date = date_start - timedelta(days=1)
balance_data = self._fetch_balance_data(self.period_from.company_id.id, date)
period_data = self._fetch_period_data(self.period_from.company_id.id)
# 生成临时总账报表记录
vals_list = []
for account in account_ids:
descendant_ids = account.get_descendant_ids(leaf=True)
# 上年结转/初始余额
balance_start = sum([balance_data[descendant_id] for descendant_id in descendant_ids])
balance_temp, direction_temp = balance_debit_to_balance_direction(balance_start)
vals_list.append({
'account_id': account.id,
'name': '初始余额',
'direction': direction_temp,
'balance': balance_temp
})
# 期间总账
balance = balance_start
debit_fiscalyear = credit_fiscalyear = 0
for period in periods.filtered(lambda x: x.state != 'unuse'):
debit_period = credit_period = 0
# 从下级科目获取
for descendant_id in descendant_ids:
data_key = f"{descendant_id}-{period.id}"
debit_period += period_data[data_key][0]
credit_period += period_data[data_key][1]
balance += debit_period - credit_period
balance, direction = balance_debit_to_balance_direction(balance)
# 本期合计
vals_list.append({
'account_id': account.id,
'period_id': period.id,
'name': '本期合计',
'debit': debit_period,
'credit': credit_period,
'direction': direction,
'balance': balance
})
# 本年累计
debit_fiscalyear += debit_period
credit_fiscalyear += credit_period
vals_list.append({
'account_id': account.id,
'period_id': period.id,
'name': '本年累计',
'debit': debit_fiscalyear,
'credit': credit_fiscalyear,
})
# 创建临时记录集
report_recs = self.env['account.ledger.temp'].create(vals_list)
# 获取总账窗口动作
act_window = self.env['ir.actions.act_window']._for_xml_id('account_ledger.AccountLedgerTempActionList')
act_window['domain'] = eval(act_window['domain'])
act_window['context'] = eval(act_window['context'])
act_window['display_name'] = '总账:'
# 添加会计期间筛选
if self.period_from and self.period_to:
act_window['domain'] += [('id', 'in', report_recs.ids)]
act_window['display_name'] = f'总账:{self.period_from.name} - {self.period_to.name}'
# 添加会计科目筛选
if len(self.account_ids) > 0:
act_window['domain'] += [('account_id', 'in', self.account_ids.ids)]
return act_window
def _fetch_balance_data(self, company_id, date_end):
# 期末余额数据读取
self.env.cr.execute(f"""
SELECT
account_id,
sum( balance ) AS balance
FROM
account_move_line
WHERE
company_id = {company_id} and date <= '{date_end}' and fr_state = 'posted'
GROUP BY
account_id
""")
balance_data = defaultdict(float)
for res in self.env.cr.fetchall():
balance_data[res[0]] = res[1]
return balance_data
def _fetch_period_data(self, company_id):
# 期间借贷发生数据读取
self.env.cr.execute(f"""
SELECT
account_id,
fr_period_id,
sum( debit ) AS debit,
sum( credit ) AS credit
FROM
account_move_line
WHERE
company_id = {company_id} and fr_state = 'posted'
GROUP BY
account_id,
fr_period_id
""")
period_data = defaultdict(lambda: (0, 0))
for res in self.env.cr.fetchall():
data_key = f"{res[0]}-{res[1]}"
period_data[data_key] = (res[2], res[3])
return period_data
class AccountLedgerTemp(models.TransientModel):
_name = 'account.ledger.temp'
_description = '总账'
_order = 'account_id, id'
# 基础字段
name = fields.Char(string='摘要')
debit = fields.Monetary(string='借方')
credit = fields.Monetary(string='贷方')
direction = fields.Selection(BALANCE_DIRECTION, string='方向')
balance = fields.Monetary(string='余额')
# 关系字段
period_id = fields.Many2one('fr.account.period', string='会计期间')
account_id = fields.Many2one('account.account', strint='会计科目')
fiscalyear_id = fields.Many2one('fr.account.fiscalyear', string='会计年度')
# 关联字段
company_id = fields.Many2one(related='account_id.company_id', string='公司')
currency_id = fields.Many2one(related='account_id.currency_id', string='币种')