Skip to content

Commit 06e5883

Browse files
committed
update the UoW to work with django. quite a lot of work
1 parent 3d0a62c commit 06e5883

6 files changed

Lines changed: 64 additions & 67 deletions

File tree

src/allocation/adapters/repository.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,19 @@ def _get(self, sku):
2323

2424
class DjangoRepository(AbstractRepository):
2525
def __init__(self):
26+
super().__init__()
2627
from djangoproject.alloc import models
2728

2829
self.django_models = models
2930

3031
def add(self, batch):
32+
super().add(batch)
33+
self.update(batch)
34+
35+
def update(self, batch):
3136
self.django_models.Batch.update_from_domain(batch)
3237

33-
def get(self, reference):
38+
def _get(self, reference):
3439
return (
3540
self.django_models.Batch.objects.filter(reference=reference)
3641
.first()
Lines changed: 9 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
11
# pylint: disable=attribute-defined-outside-init
22
from __future__ import annotations
33
import abc
4-
from sqlalchemy import create_engine
5-
from sqlalchemy.orm import sessionmaker
6-
from sqlalchemy.orm.session import Session
7-
8-
from allocation import config
4+
from django.db import transaction
95
from allocation.adapters import repository
106

117

@@ -27,28 +23,20 @@ def rollback(self):
2723
raise NotImplementedError
2824

2925

30-
DEFAULT_SESSION_FACTORY = sessionmaker(
31-
bind=create_engine(
32-
config.get_postgres_uri(),
33-
)
34-
)
35-
36-
37-
class SqlAlchemyUnitOfWork(AbstractUnitOfWork):
38-
def __init__(self, session_factory=DEFAULT_SESSION_FACTORY):
39-
self.session_factory = session_factory
40-
26+
class DjangoUnitOfWork(AbstractUnitOfWork):
4127
def __enter__(self):
42-
self.session = self.session_factory() # type: Session
43-
self.batches = repository.SqlAlchemyRepository(self.session)
28+
self.batches = repository.DjangoRepository()
29+
transaction.set_autocommit(False)
4430
return super().__enter__()
4531

4632
def __exit__(self, *args):
4733
super().__exit__(*args)
48-
self.session.close()
34+
transaction.set_autocommit(True)
4935

5036
def commit(self):
51-
self.session.commit()
37+
for batch in self.batches.seen:
38+
self.batches.update(batch)
39+
transaction.commit()
5240

5341
def rollback(self):
54-
self.session.rollback()
42+
transaction.rollback()

src/djangoproject/alloc/models.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,16 @@ class Batch(models.Model):
88
qty = models.IntegerField()
99
eta = models.DateField(blank=True, null=True)
1010

11-
@classmethod
12-
def update_from_domain(self, batch: domain_model.Batch):
11+
@staticmethod
12+
def update_from_domain(batch: domain_model.Batch):
1313
try:
1414
b = Batch.objects.get(reference=batch.reference)
1515
except Batch.DoesNotExist:
1616
b = Batch(reference=batch.reference)
1717
b.sku = batch.sku
1818
b.qty = batch._purchased_quantity
1919
b.eta = batch.eta
20+
b.allocation_set.set(Allocation.from_domain(l, b) for l in batch._allocations)
2021
b.save()
2122

2223
def to_domain(self) -> domain_model.Batch:
@@ -37,7 +38,22 @@ def to_domain(self):
3738
orderid=self.orderid, sku=self.sku, qty=self.qty
3839
)
3940

41+
@staticmethod
42+
def from_domain(line):
43+
l, _ = OrderLine.objects.get_or_create(
44+
orderid=line.orderid, sku=line.sku, qty=line.qty
45+
)
46+
return l
47+
4048

4149
class Allocation(models.Model):
4250
batch = models.ForeignKey(Batch, on_delete=models.CASCADE)
4351
line = models.ForeignKey(OrderLine, on_delete=models.CASCADE)
52+
53+
@staticmethod
54+
def from_domain(domain_line, django_batch):
55+
a, _ = Allocation.objects.get_or_create(
56+
line=OrderLine.from_domain(domain_line),
57+
batch=django_batch,
58+
)
59+
return a

tests/conftest.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,13 @@
77
from requests.exceptions import ConnectionError
88

99
from allocation import config
10-
from allocation.adapters.orm import metadata, start_mappers
10+
11+
12+
@pytest.fixture
13+
def django_models():
14+
from djangoproject.alloc import models
15+
16+
return models
1117

1218

1319
def wait_for_postgres_to_come_up(engine):

tests/integration/test_repository.py

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,6 @@
55
from allocation.adapters import repository
66

77

8-
@pytest.fixture
9-
def django_models():
10-
from djangoproject.alloc import models
11-
12-
return models
13-
14-
158
@pytest.mark.django_db
169
def test_repository_can_save_a_batch(django_models):
1710
batch = model.Batch("batch1", "RUSTY-SOAPDISH", 100, eta=date(2011, 12, 25))

tests/integration/test_uow.py

Lines changed: 24 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -3,63 +3,52 @@
33
from allocation.service_layer import unit_of_work
44

55

6-
def insert_batch(session, ref, sku, qty, eta):
7-
session.execute(
8-
"INSERT INTO batches (reference, sku, _purchased_quantity, eta)"
9-
" VALUES (:ref, :sku, :qty, :eta)",
10-
dict(ref=ref, sku=sku, qty=qty, eta=eta),
11-
)
6+
def insert_batch(django_models, ref, sku, qty, eta):
7+
django_models.Batch.objects.create(reference=ref, sku=sku, qty=qty, eta=eta)
128

139

14-
def get_allocated_batch_ref(session, orderid, sku):
15-
[[orderlineid]] = session.execute(
16-
"SELECT id FROM order_lines WHERE orderid=:orderid AND sku=:sku",
17-
dict(orderid=orderid, sku=sku),
18-
)
19-
[[batchref]] = session.execute(
20-
"SELECT b.reference FROM allocations JOIN batches AS b ON batch_id = b.id"
21-
" WHERE orderline_id=:orderlineid",
22-
dict(orderlineid=orderlineid),
23-
)
24-
return batchref
10+
def get_allocated_batch_ref(django_models, orderid, sku):
11+
print(django_models.Allocation.objects.all())
12+
return django_models.Allocation.objects.get(
13+
line__orderid=orderid, line__sku=sku
14+
).batch.reference
2515

2616

27-
def test_uow_can_retrieve_a_batch_and_allocate_to_it(session_factory):
28-
session = session_factory()
29-
insert_batch(session, "batch1", "HIPSTER-WORKBENCH", 100, None)
30-
session.commit()
17+
@pytest.mark.django_db(transaction=True)
18+
def test_uow_can_retrieve_a_batch_and_allocate_to_it(django_models):
19+
insert_batch(django_models, "batch1", "HIPSTER-WORKBENCH", 100, None)
3120

32-
uow = unit_of_work.SqlAlchemyUnitOfWork(session_factory)
21+
uow = unit_of_work.DjangoUnitOfWork()
3322
with uow:
3423
batch = uow.batches.get(reference="batch1")
3524
line = model.OrderLine("o1", "HIPSTER-WORKBENCH", 10)
3625
batch.allocate(line)
3726
uow.commit()
3827

39-
batchref = get_allocated_batch_ref(session, "o1", "HIPSTER-WORKBENCH")
28+
batchref = get_allocated_batch_ref(django_models, "o1", "HIPSTER-WORKBENCH")
4029
assert batchref == "batch1"
4130

4231

43-
def test_rolls_back_uncommitted_work_by_default(session_factory):
44-
uow = unit_of_work.SqlAlchemyUnitOfWork(session_factory)
32+
@pytest.mark.django_db(transaction=True)
33+
def test_rolls_back_uncommitted_work_by_default(django_models):
34+
uow = unit_of_work.DjangoUnitOfWork()
4535
with uow:
46-
insert_batch(uow.session, "batch1", "MEDIUM-PLINTH", 100, None)
36+
insert_batch(django_models, "batch1", "MEDIUM-PLINTH", 100, None)
4737

48-
new_session = session_factory()
49-
rows = list(new_session.execute('SELECT * FROM "batches"'))
50-
assert rows == []
38+
rows = django_models.Batch.objects.all()
39+
assert list(rows) == []
5140

5241

53-
def test_rolls_back_on_error(session_factory):
42+
@pytest.mark.django_db(transaction=True)
43+
def test_rolls_back_on_error(django_models):
5444
class MyException(Exception):
5545
pass
5646

57-
uow = unit_of_work.SqlAlchemyUnitOfWork(session_factory)
47+
uow = unit_of_work.DjangoUnitOfWork()
5848
with pytest.raises(MyException):
5949
with uow:
60-
insert_batch(uow.session, "batch1", "LARGE-FORK", 100, None)
50+
insert_batch(django_models, "batch1", "LARGE-FORK", 100, None)
6151
raise MyException()
6252

63-
new_session = session_factory()
64-
rows = list(new_session.execute('SELECT * FROM "batches"'))
65-
assert rows == []
53+
rows = django_models.Batch.objects.all()
54+
assert list(rows) == []

0 commit comments

Comments
 (0)