NOJIRA restructed into separate model files
This commit is contained in:
76
main.py
76
main.py
@@ -1,64 +1,11 @@
|
|||||||
import datetime
|
import datetime
|
||||||
from typing import List, Dict
|
from typing import List
|
||||||
|
|
||||||
from flask import render_template
|
from flask import render_template
|
||||||
from google.oauth2.service_account import Credentials
|
from google.oauth2.service_account import Credentials
|
||||||
from googleapiclient.discovery import build
|
from googleapiclient.discovery import build
|
||||||
|
|
||||||
|
from models.dto import DTO
|
||||||
class Item:
|
|
||||||
def __init__(self, name: str, amount: int):
|
|
||||||
assert name == name.lower()
|
|
||||||
self.name = name
|
|
||||||
self.amount = amount
|
|
||||||
self.__contains_fries = 'friet' in self.name or 'twister' in self.name
|
|
||||||
|
|
||||||
def __lt__(self: "Item", other: "Item") -> bool:
|
|
||||||
if self.__contains_fries and not other.__contains_fries:
|
|
||||||
return True
|
|
||||||
if not self.__contains_fries and other.__contains_fries:
|
|
||||||
return False
|
|
||||||
return self.name < other.name
|
|
||||||
|
|
||||||
|
|
||||||
class Order:
|
|
||||||
def __init__(self, value: List[str]):
|
|
||||||
self.name = _anonymize_name(value[1])
|
|
||||||
self.items = [v for v in value[2:] if v]
|
|
||||||
|
|
||||||
|
|
||||||
class DTO:
|
|
||||||
def __init__(self):
|
|
||||||
self.__applicants: List[str] = []
|
|
||||||
self.__items: Dict[str, int] = {}
|
|
||||||
self.__orders: List[Order] = []
|
|
||||||
|
|
||||||
def process_value(self, value: List[str]) -> None:
|
|
||||||
# applications
|
|
||||||
self.__applicants.append(_anonymize_name(value[1]))
|
|
||||||
# items
|
|
||||||
for item in value[2:]:
|
|
||||||
if item:
|
|
||||||
item_name = item.lower().strip()
|
|
||||||
if item_name in self.__items:
|
|
||||||
self.__items[item_name] += 1
|
|
||||||
else:
|
|
||||||
self.__items[item_name] = 1
|
|
||||||
# orders
|
|
||||||
self.__orders.append(Order(value))
|
|
||||||
|
|
||||||
@property
|
|
||||||
def items(self) -> List[Item]:
|
|
||||||
return sorted([Item(name, amount) for name, amount in self.__items.items()])
|
|
||||||
|
|
||||||
@property
|
|
||||||
def applicants(self) -> List[str]:
|
|
||||||
return sorted(self.__applicants)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def orders(self) -> List[Order]:
|
|
||||||
return sorted(self.__orders, key=lambda o: o.name)
|
|
||||||
|
|
||||||
|
|
||||||
_SCOPES = ['https://www.googleapis.com/auth/spreadsheets.readonly']
|
_SCOPES = ['https://www.googleapis.com/auth/spreadsheets.readonly']
|
||||||
|
|
||||||
@@ -90,22 +37,27 @@ def _anonymize_name(name: str) -> str:
|
|||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def _get_data() -> DTO:
|
def _load_values() -> List[List[str]]:
|
||||||
credentials: Credentials = Credentials.from_service_account_file('token.json', scopes=_SCOPES)
|
credentials: Credentials = Credentials.from_service_account_file('token.json', scopes=_SCOPES)
|
||||||
|
|
||||||
service = build('sheets', 'v4', credentials=credentials)
|
service = build('sheets', 'v4', credentials=credentials)
|
||||||
sheets = service.spreadsheets()
|
sheets = service.spreadsheets()
|
||||||
result = sheets.values().get(spreadsheetId=_SHEET_ID, range=_RANGE).execute()
|
result = sheets.values().get(spreadsheetId=_SHEET_ID, range=_RANGE).execute()
|
||||||
values = result.get('values', [])
|
values = result.get('values', [])
|
||||||
|
return values
|
||||||
|
|
||||||
|
|
||||||
|
def _get_data() -> DTO:
|
||||||
cutoff = datetime.datetime.now() - datetime.timedelta(days=4)
|
cutoff = datetime.datetime.now() - datetime.timedelta(days=4)
|
||||||
|
|
||||||
|
rows_to_process = [row for row in _load_values()
|
||||||
|
if row and datetime.datetime.strptime(row[0], '%d-%m-%Y %H:%M:%S') > cutoff]
|
||||||
|
|
||||||
result = DTO()
|
result = DTO()
|
||||||
|
|
||||||
for value in values:
|
for row in rows_to_process:
|
||||||
if value:
|
result.add(
|
||||||
moment = datetime.datetime.strptime(value[0], '%d-%m-%Y %H:%M:%S')
|
applicant_name=_anonymize_name(row[1]),
|
||||||
if moment > cutoff:
|
item_names=[item_name.lower().strip() for item_name in row[2:]],
|
||||||
result.process_value(value)
|
)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|||||||
34
models/dto.py
Normal file
34
models/dto.py
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
from typing import List, Dict
|
||||||
|
|
||||||
|
from models.item import Item
|
||||||
|
from models.order import Order
|
||||||
|
|
||||||
|
|
||||||
|
class DTO:
|
||||||
|
def __init__(self):
|
||||||
|
self.__applicants: List[str] = []
|
||||||
|
self.__items: Dict[str, int] = {}
|
||||||
|
self.__orders: List[Order] = []
|
||||||
|
|
||||||
|
def add(self, applicant_name: str, item_names: List[str]):
|
||||||
|
self.__applicants.append(applicant_name)
|
||||||
|
|
||||||
|
for item_name in item_names:
|
||||||
|
if item_name not in self.__items:
|
||||||
|
self.__items[item_name] = 0
|
||||||
|
self.__items[item_name] += 1
|
||||||
|
|
||||||
|
order = Order(applicant_name, item_names)
|
||||||
|
self.__orders.append(order)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def items(self) -> List[Item]:
|
||||||
|
return sorted([Item(name, amount) for name, amount in self.__items.items()])
|
||||||
|
|
||||||
|
@property
|
||||||
|
def applicants(self) -> List[str]:
|
||||||
|
return sorted(self.__applicants)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def orders(self) -> List[Order]:
|
||||||
|
return sorted(self.__orders)
|
||||||
13
models/item.py
Normal file
13
models/item.py
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
class Item:
|
||||||
|
def __init__(self, name: str, amount: int):
|
||||||
|
assert name == name.lower()
|
||||||
|
self.name = name
|
||||||
|
self.amount = amount
|
||||||
|
self.__contains_fries = 'friet' in self.name or 'twister' in self.name
|
||||||
|
|
||||||
|
def __lt__(self: "Item", other: "Item") -> bool:
|
||||||
|
if self.__contains_fries and not other.__contains_fries:
|
||||||
|
return True
|
||||||
|
if not self.__contains_fries and other.__contains_fries:
|
||||||
|
return False
|
||||||
|
return self.name < other.name
|
||||||
10
models/order.py
Normal file
10
models/order.py
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
from typing import List
|
||||||
|
|
||||||
|
|
||||||
|
class Order:
|
||||||
|
def __init__(self, name: str, items: List[str]):
|
||||||
|
self.name = name
|
||||||
|
self.items = items
|
||||||
|
|
||||||
|
def __lt__(self: "Order", other: "Order") -> bool:
|
||||||
|
return self.name < other.name
|
||||||
3
pack.sh
3
pack.sh
@@ -1,6 +1,7 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
zip deployable.zip \
|
zip deployable.zip \
|
||||||
templates/frietlijst.html \
|
templates/*.html \
|
||||||
|
models/*.py \
|
||||||
main.py \
|
main.py \
|
||||||
token.json \
|
token.json \
|
||||||
requirements.txt
|
requirements.txt
|
||||||
16
test.py
Normal file
16
test.py
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import unittest
|
||||||
|
|
||||||
|
from main import _anonymize_name
|
||||||
|
|
||||||
|
|
||||||
|
class TestMain(unittest.TestCase):
|
||||||
|
def test_anonymize_name(self):
|
||||||
|
given = "Alice Bobbington Charlie"
|
||||||
|
expected = "Alice B C"
|
||||||
|
actual = _anonymize_name(given)
|
||||||
|
|
||||||
|
self.assertEqual(expected, actual)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
||||||
Reference in New Issue
Block a user