added dewar type, serial number, generate unique id, qr code and generate label
This commit is contained in:
@ -1,26 +1,50 @@
|
||||
from fastapi import APIRouter, HTTPException, status, Depends
|
||||
from fastapi import APIRouter, HTTPException, status, Depends, Response
|
||||
from sqlalchemy.orm import Session, joinedload
|
||||
from typing import List
|
||||
import logging
|
||||
from sqlalchemy.exc import SQLAlchemyError
|
||||
from pydantic import ValidationError
|
||||
from app.schemas import Dewar as DewarSchema, DewarCreate, DewarUpdate
|
||||
from app.models import Dewar as DewarModel, Puck as PuckModel, \
|
||||
Sample as SampleModel # Assuming SampleModel is defined in models
|
||||
from app.schemas import (
|
||||
Dewar as DewarSchema,
|
||||
DewarCreate,
|
||||
DewarUpdate,
|
||||
DewarType as DewarTypeSchema,
|
||||
DewarTypeCreate,
|
||||
DewarSerialNumber as DewarSerialNumberSchema,
|
||||
DewarSerialNumberCreate
|
||||
)
|
||||
from app.models import (
|
||||
Dewar as DewarModel,
|
||||
Puck as PuckModel,
|
||||
Sample as SampleModel,
|
||||
DewarType as DewarTypeModel,
|
||||
DewarSerialNumber as DewarSerialNumberModel
|
||||
)
|
||||
from app.dependencies import get_db
|
||||
import uuid
|
||||
import qrcode
|
||||
import io
|
||||
from io import BytesIO
|
||||
from PIL import Image
|
||||
from reportlab.lib.pagesizes import A5
|
||||
from reportlab.lib.units import cm
|
||||
from reportlab.pdfgen import canvas
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.get("/", response_model=List[DewarSchema])
|
||||
async def get_dewars(db: Session = Depends(get_db)):
|
||||
dewars = db.query(DewarModel).options(joinedload(DewarModel.pucks)).all()
|
||||
return dewars
|
||||
|
||||
def generate_unique_id(db: Session) -> str:
|
||||
while True:
|
||||
unique_id = str(uuid.uuid4())
|
||||
existing_dewar = db.query(DewarModel).filter(DewarModel.unique_id == unique_id).first()
|
||||
if not existing_dewar:
|
||||
break
|
||||
return unique_id
|
||||
|
||||
@router.post("/", response_model=DewarSchema, status_code=status.HTTP_201_CREATED)
|
||||
async def create_dewar(dewar: DewarCreate, db: Session = Depends(get_db)) -> DewarSchema:
|
||||
try:
|
||||
unique_id = generate_unique_id(db)
|
||||
db_dewar = DewarModel(
|
||||
dewar_name=dewar.dewar_name,
|
||||
tracking_number=dewar.tracking_number,
|
||||
@ -29,11 +53,10 @@ async def create_dewar(dewar: DewarCreate, db: Session = Depends(get_db)) -> Dew
|
||||
shipping_date=dewar.shipping_date,
|
||||
arrival_date=dewar.arrival_date,
|
||||
returning_date=dewar.returning_date,
|
||||
qrcode=dewar.qrcode,
|
||||
contact_person_id=dewar.contact_person_id,
|
||||
return_address_id=dewar.return_address_id
|
||||
return_address_id=dewar.return_address_id,
|
||||
unique_id=unique_id
|
||||
)
|
||||
|
||||
db.add(db_dewar)
|
||||
db.commit()
|
||||
db.refresh(db_dewar)
|
||||
@ -54,7 +77,6 @@ async def create_dewar(dewar: DewarCreate, db: Session = Depends(get_db)) -> Dew
|
||||
puck_id=puck.id,
|
||||
sample_name=sample_data.sample_name,
|
||||
position=sample_data.position,
|
||||
# Ensure only valid attributes are set
|
||||
data_collection_parameters=sample_data.data_collection_parameters,
|
||||
)
|
||||
db.add(sample)
|
||||
@ -70,24 +92,142 @@ async def create_dewar(dewar: DewarCreate, db: Session = Depends(get_db)) -> Dew
|
||||
logging.error(f"Validation error occurred: {e}")
|
||||
raise HTTPException(status_code=400, detail="Validation error")
|
||||
|
||||
@router.post("/{dewar_id}/generate-qrcode")
|
||||
async def generate_dewar_qrcode(dewar_id: int, db: Session = Depends(get_db)):
|
||||
dewar = db.query(DewarModel).filter(DewarModel.id == dewar_id).first()
|
||||
if not dewar:
|
||||
raise HTTPException(status_code=404, detail="Dewar not found")
|
||||
|
||||
if not dewar.unique_id:
|
||||
dewar.unique_id = generate_unique_id(db)
|
||||
|
||||
qr = qrcode.QRCode(version=1, box_size=10, border=5)
|
||||
qr.add_data(dewar.unique_id)
|
||||
qr.make(fit=True)
|
||||
img = qr.make_image(fill='black', back_color='white')
|
||||
|
||||
buf = io.BytesIO()
|
||||
img.save(buf)
|
||||
buf.seek(0)
|
||||
dewar.qrcode = dewar.unique_id
|
||||
dewar.qrcode_image = buf.getvalue()
|
||||
db.commit()
|
||||
|
||||
return {"message": "QR Code generated", "qrcode": dewar.unique_id}
|
||||
|
||||
|
||||
def generate_label(dewar):
|
||||
buffer = BytesIO()
|
||||
c = canvas.Canvas(buffer, pagesize=A5)
|
||||
|
||||
# Draw header
|
||||
c.setFont("Helvetica-Bold", 16)
|
||||
c.drawCentredString(10.5 * cm, 14 * cm, "COMPANY LOGO / TITLE")
|
||||
|
||||
# Draw details section
|
||||
c.setFont("Helvetica", 12)
|
||||
c.drawString(2 * cm, 12.5 * cm, f"Dewar Name: {dewar.dewar_name}")
|
||||
c.drawString(2 * cm, 11.5 * cm, f"Unique ID: {dewar.unique_id}")
|
||||
if dewar.dewar_type:
|
||||
c.drawString(2 * cm, 10.5 * cm, f"Dewar Type: {dewar.dewar_type.dewar_type}")
|
||||
else:
|
||||
c.drawString(2 * cm, 10.5 * cm, "Dewar Type: Unknown")
|
||||
c.drawString(2 * cm, 9.5 * cm, "Beamtime Information: Placeholder")
|
||||
|
||||
# Generate QR code
|
||||
qr = qrcode.QRCode(version=1, box_size=10, border=5)
|
||||
qr.add_data(dewar.unique_id)
|
||||
qr.make(fit=True)
|
||||
img = qr.make_image(fill='black', back_color='white')
|
||||
qr_io = BytesIO()
|
||||
img.save(qr_io, format='PNG')
|
||||
qr_io.seek(0)
|
||||
qr_image = Image.open(qr_io)
|
||||
|
||||
# Add QR code to PDF
|
||||
c.drawInlineImage(qr_image, 8 * cm, 5 * cm, width=4 * cm, height=4 * cm)
|
||||
|
||||
# Add footer text
|
||||
c.setFont("Helvetica", 10)
|
||||
c.drawCentredString(10.5 * cm, 4 * cm, "Scan for more information")
|
||||
|
||||
# Draw border
|
||||
c.rect(1 * cm, 3 * cm, 18 * cm, 12 * cm)
|
||||
|
||||
# Finalize the canvas
|
||||
c.showPage()
|
||||
c.save()
|
||||
|
||||
buffer.seek(0)
|
||||
return buffer
|
||||
|
||||
@router.get("/{dewar_id}/download-label", response_class=Response)
|
||||
async def download_dewar_label(dewar_id: int, db: Session = Depends(get_db)):
|
||||
dewar = db.query(DewarModel).options(joinedload(DewarModel.dewar_type)).filter(DewarModel.id == dewar_id).first()
|
||||
if not dewar:
|
||||
raise HTTPException(status_code=404, detail="Dewar not found")
|
||||
if not dewar.unique_id:
|
||||
raise HTTPException(status_code=404, detail="QR Code not generated for this dewar")
|
||||
|
||||
buffer = generate_label(dewar)
|
||||
|
||||
return Response(buffer.getvalue(), media_type="application/pdf", headers={
|
||||
"Content-Disposition": f"attachment; filename=dewar_label_{dewar.id}.pdf"
|
||||
})
|
||||
|
||||
@router.get("/", response_model=List[DewarSchema])
|
||||
async def get_dewars(db: Session = Depends(get_db)):
|
||||
try:
|
||||
dewars = db.query(DewarModel).options(joinedload(DewarModel.pucks)).all()
|
||||
return dewars
|
||||
except SQLAlchemyError as e:
|
||||
logging.error(f"Database error occurred: {e}")
|
||||
raise HTTPException(status_code=500, detail="Internal server error")
|
||||
|
||||
@router.get("/dewar-types", response_model=List[DewarTypeSchema])
|
||||
def get_dewar_types(db: Session = Depends(get_db)):
|
||||
return db.query(DewarTypeModel).all()
|
||||
|
||||
@router.get("/dewar-types/{type_id}/serial-numbers", response_model=List[DewarSerialNumberSchema])
|
||||
def get_serial_numbers(type_id: int, db: Session = Depends(get_db)):
|
||||
return db.query(DewarSerialNumberModel).filter(DewarSerialNumberModel.dewar_type_id == type_id).all()
|
||||
|
||||
@router.post("/dewar-types", response_model=DewarTypeSchema)
|
||||
def create_dewar_type(dewar_type: DewarTypeCreate, db: Session = Depends(get_db)):
|
||||
db_type = DewarTypeModel(**dewar_type.dict())
|
||||
db.add(db_type)
|
||||
db.commit()
|
||||
db.refresh(db_type)
|
||||
return db_type
|
||||
|
||||
@router.post("/dewar-serial-numbers", response_model=DewarSerialNumberSchema)
|
||||
def create_dewar_serial_number(serial_number: DewarSerialNumberCreate, db: Session = Depends(get_db)):
|
||||
db_serial = DewarSerialNumberModel(**serial_number.dict())
|
||||
db.add(db_serial)
|
||||
db.commit()
|
||||
db.refresh(db_serial)
|
||||
return db_serial
|
||||
|
||||
@router.get("/dewar-serial-numbers", response_model=List[DewarSerialNumberSchema])
|
||||
def get_all_serial_numbers(db: Session = Depends(get_db)):
|
||||
try:
|
||||
serial_numbers = db.query(DewarSerialNumberModel).all()
|
||||
return serial_numbers
|
||||
except SQLAlchemyError as e:
|
||||
logging.error(f"Database error occurred: {e}")
|
||||
raise HTTPException(status_code=500, detail="Internal server error")
|
||||
|
||||
@router.get("/{dewar_id}", response_model=DewarSchema)
|
||||
async def get_dewar(dewar_id: int, db: Session = Depends(get_db)):
|
||||
dewar = db.query(DewarModel).options(
|
||||
joinedload(DewarModel.pucks).joinedload(PuckModel.positions)
|
||||
joinedload(DewarModel.pucks).joinedload(PuckModel.samples)
|
||||
).filter(DewarModel.id == dewar_id).first()
|
||||
|
||||
if not dewar:
|
||||
raise HTTPException(status_code=404, detail="Dewar not found")
|
||||
|
||||
# Ensure dewar.pucks is an empty list if there are no pucks
|
||||
dewar_dict = dewar.__dict__
|
||||
if dewar_dict.get("pucks") is None:
|
||||
dewar_dict["pucks"] = []
|
||||
|
||||
return DewarSchema.from_orm(dewar)
|
||||
|
||||
|
||||
@router.put("/{dewar_id}", response_model=DewarSchema)
|
||||
async def update_dewar(dewar_id: int, dewar_update: DewarUpdate, db: Session = Depends(get_db)) -> DewarSchema:
|
||||
dewar = db.query(DewarModel).filter(DewarModel.id == dewar_id).first()
|
||||
@ -96,22 +236,20 @@ async def update_dewar(dewar_id: int, dewar_update: DewarUpdate, db: Session = D
|
||||
raise HTTPException(status_code=404, detail="Dewar not found")
|
||||
|
||||
for key, value in dewar_update.dict(exclude_unset=True).items():
|
||||
# Ensure we're only setting directly settable attributes
|
||||
if hasattr(dewar, key):
|
||||
setattr(dewar, key, value)
|
||||
|
||||
db.commit()
|
||||
db.refresh(dewar)
|
||||
|
||||
return dewar
|
||||
|
||||
|
||||
@router.delete("/{dewar_id}", status_code=status.HTTP_204_NO_CONTENT)
|
||||
async def delete_dewar(dewar_id: int, db: Session = Depends(get_db)):
|
||||
dewar = db.query(DewarModel).filter(DewarModel.id == dewar_id).first()
|
||||
|
||||
if not dewar:
|
||||
raise HTTPException(status_code=404, detail="Dewar not found")
|
||||
|
||||
db.delete(dewar)
|
||||
db.commit()
|
||||
return
|
||||
return
|
Reference in New Issue
Block a user