123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128 |
- import pandas as pd
- import numpy as np
- import xml.etree.ElementTree as ET
- from xml.dom import minidom
- from datetime import datetime
- base_dir = '/home/robert/projekte/python/gcstruct/'
- account_translation = base_dir + 'Kontenrahmen_kombiniert.csv'
- account_bookings = base_dir + 'GuV_Salden.csv'
- first_month_of_financial_year = '01'
- current_year = '2021'
- current_month = '04'
- account_ignored = base_dir + 'Buchungen_ignoriert.csv'
- last_year = str(int(current_year) - 1)
- next_year = str(int(current_year) + 1)
- def header(makes, sites):
- return {
- 'Country': 'DE',
- 'MainBmCode': sites[0]['Marke_HBV'],
- 'Month': current_month,
- 'Year': current_year,
- 'Currency': 'EUR',
- 'NumberOfMakes': len(makes),
- 'NumberOfSites': len(sites),
- 'ExtractionDate': datetime.now().strftime('%d.%m.%Y'),
- 'ExtractionTime': datetime.now().strftime('%H:%M:%S'),
- 'BeginFiscalYear': first_month_of_financial_year
- }
- def bookkeep_filter():
- period = [current_year + str(i).zfill(2) for i in range(1, 13)]
- if first_month_of_financial_year != '01':
- if first_month_of_financial_year > current_month:
- period = [last_year + str(i).zfill(2) for i in range(1, 13)] + period
- else:
- period = period + [next_year + str(i).zfill(2) for i in range(1, 13)]
- fm = int(first_month_of_financial_year)
- period = period[fm - 1:fm + 12]
- rename_to = ['Period' + str(i).zfill(2) for i in range(1, 13)]
- return dict(zip(period, rename_to))
- def main():
- # Übersetzungstabelle laden
- df_translate = pd.read_csv(account_translation, decimal=',', sep=';', encoding='latin-1', converters={i: str for i in range(0, 200)})
- # Kontensalden laden
- df_bookings = pd.read_csv(account_bookings, decimal=',', sep=';', encoding='latin-1', converters={0: str, 1: str})
- # Kontensalden auf gegebenen Monat filtern
- filter_from = current_year + first_month_of_financial_year
- if first_month_of_financial_year > current_month:
- filter_from = last_year + first_month_of_financial_year
- filter_to = current_year + current_month
- df_bookings = df_bookings[(df_bookings['Bookkeep Period'] >= filter_from) & (df_bookings['Bookkeep Period'] <= filter_to)]
- bk_filter = bookkeep_filter()
- # Spalten konvertieren
- df_bookings['period'] = df_bookings['Bookkeep Period'].apply(lambda x: bk_filter[x])
- df_bookings['amount'] = df_bookings['Debit Amount'] + df_bookings['Credit Amount']
- df_bookings['quantity'] = df_bookings['Debit Quantity'] + df_bookings['Credit Quantity']
- # Join auf Übersetzung
- df_combined = df_bookings.merge(df_translate, how='inner', on='Konto_Nr_Händler')
- # Gruppieren
- # df_grouped = df_combined.groupby(['Konto_Nr_SKR51', 'period']).sum()
- df_pivot = df_combined.pivot_table(index=['Konto_Nr_SKR51'], columns=['period'], values='amount',
- aggfunc=np.sum, margins=True, margins_name='CumulatedYear')
- # Infos ergänzen
- df_pivot['Decimals'] = 2
- df_pivot['OpeningBalance'] = 0.0
- df = df_translate.drop(columns=['Konto_Nr_Händler', 'Kostenträger_Ebene']).drop_duplicates()
- df = df.merge(df_pivot, how='inner', on='Konto_Nr_SKR51')
- from_label = ['Marke', 'Standort', 'Konto_Nr', 'Kostenstelle', 'Absatzkanal', 'Kostenträger']
- to_label = ['Make', 'Site', 'Account', 'Origin', 'SalesChannel', 'CostCarrier']
- df = df.rename(columns=dict(zip(from_label, to_label)))
- df['CostAccountingString'] = df['Make'] + df['Site'] + df['Origin'] + \
- df['SalesChannel'] + df['CostCarrier']
- makes = df[['Make', 'Marke_HBV']].drop_duplicates().sort_values(by=['Make']).to_dict(orient='records')
- sites = df[['Make', 'Site', 'Marke_HBV']].drop_duplicates().sort_values(by=['Make', 'Site']).to_dict(orient='records')
- # Join auf Übersetzung - nicht zugeordnet
- df_ignored = df_bookings.merge(df_translate, how='left', on='Konto_Nr_Händler')
- df_ignored = df_ignored[df_ignored['Konto_Nr_SKR51'].isna()] # [['Konto_Nr_Händler', 'Bookkeep Period', 'amount', 'quantity']]
- if not df_ignored.empty:
- df_ignored = df_ignored.pivot_table(index=['Konto_Nr_Händler'], columns=['period'], values='amount',
- aggfunc=np.sum, margins=True, margins_name='CumulatedYear')
- df_ignored.to_csv(account_ignored, decimal=',', sep=';', encoding='latin-1')
- # als xml exportieren
- res = df.to_dict(orient='records')
- record_elements = ['Account', 'Make', 'Site', 'Origin', 'SalesChannel', 'CostCarrier', 'CostAccountingString',
- 'Decimals', 'OpeningBalance'] + list(bk_filter.values()) + ['CumulatedYear']
- root = ET.Element('HbvData')
- h = ET.SubElement(root, 'Header')
- for k, v in header(makes, sites).items():
- ET.SubElement(h, k).text = str(v)
- make_list = ET.SubElement(root, 'MakeList')
- for m in makes:
- e = ET.SubElement(make_list, 'MakeListEntry')
- ET.SubElement(e, 'Make').text = m['Make']
- ET.SubElement(e, 'MakeCode').text = m['Marke_HBV']
- bm_code_list = ET.SubElement(root, 'BmCodeList')
- for s in sites:
- e = ET.SubElement(bm_code_list, 'BmCodeListEntry')
- ET.SubElement(e, 'Make').text = s['Make']
- ET.SubElement(e, 'Site').text = s['Site']
- ET.SubElement(e, 'BmCode').text = s['Marke_HBV']
- record_list = ET.SubElement(root, 'RecordList')
- for row in res:
- record = ET.SubElement(record_list, 'Record')
- for e in record_elements:
- child = ET.SubElement(record, e)
- field = row.get(e, 0.0)
- if type(field) is float:
- field = '{:.0f}'.format(field * 100)
- child.text = str(field)
- with open(base_dir + 'export_2021-04.xml', 'w', encoding='utf-8') as f:
- f.write(minidom.parseString(ET.tostring(root)).toprettyxml(indent=' '))
- if __name__ == '__main__':
- print(bookkeep_filter())
- main()
|