123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277 |
- """
- Provides access to the models stored in the database, via the server.
- """
- import datetime
- from typing import NamedTuple
- from urllib.parse import urljoin
- import requests
- from . import logger
- LOG = logger.getLogger("model")
- SERVER_URL = "http://127.0.0.1:5000"
- class Person(NamedTuple):
- """ Represents a Person, as retrieved from the database. """
- name: str
- person_id: int = None
- consumptions: dict = {}
- def add_consumption(self, type_id: str) -> bool:
- """ Register a consumption for this Person. """
- req = requests.post(
- urljoin(SERVER_URL, f"people/{self.person_id}/add_consumption/{type_id}")
- )
- try:
- data = req.json()
- if "error" in data:
- LOG.error(
- "Could not add consumption for %s (%s): %s",
- self.person_id,
- req.status_code,
- data,
- )
- return False
- self.consumptions.update(data["person"]["consumptions"])
- return Consumption.from_dict(data["consumption"])
- except ValueError:
- LOG.error(
- "Did not get JSON on adding Consumption (%s): %s",
- req.status_code,
- req.content,
- )
- return False
- def create(self) -> "Person":
- """ Create a new Person from the current attributes. As tuples are
- immutable, a new Person with the correct id is returned. """
- req = requests.post(
- urljoin(SERVER_URL, "people"), json={"person": {"name": self.name}}
- )
- try:
- data = req.json()
- except ValueError:
- LOG.error(
- "Did not get JSON on adding Person (%s): %s",
- req.status_code,
- req.content,
- )
- return None
- if "error" in data or req.status_code != 201:
- LOG.error("Could not create Person (%s): %s", req.status_code, data)
- return None
- return Person.from_dict(data["person"])
- @classmethod
- def get(cls, person_id: int) -> "Person":
- """ Retrieve a Person by id. """
- req = requests.get(urljoin(SERVER_URL, f"/people/{person_id}"))
- try:
- data = req.json()
- if "error" in data:
- LOG.warning(
- "Could not get person %s (%s): %s", person_id, req.status_code, data
- )
- return None
- return Person.from_dict(data["person"])
- except ValueError:
- LOG.error(
- "Did not get JSON from server on getting Person (%s): %s",
- req.status_code,
- req.content,
- )
- return None
- @classmethod
- def get_all(cls, active=None) -> ["Person"]:
- """ Get all active People. """
- active = int(active)
- req = requests.get(urljoin(SERVER_URL, "/people"),
- params={'active':active})
- try:
- data = req.json()
- if "error" in data:
- LOG.warning("Could not get people (%s): %s", req.status_code, data)
- return [Person.from_dict(item) for item in data["people"]]
- except ValueError:
- LOG.error(
- "Did not get JSON from server on getting People (%s): %s",
- req.status_code,
- req.content,
- )
- return None
- @classmethod
- def from_dict(cls, data: dict) -> "Person":
- """ Reconstruct a Person object from a dict. """
- return Person(
- name=data["name"],
- person_id=data["person_id"],
- consumptions=data["consumptions"],
- )
- class ConsumptionType(NamedTuple):
- """ Represents a stored ConsumptionType. """
- name: str
- consumption_type_id: int = None
- icon: str = None
- def create(self) -> "ConsumptionType":
- """ Create a new ConsumptionType from the current attributes. As tuples
- are immutable, a new ConsumptionType with the correct id is returned.
- """
- req = requests.post(
- urljoin(SERVER_URL, "consumption_types"),
- json={"consumption_type": {"name": self.name, "icon": self.icon}},
- )
- try:
- data = req.json()
- except ValueError:
- LOG.error(
- "Did not get JSON on adding ConsumptionType (%s): %s",
- req.status_code,
- req.content,
- )
- return None
- if "error" in data or req.status_code != 201:
- LOG.error(
- "Could not create ConsumptionType (%s): %s", req.status_code, data
- )
- return None
- return ConsumptionType.from_dict(data["consumption_type"])
- @classmethod
- def get(cls, consumption_type_id: int) -> "ConsumptionType":
- """ Retrieve a ConsumptionType by id. """
- req = requests.get(
- urljoin(SERVER_URL, f"/consumption_types/{consumption_type_id}")
- )
- try:
- data = req.json()
- if "error" in data:
- LOG.warning(
- "Could not get consumption type %s (%s): %s",
- consumption_type_id,
- req.status_code,
- data,
- )
- return None
- return cls.from_dict(data["consumption_type"])
- except ValueError:
- LOG.error(
- "Did not get JSON from server on getting consumption type (%s): %s",
- req.status_code,
- req.content,
- )
- return None
- @classmethod
- def get_all(cls) -> ["ConsumptionType"]:
- """ Get all active ConsumptionTypes. """
- req = requests.get(urljoin(SERVER_URL, "/consumption_types"))
- try:
- data = req.json()
- if "error" in data:
- LOG.warning(
- "Could not get consumption types (%s): %s", req.status_code, data
- )
- return [cls.from_dict(item) for item in data["consumption_types"]]
- except ValueError:
- LOG.error(
- "Did not get JSON from server on getting ConsumptionTypes (%s): %s",
- req.status_code,
- req.content,
- )
- return None
- @classmethod
- def from_dict(cls, data: dict) -> "ConsumptionType":
- """ Reconstruct a ConsumptionType from a dict. """
- return cls(
- name=data["name"],
- consumption_type_id=data["consumption_type_id"],
- icon=data.get("icon"),
- )
- class Consumption(NamedTuple):
- """ Represents a stored Consumption. """
- consumption_id: int
- person_id: int
- consumption_type_id: int
- created_at: datetime.datetime
- reversed: bool = False
- settlement_id: int = None
- @classmethod
- def from_dict(cls, data: dict) -> "Consumption":
- """ Reconstruct a Consumption from a dict. """
- return cls(
- consumption_id=data["consumption_id"],
- person_id=data["person_id"],
- consumption_type_id=data["consumption_type_id"],
- settlement_id=data["settlement_id"],
- created_at=datetime.datetime.fromisoformat(data["created_at"]),
- reversed=data["reversed"],
- )
- def reverse(self) -> "Consumption":
- """ Reverse this consumption. """
- req = requests.delete(
- urljoin(SERVER_URL, f"/consumptions/{self.consumption_id}")
- )
- try:
- data = req.json()
- if "error" in data:
- LOG.error(
- "Could not reverse consumption %s (%s): %s",
- self.consumption_id,
- req.status_code,
- data,
- )
- return False
- return Consumption.from_dict(data["consumption"])
- except ValueError:
- LOG.error(
- "Did not get JSON on reversing Consumption (%s): %s",
- req.status_code,
- req.content,
- )
- return False
|