now associating a dewar to a slot
This commit is contained in:
parent
bf46a7ff37
commit
98d6265ae1
@ -79,7 +79,6 @@ class Dewar(Base):
|
|||||||
contact_person_id = Column(Integer, ForeignKey("contact_persons.id"))
|
contact_person_id = Column(Integer, ForeignKey("contact_persons.id"))
|
||||||
|
|
||||||
shipment = relationship("Shipment", back_populates="dewars")
|
shipment = relationship("Shipment", back_populates="dewars")
|
||||||
events = relationship("LogisticsEvent", back_populates="dewar")
|
|
||||||
return_address = relationship("Address")
|
return_address = relationship("Address")
|
||||||
contact_person = relationship("ContactPerson")
|
contact_person = relationship("ContactPerson")
|
||||||
pucks = relationship("Puck", back_populates="dewar")
|
pucks = relationship("Puck", back_populates="dewar")
|
||||||
@ -87,6 +86,7 @@ class Dewar(Base):
|
|||||||
dewar_type = relationship("DewarType")
|
dewar_type = relationship("DewarType")
|
||||||
dewar_serial_number = relationship("DewarSerialNumber")
|
dewar_serial_number = relationship("DewarSerialNumber")
|
||||||
slot = relationship("Slot", back_populates="dewar")
|
slot = relationship("Slot", back_populates="dewar")
|
||||||
|
events = relationship("LogisticsEvent", back_populates="dewar")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def number_of_pucks(self) -> int:
|
def number_of_pucks(self) -> int:
|
||||||
@ -147,6 +147,7 @@ class Slot(Base):
|
|||||||
time_until_refill = Column(Integer) # store as total seconds
|
time_until_refill = Column(Integer) # store as total seconds
|
||||||
dewar_unique_id = Column(String, ForeignKey('dewars.unique_id'), nullable=True) # Added field
|
dewar_unique_id = Column(String, ForeignKey('dewars.unique_id'), nullable=True) # Added field
|
||||||
dewar = relationship("Dewar", back_populates="slot")
|
dewar = relationship("Dewar", back_populates="slot")
|
||||||
|
events = relationship("LogisticsEvent", back_populates="slot")
|
||||||
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -155,13 +156,14 @@ class Slot(Base):
|
|||||||
return self.last_refill + self.time_until_refill - datetime.utcnow()
|
return self.last_refill + self.time_until_refill - datetime.utcnow()
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
class LogisticsEvent(Base):
|
class LogisticsEvent(Base):
|
||||||
__tablename__ = 'logistics_events'
|
__tablename__ = "logistics_events"
|
||||||
id = Column(Integer, primary_key=True, index=True, autoincrement=True)
|
|
||||||
dewar_id = Column(Integer, ForeignKey('dewars.id'), nullable=False)
|
|
||||||
event_type = Column(String, nullable=False)
|
|
||||||
timestamp = Column(DateTime, default=datetime.utcnow)
|
|
||||||
|
|
||||||
|
id = Column(Integer, primary_key=True, index=True)
|
||||||
|
dewar_id = Column(Integer, ForeignKey('dewars.id')) # corrected table name
|
||||||
|
slot_id = Column(Integer, ForeignKey('slots.id')) # corrected table name
|
||||||
|
event_type = Column(String, index=True)
|
||||||
|
timestamp = Column(DateTime, default=datetime.utcnow)
|
||||||
|
action_details = Column(String)
|
||||||
dewar = relationship("Dewar", back_populates="events")
|
dewar = relationship("Dewar", back_populates="events")
|
||||||
slot_id = Column(String, ForeignKey('slots.id'), nullable=True)
|
slot = relationship("Slot", back_populates="events")
|
@ -87,4 +87,22 @@ async def scan_dewar(event_data: LogisticsEventCreate, db: Session = Depends(get
|
|||||||
def log_event(db: Session, dewar_id: int, slot_id: int, event_type: str):
|
def log_event(db: Session, dewar_id: int, slot_id: int, event_type: str):
|
||||||
new_event = LogisticsEventModel(dewar_id=dewar_id, slot_id=slot_id, event_type=event_type)
|
new_event = LogisticsEventModel(dewar_id=dewar_id, slot_id=slot_id, event_type=event_type)
|
||||||
db.add(new_event)
|
db.add(new_event)
|
||||||
db.commit()
|
db.commit()
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/dewar/refill", response_model=dict)
|
||||||
|
async def refill_dewar(qr_code: str, db: Session = Depends(get_db)):
|
||||||
|
dewar = db.query(DewarModel).filter(DewarModel.unique_id == qr_code).first()
|
||||||
|
if not dewar:
|
||||||
|
raise HTTPException(status_code=404, detail="Dewar not found")
|
||||||
|
|
||||||
|
# Process refill
|
||||||
|
dewar.last_refill = datetime.now()
|
||||||
|
new_event = LogisticsEventModel(
|
||||||
|
dewar_id=dewar.id, slot_id=None, # No specific slot, as it's a refill event
|
||||||
|
event_type="refill",
|
||||||
|
action_details=f"{dewar.unique_id} refilled"
|
||||||
|
)
|
||||||
|
db.add(new_event)
|
||||||
|
db.commit()
|
||||||
|
return {"message": "Dewar refilled successfully"}
|
33
logistics/src/components/CountdownTimer.tsx
Normal file
33
logistics/src/components/CountdownTimer.tsx
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import React, { useEffect, useState } from 'react';
|
||||||
|
import { Typography } from '@mui/material';
|
||||||
|
|
||||||
|
interface CountdownTimerProps {
|
||||||
|
totalSeconds: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CountdownTimer: React.FC<CountdownTimerProps> = ({ totalSeconds }) => {
|
||||||
|
const [timeLeft, setTimeLeft] = useState(totalSeconds);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const timerId = setInterval(() => {
|
||||||
|
setTimeLeft(prev => Math.max(prev - 1, 0));
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
|
return () => clearInterval(timerId);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const formatTime = (seconds: number) => {
|
||||||
|
const hrs = Math.floor(seconds / 3600);
|
||||||
|
const min = Math.floor((seconds % 3600) / 60);
|
||||||
|
const sec = seconds % 60;
|
||||||
|
return `${hrs}h ${min}m ${sec}s`;
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Typography variant="body2" style={{ color: timeLeft < 300 ? 'red' : 'white' }} > {/* Warn with red color if less than 5 minutes */}
|
||||||
|
{`Time until refill: ${formatTime(timeLeft)}`}
|
||||||
|
</Typography>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CountdownTimer;
|
@ -2,6 +2,7 @@ import React from 'react';
|
|||||||
import { Box, Typography } from '@mui/material';
|
import { Box, Typography } from '@mui/material';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import LocalGasStationIcon from '@mui/icons-material/LocalGasStation'; // Icon for refilling indicator.
|
import LocalGasStationIcon from '@mui/icons-material/LocalGasStation'; // Icon for refilling indicator.
|
||||||
|
import CountdownTimer from './CountdownTimer'; // Import the CountdownTimer component
|
||||||
|
|
||||||
export interface SlotData {
|
export interface SlotData {
|
||||||
id: string;
|
id: string;
|
||||||
@ -12,6 +13,7 @@ export interface SlotData {
|
|||||||
dewar_unique_id?: string; // Optional additional information.
|
dewar_unique_id?: string; // Optional additional information.
|
||||||
dewar_name?: string; // Optional dewar information.
|
dewar_name?: string; // Optional dewar information.
|
||||||
needs_refill?: boolean; // Indicator for refill requirement.
|
needs_refill?: boolean; // Indicator for refill requirement.
|
||||||
|
time_until_refill?: number; // Time until refill in seconds, optional field
|
||||||
}
|
}
|
||||||
|
|
||||||
interface SlotProps {
|
interface SlotProps {
|
||||||
@ -24,7 +26,7 @@ const StyledSlot = styled(Box)<{ isSelected: boolean; isOccupied: boolean }>`
|
|||||||
padding: 16px;
|
padding: 16px;
|
||||||
margin: 8px;
|
margin: 8px;
|
||||||
width: 150px; // Increase the width to accommodate more info.
|
width: 150px; // Increase the width to accommodate more info.
|
||||||
height: 150px; // Increase the height to accommodate more info.
|
height: 200px; // Increase the height to accommodate more info.
|
||||||
background-color: ${({ isSelected, isOccupied }) =>
|
background-color: ${({ isSelected, isOccupied }) =>
|
||||||
isSelected ? '#3f51b5' : isOccupied ? '#f44336' : '#4caf50'};
|
isSelected ? '#3f51b5' : isOccupied ? '#f44336' : '#4caf50'};
|
||||||
color: white;
|
color: white;
|
||||||
@ -57,6 +59,10 @@ const Slot: React.FC<SlotProps> = ({ data, isSelected, onSelect }) => {
|
|||||||
<Typography variant="body2">{`ID: ${data.dewar_unique_id}`}</Typography>
|
<Typography variant="body2">{`ID: ${data.dewar_unique_id}`}</Typography>
|
||||||
)}
|
)}
|
||||||
{data.needs_refill && <LocalGasStationIcon />}
|
{data.needs_refill && <LocalGasStationIcon />}
|
||||||
|
{/* Display countdown timer only for slots that have an associated dewar */}
|
||||||
|
{data.dewar_unique_id && data.time_until_refill !== undefined && (
|
||||||
|
<CountdownTimer totalSeconds={data.time_until_refill} />
|
||||||
|
)}
|
||||||
</StyledSlot>
|
</StyledSlot>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user