GL detail report

This commit is contained in:
2026-05-21 13:39:21 +02:00
parent f29664fd77
commit f16b334089
5 changed files with 253 additions and 0 deletions

View File

@@ -120,6 +120,7 @@ def register():
Pool.register(
account.AccountTypeStatement,
account.GeneralLedger,
account.GeneralLedgerDetailReport,
account.TrialBalance,
account.AgedBalanceReport,
move.GeneralJournal,

View File

@@ -3145,6 +3145,52 @@ class GeneralLedger(Report):
return report_context
class GeneralLedgerDetailReport(Report):
__name__ = 'account.general_ledger.detail.report'
@classmethod
def get_context(cls, records, header, data):
pool = Pool()
Company = pool.get('company.company')
Fiscalyear = pool.get('account.fiscalyear')
Period = pool.get('account.period')
context = Transaction().context
report_context = super().get_context(records, header, data)
report_context['company'] = Company(context['company'])
report_context['fiscalyear'] = Fiscalyear(context['fiscalyear'])
for period in ['start_period', 'end_period']:
if context.get(period):
report_context[period] = Period(context[period])
else:
report_context[period] = None
report_context['from_date'] = context.get('from_date')
report_context['to_date'] = context.get('to_date')
report_context['groups'] = cls._groups(records)
return report_context
@classmethod
def _groups(cls, records):
groups = []
current_key = None
current = None
for line in records:
currency = getattr(line, 'transaction_currency', None)
key = (
getattr(line, 'account_code', None),
getattr(currency, 'id', None))
if key != current_key:
current = {
'account': line.account_code or line.account_name or '',
'currency': currency,
'lines': [],
}
groups.append(current)
current_key = key
current['lines'].append(line)
return groups
class TrialBalance(Report):
__name__ = 'account.trial_balance'

View File

@@ -823,6 +823,18 @@ this repository contains the full copyright notices and license terms. -->
<field name="view" ref="general_ledger_detail_view_list"/>
<field name="act_window" ref="act_general_ledger_detail_form"/>
</record>
<record model="ir.action.report" id="report_general_ledger_detail">
<field name="name">General Ledger Detail</field>
<field name="records">listed</field>
<field name="model">account.general_ledger.detail</field>
<field name="report_name">account.general_ledger.detail.report</field>
<field name="report">account/general_ledger_detail.fodt</field>
</record>
<record model="ir.action.keyword" id="report_general_ledger_detail_keyword">
<field name="keyword">form_print</field>
<field name="model">account.general_ledger.detail,-1</field>
<field name="action" ref="report_general_ledger_detail"/>
</record>
<menuitem
name="General Ledger Detail"
parent="menu_reporting"

View File

@@ -0,0 +1,157 @@
<?xml version="1.0" encoding="UTF-8"?>
<office:document
xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0"
xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0"
xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0"
xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0"
xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0"
xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0"
office:version="1.2">
<office:font-face-decls>
<style:font-face style:name="Liberation Sans" svg:font-family="&apos;Liberation Sans&apos;" style:font-family-generic="swiss"/>
</office:font-face-decls>
<office:styles>
<style:default-style style:family="paragraph">
<style:paragraph-properties fo:margin-top="0cm" fo:margin-bottom="0.08cm"/>
<style:text-properties style:font-name="Liberation Sans" fo:font-size="8pt"/>
</style:default-style>
<style:style style:name="Title" style:family="paragraph">
<style:paragraph-properties fo:text-align="center" fo:margin-bottom="0.2cm"/>
<style:text-properties style:font-name="Liberation Sans" fo:font-size="16pt" fo:font-weight="bold" fo:color="#003333"/>
</style:style>
<style:style style:name="Subtitle" style:family="paragraph">
<style:paragraph-properties fo:text-align="center" fo:margin-bottom="0.25cm"/>
<style:text-properties style:font-name="Liberation Sans" fo:font-size="9pt" fo:color="#444444"/>
</style:style>
<style:style style:name="Group" style:family="paragraph">
<style:text-properties style:font-name="Liberation Sans" fo:font-size="9pt" fo:font-weight="bold" fo:color="#003333"/>
</style:style>
<style:style style:name="Header" style:family="paragraph">
<style:paragraph-properties fo:text-align="center"/>
<style:text-properties style:font-name="Liberation Sans" fo:font-size="7pt" fo:font-weight="bold" fo:color="#ffffff"/>
</style:style>
<style:style style:name="Cell" style:family="paragraph">
<style:text-properties style:font-name="Liberation Sans" fo:font-size="7pt"/>
</style:style>
<style:style style:name="CellRight" style:family="paragraph">
<style:paragraph-properties fo:text-align="end"/>
<style:text-properties style:font-name="Liberation Sans" fo:font-size="7pt"/>
</style:style>
<style:style style:name="Summary" style:family="paragraph">
<style:text-properties style:font-name="Liberation Sans" fo:font-size="7pt" fo:font-weight="bold"/>
</style:style>
<style:style style:name="SummaryRight" style:family="paragraph">
<style:paragraph-properties fo:text-align="end"/>
<style:text-properties style:font-name="Liberation Sans" fo:font-size="7pt" fo:font-weight="bold"/>
</style:style>
<style:style style:name="ReportTable" style:family="table">
<style:table-properties table:border-model="collapsing" style:width="27.4cm"/>
</style:style>
<style:style style:name="C1" style:family="table-column"><style:table-column-properties style:column-width="1.35cm"/></style:style>
<style:style style:name="C2" style:family="table-column"><style:table-column-properties style:column-width="1.55cm"/></style:style>
<style:style style:name="C3" style:family="table-column"><style:table-column-properties style:column-width="1.55cm"/></style:style>
<style:style style:name="C4" style:family="table-column"><style:table-column-properties style:column-width="2.1cm"/></style:style>
<style:style style:name="C5" style:family="table-column"><style:table-column-properties style:column-width="2.0cm"/></style:style>
<style:style style:name="C6" style:family="table-column"><style:table-column-properties style:column-width="2.4cm"/></style:style>
<style:style style:name="C7" style:family="table-column"><style:table-column-properties style:column-width="4.25cm"/></style:style>
<style:style style:name="C8" style:family="table-column"><style:table-column-properties style:column-width="2.3cm"/></style:style>
<style:style style:name="C9" style:family="table-column"><style:table-column-properties style:column-width="2.0cm"/></style:style>
<style:style style:name="C10" style:family="table-column"><style:table-column-properties style:column-width="2.0cm"/></style:style>
<style:style style:name="C11" style:family="table-column"><style:table-column-properties style:column-width="2.0cm"/></style:style>
<style:style style:name="C12" style:family="table-column"><style:table-column-properties style:column-width="2.0cm"/></style:style>
<style:style style:name="HeaderCell" style:family="table-cell">
<style:table-cell-properties fo:background-color="#156082" fo:border="0.5pt solid #156082" fo:padding="0.04cm"/>
</style:style>
<style:style style:name="GroupCell" style:family="table-cell">
<style:table-cell-properties fo:background-color="#d9ead3" fo:border="0.5pt solid #808080" fo:padding="0.05cm"/>
</style:style>
<style:style style:name="DataCell" style:family="table-cell">
<style:table-cell-properties fo:border="0.3pt solid #c0c0c0" fo:padding="0.04cm"/>
</style:style>
<style:style style:name="SummaryCell" style:family="table-cell">
<style:table-cell-properties fo:background-color="#f2f2f2" fo:border="0.5pt solid #808080" fo:padding="0.04cm"/>
</style:style>
</office:styles>
<office:automatic-styles>
<style:page-layout style:name="PageLayout">
<style:page-layout-properties fo:page-width="29.7cm" fo:page-height="21cm" style:print-orientation="landscape" fo:margin-top="1cm" fo:margin-bottom="1cm" fo:margin-left="1cm" fo:margin-right="1cm"/>
</style:page-layout>
</office:automatic-styles>
<office:master-styles>
<style:master-page style:name="Standard" style:page-layout-name="PageLayout"/>
</office:master-styles>
<office:body>
<office:text>
<text:p text:style-name="Title">General Ledger Detail</text:p>
<text:p text:style-name="Subtitle">
<text:placeholder text:placeholder-type="text">&lt;company.rec_name&gt;</text:placeholder>
<text:s/>- Fiscal Year:
<text:s/><text:placeholder text:placeholder-type="text">&lt;fiscalyear.rec_name&gt;</text:placeholder>
</text:p>
<text:p text:style-name="Subtitle">
From
<text:s/><text:placeholder text:placeholder-type="text">&lt;format_date(from_date, user.language) if from_date else &apos;&apos;&gt;</text:placeholder>
<text:s/>to
<text:s/><text:placeholder text:placeholder-type="text">&lt;format_date(to_date, user.language) if to_date else &apos;&apos;&gt;</text:placeholder>
</text:p>
<text:p><text:placeholder text:placeholder-type="text">&lt;for each=&quot;group in groups&quot;&gt;</text:placeholder></text:p>
<table:table table:name="GeneralLedgerDetail" table:style-name="ReportTable">
<table:table-column table:style-name="C1"/>
<table:table-column table:style-name="C2"/>
<table:table-column table:style-name="C3"/>
<table:table-column table:style-name="C4"/>
<table:table-column table:style-name="C5"/>
<table:table-column table:style-name="C6"/>
<table:table-column table:style-name="C7"/>
<table:table-column table:style-name="C8"/>
<table:table-column table:style-name="C9"/>
<table:table-column table:style-name="C10"/>
<table:table-column table:style-name="C11"/>
<table:table-column table:style-name="C12"/>
<table:table-row>
<table:table-cell table:style-name="GroupCell" table:number-columns-spanned="12" office:value-type="string">
<text:p text:style-name="Group">
<text:placeholder text:placeholder-type="text">&lt;group[&apos;account&apos;]&gt;</text:placeholder>
<text:s/>/
<text:s/><text:placeholder text:placeholder-type="text">&lt;group[&apos;currency&apos;].rec_name if group[&apos;currency&apos;] else &apos;&apos;&gt;</text:placeholder>
</text:p>
</table:table-cell>
<table:covered-table-cell/><table:covered-table-cell/><table:covered-table-cell/><table:covered-table-cell/><table:covered-table-cell/>
<table:covered-table-cell/><table:covered-table-cell/><table:covered-table-cell/><table:covered-table-cell/><table:covered-table-cell/><table:covered-table-cell/>
</table:table-row>
<table:table-row>
<table:table-cell table:style-name="HeaderCell"><text:p text:style-name="Header">Type</text:p></table:table-cell>
<table:table-cell table:style-name="HeaderCell"><text:p text:style-name="Header">Date</text:p></table:table-cell>
<table:table-cell table:style-name="HeaderCell"><text:p text:style-name="Header">Journal</text:p></table:table-cell>
<table:table-cell table:style-name="HeaderCell"><text:p text:style-name="Header">Entry</text:p></table:table-cell>
<table:table-cell table:style-name="HeaderCell"><text:p text:style-name="Header">Document</text:p></table:table-cell>
<table:table-cell table:style-name="HeaderCell"><text:p text:style-name="Header">Party</text:p></table:table-cell>
<table:table-cell table:style-name="HeaderCell"><text:p text:style-name="Header">Description</text:p></table:table-cell>
<table:table-cell table:style-name="HeaderCell"><text:p text:style-name="Header">Reference</text:p></table:table-cell>
<table:table-cell table:style-name="HeaderCell"><text:p text:style-name="Header">Debit</text:p></table:table-cell>
<table:table-cell table:style-name="HeaderCell"><text:p text:style-name="Header">Credit</text:p></table:table-cell>
<table:table-cell table:style-name="HeaderCell"><text:p text:style-name="Header">Balance</text:p></table:table-cell>
<table:table-cell table:style-name="HeaderCell"><text:p text:style-name="Header">Running</text:p></table:table-cell>
</table:table-row>
<table:table-row>
<table:table-cell table:style-name="DataCell" office:value-type="string">
<text:p text:style-name="Cell"><text:placeholder text:placeholder-type="text">&lt;for each=&quot;line in group[&apos;lines&apos;]&quot;&gt;</text:placeholder><text:placeholder text:placeholder-type="text">&lt;line.row_type.title() if line.row_type else &apos;&apos;&gt;</text:placeholder></text:p>
</table:table-cell>
<table:table-cell table:style-name="DataCell" office:value-type="string"><text:p text:style-name="Cell"><text:placeholder text:placeholder-type="text">&lt;format_date(line.posting_date, user.language) if line.posting_date else &apos;&apos;&gt;</text:placeholder></text:p></table:table-cell>
<table:table-cell table:style-name="DataCell" office:value-type="string"><text:p text:style-name="Cell"><text:placeholder text:placeholder-type="text">&lt;line.journal.rec_name if line.journal else &apos;&apos;&gt;</text:placeholder></text:p></table:table-cell>
<table:table-cell table:style-name="DataCell" office:value-type="string"><text:p text:style-name="Cell"><text:placeholder text:placeholder-type="text">&lt;line.journal_entry_number or &apos;&apos;&gt;</text:placeholder></text:p></table:table-cell>
<table:table-cell table:style-name="DataCell" office:value-type="string"><text:p text:style-name="Cell"><text:placeholder text:placeholder-type="text">&lt;line.document_number or line.voucher_number or &apos;&apos;&gt;</text:placeholder></text:p></table:table-cell>
<table:table-cell table:style-name="DataCell" office:value-type="string"><text:p text:style-name="Cell"><text:placeholder text:placeholder-type="text">&lt;line.party.rec_name if line.party else &apos;&apos;&gt;</text:placeholder></text:p></table:table-cell>
<table:table-cell table:style-name="DataCell" office:value-type="string"><text:p text:style-name="Cell"><text:placeholder text:placeholder-type="text">&lt;line.description or line.move_description or &apos;&apos;&gt;</text:placeholder></text:p></table:table-cell>
<table:table-cell table:style-name="DataCell" office:value-type="string"><text:p text:style-name="Cell"><text:placeholder text:placeholder-type="text">&lt;line.reference or &apos;&apos;&gt;</text:placeholder></text:p></table:table-cell>
<table:table-cell table:style-name="DataCell" office:value-type="string"><text:p text:style-name="CellRight"><text:placeholder text:placeholder-type="text">&lt;format_currency(line.debit_base_currency or 0, user.language, line.base_currency or company.currency)&gt;</text:placeholder></text:p></table:table-cell>
<table:table-cell table:style-name="DataCell" office:value-type="string"><text:p text:style-name="CellRight"><text:placeholder text:placeholder-type="text">&lt;format_currency(line.credit_base_currency or 0, user.language, line.base_currency or company.currency)&gt;</text:placeholder></text:p></table:table-cell>
<table:table-cell table:style-name="DataCell" office:value-type="string"><text:p text:style-name="CellRight"><text:placeholder text:placeholder-type="text">&lt;format_currency(line.balance_base_currency or 0, user.language, line.base_currency or company.currency)&gt;</text:placeholder></text:p></table:table-cell>
<table:table-cell table:style-name="DataCell" office:value-type="string"><text:p text:style-name="CellRight"><text:placeholder text:placeholder-type="text">&lt;format_currency(line.running_balance_base_currency or 0, user.language, line.base_currency or company.currency)&gt;</text:placeholder><text:placeholder text:placeholder-type="text">&lt;/for&gt;</text:placeholder></text:p></table:table-cell>
</table:table-row>
</table:table>
<text:p/>
<text:p><text:placeholder text:placeholder-type="text">&lt;/for&gt;</text:placeholder></text:p>
</office:text>
</office:body>
</office:document>

View File

@@ -2103,6 +2103,8 @@ class AccountTestCase(
pool = Pool()
Detail = pool.get('account.general_ledger.detail')
DetailContext = pool.get('account.general_ledger.detail.context')
DetailReport = pool.get(
'account.general_ledger.detail.report', type='report')
for name in [
'row_type', 'account_code', 'transaction_currency',
@@ -2124,6 +2126,41 @@ class AccountTestCase(
self.assertIn('||', str(account_label))
self.assertNotIn(' + ', str(account_label))
self.assertEqual(account_label.params, ('', ' - ', ''))
self.assertEqual(
DetailReport.__name__, 'account.general_ledger.detail.report')
@with_transaction()
def test_general_ledger_detail_report_groups_by_account_currency(self):
"Test General Ledger Detail report groups lines by account and currency"
DetailReport = Pool().get(
'account.general_ledger.detail.report', type='report')
currency = type('Currency', (), {'id': 1})()
other_currency = type('Currency', (), {'id': 2})()
first = type('Line', (), {
'account_code': '1000 - Cash',
'account_name': 'Cash',
'transaction_currency': currency,
})()
second = type('Line', (), {
'account_code': '1000 - Cash',
'account_name': 'Cash',
'transaction_currency': currency,
})()
third = type('Line', (), {
'account_code': '2000 - Revenue',
'account_name': 'Revenue',
'transaction_currency': other_currency,
})()
groups = DetailReport._groups([first, second, third])
self.assertEqual(len(groups), 2)
self.assertEqual(groups[0]['account'], '1000 - Cash')
self.assertEqual(groups[0]['currency'], currency)
self.assertEqual(groups[0]['lines'], [first, second])
self.assertEqual(groups[1]['account'], '2000 - Revenue')
self.assertEqual(groups[1]['currency'], other_currency)
self.assertEqual(groups[1]['lines'], [third])
@with_transaction()
def test_general_ledger_detail_date_contexts(self):