Simplify currentPlan

This commit is contained in:
Roland Geider
2025-09-12 14:37:32 +02:00
parent 0fd2af030d
commit 6cc96310c5
5 changed files with 117 additions and 23 deletions

View File

@@ -74,7 +74,7 @@ class NutritionalPlan {
NutritionalPlan({
this.id,
required this.description,
required this.creationDate,
DateTime? creationDate,
required this.startDate,
this.endDate,
this.onlyLogging = false,
@@ -85,7 +85,7 @@ class NutritionalPlan {
this.goalFiber,
List<Meal>? meals,
List<Log>? diaryEntries,
}) {
}) : creationDate = creationDate ?? DateTime.now() {
this.meals = meals ?? [];
this.diaryEntries = diaryEntries ?? [];
}

View File

@@ -26,7 +26,8 @@ NutritionalPlan _$NutritionalPlanFromJson(Map<String, dynamic> json) {
return NutritionalPlan(
id: (json['id'] as num?)?.toInt(),
description: json['description'] as String,
creationDate: DateTime.parse(json['creation_date'] as String),
creationDate:
json['creation_date'] == null ? null : DateTime.parse(json['creation_date'] as String),
startDate: DateTime.parse(json['start'] as String),
endDate: json['end'] == null ? null : DateTime.parse(json['end'] as String),
onlyLogging: json['only_logging'] as bool? ?? false,

View File

@@ -18,6 +18,7 @@
import 'dart:convert';
import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
import 'package:logging/logging.dart';
import 'package:wger/core/locator.dart';
@@ -72,25 +73,13 @@ class NutritionPlansProvider with ChangeNotifier {
/// - Its end date is after now or not set
/// If multiple plans match these criteria, the one with the most recent creation date is returned.
NutritionalPlan? get currentPlan {
if (_plans.isEmpty) {
return null;
}
final now = DateTime.now();
final activePlans = _plans.where((plan) {
final isAfterStart = plan.startDate.isBefore(now);
final isBeforeEnd = plan.endDate == null || plan.endDate!.isAfter(now);
return isAfterStart && isBeforeEnd;
}).toList();
if (activePlans.isEmpty) {
return null;
}
// Sort by creation date (newest first) and return the first one
// TODO: this should already be done on _plans. this whole function can be a firstWhere() ?
activePlans.sort((a, b) => b.creationDate.compareTo(a.creationDate));
return activePlans.first;
return _plans
.where((plan) =>
plan.startDate.isBefore(now) && (plan.endDate == null || plan.endDate!.isAfter(now)))
.toList()
.sorted((a, b) => b.creationDate.compareTo(a.creationDate))
.firstOrNull;
}
NutritionalPlan findById(int id) {

View File

@@ -744,10 +744,10 @@ packages:
dependency: transitive
description:
name: leak_tracker
sha256: "8dcda04c3fc16c14f48a7bb586d4be1f0d1572731b6d81d51772ef47c02081e0"
sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de"
url: "https://pub.dev"
source: hosted
version: "11.0.1"
version: "11.0.2"
leak_tracker_flutter_testing:
dependency: transitive
description:

View File

@@ -5,12 +5,14 @@ import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/mockito.dart';
import 'package:wger/database/ingredients/ingredients_database.dart';
import 'package:wger/models/nutrition/ingredient.dart';
import 'package:wger/models/nutrition/nutritional_plan.dart';
import 'package:wger/providers/nutrition.dart';
import '../fixtures/fixture_reader.dart';
import '../measurements/measurement_provider_test.mocks.dart';
void main() {
final now = DateTime.now();
late NutritionPlansProvider nutritionProvider;
late MockWgerBaseProvider mockWgerBaseProvider;
late IngredientDatabase database;
@@ -110,6 +112,108 @@ void main() {
});
});
group('currentPlan', () {
test('gibt den aktiven Plan zurück, wenn nur einer aktiv ist', () {
final plan = NutritionalPlan(
id: 1,
description: 'Aktiver Plan',
startDate: now.subtract(const Duration(days: 1)),
endDate: now.add(const Duration(days: 1)),
creationDate: now.subtract(const Duration(days: 2)),
);
nutritionProvider = NutritionPlansProvider(mockWgerBaseProvider, [plan], database: database);
expect(nutritionProvider.currentPlan, equals(plan));
});
test('gibt den neuesten aktiven Plan zurück, wenn mehrere aktiv sind', () {
final olderPlan = NutritionalPlan(
id: 1,
description: 'Älterer aktiver Plan',
startDate: now.subtract(const Duration(days: 10)),
endDate: now.add(const Duration(days: 10)),
creationDate: now.subtract(const Duration(days: 10)),
);
final newerPlan = NutritionalPlan(
id: 2,
description: 'Neuerer aktiver Plan',
startDate: now.subtract(const Duration(days: 5)),
endDate: now.add(const Duration(days: 5)),
creationDate: now.subtract(const Duration(days: 2)),
);
nutritionProvider =
NutritionPlansProvider(mockWgerBaseProvider, [olderPlan, newerPlan], database: database);
expect(nutritionProvider.currentPlan, equals(newerPlan));
});
});
group('currentPlan correctly returns the active plan', () {
test('no plans available -> null', () {
nutritionProvider = NutritionPlansProvider(mockWgerBaseProvider, [], database: database);
expect(nutritionProvider.currentPlan, isNull);
});
test('no active plan -> null', () {
final plans = [
NutritionalPlan(
id: 1,
description: 'plan 1',
startDate: now.subtract(const Duration(days: 30)),
endDate: now.subtract(const Duration(days: 5)),
),
NutritionalPlan(
id: 2,
description: 'plan 2',
startDate: now.add(const Duration(days: 100)),
endDate: now.add(const Duration(days: 50)),
),
];
nutritionProvider = NutritionPlansProvider(mockWgerBaseProvider, plans, database: database);
expect(nutritionProvider.currentPlan, isNull);
});
test('active plan exists -> return it', () {
final plan = NutritionalPlan(
description: 'Active plan',
startDate: now.subtract(const Duration(days: 10)),
endDate: now.add(const Duration(days: 10)),
);
nutritionProvider = NutritionPlansProvider(mockWgerBaseProvider, [plan], database: database);
expect(nutritionProvider.currentPlan, equals(plan));
});
test('inactive plans are ignored', () {
final inactivePlan = NutritionalPlan(
description: 'Inactive plan',
startDate: now.subtract(const Duration(days: 10)),
endDate: now.add(const Duration(days: 5)),
);
final plan = NutritionalPlan(
description: 'Active plan',
startDate: now.subtract(const Duration(days: 10)),
endDate: now.add(const Duration(days: 10)),
);
nutritionProvider =
NutritionPlansProvider(mockWgerBaseProvider, [plan, inactivePlan], database: database);
expect(nutritionProvider.currentPlan, equals(plan));
});
test('several active plans exists -> return newest', () {
final olderPlan = NutritionalPlan(
description: 'Old active plan',
startDate: now.subtract(const Duration(days: 10)),
endDate: now.add(const Duration(days: 10)),
);
final newerPlan = NutritionalPlan(
description: 'Newer active plan',
startDate: now.subtract(const Duration(days: 5)),
endDate: now.add(const Duration(days: 5)),
);
nutritionProvider =
NutritionPlansProvider(mockWgerBaseProvider, [olderPlan, newerPlan], database: database);
expect(nutritionProvider.currentPlan, equals(newerPlan));
});
});
group('Ingredient cache DB', () {
test('that if there is already valid data in the DB, the API is not hit', () async {
// Arrange