Merge pull request #22487 from frappe/mergify/bp/version-13-beta-pre-release/pr-21690

fix(regional): DATEV report (bp #21690)
This commit is contained in:
Deepesh Garg 2020-06-28 21:38:58 +05:30 committed by GitHub
commit 23c64c0b3a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 63 additions and 33 deletions

View File

@ -8,17 +8,18 @@ Provide a report and downloadable CSV according to the German DATEV format.
all required columns. Used to import the data into the DATEV Software. all required columns. Used to import the data into the DATEV Software.
""" """
from __future__ import unicode_literals from __future__ import unicode_literals
import datetime import datetime
import json import json
import zlib
import zipfile import zipfile
import six import six
import frappe
import pandas as pd
from frappe import _
from csv import QUOTE_NONNUMERIC from csv import QUOTE_NONNUMERIC
from six import BytesIO from six import BytesIO
from six import string_types from six import string_types
import frappe
from frappe import _
import pandas as pd
from .datev_constants import DataCategory from .datev_constants import DataCategory
from .datev_constants import Transactions from .datev_constants import Transactions
from .datev_constants import DebtorsCreditors from .datev_constants import DebtorsCreditors
@ -130,8 +131,10 @@ def get_customers(filters):
SELECT SELECT
acc.account_number as 'Konto', acc.account_number as 'Konto',
cus.customer_name as 'Name (Adressatentyp Unternehmen)', CASE cus.customer_type WHEN 'Company' THEN cus.customer_name ELSE null END as 'Name (Adressatentyp Unternehmen)',
case cus.customer_type when 'Individual' then 1 when 'Company' then 2 else 0 end as 'Adressatentyp', CASE cus.customer_type WHEN 'Individual' THEN con.last_name ELSE null END as 'Name (Adressatentyp natürl. Person)',
CASE cus.customer_type WHEN 'Individual' THEN con.first_name ELSE null END as 'Vorname (Adressatentyp natürl. Person)',
CASE cus.customer_type WHEN 'Individual' THEN '1' WHEN 'Company' THEN '2' ELSE '0' end as 'Adressatentyp',
adr.address_line1 as 'Straße', adr.address_line1 as 'Straße',
adr.pincode as 'Postleitzahl', adr.pincode as 'Postleitzahl',
adr.city as 'Ort', adr.city as 'Ort',
@ -140,8 +143,7 @@ def get_customers(filters):
con.email_id as 'E-Mail', con.email_id as 'E-Mail',
coalesce(con.mobile_no, con.phone) as 'Telefon', coalesce(con.mobile_no, con.phone) as 'Telefon',
cus.website as 'Internet', cus.website as 'Internet',
cus.tax_id as 'Steuernummer', cus.tax_id as 'Steuernummer'
ccl.credit_limit as 'Kreditlimit (Debitor)'
FROM `tabParty Account` par FROM `tabParty Account` par
@ -160,10 +162,6 @@ def get_customers(filters):
left join `tabContact` con left join `tabContact` con
on con.name = cus.customer_primary_contact on con.name = cus.customer_primary_contact
left join `tabCustomer Credit Limit` ccl
on ccl.parent = cus.name
and ccl.company = par.company
WHERE par.company = %(company)s WHERE par.company = %(company)s
AND par.parenttype = 'Customer'""", filters, as_dict=1) AND par.parenttype = 'Customer'""", filters, as_dict=1)
@ -179,8 +177,10 @@ def get_suppliers(filters):
SELECT SELECT
acc.account_number as 'Konto', acc.account_number as 'Konto',
sup.supplier_name as 'Name (Adressatentyp Unternehmen)', CASE sup.supplier_type WHEN 'Company' THEN sup.supplier_name ELSE null END as 'Name (Adressatentyp Unternehmen)',
case sup.supplier_type when 'Individual' then '1' when 'Company' then '2' else '0' end as 'Adressatentyp', CASE sup.supplier_type WHEN 'Individual' THEN con.last_name ELSE null END as 'Name (Adressatentyp natürl. Person)',
CASE sup.supplier_type WHEN 'Individual' THEN con.first_name ELSE null END as 'Vorname (Adressatentyp natürl. Person)',
CASE sup.supplier_type WHEN 'Individual' THEN '1' WHEN 'Company' THEN '2' ELSE '0' end as 'Adressatentyp',
adr.address_line1 as 'Straße', adr.address_line1 as 'Straße',
adr.pincode as 'Postleitzahl', adr.pincode as 'Postleitzahl',
adr.city as 'Ort', adr.city as 'Ort',
@ -226,9 +226,18 @@ def get_suppliers(filters):
def get_account_names(filters): def get_account_names(filters):
return frappe.get_list("Account", return frappe.db.sql("""
fields=["account_number as Konto", "name as Kontenbeschriftung"], SELECT
filters={"company": filters.get("company"), "is_group": "0"})
account_number as 'Konto',
LEFT(account_name, 40) as 'Kontenbeschriftung',
'de-DE' as 'Sprach-ID'
FROM `tabAccount`
WHERE company = %(company)s
AND is_group = 0
AND account_number != ''
""", filters, as_dict=1)
def get_datev_csv(data, filters, csv_class): def get_datev_csv(data, filters, csv_class):
@ -287,9 +296,7 @@ def get_datev_csv(data, filters, csv_class):
def get_header(filters, csv_class): def get_header(filters, csv_class):
coa = frappe.get_value("Company", filters.get("company"), "chart_of_accounts") description = filters.get('voucher_type', csv_class.FORMAT_NAME)
description = filters.get("voucher_type", csv_class.FORMAT_NAME)
coa_used = "04" if "SKR04" in coa else ("03" if "SKR03" in coa else "")
header = [ header = [
# DATEV format # DATEV format
@ -316,19 +323,19 @@ def get_header(filters, csv_class):
# J = Imported by -- stays empty # J = Imported by -- stays empty
'', '',
# K = Tax consultant number (Beraternummer) # K = Tax consultant number (Beraternummer)
frappe.get_value("DATEV Settings", filters.get("company"), "consultant_number"), filters.get('consultant_number', '0000000'),
# L = Tax client number (Mandantennummer) # L = Tax client number (Mandantennummer)
frappe.get_value("DATEV Settings", filters.get("company"), "client_number"), filters.get('client_number', '00000'),
# M = Start of the fiscal year (Wirtschaftsjahresbeginn) # M = Start of the fiscal year (Wirtschaftsjahresbeginn)
frappe.utils.formatdate(frappe.defaults.get_user_default("year_start_date"), "yyyyMMdd"), frappe.utils.formatdate(frappe.defaults.get_user_default("year_start_date"), "yyyyMMdd"),
# N = Length of account numbers (Sachkontenlänge) # N = Length of account numbers (Sachkontenlänge)
'4', '%d' % filters.get('acc_len', 4),
# O = Transaction batch start date (YYYYMMDD) # O = Transaction batch start date (YYYYMMDD)
frappe.utils.formatdate(filters.get('from_date'), "yyyyMMdd"), frappe.utils.formatdate(filters.get('from_date'), "yyyyMMdd") if csv_class.DATA_CATEGORY == DataCategory.TRANSACTIONS else '',
# P = Transaction batch end date (YYYYMMDD) # P = Transaction batch end date (YYYYMMDD)
frappe.utils.formatdate(filters.get('to_date'), "yyyyMMdd"), frappe.utils.formatdate(filters.get('to_date'), "yyyyMMdd") if csv_class.DATA_CATEGORY == DataCategory.TRANSACTIONS else '',
# Q = Description (for example, "Sales Invoice") Max. 30 chars # Q = Description (for example, "Sales Invoice") Max. 30 chars
'"{}"'.format(_(description)), '"{}"'.format(_(description)) if csv_class.DATA_CATEGORY == DataCategory.TRANSACTIONS else '',
# R = Diktatkürzel # R = Diktatkürzel
'', '',
# S = Buchungstyp # S = Buchungstyp
@ -343,12 +350,12 @@ def get_header(filters, csv_class):
# 40 = Kalkulatorik # 40 = Kalkulatorik
# 11 = Reserviert # 11 = Reserviert
# 12 = Reserviert # 12 = Reserviert
'0', '0' if csv_class.DATA_CATEGORY == DataCategory.TRANSACTIONS else '',
# U = Festschreibung # U = Festschreibung
# TODO: Filter by Accounting Period. In export for closed Accounting Period, this will be "1" # TODO: Filter by Accounting Period. In export for closed Accounting Period, this will be "1"
'0', '0',
# V = Default currency, for example, "EUR" # V = Default currency, for example, "EUR"
'"%s"' % frappe.get_value("Company", filters.get("company"), "default_currency"), '"%s"' % filters.get('default_currency', 'EUR') if csv_class.DATA_CATEGORY == DataCategory.TRANSACTIONS else '',
# reserviert # reserviert
'', '',
# Derivatskennzeichen # Derivatskennzeichen
@ -358,7 +365,7 @@ def get_header(filters, csv_class):
# reserviert # reserviert
'', '',
# SKR # SKR
'"%s"' % coa_used, '"%s"' % filters.get('skr', '04'),
# Branchen-Lösungs-ID # Branchen-Lösungs-ID
'', '',
# reserviert # reserviert
@ -389,6 +396,18 @@ def download_datev_csv(filters=None):
validate(filters) validate(filters)
# set chart of accounts used
coa = frappe.get_value('Company', filters.get('company'), 'chart_of_accounts')
filters['skr'] = '04' if 'SKR04' in coa else ('03' if 'SKR03' in coa else '')
# set account number length
account_numbers = frappe.get_list('Account', fields=['account_number'], filters={'is_group': 0, 'account_number': ('!=', '')})
filters['acc_len'] = max([len(a.account_number) for a in account_numbers])
filters['consultant_number'] = frappe.get_value('DATEV Settings', filters.get('company'), 'consultant_number')
filters['client_number'] = frappe.get_value('DATEV Settings', filters.get('company'), 'client_number')
filters['default_currency'] = frappe.get_value('Company', filters.get('company'), 'default_currency')
# This is where my zip will be written # This is where my zip will be written
zip_buffer = BytesIO() zip_buffer = BytesIO()
# This is my zip file # This is my zip file

View File

@ -465,60 +465,71 @@ QUERY_REPORT_COLUMNS = [
"label": "Umsatz (ohne Soll/Haben-Kz)", "label": "Umsatz (ohne Soll/Haben-Kz)",
"fieldname": "Umsatz (ohne Soll/Haben-Kz)", "fieldname": "Umsatz (ohne Soll/Haben-Kz)",
"fieldtype": "Currency", "fieldtype": "Currency",
"width": 100
}, },
{ {
"label": "Soll/Haben-Kennzeichen", "label": "Soll/Haben-Kennzeichen",
"fieldname": "Soll/Haben-Kennzeichen", "fieldname": "Soll/Haben-Kennzeichen",
"fieldtype": "Data", "fieldtype": "Data",
"width": 100
}, },
{ {
"label": "Konto", "label": "Konto",
"fieldname": "Konto", "fieldname": "Konto",
"fieldtype": "Data", "fieldtype": "Data",
"width": 100
}, },
{ {
"label": "Gegenkonto (ohne BU-Schlüssel)", "label": "Gegenkonto (ohne BU-Schlüssel)",
"fieldname": "Gegenkonto (ohne BU-Schlüssel)", "fieldname": "Gegenkonto (ohne BU-Schlüssel)",
"fieldtype": "Data", "fieldtype": "Data",
"width": 100
}, },
{ {
"label": "Belegdatum", "label": "Belegdatum",
"fieldname": "Belegdatum", "fieldname": "Belegdatum",
"fieldtype": "Date", "fieldtype": "Date",
"width": 100
}, },
{ {
"label": "Belegfeld 1", "label": "Belegfeld 1",
"fieldname": "Belegfeld 1", "fieldname": "Belegfeld 1",
"fieldtype": "Data", "fieldtype": "Data",
"width": 150
}, },
{ {
"label": "Buchungstext", "label": "Buchungstext",
"fieldname": "Buchungstext", "fieldname": "Buchungstext",
"fieldtype": "Text", "fieldtype": "Text",
"width": 300
}, },
{ {
"label": "Beleginfo - Art 1", "label": "Beleginfo - Art 1",
"fieldname": "Beleginfo - Art 1", "fieldname": "Beleginfo - Art 1",
"fieldtype": "Link", "fieldtype": "Link",
"options": "DocType" "options": "DocType",
"width": 100
}, },
{ {
"label": "Beleginfo - Inhalt 1", "label": "Beleginfo - Inhalt 1",
"fieldname": "Beleginfo - Inhalt 1", "fieldname": "Beleginfo - Inhalt 1",
"fieldtype": "Dynamic Link", "fieldtype": "Dynamic Link",
"options": "Beleginfo - Art 1" "options": "Beleginfo - Art 1",
"width": 150
}, },
{ {
"label": "Beleginfo - Art 2", "label": "Beleginfo - Art 2",
"fieldname": "Beleginfo - Art 2", "fieldname": "Beleginfo - Art 2",
"fieldtype": "Link", "fieldtype": "Link",
"options": "DocType" "options": "DocType",
"width": 100
}, },
{ {
"label": "Beleginfo - Inhalt 2", "label": "Beleginfo - Inhalt 2",
"fieldname": "Beleginfo - Inhalt 2", "fieldname": "Beleginfo - Inhalt 2",
"fieldtype": "Dynamic Link", "fieldtype": "Dynamic Link",
"options": "Beleginfo - Art 2" "options": "Beleginfo - Art 2",
"width": 150
} }
] ]