From 8caba5e514c361a5ca6c98c51ca0af988e8cb726 Mon Sep 17 00:00:00 2001 From: Charles-Henri Decultot Date: Fri, 3 May 2024 15:22:15 +0200 Subject: [PATCH 1/2] feat: Calculation of ecriturenum on closing --- .../accounting_journal.json | 4 +- .../accounting_journal/accounting_journal.py | 2 +- .../accounts/doctype/gl_entry/gl_entry.json | 17 ++++++- erpnext/accounts/doctype/gl_entry/gl_entry.py | 1 + erpnext/accounts/general_ledger.py | 4 +- erpnext/hooks.py | 4 +- erpnext/regional/france/utils.py | 34 +++++++++++++- .../fichier_des_ecritures_comptables.py | 46 ++++++++++++++++--- 8 files changed, 96 insertions(+), 16 deletions(-) diff --git a/erpnext/accounts/doctype/accounting_journal/accounting_journal.json b/erpnext/accounts/doctype/accounting_journal/accounting_journal.json index 260a570fb7..9fcaedc608 100644 --- a/erpnext/accounts/doctype/accounting_journal/accounting_journal.json +++ b/erpnext/accounts/doctype/accounting_journal/accounting_journal.json @@ -28,7 +28,7 @@ "fieldname": "type", "fieldtype": "Select", "label": "Type", - "options": "Sales\nPurchase\nCash\nBank\nMiscellaneous" + "options": "Sales\nPurchase\nCash\nBank\nOpening\nMiscellaneous" }, { "fieldname": "conditions_section", @@ -76,7 +76,7 @@ ], "index_web_pages_for_search": 1, "links": [], - "modified": "2024-04-17 11:03:25.242452", + "modified": "2024-05-03 14:52:20.933209", "modified_by": "Administrator", "module": "Accounts", "name": "Accounting Journal", diff --git a/erpnext/accounts/doctype/accounting_journal/accounting_journal.py b/erpnext/accounts/doctype/accounting_journal/accounting_journal.py index eb8a8fa311..a51a3a499a 100644 --- a/erpnext/accounts/doctype/accounting_journal/accounting_journal.py +++ b/erpnext/accounts/doctype/accounting_journal/accounting_journal.py @@ -28,7 +28,7 @@ class AccountingJournal(Document): disabled: DF.Check journal_code: DF.Data journal_name: DF.Data - type: DF.Literal["Sales", "Purchase", "Cash", "Bank", "Miscellaneous"] + type: DF.Literal["Sales", "Purchase", "Cash", "Bank", "Opening", "Miscellaneous"] # end: auto-generated types def autoname(self): diff --git a/erpnext/accounts/doctype/gl_entry/gl_entry.json b/erpnext/accounts/doctype/gl_entry/gl_entry.json index 4de6e945a0..9e85e9aff9 100644 --- a/erpnext/accounts/doctype/gl_entry/gl_entry.json +++ b/erpnext/accounts/doctype/gl_entry/gl_entry.json @@ -38,7 +38,9 @@ "transaction_currency", "debit_in_transaction_currency", "credit_in_transaction_currency", - "transaction_exchange_rate" + "transaction_exchange_rate", + "fec_tab", + "ecriturenum" ], "fields": [ { @@ -294,13 +296,24 @@ "fieldname": "voucher_subtype", "fieldtype": "Small Text", "label": "Voucher Subtype" + }, + { + "fieldname": "fec_tab", + "fieldtype": "Tab Break", + "label": "FEC" + }, + { + "fieldname": "ecriturenum", + "fieldtype": "Int", + "label": "EcritureNum", + "non_negative": 1 } ], "icon": "fa fa-list", "idx": 1, "in_create": 1, "links": [], - "modified": "2023-12-26 02:10:11.291699", + "modified": "2024-05-03 14:45:16.695999", "modified_by": "Administrator", "module": "Accounts", "name": "GL Entry", diff --git a/erpnext/accounts/doctype/gl_entry/gl_entry.py b/erpnext/accounts/doctype/gl_entry/gl_entry.py index 0c2f60846d..44dbfe546e 100644 --- a/erpnext/accounts/doctype/gl_entry/gl_entry.py +++ b/erpnext/accounts/doctype/gl_entry/gl_entry.py @@ -47,6 +47,7 @@ class GLEntry(Document): debit_in_account_currency: DF.Currency debit_in_transaction_currency: DF.Currency due_date: DF.Date | None + ecriturenum: DF.Int finance_book: DF.Link | None fiscal_year: DF.Link | None is_advance: DF.Literal["No", "Yes"] diff --git a/erpnext/accounts/general_ledger.py b/erpnext/accounts/general_ledger.py index 1ccdb31a93..46068a8a71 100644 --- a/erpnext/accounts/general_ledger.py +++ b/erpnext/accounts/general_ledger.py @@ -7,7 +7,7 @@ import frappe from frappe import _ from frappe.model.meta import get_field_precision from frappe.model.naming import make_autoname -from frappe.utils import cint, cstr, flt, formatdate, getdate, now +from frappe.utils import cint, flt, formatdate, getdate, now import erpnext from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import ( @@ -707,7 +707,7 @@ def make_reverse_gl_entries( for entry in gl_entries: new_gle = copy.deepcopy(entry) new_gle["name"] = None - new_gle["posting_date"] = getdate() + # new_gle["posting_date"] = getdate() new_gle["accounting_entry_number"] = accounting_number debit = new_gle.get("debit", 0) credit = new_gle.get("credit", 0) diff --git a/erpnext/hooks.py b/erpnext/hooks.py index 31afb5b19b..afffbd198e 100644 --- a/erpnext/hooks.py +++ b/erpnext/hooks.py @@ -428,7 +428,9 @@ doc_events = { "Supplier": {"validate": "erpnext.regional.france.extensions.supplier.validate"}, "Customer": {"validate": "erpnext.regional.france.extensions.customer.validate"}, "Global Defaults": {"on_update": "erpnext.regional.france.pappers.api.setup_pappers"}, - "Period Closing Voucher": {"before_submit": "erpnext.regional.france.utils.generate_fec_report"}, + "Period Closing Voucher": { + "before_submit": "erpnext.regional.france.utils.on_closing_voucher_submission" + }, } # function should expect the variable and doc as arguments diff --git a/erpnext/regional/france/utils.py b/erpnext/regional/france/utils.py index 8756060c2b..9d951bd32d 100644 --- a/erpnext/regional/france/utils.py +++ b/erpnext/regional/france/utils.py @@ -1,6 +1,8 @@ # Copyright (c) 2018, Frappe Technologies and contributors # For license information, please see license.txt +from itertools import groupby + import frappe from erpnext.regional.report.fichier_des_ecritures_comptables.fichier_des_ecritures_comptables import ( @@ -14,9 +16,37 @@ def test_method(): return "overridden" -def generate_fec_report(doc, method): +def on_closing_voucher_submission(doc, method): + generate_ecriturenum(doc) + generate_fec_report(doc) + + +def generate_ecriturenum(doc): + gl_entries = frappe.get_all( + "GL Entry", + filters={ + "fiscal_year": doc.fiscal_year, + "posting_date": ("between", [doc.year_start_date, doc.posting_date]), + }, + fields=["name", "accounting_entry_number", "posting_date", "accounting_journal"], + order_by="accounting_journal, posting_date ASC", + ) + + entries_by_journal = groupby(gl_entries, lambda x: x.accounting_journal) + for _, values in entries_by_journal: + for index, folio in enumerate(groupby(values, lambda x: x.accounting_entry_number)): + for entry in folio[1]: + frappe.db.set_value("GL Entry", entry.name, "ecriturenum", index + 1) + + +def generate_fec_report(doc): if frappe.db.get_value("Company", doc.company, "country") == "France": - filters = {"company": doc.company, "fiscal_year": doc.fiscal_year} + filters = { + "company": doc.company, + "fiscal_year": doc.fiscal_year, + "from_date": doc.year_start_date, + "to_date": doc.posting_date, + } fec_file, title = export_report(filters, return_file=True) _file = frappe.get_doc( diff --git a/erpnext/regional/report/fichier_des_ecritures_comptables/fichier_des_ecritures_comptables.py b/erpnext/regional/report/fichier_des_ecritures_comptables/fichier_des_ecritures_comptables.py index c675449be9..72d3f49888 100644 --- a/erpnext/regional/report/fichier_des_ecritures_comptables/fichier_des_ecritures_comptables.py +++ b/erpnext/regional/report/fichier_des_ecritures_comptables/fichier_des_ecritures_comptables.py @@ -2,7 +2,6 @@ # For license information, please see license.txt import io -import re import zipfile import frappe @@ -120,6 +119,7 @@ def get_gl_entries(company, fiscal_year, from_date, to_date): debit_currency, credit_currency, gle.accounting_entry_number, + gle.ecriturenum, gle.voucher_type, gle.voucher_no, gle.against_voucher_type, @@ -130,6 +130,7 @@ def get_gl_entries(company, fiscal_year, from_date, to_date): gle.party, gle.accounting_journal, gle.remarks, + gle.is_opening, sales_invoice.name.as_("InvName"), sales_invoice.title.as_("InvTitle"), sales_invoice.posting_date.as_("InvPostDate"), @@ -149,9 +150,13 @@ def get_gl_entries(company, fiscal_year, from_date, to_date): employee.employee_name, employee.name.as_("empName"), ) - .where((gle.company == company) & (gle.fiscal_year == fiscal_year)) - .groupby(gle.voucher_type, gle.voucher_no, gle.account, gle.name, gle.accounting_entry_number) - .orderby(gle.posting_date, gle.voucher_no, gle.accounting_entry_number) + .where( + (gle.company == company) + & (gle.fiscal_year == fiscal_year) + & (gle.voucher_type != "Period Closing Voucher") + ) + .groupby(gle.voucher_type, gle.voucher_no, gle.account, gle.name, gle.ecriturenum) + .orderby(gle.accounting_journal, gle.ecriturenum, gle.posting_date) ) if from_date: @@ -165,6 +170,7 @@ def get_gl_entries(company, fiscal_year, from_date, to_date): def get_result(company, fiscal_year, from_date, to_date): data = get_gl_entries(company, fiscal_year, from_date, to_date) + data = order_data(data) result = [] @@ -174,6 +180,11 @@ def get_result(company, fiscal_year, from_date, to_date): filters={"Company": company}, fields=["name", "account_number", "account_name"], ) + journal_codes = { + j.name: j.journal_code + for j in frappe.get_all("Accounting Journal", fields=["journal_code", "name"]) + } + journals = { j.journal_code: j.journal_name for j in frappe.get_all("Accounting Journal", fields=["journal_code", "journal_name"]) @@ -182,8 +193,10 @@ def get_result(company, fiscal_year, from_date, to_date): party_data = [x for x in data if x.get("against_voucher")] for d in data: - JournalCode = d.get("accounting_journal") or re.split("-|/|[0-9]", d.get("voucher_no"))[0] - EcritureNum = d.get("accounting_entry_number") + JournalCode = journal_codes.get( + d.get("accounting_journal") + ) # or re.split("-|/|[0-9]", d.get("voucher_no"))[0] + EcritureNum = d.get("ecriturenum") or d.get("accounting_entry_number") EcritureDate = format_datetime(d.get("GlPostDate"), "yyyyMMdd") @@ -318,6 +331,27 @@ def get_date_let(d, data): return format_datetime(max(let_dates), "yyyyMMdd") if len(let_dates) > 1 else None +def order_data(data): + ano_data = [] + other_data = [] + + ano_journal = frappe.db.get_value("Accounting Journal", filters={"type": "Opening"}) + + for d in data: + if ano_journal: + if d.accounting_journal == ano_journal: + ano_data.append(d) + else: + other_data.append(d) + else: + if d.is_opening: + ano_data.append(d) + else: + other_data.append(d) + + return ano_data + other_data + + @frappe.whitelist() def export_report(filters, with_files=False, return_file=False): from frappe.utils.csvutils import to_csv -- GitLab From aea739e37bc56f87ba2a8cbd586443865a66c6f9 Mon Sep 17 00:00:00 2001 From: Charles-Henri Decultot Date: Fri, 3 May 2024 19:38:04 +0000 Subject: [PATCH 2/2] fix: missing import --- erpnext/accounts/general_ledger.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/erpnext/accounts/general_ledger.py b/erpnext/accounts/general_ledger.py index 46068a8a71..ff8a450d2a 100644 --- a/erpnext/accounts/general_ledger.py +++ b/erpnext/accounts/general_ledger.py @@ -7,7 +7,7 @@ import frappe from frappe import _ from frappe.model.meta import get_field_precision from frappe.model.naming import make_autoname -from frappe.utils import cint, flt, formatdate, getdate, now +from frappe.utils import cint, cstr, flt, formatdate, getdate, now import erpnext from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import ( -- GitLab