Skip to content

Commit ff1afe4

Browse files
committed
Merge branch 'master' into improvement/lims-2051/pdf-report
2 parents 0310251 + 82c8ba8 commit ff1afe4

9 files changed

Lines changed: 113 additions & 16 deletions

File tree

CHANGELOG.rst

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,20 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
88
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
99

1010
+++++++++
11-
v0.18.2 (09/01/2025)
11+
v0.19.0 (16/01/2026)
12+
+++++++++
13+
14+
**Changed**
15+
16+
- All grids are now displayed in PDF reports, even if they don't have a cassette slot assigned
17+
18+
**Added**
19+
20+
- Perform manufacturer serial number check when creating dewars
21+
- Add endpoint for creating inventory dewar
22+
23+
+++++++++
24+
v0.18.2 (09/01/2026)
1225
+++++++++
1326

1427
**Changed**
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
"""Increase name character limit
2+
3+
Revision ID: 31b603858335
4+
Revises: 730f6f07da68
5+
Create Date: 2026-01-23 14:09:57.262059
6+
7+
"""
8+
from typing import Sequence, Union
9+
10+
from alembic import op
11+
import sqlalchemy as sa
12+
13+
14+
# revision identifiers, used by Alembic.
15+
revision: str = '31b603858335'
16+
down_revision: Union[str, None] = '730f6f07da68'
17+
branch_labels: Union[str, Sequence[str], None] = None
18+
depends_on: Union[str, Sequence[str], None] = None
19+
20+
21+
def upgrade() -> None:
22+
# ### commands auto generated by Alembic - please adjust! ###
23+
op.alter_column('Container', 'name',
24+
existing_type=sa.VARCHAR(length=40),
25+
type_=sa.String(length=80),
26+
existing_nullable=False)
27+
op.alter_column('Sample', 'name',
28+
existing_type=sa.VARCHAR(length=40),
29+
type_=sa.String(length=80),
30+
existing_nullable=False)
31+
op.alter_column('Shipment', 'name',
32+
existing_type=sa.VARCHAR(length=40),
33+
type_=sa.String(length=80),
34+
existing_nullable=False)
35+
op.alter_column('TopLevelContainer', 'name',
36+
existing_type=sa.VARCHAR(length=40),
37+
type_=sa.String(length=80),
38+
existing_nullable=False)
39+
# ### end Alembic commands ###
40+
41+
42+
def downgrade() -> None:
43+
# ### commands auto generated by Alembic - please adjust! ###
44+
op.alter_column('TopLevelContainer', 'name',
45+
existing_type=sa.String(length=80),
46+
type_=sa.VARCHAR(length=40),
47+
existing_nullable=False)
48+
op.alter_column('Shipment', 'name',
49+
existing_type=sa.String(length=80),
50+
type_=sa.VARCHAR(length=40),
51+
existing_nullable=False)
52+
op.alter_column('Sample', 'name',
53+
existing_type=sa.String(length=80),
54+
type_=sa.VARCHAR(length=40),
55+
existing_nullable=False)
56+
op.alter_column('Container', 'name',
57+
existing_type=sa.String(length=80),
58+
type_=sa.VARCHAR(length=40),
59+
existing_nullable=False)
60+
# ### end Alembic commands ###

database/data.sql

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22
-- PostgreSQL database dump
33
--
44

5-
-- Dumped from database version 17.5
6-
-- Dumped by pg_dump version 17.4
5+
\restrict U6bOmzaZYjYIO0Hg2gWsqgE5LjK1vVHNNCtv3caSVlfRNEoi3Gvy4hpNaeUfHGq
6+
7+
-- Dumped from database version 17.6 (Debian 17.6-2.pgdg13+1)
8+
-- Dumped by pg_dump version 18.0
79

810
SET statement_timeout = 0;
911
SET lock_timeout = 0;
@@ -45,7 +47,7 @@ CREATE TABLE public."Container" (
4547
details json,
4648
"requestedReturn" boolean NOT NULL,
4749
"registeredContainer" character varying,
48-
name character varying(40) NOT NULL,
50+
name character varying(80) NOT NULL,
4951
"externalId" integer,
5052
comments character varying(255),
5153
"isInternal" boolean NOT NULL,
@@ -161,7 +163,7 @@ CREATE TABLE public."Sample" (
161163
location smallint,
162164
details json,
163165
"containerId" integer,
164-
name character varying(40) NOT NULL,
166+
name character varying(80) NOT NULL,
165167
"externalId" integer,
166168
comments character varying(255),
167169
"subLocation" smallint,
@@ -250,7 +252,7 @@ CREATE TABLE public."Shipment" (
250252
"creationDate" timestamp with time zone DEFAULT now() NOT NULL,
251253
"shipmentRequest" integer,
252254
status character varying(25) DEFAULT 'Created'::character varying,
253-
name character varying(40) NOT NULL,
255+
name character varying(80) NOT NULL,
254256
"externalId" integer,
255257
comments character varying(255),
256258
"proposalCode" character varying(2) NOT NULL,
@@ -301,7 +303,7 @@ CREATE TABLE public."TopLevelContainer" (
301303
details json,
302304
code character varying(20) NOT NULL,
303305
type character varying(40) DEFAULT 'dewar'::character varying NOT NULL,
304-
name character varying(40) NOT NULL,
306+
name character varying(80) NOT NULL,
305307
"externalId" integer,
306308
comments character varying(255),
307309
"isInternal" boolean NOT NULL,
@@ -498,7 +500,7 @@ COPY public."TopLevelContainer" ("topLevelContainerId", "shipmentId", details, c
498500
--
499501

500502
COPY public.alembic_version (version_num) FROM stdin;
501-
730f6f07da68
503+
31b603858335
502504
\.
503505

504506

@@ -861,3 +863,5 @@ GRANT ALL ON SCHEMA public TO PUBLIC;
861863
-- PostgreSQL database dump complete
862864
--
863865

866+
\unrestrict U6bOmzaZYjYIO0Hg2gWsqgE5LjK1vVHNNCtv3caSVlfRNEoi3Gvy4hpNaeUfHGq
867+

src/scaup/crud/samples.py

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@
33
from fastapi import HTTPException, status
44
from lims_utils.logging import app_logger
55
from lims_utils.models import Paged, ProposalReference
6+
from psycopg.errors import ForeignKeyViolation
67
from sqlalchemy import and_, insert, select
8+
from sqlalchemy.exc import IntegrityError
79

810
from ..models.inner_db.tables import Container, Sample, SampleParentChild, Shipment
911
from ..models.samples import OptionalSample, SampleIn, SampleOut
1012
from ..utils.config import Config
11-
from ..utils.crud import assert_not_booked, edit_item
13+
from ..utils.crud import assert_not_booked, delete_item, edit_item
1214
from ..utils.database import inner_db
1315
from ..utils.external import Expeye, ExternalRequest
1416
from ..utils.session import retry_if_exists
@@ -189,3 +191,16 @@ def get_samples(
189191
pass
190192

191193
return validated_samples
194+
195+
196+
def delete_sample(sample_id: int):
197+
try:
198+
delete_item(table=Sample, item_id=sample_id)
199+
except IntegrityError as e:
200+
if isinstance(e.__cause__, ForeignKeyViolation):
201+
# If a foreign key violation occurs, that's because the sample is in SampleParentChild
202+
raise HTTPException(
203+
status_code=status.HTTP_409_CONFLICT,
204+
detail="Sample is linked to a different session and cannot be deleted",
205+
)
206+
raise

src/scaup/crud/shipments.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ def _get_children(
170170
@assert_no_unassigned
171171
def build_shipment_request(shipmentId: int, token: str):
172172
shipment = _get_shipment_tree(shipmentId)
173-
proposal_reference = f"{shipment.proposalCode}{shipment.proposalNumber:06}"
173+
proposal_reference = f"{shipment.proposalCode}{shipment.proposalNumber}"
174174

175175
packages: list[dict] = []
176176
for tlc in shipment.children:
@@ -252,7 +252,6 @@ def build_shipment_request(shipmentId: int, token: str):
252252
)
253253

254254
built_request_body = {
255-
# TODO: remove padding once shipping service removes regex check
256255
"session_number": shipment.visitNumber,
257256
"proposal": proposal_reference,
258257
"external_id": shipment.externalId,

src/scaup/models/inner_db/tables.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ class Base(DeclarativeBase):
2222

2323

2424
class BaseColumns:
25-
name: Mapped[str] = mapped_column(String(40))
25+
name: Mapped[str] = mapped_column(String(80))
2626
externalId: Mapped[int | None] = mapped_column(unique=True, comment="Item ID in ISPyB")
2727
comments: Mapped[str | None] = mapped_column(String(255))
2828
creationDate: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now())

src/scaup/routes/samples.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@
33

44
from ..auth import Permissions, auth_scheme
55
from ..crud import samples as crud
6-
from ..models.inner_db.tables import Sample
76
from ..models.samples import OptionalSample, SampleOut
8-
from ..utils.crud import delete_item
97

108
auth_sample = Permissions.sample
119

@@ -29,4 +27,4 @@ def edit_sample(
2927
@router.delete("/{sampleId}", status_code=status.HTTP_204_NO_CONTENT)
3028
def delete_sample(sampleId=Depends(auth_sample)):
3129
"""Create new sample in shipment"""
32-
return delete_item(table=Sample, item_id=sampleId)
30+
return crud.delete_sample(sample_id=sampleId)
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
def test_delete_with_parent(client):
2+
"""Should fail if sample is referenced in SampleParentChild"""
3+
4+
resp = client.delete(
5+
"/samples/1877",
6+
)
7+
8+
assert resp.status_code == 409

tests/shipments/test_create_request.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ def test_request_fail(client):
188188
def test_invalid_dewar_response_from_ispyb(client):
189189
"""Should throw error if ISPyB returns error when getting dewar from dewar registry"""
190190
responses.get(
191-
f"{Config.ispyb_api.url}/proposals/cm000003/dewar-registry/DLS-4",
191+
f"{Config.ispyb_api.url}/proposals/cm3/dewar-registry/DLS-4",
192192
status=404,
193193
json={},
194194
)

0 commit comments

Comments
 (0)