Skip to content

Commit

Permalink
Merge branch 'feature/yearly-report2' into test-prod
Browse files Browse the repository at this point in the history
  • Loading branch information
jhagberg committed Jan 1, 2025
2 parents 206cc5b + b7f1853 commit 8679a54
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 75 deletions.
3 changes: 3 additions & 0 deletions app/utils/data_access.py
Original file line number Diff line number Diff line change
Expand Up @@ -2543,6 +2543,7 @@ def get_yearly_reports(round_id: int, genebank_id: int) -> List[Dict]:
"submission_date": (
r.report_date.strftime("%Y-%m-%d") if r.report_date else None
),
"fullname": r.generated_by.fullname,
}
formatted_reports.append(report)

Expand Down Expand Up @@ -2593,6 +2594,7 @@ def export_yearly_reports_csv(round_id: int, genebank_id: int) -> str:
"Defekter/missbildningar",
"Sjukdomsfall under året",
"Datum för ifyllnad",
"Ifylld av",
]

# Create output lines
Expand Down Expand Up @@ -2620,6 +2622,7 @@ def export_yearly_reports_csv(round_id: int, genebank_id: int) -> str:
report["defects_malformations"] or "",
report["disease_cases"] or "Inga rapporterade sjukdomsfall",
report["submission_date"] or "",
report["fullname"] or "",
]
# Escape semicolons in fields and wrap in quotes if needed
escaped_row = [
Expand Down
108 changes: 66 additions & 42 deletions frontend/src/BatchRabbitUpdateForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import { dateFormat, inputVariant, BodyFat } from "@app/data_context_global";
import {
filterRabbitsForYearlyReport,
Individual,
hasValidTrackingInPeriod,
} from "./utils/rabbit_filters";
import { RabbitList } from "./BatchRabbitUpdateStep";

Expand Down Expand Up @@ -96,6 +97,7 @@ const BatchRabbitUpdateForm: React.FC<BatchRabbitUpdateFormProps> = ({
const [rabbits, setRabbits] = useState<RabbitData[]>([]);
const [loading, setLoading] = useState(true);
const [isCompleted, setIsCompleted] = useState(false);
const [reportRound, setReportRound] = useState<any>(null);
const { userMessage } = useMessageContext();
const { loadData } = useDataContext();

Expand Down Expand Up @@ -127,6 +129,7 @@ const BatchRabbitUpdateForm: React.FC<BatchRabbitUpdateFormProps> = ({
setLoading(false);
return;
}
setReportRound(reportRound);
const startDate = new Date(`${reportYear}-12-01`);
const endDate = new Date(reportRound.end_date);

Expand All @@ -143,10 +146,8 @@ const BatchRabbitUpdateForm: React.FC<BatchRabbitUpdateFormProps> = ({

// Initialize rabbit data for those needing updates
const rabbitDataList: RabbitData[] = needUpdate.map((individual) => {
const hasValidTracking = individual.herd_tracking?.some(
(tracking: { date: string }) =>
new Date(tracking.date) >= new Date(`${reportYear}-12-31`)
);
// Default date for new measurements
const defaultDate = new Date(`${reportYear}-12-31`);

// Check for existing weight/bodyfat in the period
const periodWeight = individual.weights?.find((w) => {
Expand All @@ -159,9 +160,6 @@ const BatchRabbitUpdateForm: React.FC<BatchRabbitUpdateFormProps> = ({
return bfDate >= startDate && bfDate <= endDate;
}) as Bodyfat | undefined;

// Default date for new measurements
const defaultDate = new Date(`${reportYear}-12-31`);

return {
individual,
isAlive: true,
Expand All @@ -170,7 +168,7 @@ const BatchRabbitUpdateForm: React.FC<BatchRabbitUpdateFormProps> = ({
weightDate: periodWeight
? new Date(periodWeight.date)
: defaultDate,
bodyFat: periodBodyfat ? periodBodyfat.bodyfat : "normal",
bodyFat: periodBodyfat ? periodBodyfat.bodyfat : "",
bodyFatDate: periodBodyfat
? new Date(periodBodyfat.date)
: defaultDate,
Expand Down Expand Up @@ -205,16 +203,24 @@ const BatchRabbitUpdateForm: React.FC<BatchRabbitUpdateFormProps> = ({
`Ange ett dödsdatum för kaninen ${rabbit.individual.name} ${rabbit.individual.number}.`
);
}
if (rabbit.isAlive) {
if (!rabbit.weight || !rabbit.weightDate) {
errors.push(
`Ange vikt och viktdatum för kaninen ${rabbit.individual.name} ${rabbit.individual.number}.`
);
}
if (!rabbit.bodyFat || !rabbit.bodyFatDate) {
errors.push(
`Ange hull och hulldatum för kaninen ${rabbit.individual.name} ${rabbit.individual.number}.`
);
if (rabbit.isAlive && reportYear) {
// Check if rabbit was born during the report year
const birthYear = rabbit.individual.birth_date
? new Date(rabbit.individual.birth_date).getFullYear()
: 0;
const requireMeasurements = birthYear < reportYear;

if (requireMeasurements) {
if (!rabbit.weight || !rabbit.weightDate) {
errors.push(
`Ange vikt och viktdatum för kaninen ${rabbit.individual.name} ${rabbit.individual.number}.`
);
}
if (!rabbit.bodyFat || !rabbit.bodyFatDate) {
errors.push(
`Ange hull och hulldatum för kaninen ${rabbit.individual.name} ${rabbit.individual.number}.`
);
}
}
}
}
Expand All @@ -233,11 +239,11 @@ const BatchRabbitUpdateForm: React.FC<BatchRabbitUpdateFormProps> = ({
};

if (rabbit.isAlive) {
// Check if we have tracking on or after report date
const latestTracking = rabbit.individual.herd_tracking?.[0];
const hasValidTracking =
latestTracking &&
new Date(latestTracking.date) >= new Date(rabbit.reportDate || "");
// Check if we have tracking on or after report date using shared function
const hasValidTracking = hasValidTrackingInPeriod(
rabbit.individual,
reportYear!
);

// Only include yearly_report_date if no valid tracking exists
if (rabbit.reportDate && !hasValidTracking) {
Expand Down Expand Up @@ -303,11 +309,12 @@ const BatchRabbitUpdateForm: React.FC<BatchRabbitUpdateFormProps> = ({
return <div>Laddar...</div>;
}

if (isCompleted && reportYear) {
if (isCompleted && reportYear && reportRound) {
return (
<RabbitList
rabbits={rabbits.map((r) => r.individual)}
reportYear={reportYear}
reportRoundEndDate={reportRound.end_date}
/>
);
}
Expand Down Expand Up @@ -436,25 +443,42 @@ const BatchRabbitUpdateForm: React.FC<BatchRabbitUpdateFormProps> = ({
/>
</Grid>
<Grid item xs={12} sm={6}>
<TextField
label="Hull"
variant={inputVariant}
select
SelectProps={{
native: true,
}}
value={rabbit.bodyFat}
onChange={(e) => {
const updatedRabbits = [...rabbits];
updatedRabbits[index].bodyFat = e.target.value;
setRabbits(updatedRabbits);
}}
fullWidth
<FormControl
component="fieldset"
className={classes.wideControl}
>
<option value="low">Låg</option>
<option value="normal">Normal</option>
<option value="high">Hög</option>
</TextField>
<FormLabel component="legend">Hull</FormLabel>
<RadioGroup
row
value={rabbit.bodyFat}
onChange={(e) => {
const updatedRabbits = [...rabbits];
updatedRabbits[index].bodyFat = e.target.value;
setRabbits(updatedRabbits);
}}
>
<FormControlLabel
value=""
control={<Radio />}
label="Ej angett"
/>
<FormControlLabel
value="low"
control={<Radio />}
label="Under"
/>
<FormControlLabel
value="normal"
control={<Radio />}
label="Normal"
/>
<FormControlLabel
value="high"
control={<Radio />}
label="Över"
/>
</RadioGroup>
</FormControl>
</Grid>
<Grid item xs={12} sm={6}>
<KeyboardDatePicker
Expand Down
34 changes: 26 additions & 8 deletions frontend/src/BatchRabbitUpdateStep.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,6 @@ export const RabbitList: React.FC<{

return (
<div>
<Typography>
Alla kaniner har redan uppdaterad information. Detta steg kan hoppas
över.
</Typography>
<Typography variant="h6" style={{ marginTop: "1em" }}>
Följande kaniner kommer att inkluderas i årsrapporten:
</Typography>
Expand Down Expand Up @@ -110,8 +106,8 @@ export const BatchRabbitUpdateStep: React.FC<BatchRabbitUpdateStepProps> = ({
reportYear,
onUpdateStatus,
}) => {
const [skipStep, setSkipStep] = useState(false);
const [loading, setLoading] = useState(true);
const [skipStep, setSkipStep] = useState(false);
const [skippedRabbits, setSkippedRabbits] = useState<Individual[]>([]);
const [reportRound, setReportRound] = useState<any>(null);
const { userMessage } = useMessageContext();
Expand Down Expand Up @@ -156,10 +152,14 @@ export const BatchRabbitUpdateStep: React.FC<BatchRabbitUpdateStepProps> = ({
herdId
);

setSkippedRabbits(canSkip);
// If all rabbits can be skipped, show the list immediately
if (needUpdate.length === 0) {
setSkippedRabbits([...canSkip]);
setSkipStep(true);
onUpdateStatus?.("completed");
} else {
// Otherwise, show the form with rabbits that need updates
setSkippedRabbits(canSkip);
}
} catch (error) {
console.error(error);
Expand Down Expand Up @@ -205,9 +205,27 @@ export const BatchRabbitUpdateStep: React.FC<BatchRabbitUpdateStepProps> = ({
reportYear={reportYear}
reportRoundId={reportRoundId}
onUpdateStatus={onUpdateStatus}
onUpdateComplete={() => {
onUpdateComplete={async () => {
if (herdId && reportYear && reportRoundId) {
fetchValidRabbits(herdId, reportYear, reportRoundId);
// Fetch all rabbits again to get the complete list
const herdResponse = await get(`/api/herd/${herdId}`);
const individualsData = herdResponse.individuals || [];
const startDate = new Date(`${reportYear}-12-01`);
const endDate = new Date(reportRound.end_date);

// Filter rabbits using the shared filtering logic
const { needUpdate, canSkip } = filterRabbitsForYearlyReport(
individualsData,
reportYear,
startDate,
endDate,
herdId
);

// Set both lists to show all rabbits that will be in the report
setSkippedRabbits([...needUpdate, ...canSkip]);
setSkipStep(true);
onUpdateStatus?.("completed");
}
}}
/>
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/SelectHerdStep.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ export const SelectHerdStep: React.FC<SelectHerdStepProps> = ({
},
(error) => {
userMessage("Kunde inte hämta kullar.", "error");
console.error("Failed to fetch breedings:", error);
}
);
} else {
Expand Down Expand Up @@ -215,7 +216,7 @@ export const SelectHerdStep: React.FC<SelectHerdStepProps> = ({
// Helper function to determine if a row should be highlighted
const getRowStyle = (breeding: any) => {
// Red background for missing birth date or missing litter size at 6 weeks
if (!breeding.birth_date || breeding.litter_size6w === undefined) {
if (!breeding.birth_date || breeding.litter_size6w == null) {
return { backgroundColor: "#ffebee" }; // Light red background
}
// Yellow background when litter size at 6 weeks is 0 (for verification)
Expand Down
3 changes: 3 additions & 0 deletions frontend/src/YearlyReportViewer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ interface YearlyReport {
defects_malformations: string;
disease_cases: string;
submission_date: string;
fullname?: string;
}

/**
Expand Down Expand Up @@ -209,6 +210,7 @@ export function YearlyReportViewer() {
<TableCell>Defekter/missbildningar</TableCell>
<TableCell>Sjukdomsfall under året</TableCell>
<TableCell>Datum för ifyllnad</TableCell>
<TableCell>Ifylld av</TableCell>
</TableRow>
</TableHead>
<TableBody>
Expand All @@ -234,6 +236,7 @@ export function YearlyReportViewer() {
<TableCell>{report.defects_malformations}</TableCell>
<TableCell>{report.disease_cases}</TableCell>
<TableCell>{report.submission_date}</TableCell>
<TableCell>{report.fullname}</TableCell>
</TableRow>
))}
</TableBody>
Expand Down
Loading

0 comments on commit 8679a54

Please sign in to comment.