Skip to content

Commit f3d3d95

Browse files
committed
Add endpoint for creating inventory dewar
1 parent 7c8f16b commit f3d3d95

File tree

6 files changed

+80
-4
lines changed

6 files changed

+80
-4
lines changed

src/scaup/crud/internal.py

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1-
from sqlalchemy import select
1+
from sqlalchemy import insert, select
22
from sqlalchemy.orm import joinedload
33

44
from ..models.inner_db.tables import Container, TopLevelContainer
55
from ..models.shipments import ShipmentChildren
66
from ..models.top_level_containers import TopLevelContainerOut
77
from ..utils.database import inner_db
88
from ..utils.query import query_result_to_object
9+
from ..utils.session import retry_if_exists
910

1011

1112
def get_unassigned(limit: int, page: int):
@@ -43,3 +44,39 @@ def get_internal_containers(limit: int, page: int):
4344
query = select(TopLevelContainer).filter(TopLevelContainer.isInternal.is_(True))
4445

4546
return inner_db.paginate(query, limit, page, slow_count=False, scalar=False)
47+
48+
49+
@retry_if_exists
50+
def create_preloaded_inventory_dewar(name: str):
51+
tlc = inner_db.session.scalar(
52+
insert(TopLevelContainer).returning(TopLevelContainer),
53+
{"name": name, "isInternal": True, "code": name},
54+
)
55+
56+
containers = inner_db.session.scalars(
57+
insert(Container).returning(Container),
58+
[
59+
{"name": i, "isInternal": True, "topLevelContainerId": tlc.id, "type": "puck", "subType": "2"}
60+
for i in range(1, 6)
61+
],
62+
).all()
63+
64+
inner_db.session.execute(
65+
insert(Container),
66+
[
67+
{
68+
"name": f"Gridbox_{pos + 1}_Puck_{container.name}",
69+
"isInternal": True,
70+
"parentId": container.id,
71+
"type": "gridBox",
72+
"subType": "auto",
73+
"location": pos + 1,
74+
}
75+
for pos in range(12)
76+
for container in containers
77+
],
78+
)
79+
80+
inner_db.session.commit()
81+
82+
return tlc

src/scaup/models/containers.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ class OptionalContainer(BaseContainer):
6868

6969

7070
class ContainerOut(BaseContainer):
71-
shipmentId: int
71+
shipmentId: int | None = None
7272
id: int = Field(validation_alias=AliasChoices("containerId", "id"))
7373
model_config = ConfigDict(from_attributes=True, arbitrary_types_allowed=True)
7474
type: str

src/scaup/models/samples.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ class OptionalSample(BaseSample):
4040

4141
class SampleOut(BaseSample):
4242
id: int = Field(validation_alias=AliasChoices("sampleId", "id", AliasPath("Sample", "id")))
43-
shipmentId: int = Field(validation_alias=InnerAlias("shipmentId"))
43+
shipmentId: int | None = Field(default=None, validation_alias=InnerAlias("shipmentId"))
4444
proteinId: int = Field(validation_alias=InnerAlias("proteinId"))
4545
containerName: Optional[str] = None
4646
type: str = Field(validation_alias=InnerAlias("type"))

src/scaup/models/top_level_containers.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ class TopLevelContainerHistory(BaseModel):
1414
arrivalDate: datetime | None = None
1515

1616

17+
class PreloadedInventoryDewar(BaseModel):
18+
name: str
19+
20+
1721
class BaseTopLevelContainer(BaseModel):
1822
details: Optional[dict[str, Any]] = None
1923
comments: Optional[str] = None

src/scaup/routes/internal.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from ..crud.top_level_containers import create_top_level_container
99
from ..models.containers import ContainerIn, ContainerOut
1010
from ..models.shipments import GenericItem, ShipmentChildren
11-
from ..models.top_level_containers import TopLevelContainerIn, TopLevelContainerOut
11+
from ..models.top_level_containers import PreloadedInventoryDewar, TopLevelContainerIn, TopLevelContainerOut
1212
from ..utils.auth import check_em_staff
1313

1414

@@ -77,3 +77,13 @@ def create_orphan_top_level_container(
7777
def get_internal_container(topLevelContainerId: int):
7878
"""Get internal top level container and its children"""
7979
return crud.get_internal_container_tree(top_level_container_id=topLevelContainerId)
80+
81+
82+
@router.post(
83+
"/preloaded-dewars",
84+
response_model=TopLevelContainerOut,
85+
status_code=status.HTTP_201_CREATED,
86+
)
87+
def create_preloaded_inventory_dewar(parameters: PreloadedInventoryDewar = Body()):
88+
"""Create preloaded inventory dewar with pucks and grid boxes"""
89+
return crud.create_preloaded_inventory_dewar(name=parameters.name)
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import pytest
2+
from sqlalchemy import func, select
3+
4+
from scaup.models.inner_db.tables import Container, TopLevelContainer
5+
from scaup.utils.database import inner_db
6+
7+
from ..test_utils.users import admin
8+
9+
10+
@pytest.mark.parametrize("mock_user", [admin], indirect=True)
11+
def test_create(mock_user, client):
12+
"""Should create internal preloaded dewar"""
13+
resp = client.post(
14+
"/internal-containers/preloaded-dewars",
15+
json={"name": "foo"},
16+
)
17+
18+
assert resp.status_code == 201
19+
20+
item_id = resp.json()["id"]
21+
22+
assert inner_db.session.scalar(select(TopLevelContainer).filter(TopLevelContainer.id == item_id)) is not None
23+
assert (
24+
inner_db.session.scalar(select(func.count(Container.id)).filter(Container.topLevelContainerId == item_id)) == 5
25+
)

0 commit comments

Comments
 (0)