Skip to content

Commit

Permalink
Merge pull request #18 from alyf-de/summen-und-salden-liste
Browse files Browse the repository at this point in the history
feat: new report "Summen- und Saldenliste"
  • Loading branch information
barredterra authored Dec 29, 2023
2 parents 79b7acb + 2d35592 commit d392195
Show file tree
Hide file tree
Showing 6 changed files with 282 additions and 0 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ App to hold regional code for Germany, built on top of ERPNext.

### Features

- German accounting reports

- _Summen- und Saldenliste_

- Section for Register Information (Registerart, -gericht und nummer) in **Company**, **Customer** and **Supplier**

![Section with Register Information](docs/register_information.png)
Expand Down
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Copyright (c) 2023, ALYF GmbH and contributors
// For license information, please see license.txt
/* eslint-disable */

frappe.query_reports["Summen- und Saldenliste"] = {
filters: [
{
fieldname: "company",
label: __("Company"),
fieldtype: "Link",
options: "Company",
default: frappe.defaults.get_user_default("Company"),
reqd: 1,
},
{
fieldname: "fiscal_year",
label: __("Fiscal Year"),
fieldtype: "Link",
options: "Fiscal Year",
default: erpnext.utils.get_fiscal_year(),
reqd: 1,
},
{
fieldname: "month",
label: __("Month"),
fieldtype: "Select",
default: get_previous_month(),
options: [
{ value: 1, label: __("January") },
{ value: 2, label: __("February") },
{ value: 3, label: __("March") },
{ value: 4, label: __("April") },
{ value: 5, label: __("May") },
{ value: 6, label: __("June") },
{ value: 7, label: __("July") },
{ value: 8, label: __("August") },
{ value: 9, label: __("September") },
{ value: 10, label: __("October") },
{ value: 11, label: __("November") },
{ value: 12, label: __("December") },
],
reqd: 1,
},
],
};

function get_previous_month() {
/* Return the 1-indexed number of the previous month */
const date = new Date();
date.setDate(0); // set to last day of previous month
return date.getMonth() + 1; // getMonth() is 0-indexed
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"add_total_row": 0,
"columns": [],
"creation": "2023-12-28 20:21:45.244186",
"disable_prepared_report": 1,
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
"filters": [],
"idx": 0,
"is_standard": "Yes",
"letter_head": "ALYF GmbH",
"modified": "2023-12-28 20:21:50.528134",
"modified_by": "Administrator",
"module": "ERPNext Germany",
"name": "Summen- und Saldenliste",
"owner": "Administrator",
"prepared_report": 0,
"ref_doctype": "GL Entry",
"report_name": "Summen- und Saldenliste",
"report_type": "Script Report",
"roles": [
{
"role": "Accounts User"
},
{
"role": "Accounts Manager"
},
{
"role": "Auditor"
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
# Copyright (c) 2023, ALYF GmbH and contributors
# For license information, please see license.txt

from datetime import date
from calendar import monthrange
from babel.dates import format_date

import frappe
from frappe import _
from frappe.query_builder.functions import Sum, Cast
from pypika.terms import Case


def execute(filters=None):
fy_start, month_start, month_end = get_dates(
int(filters.month), filters.fiscal_year
)
current_month_name = format_date(
month_start, format="MMMM", locale=frappe.local.lang
)
return get_columns(current_month_name), get_data(
filters.company, fy_start, month_start, month_end
)


def get_columns(current_month_name: str):
return [
{
"fieldname": "account",
"label": _("Account"),
"fieldtype": "Link",
"options": "Account",
"width": 400,
},
{
"fieldname": "account_currency",
"label": _("Currency"),
"fieldtype": "Link",
"options": "Currency",
"width": 100,
},
{
"fieldname": "debit_opening_balance",
"label": _("Debit Opening Balance"),
"fieldtype": "Currency",
"width": 170,
"options": "account_currency",
},
{
"fieldname": "credit_opening_balance",
"label": _("Credit Opening Balance"),
"fieldtype": "Currency",
"width": 170,
"options": "account_currency",
},
{
"fieldname": "debit_until_evaluation_period",
"label": _("Debit until {0}").format(current_month_name),
"fieldtype": "Currency",
"width": 170,
"options": "account_currency",
},
{
"fieldname": "credit_until_evaluation_period",
"label": _("Credit until {0}").format(current_month_name),
"fieldtype": "Currency",
"width": 170,
"options": "account_currency",
},
{
"fieldname": "debit_in_evaluation_period",
"label": _("Debit in {0}").format(current_month_name),
"fieldtype": "Currency",
"width": 170,
"options": "account_currency",
},
{
"fieldname": "credit_in_evaluation_period",
"label": _("Credit in {0}").format(current_month_name),
"fieldtype": "Currency",
"width": 170,
"options": "account_currency",
},
]


def get_data(company: str, fy_start, month_start, month_end):
gl_entry = frappe.qb.DocType("GL Entry")
account = frappe.qb.DocType("Account")

opening_balance = (
frappe.qb.from_(gl_entry)
.left_join(account)
.on(gl_entry.account == account.name)
.select(
gl_entry.account,
Case()
.when(
account.root_type == "Asset",
Sum(gl_entry.debit_in_account_currency)
- Sum(gl_entry.credit_in_account_currency),
)
.else_(None)
.as_("debit"),
Case()
.when(
account.root_type.isin(("Liability", "Equity")),
Sum(gl_entry.credit_in_account_currency)
- Sum(gl_entry.debit_in_account_currency),
)
.else_(None)
.as_("credit"),
)
.where(
(gl_entry.company == company)
& (gl_entry.is_cancelled == 0)
& (gl_entry.posting_date < fy_start)
)
.groupby(gl_entry.account)
)

sum_until_month = (
frappe.qb.from_(gl_entry)
.select(
gl_entry.account,
Sum(gl_entry.debit_in_account_currency).as_("debit"),
Sum(gl_entry.credit_in_account_currency).as_("credit"),
)
.where(
(gl_entry.company == company)
& (gl_entry.is_cancelled == 0)
& (gl_entry.posting_date >= fy_start)
& (gl_entry.posting_date < month_start)
& (gl_entry.voucher_type != "Period Closing Voucher")
)
.groupby(gl_entry.account)
)

sum_in_month = (
frappe.qb.from_(gl_entry)
.left_join(account)
.on(gl_entry.account == account.name)
.select(
gl_entry.account,
gl_entry.account_currency,
Sum(gl_entry.debit_in_account_currency).as_("debit"),
Sum(gl_entry.credit_in_account_currency).as_("credit"),
)
.where(
(gl_entry.company == company)
& (gl_entry.is_cancelled == 0)
& (gl_entry.posting_date >= month_start)
& (gl_entry.posting_date <= month_end)
& (gl_entry.voucher_type != "Period Closing Voucher")
)
.orderby(Cast(account.account_number, "int"))
.groupby(gl_entry.account, gl_entry.account_currency)
)

query = (
frappe.qb.from_(sum_in_month)
.left_join(sum_until_month)
.on(sum_until_month.account == sum_in_month.account)
.left_join(opening_balance)
.on(opening_balance.account == sum_in_month.account)
.select(
sum_in_month.account,
sum_in_month.account_currency,
opening_balance.debit,
opening_balance.credit,
sum_until_month.debit,
sum_until_month.credit,
sum_in_month.debit,
sum_in_month.credit,
)
)

return query.run()


def get_dates(month: int, fiscal_year: str):
"""Returns the start and end date for the given month."""
fy_start: date = frappe.db.get_value("Fiscal Year", fiscal_year, "year_start_date")
month_start = fy_start.replace(month=month, day=1)
last_day_of_month = monthrange(month_start.year, month_start.month)[1]
month_end = month_start.replace(day=last_day_of_month)
return fy_start, month_start, month_end
6 changes: 6 additions & 0 deletions erpnext_germany/translations/de.csv
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,9 @@ Invalid Input,Ungültige Eingabe
Error,Fehler
Cannot delete this transaction,Diese Transaktion kann nicht gelöscht werden
Only the most recent {0} can be deleted in order to avoid gaps in numbering.,"Nur die neueste Transaktion vom Typ {0} kann gelöscht werden, um Lücken in der Nummerierung zu vermeiden."
Debit until {0},Soll bis {0},
Credit until {0},Haben bis {0},
Debit in {0},Soll im {0},
Credit in {0},Haben im {0},
Debit Opening Balance,Soll Anfangsbestand,
Credit Opening Balance,Haben Anfangsbestand,

0 comments on commit d392195

Please sign in to comment.