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
209 lines
7.7 KiB
Python
# -*- 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='币种')
|