-
Notifications
You must be signed in to change notification settings - Fork 22
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Read purchase information from BioOffice and show monthly basket stat…
…istics.
- Loading branch information
1 parent
8e941a9
commit 7553e80
Showing
19 changed files
with
657 additions
and
26 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,12 @@ | ||
import csv | ||
import os | ||
|
||
import environ | ||
from django.core.management import BaseCommand | ||
|
||
from tapir import settings | ||
from tapir.accounts.models import TapirUser | ||
from tapir.settings import GROUP_VORSTAND | ||
from tapir.utils.shortcuts import setup_ssh_for_biooffice_storage | ||
from tapir.utils.user_utils import UserUtils | ||
|
||
|
||
|
@@ -59,20 +59,7 @@ def send_file_to_server(cls): | |
) | ||
return | ||
|
||
env = environ.Env() | ||
|
||
os.system("mkdir -p ~/.ssh") | ||
os.system( | ||
f'bash -c \'echo -e "{env("TAPIR_SSH_KEY_PRIVATE")}" > ~/.ssh/biooffice_id_rsa\'' | ||
) | ||
os.system("chmod u=rw,g=,o= ~/.ssh/biooffice_id_rsa") | ||
os.system( | ||
f'bash -c \'echo -e "{env("TAPIR_SSH_KEY_PUBLIC")}" > ~/.ssh/biooffice_id_rsa.pub\'' | ||
) | ||
os.system("chmod u=rw,g=r,o=r ~/.ssh/biooffice_id_rsa.pub") | ||
os.system( | ||
f'bash -c \'echo -e "{env("BIOOFFICE_SERVER_SSH_KEY_FINGERPRINT")}" > ~/.ssh/biooffice_known_hosts\'' | ||
) | ||
setup_ssh_for_biooffice_storage() | ||
os.system( | ||
f"scp -o 'NumberOfPasswordPrompts=0' -o 'UserKnownHostsFile=~/.ssh/biooffice_known_hosts' -i ~/.ssh/biooffice_id_rsa -P 23 {cls.FILE_NAME} [email protected]:./" | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
Empty file.
77 changes: 77 additions & 0 deletions
77
tapir/statistics/management/commands/process_purchase_files.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
import csv | ||
import datetime | ||
import fnmatch | ||
import io | ||
from typing import Dict | ||
|
||
import environ | ||
import paramiko | ||
from django.core.management.base import BaseCommand | ||
from django.db import transaction | ||
from django.utils import timezone | ||
from fabric import Connection | ||
from paramiko.sftp_file import SFTPFile | ||
|
||
from tapir.accounts.models import TapirUser | ||
from tapir.statistics.models import ProcessedPurchaseFiles, PurchaseBasket | ||
from tapir.utils.shortcuts import get_timezone_aware_datetime | ||
|
||
|
||
class Command(BaseCommand): | ||
help = "If a new cycle has started, remove one shift point from all active members." | ||
|
||
def handle(self, *args, **options): | ||
env = environ.Env() | ||
private_key = paramiko.RSAKey.from_private_key( | ||
io.StringIO(env("TAPIR_SSH_KEY_PRIVATE")) | ||
) | ||
connection = Connection( | ||
host="u326634-sub6.your-storagebox.de", | ||
user="u326634-sub6", | ||
connect_kwargs={"pkey": private_key}, | ||
) | ||
sftp_client = connection.sftp() | ||
ProcessedPurchaseFiles.objects.all().delete() | ||
for file_name in fnmatch.filter( | ||
sftp_client.listdir(), "Statistics_Members_*.csv" | ||
): | ||
if ProcessedPurchaseFiles.objects.filter(file_name=file_name).exists(): | ||
continue | ||
self.process_file(sftp_client.open(file_name), file_name) | ||
|
||
@classmethod | ||
@transaction.atomic | ||
def process_file(cls, file: SFTPFile, file_name: str): | ||
source_file = ProcessedPurchaseFiles.objects.create( | ||
file_name=file_name[: ProcessedPurchaseFiles.MAX_FILE_NAME_LENGTH], | ||
processed_on=timezone.now(), | ||
) | ||
for row in csv.DictReader(file, delimiter=",", quotechar='"'): | ||
row: Dict | ||
purchase_date = get_timezone_aware_datetime( | ||
date=datetime.datetime.strptime( | ||
row['\ufeff"Datum"'], "%Y-%m-%d" | ||
).date(), | ||
time=datetime.datetime.strptime(row["Zeit"], "%H:%M:%S").time(), | ||
) | ||
|
||
tapir_user = ( | ||
TapirUser.objects.filter(id=int(row["Kunde"][3:])).first() | ||
if row["Kunde"].isnumeric() and len(row["Kunde"]) > 3 | ||
else None | ||
) | ||
PurchaseBasket.objects.create( | ||
source_file=source_file, | ||
purchase_date=purchase_date, | ||
cashier=row["cKasse"], | ||
purchase_counter=row["Bon"], | ||
tapir_user=tapir_user, | ||
gross_amount=cls.parse_german_number(row["VKBrutto_SUM"]), | ||
first_net_amount=cls.parse_german_number(row["VKNetto_SUM"]), | ||
second_net_amount=cls.parse_german_number(row["EKNetto_SUM"]), | ||
discount=cls.parse_german_number(row["Rabatt_SUM"]), | ||
) | ||
|
||
@staticmethod | ||
def parse_german_number(string: str) -> float: | ||
return float(string.replace(",", ".")) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
# Generated by Django 3.2.21 on 2023-10-20 13:41 | ||
|
||
import django.db.models.deletion | ||
from django.conf import settings | ||
from django.db import migrations, models | ||
|
||
|
||
class Migration(migrations.Migration): | ||
initial = True | ||
|
||
dependencies = [ | ||
migrations.swappable_dependency(settings.AUTH_USER_MODEL), | ||
] | ||
|
||
operations = [ | ||
migrations.CreateModel( | ||
name="ProcessedPurchaseFiles", | ||
fields=[ | ||
( | ||
"id", | ||
models.BigAutoField( | ||
auto_created=True, | ||
primary_key=True, | ||
serialize=False, | ||
verbose_name="ID", | ||
), | ||
), | ||
("file_name", models.CharField(max_length=255)), | ||
("processed_on", models.DateTimeField()), | ||
], | ||
), | ||
migrations.CreateModel( | ||
name="PurchaseBasket", | ||
fields=[ | ||
( | ||
"id", | ||
models.BigAutoField( | ||
auto_created=True, | ||
primary_key=True, | ||
serialize=False, | ||
verbose_name="ID", | ||
), | ||
), | ||
("purchase_date", models.DateTimeField()), | ||
("cashier", models.IntegerField()), | ||
("purchase_counter", models.IntegerField()), | ||
("gross_amount", models.FloatField()), | ||
("first_net_amount", models.FloatField()), | ||
("second_net_amount", models.FloatField()), | ||
("discount", models.FloatField()), | ||
( | ||
"source_file", | ||
models.ForeignKey( | ||
on_delete=django.db.models.deletion.CASCADE, | ||
to="statistics.processedpurchasefiles", | ||
), | ||
), | ||
( | ||
"tapir_user", | ||
models.ForeignKey( | ||
on_delete=django.db.models.deletion.CASCADE, | ||
to=settings.AUTH_USER_MODEL, | ||
), | ||
), | ||
], | ||
), | ||
] |
24 changes: 24 additions & 0 deletions
24
tapir/statistics/migrations/0002_alter_purchasebasket_tapir_user.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
# Generated by Django 3.2.21 on 2023-10-20 16:09 | ||
|
||
import django.db.models.deletion | ||
from django.conf import settings | ||
from django.db import migrations, models | ||
|
||
|
||
class Migration(migrations.Migration): | ||
dependencies = [ | ||
migrations.swappable_dependency(settings.AUTH_USER_MODEL), | ||
("statistics", "0001_initial"), | ||
] | ||
|
||
operations = [ | ||
migrations.AlterField( | ||
model_name="purchasebasket", | ||
name="tapir_user", | ||
field=models.ForeignKey( | ||
null=True, | ||
on_delete=django.db.models.deletion.CASCADE, | ||
to=settings.AUTH_USER_MODEL, | ||
), | ||
), | ||
] |
24 changes: 24 additions & 0 deletions
24
tapir/statistics/migrations/0003_alter_purchasebasket_tapir_user.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
# Generated by Django 3.2.21 on 2023-10-20 16:24 | ||
|
||
import django.db.models.deletion | ||
from django.conf import settings | ||
from django.db import migrations, models | ||
|
||
|
||
class Migration(migrations.Migration): | ||
dependencies = [ | ||
migrations.swappable_dependency(settings.AUTH_USER_MODEL), | ||
("statistics", "0002_alter_purchasebasket_tapir_user"), | ||
] | ||
|
||
operations = [ | ||
migrations.AlterField( | ||
model_name="purchasebasket", | ||
name="tapir_user", | ||
field=models.ForeignKey( | ||
null=True, | ||
on_delete=django.db.models.deletion.SET_NULL, | ||
to=settings.AUTH_USER_MODEL, | ||
), | ||
), | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,25 @@ | ||
# Create your models here. | ||
from django.db import models | ||
|
||
from tapir.accounts.models import TapirUser | ||
|
||
|
||
class ProcessedPurchaseFiles(models.Model): | ||
MAX_FILE_NAME_LENGTH = 255 | ||
|
||
file_name = models.CharField(max_length=255) | ||
processed_on = models.DateTimeField() | ||
|
||
|
||
class PurchaseBasket(models.Model): | ||
source_file = models.ForeignKey(ProcessedPurchaseFiles, on_delete=models.CASCADE) | ||
purchase_date = models.DateTimeField() # Datum & Zeit | ||
cashier = models.IntegerField() # cKasse (column names from the CSV source file) | ||
purchase_counter = models.IntegerField() # Bon | ||
tapir_user = models.ForeignKey( | ||
TapirUser, on_delete=models.SET_NULL, null=True | ||
) # Kunde | ||
gross_amount = models.FloatField() # VKBrutto_SUM | ||
first_net_amount = models.FloatField() # VKNetto_SUM | ||
second_net_amount = models.FloatField() # EKNetto_SUM | ||
discount = models.FloatField() # Rabatt_SUM |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
from celery import shared_task | ||
from django.core.management import call_command | ||
|
||
|
||
@shared_task | ||
def process_purchase_files(): | ||
call_command("process_purchase_files") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
34 changes: 34 additions & 0 deletions
34
tapir/statistics/templates/statistics/tags/purchase_statistics_card.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
{% load i18n %} | ||
{% load shifts %} | ||
{% load core %} | ||
|
||
<div class="card mb-2"> | ||
<h5 class="card-header d-flex justify-content-between align-items-center"> | ||
{% translate "Purchases" %} | ||
</h5> | ||
<ul class="list-group list-group-flush"> | ||
<li class="list-group-item"> | ||
{% blocktranslate with average=average_basket_per_month %} | ||
Your average basket per month is {{ average }}€. | ||
{% endblocktranslate %} | ||
</li> | ||
<li class="list-group-item"> | ||
<table class="{% tapir_table_classes %}" aria-label="{% translate 'List of the last purchases' %}"> | ||
<thead> | ||
<tr> | ||
<th>{% translate 'Date' %}</th> | ||
<th>{% translate 'Gross amount' %}</th> | ||
</tr> | ||
</thead> | ||
<tbody> | ||
{% for purchase in last_purchases %} | ||
<tr> | ||
<td>{{ purchase.purchase_date|date:"d.m.Y H:i" }}</td> | ||
<td>{{ purchase.gross_amount }}€</td> | ||
</tr> | ||
{% endfor %} | ||
</tbody> | ||
</table> | ||
</li> | ||
</ul> | ||
</div> |
Empty file.
Oops, something went wrong.