Skip to content

Commit

Permalink
Merge pull request #6 from f1shl/pyinstaller_build
Browse files Browse the repository at this point in the history
Added more robust handling of the PDF file from DPSG.
  • Loading branch information
f1shl authored Jan 30, 2024
2 parents 766c965 + 894a8a5 commit 790dce4
Show file tree
Hide file tree
Showing 9 changed files with 121 additions and 108 deletions.
92 changes: 4 additions & 88 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,19 +1,12 @@
# Created by .ignore support plugin (hsz.mobi)
# Project specific files
config.ini
invoices/
*.pdf
*.xml
*.csv

### Python template
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Python
__pycache__
# Distribution / packaging
.Python
env/
Expand All @@ -36,7 +29,6 @@ var/
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
Expand All @@ -53,48 +45,19 @@ coverage.xml
*,cover
.hypothesis/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
target/

# IPython Notebook
.ipynb_checkpoints

# pyenv
.python-version

# celery beat schedule file
celerybeat-schedule

# dotenv
.env

# virtualenv
venv/
ENV/

# Spyder project settings
.spyderproject

# Rope project settings
.ropeproject
### VirtualEnv template
# Virtualenv
# http://iamzed.com/2009/05/07/a-primer-on-virtualenv/
Expand All @@ -107,51 +70,4 @@ ENV/
[Ss]cripts
pyvenv.cfg
.venv
pip-selfcheck.json
### JetBrains template
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839

# User-specific stuff:
.idea/workspace.xml
.idea/tasks.xml
.idea/dictionaries
.idea/vcs.xml
.idea/jsLibraryMappings.xml

# Sensitive or high-churn files:
.idea/dataSources.ids
.idea/dataSources.xml
.idea/dataSources.local.xml
.idea/sqlDataSources.xml
.idea/dynamic.xml
.idea/uiDesigner.xml

# Gradle:
.idea/gradle.xml
.idea/libraries

# Mongo Explorer plugin:
.idea/mongoSettings.xml

.idea/

## File-based project format:
*.iws

## Plugin-specific files:

# IntelliJ
/out/

# mpeltonen/sbt-idea plugin
.idea_modules/

# JIRA plugin
atlassian-ide-plugin.xml

# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
.idea/
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "pynami"]
path = pynami
url = https://github.com/sscholz93/pynami.git
23 changes: 12 additions & 11 deletions accounting.py
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ def process(self):
# e.g. Removes first half year entries if second half year shall be booked
dpsg_members = self.download_invoices()
nof_dpsg_members = dpsg_members.get_nof_unique_members()

booking_value_dpsg = dpsg_members.get_value_booked_by_dpsg()
print('Herunterladen aller aktiven Mitglieder aus der Nami...')
result = self._nami.get_active_members()
result_schnupper = self._nami.get_schnupper_members()
Expand Down Expand Up @@ -243,14 +243,15 @@ def process(self):
print("")
tools.print_info('Verarbeitete Mandate: ' + str(overall))
tools.print_info('Benutzte Mandate: ' + str(used) + '/' + str(overall))
tools.print_info('Gesamtsumme: ' + str(booking_value) + ' EUR')
tools.print_info(f'Buchungssumme DPSG: {booking_value_dpsg: .2f} €')
tools.print_info(f'Buchungssumme Stamm: {booking_value: .2f} €')
print("")
if not_used == 0:
tools.print_info('Alle SEPA-Mandate wurden erfolgreich verwendet.')
else:
tools.print_error(
'Nicht alle SEPA-Mandate wurden verwendet. Nochmal die Mandate überprüfen und ggf. bereinigen.')
tools.print_info('-------------------------------------------------------------------------------')
tools.print_info('------------------------------------------------------------------------')
print("")

self.print_member_entry_this_year_as_schnupper(list_of_members_active_schnupper)
Expand All @@ -269,7 +270,7 @@ def print_missing_mandate_members(self, members):
for m in members:
combinedName = m.vorname + ' ' + m.nachname
tools.print_error('Mitgliedsnummer: ' + str(m.mitgliedsNummer) + ' Name: ' + combinedName)
tools.print_error('-----------------------------------------------------------------------------')
tools.print_error('------------------------------------------------------------------------')
if len(members) != 0:
tools.print_error('Bitte die fehlenden Mandate in VR Networld für die Mitglieder anlegen.')
print("")
Expand All @@ -279,19 +280,19 @@ def print_not_used_mandate(self, mandate: VRMandat):
for m in mandate:
combinedName = m.vorname + ' ' + m.nachname
tools.print_error('Mandatsreferenz: ' + m.mandatsreferenz + ' Name: ' + combinedName)
tools.print_error('-------------------------------------------------------------------------------')
tools.print_error('------------------------------------------------------------------------')
if len(mandate) != 0:
tools.print_error('Bitte nochmal die DPSG Nami und VR-Networld überprüfen und die nicht verwendenten Mandate entfernen.')
print("")

def print_member_entry_this_year_as_schnupper(self, members):
tools.print_info('-------------- Aktive Schnuppermitglieder Jahr --------------')
tools.print_info('-------------------- Aktive Schnuppermitglieder Jahr -------------------')
for m in members:
combinedName = m.vorname + ' ' + m.nachname
tools.print_info('Initiales Eintrittsdatum: ' + datetime.datetime.strftime(m.eintrittsdatum, self._config.get_datetime_format()) +
' Abrechenbares Eintrittsdatum: ' + datetime.datetime.strftime(m.correct_eintrittsdatum, self._config.get_datetime_format()) +
' Mitglied ' + combinedName)
tools.print_info('-------------------------------------------------------------')
tools.print_info('------------------------------------------------------------------------')
print("")

def print_member_entry_second_half(self, members):
Expand All @@ -301,7 +302,7 @@ def print_member_entry_second_half(self, members):
tools.print_info('Initiales Eintrittsdatum: ' + datetime.datetime.strftime(m.eintrittsdatum, self._config.get_datetime_format()) +
' Abrechenbares Eintrittsdatum: ' + datetime.datetime.strftime(m.correct_eintrittsdatum, self._config.get_datetime_format()) +
' Mitglied ' + combinedName)
tools.print_info('-----------------------------------------------------------------------------------------')
tools.print_info('------------------------------------------------------------------------')
print("")


Expand All @@ -312,7 +313,7 @@ def print_member_entry_new_year(self, members):
tools.print_info('Initiales Eintrittsdatum: ' + datetime.datetime.strftime(m.eintrittsdatum, self._config.get_datetime_format()) +
' Abrechenbares Eintrittsdatum: ' + datetime.datetime.strftime(m.correct_eintrittsdatum, self._config.get_datetime_format()) +
' Mitglied ' + combinedName)
tools.print_info('------------------------------------------------------------------------------')
tools.print_info('------------------------------------------------------------------------')
print("")

def print_member_booked_by_dpsg_but_not_here(self, members):
Expand All @@ -322,7 +323,7 @@ def print_member_booked_by_dpsg_but_not_here(self, members):
tools.print_info('Rechnungsdatum: ' + datetime.datetime.strftime(m.datumVon, self._config.get_datetime_format()) +
' - ' + datetime.datetime.strftime(m.datumBis, self._config.get_datetime_format()) +
' Mitglied ' + combinedName)
tools.print_info('------------------------------------------------------------------------------------')
tools.print_info('------------------------------------------------------------------------')
print("")

def print_member_not_booked_by_dpsg(self, members):
Expand All @@ -332,7 +333,7 @@ def print_member_not_booked_by_dpsg(self, members):
tools.print_info('Initiales Eintrittsdatum: ' + datetime.datetime.strftime(m.eintrittsdatum, self._config.get_datetime_format()) +
' Abrechenbares Eintrittsdatum: ' + datetime.datetime.strftime(m.correct_eintrittsdatum, self._config.get_datetime_format()) +
' Mitglied ' + combinedName)
tools.print_info('------------------------------------------------------------------------------------')
tools.print_info('------------------------------------------------------------------------')
print("")

def download_invoices(self) -> PdfMemberList:
Expand Down
6 changes: 5 additions & 1 deletion build_executable_mac.sh
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
pyinstaller --clean --onefile --windowed --name "Nami Beitragsrechner" --osx-bundle-identifier "com.nami-beitragsrechner" --icon="img/favicon.ico" --collect-data sv_ttk --collect-data pycountry --copy-metadata schwifty --hidden-import babel.numbers --add-data="venv/lib/python3.10/site-packages/schwifty/bank_registry/:bank_registry" --add-data="venv/lib/python3.10/site-packages/schwifty/iban_registry/:iban_registry" --add-data="img/dpsg_logo.png:img" --add-data="img/favicon.ico:img" main.py

bash init_venv.sh
source .venv/bin/activate
pyinstaller main.spec
deactivate
11 changes: 11 additions & 0 deletions init_venv.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@

echo "Creating venv"
python3 -m venv .venv
source .venv/bin/activate
pip install --upgrade pip
echo "Installing python packages from requirements.txt"
pip install -r requirements.txt
deactivate

echo "Successfully created venv for nami-beitragsrechner"

65 changes: 65 additions & 0 deletions main.spec
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# -*- mode: python ; coding: utf-8 -*-
from PyInstaller.utils.hooks import collect_data_files
from PyInstaller.utils.hooks import copy_metadata
import platform

python_version = platform.python_version()
last_dot = python_version.rfind('.')
python_version = python_version[0:last_dot]
datas = [('img/dpsg_logo.png', 'img'), ('img/favicon.ico', 'img')]
datas.append((f'.venv/lib/python{python_version}/site-packages/schwifty/bank_registry/', 'bank_registry'))
datas.append((f'.venv/lib/python{python_version}/site-packages/schwifty/iban_registry/', 'iban_registry'))
datas += collect_data_files('sv_ttk')
datas += collect_data_files('pycountry')
datas += collect_data_files('schwifty')
datas += copy_metadata('schwifty')


block_cipher = None


a = Analysis(
['main.py'],
pathex=[],
binaries=[],
datas=datas,
hiddenimports=['babel.numbers'],
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False,
)
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)

exe = EXE(
pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
[],
name='Nami Beitragsrechner',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=False,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
icon=['img/favicon.ico'],
)
app = BUNDLE(
exe,
name='Nami Beitragsrechner.app',
icon='img/favicon.ico',
bundle_identifier='com.nami-beitragsrechner',
)
22 changes: 17 additions & 5 deletions pdf_converter.py
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,13 @@ def get_nof_unique_members(self):

return len(unqiue_members)

def get_value_booked_by_dpsg(self) -> float:
overall_value = 0
for m in self:
overall_value += m.beitrag

return overall_value


class PdfConverter:

Expand All @@ -59,15 +66,20 @@ def convert(pdfpath) -> list:
for p in range(1, len(pdf.pages)):
page = pdf.pages[p]
lines = list(filter(None, page.extract_text(layout=True).splitlines()))
# Search for header line
i = 0
while 'Mitgliedsnr. Name' not in lines[i]:
i = i+1
lines = lines[i+1:-1]
# Strip leading and trailing spaces
lines = list(map(str.strip, lines))
# Remove empty lines
lines = list(filter(None, lines))
# Remove all lines which are not a member line
lines = [x for x in lines if 'Einzelnachweise:' not in x]
lines = [x for x in lines if 'Mitgliedsnr. Name' not in x]
lines = [x for x in lines if 'Rechnungsnr.:' not in x]
overall_lines.extend(lines)

for line in overall_lines:
line = line.strip()
if line == '':
continue
# Extract mglNo
pos = line.find(' ')
mglNo = int(line[:pos])
Expand Down
1 change: 1 addition & 0 deletions pynami
Submodule pynami added at 2c7116
6 changes: 3 additions & 3 deletions requirements.txt
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ future
Pygments
docutils
cffi
PySide6
Pillow
pip
toml
Expand All @@ -18,5 +17,6 @@ Wand
chardet
pycparser
setuptools
pynami
sepaxml
./pynami
sepaxml
pyinstaller

0 comments on commit 790dce4

Please sign in to comment.