Skip to content

Commit

Permalink
Added rest of the system (households, samples, batches of results.
Browse files Browse the repository at this point in the history
  • Loading branch information
johnbywater committed Apr 1, 2020
1 parent 0c8c52c commit 989c9e2
Show file tree
Hide file tree
Showing 14 changed files with 375 additions and 103 deletions.
3 changes: 3 additions & 0 deletions peto/application/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@



86 changes: 86 additions & 0 deletions peto/application/households.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
from uuid import uuid5, NAMESPACE_URL

from eventsourcing.application.decorators import applicationpolicy
from eventsourcing.application.process import ProcessApplication, WrappedRepository
from eventsourcing.domain.model.aggregate import TAggregate, TAggregateEvent
from eventsourcing.exceptions import RepositoryKeyError

from peto.domainmodel.exceptions import HouseholdNotFound
from peto.domainmodel.household import Household
from peto.domainmodel.person import Person


class HouseholdsApplication(ProcessApplication):
persist_event_type = Household.Event

def get_household_by_address(self, postcode, house_num) -> Household:
return self._get_household_by_address(self.repository, postcode, house_num)

def _get_household_by_address(self, repository, postcode, house_num) -> Household:
household_id = create_household_id(postcode=postcode, house_num=house_num)
return self._get_household_by_id(repository, household_id)

def get_household_by_id(self, household_id) -> Household:
return self._get_household_by_id(self.repository, household_id)

def _get_household_by_id(self, repository, household_id):
try:
household = repository[household_id]
except RepositoryKeyError:
raise HouseholdNotFound
else:
assert isinstance(household, Household)
return household

@applicationpolicy
def policy(self, repository, event):
pass

@policy.register(Person.Created)
def _(self, repository, event):
postcode = event.postcode
house_num = event.house_num
try:
household = self._get_household_by_address(repository, postcode, house_num)
except HouseholdNotFound:
household = self.register_household(postcode=postcode, house_num=house_num)
household.add_person(event.nhs_num)
return household

@policy.register(Person.AddressChanged)
def _(self, repository, event):
nhs_num = event.nhs_num
old_postcode = event.old_postcode
old_house_num = event.old_house_num
new_postcode = event.new_postcode
new_house_num = event.new_house_num
old_household = self._get_household_by_address(repository, old_postcode, old_house_num)
old_household.remove_person(nhs_num)

try:
household = self._get_household_by_address(repository, new_postcode, new_house_num)
except HouseholdNotFound:
household = self.register_household(postcode=new_postcode, house_num=new_house_num)

household.add_person(event.nhs_num)
return household

def register_household(self, postcode, house_num):
household = Household.__create__(
originator_id=create_household_id(postcode, house_num),
postcode=postcode,
house_num=house_num
)
return household

def select_household_ids(self, slot, cycle):
selection = []
for household_id in self.repository.event_store.record_manager.all_sequence_ids():
if (household_id.int % cycle) == slot:
selection.append(household_id)
return selection


def create_household_id(postcode, house_num):
return uuid5(NAMESPACE_URL, f"/household/{postcode}/{house_num}")

15 changes: 5 additions & 10 deletions peto/application.py → peto/application/people.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
from eventsourcing.application.simple import SimpleApplication
from eventsourcing.application.process import ProcessApplication
from eventsourcing.exceptions import RepositoryKeyError

from peto.domainmodel import PetoAggregateRoot, Person, create_person_id, PersonNotFound, ResultsBatch
from peto.domainmodel.exceptions import PersonNotFound
from peto.domainmodel.person import Person, create_person_id


class PetoCore(SimpleApplication):
persist_event_type = PetoAggregateRoot.Event
class PeopleApplication(ProcessApplication):
persist_event_type = Person.Event

def register_person(self, name, dob, nhs_num, tel_num, email, postcode, house_num):
person = Person.__create__(
Expand Down Expand Up @@ -34,9 +35,3 @@ def get_person_by_nhs_num(self, nhs_num) -> Person:
else:
assert isinstance(person, Person)
return person

def register_batch_of_results(self, lab_id, results):
ResultsBatch.__create__(
lab_id=lab_id,
results=results,
)
45 changes: 45 additions & 0 deletions peto/application/samples.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
from eventsourcing.application.decorators import applicationpolicy
from eventsourcing.application.process import ProcessApplication

from peto.domainmodel.batchofresults import BatchOfResults
from peto.domainmodel.sample import Sample


class BatchesApplication(ProcessApplication):
persist_event_type = BatchOfResults.Event

def register_batch_of_results(self, lab_id, results):
batch = BatchOfResults.__create__(
lab_id=lab_id,
results=results,
)
batch.__save__()


class SamplesApplication(ProcessApplication):
persist_event_type = Sample.Event

def register_sample(self, sample_id, name, dob, nhs_num):
sample = Sample.__create__(
originator_id=sample_id,
name=name,
dob=dob,
nhs_num=nhs_num,
)
sample.__save__()

@applicationpolicy
def policy(self, repository, event):
pass

@policy.register(BatchOfResults.Created)
def _(self, repository, event):
for result in event.results:
sample: Sample = self._get_sample(repository, result[0])
sample.record_result(result[1])

def get_sample(self, sample_id):
return self._get_sample(self.repository, sample_id)

def _get_sample(self, repository, sample_id):
return repository[sample_id]
10 changes: 10 additions & 0 deletions peto/application/system.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from eventsourcing.system.definition import System

from peto.application.people import PeopleApplication
from peto.application.households import HouseholdsApplication
from peto.application.samples import SamplesApplication, BatchesApplication

system = System(
PeopleApplication | HouseholdsApplication,
BatchesApplication | SamplesApplication
)
Empty file added peto/domainmodel/__init__.py
Empty file.
5 changes: 5 additions & 0 deletions peto/domainmodel/base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from eventsourcing.domain.model.aggregate import BaseAggregateRoot


class PetoAggregateRoot(BaseAggregateRoot):
__subclassevents__ = True
8 changes: 8 additions & 0 deletions peto/domainmodel/batchofresults.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from peto.domainmodel.base import PetoAggregateRoot


class BatchOfResults(PetoAggregateRoot):
def __init__(self, lab_id, results, **kwargs):
super(BatchOfResults, self).__init__(**kwargs)
self.lab_id = lab_id
self.results = results
10 changes: 10 additions & 0 deletions peto/domainmodel/exceptions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
class PetoException(Exception):
pass


class HouseholdNotFound(PetoException):
pass


class PersonNotFound(PetoException):
pass
31 changes: 31 additions & 0 deletions peto/domainmodel/household.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
from peto.domainmodel.base import PetoAggregateRoot


class Household(PetoAggregateRoot):
def __init__(self, *, postcode, house_num, **kwargs):
super(Household, self).__init__(**kwargs)
self.postcode = postcode
self.house_num = house_num
self.people = set()

def add_person(self, nhs_num):
self.__trigger_event__(self.PersonAdded, nhs_num=nhs_num)

class PersonAdded(PetoAggregateRoot.Event):
@property
def nhs_num(self):
return self.__dict__['nhs_num']

def mutate(self, obj: "Household"):
obj.people.add(self.nhs_num)

def remove_person(self, nhs_num):
self.__trigger_event__(self.PersonRemoved, nhs_num=nhs_num)

class PersonRemoved(PetoAggregateRoot.Event):
@property
def nhs_num(self):
return self.__dict__['nhs_num']

def mutate(self, obj: "Household"):
obj.people.remove(self.nhs_num)
20 changes: 3 additions & 17 deletions peto/domainmodel.py → peto/domainmodel/person.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
from uuid import uuid5, NAMESPACE_URL

from eventsourcing.domain.model.aggregate import BaseAggregateRoot


class PetoAggregateRoot(BaseAggregateRoot):
__subclassevents__ = True
from peto.domainmodel.base import PetoAggregateRoot


class Person(PetoAggregateRoot):
Expand All @@ -21,6 +17,7 @@ def __init__(self, name, dob, nhs_num, tel_num, email, postcode, house_num, **kw
def change_address(self, new_postcode, new_house_num):
self.__trigger_event__(
self.AddressChanged,
nhs_num=self.nhs_num,
old_postcode=self.postcode,
old_house_num=self.house_num,
new_postcode=new_postcode,
Expand Down Expand Up @@ -50,15 +47,4 @@ def mutate(self, obj: "Person") -> None:


def create_person_id(nhs_num):
return uuid5(NAMESPACE_URL, f"/nhs_num/{nhs_num}")


class PersonNotFound(Exception):
pass


class ResultsBatch(PetoAggregateRoot):
def __init__(self, lab_id, results, **kwargs):
super(ResultsBatch, self).__init__(**kwargs)
self.lab_id = lab_id
self.results = results
return uuid5(NAMESPACE_URL, f"/person/{nhs_num}")
21 changes: 21 additions & 0 deletions peto/domainmodel/sample.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from peto.domainmodel.base import PetoAggregateRoot


class Sample(PetoAggregateRoot):
def __init__(self, *, name, dob, nhs_num, **kwargs):
super(Sample, self).__init__(**kwargs)
self.name = name
self.dob = dob
self.nhs_num = nhs_num
self.result = None

def record_result(self, result):
self.__trigger_event__(self.ResultRecorded, result=result)

class ResultRecorded(PetoAggregateRoot.Event):
@property
def result(self):
return self.__dict__['result']

def mutate(self, obj):
obj.result = self.result
76 changes: 0 additions & 76 deletions test_application.py

This file was deleted.

0 comments on commit 989c9e2

Please sign in to comment.