Commit e30ebb2
Changed files (4)
health_data_store
lib
src
test
src
repositories
health_data_store/lib/src/repositories/medicine_repository.dart
@@ -1,33 +1,67 @@
import 'package:health_data_store/src/database_manager.dart';
-import 'package:health_data_store/src/repositories/repository.dart';
-import 'package:health_data_store/src/types/date_range.dart';
import 'package:health_data_store/src/types/medicine.dart';
import 'package:sqflite_common/sqflite.dart';
/// Repository for medicines that are taken by the user.
-class MedicineRepository extends Repository<Medicine> {
+class MedicineRepository {
/// Create the medicine repository.
MedicineRepository(this._db);
/// The [DatabaseManager] managed database.
final Database _db;
- @override
- Future<void> add(Medicine value) {
- // TODO: implement add
- throw UnimplementedError();
- }
+ /// Store a [Medicine] in the repository.
+ Future<void> add(Medicine medicine) => _db.transaction((txn) async {
+ final idRes = await txn.query('Medicine', columns: ['MAX(medID)']);
+ final id = (idRes.firstOrNull?['MAX(medID)']?.castOrNull<int>() ?? 0) + 1;
+ await txn.insert('Medicine', {
+ 'medID': id,
+ 'designation': medicine.designation,
+ 'defaultDose': medicine.dosis,
+ 'color': medicine.color,
+ 'removed': 0,
+ });
+ });
- @override
- Future<List<Medicine>> get(DateRange range) {
- // TODO: implement get
- throw UnimplementedError();
- }
+ /// Get a list of all stored Medicines that haven't been marked as removed.
+ Future<List<Medicine>> getAll() async {
+ final medData = await _db.query('Medicine',
+ columns: ['designation', 'defaultDose', 'color'],
+ where: 'removed = false'
+ );
+ final meds = <Medicine>[];
+ for (final m in medData) {
+ meds.add(Medicine(
+ designation: m['designation'].toString(),
+ dosis: m['defaultDose'] as double?,
+ color: m['color'] as int?,
+ ));
+ }
- @override
- Future<void> remove(Medicine value) {
- // TODO: implement remove
- throw UnimplementedError();
+ return meds;
}
+ /// Mark a medicine as deleted.
+ ///
+ /// Intakes will be deleted as soon as there is no [MedicineIntake]s
+ /// referencing them. They need to be stored to allow intakes of them to be
+ /// still displayed correctly.
+ Future<void> remove(Medicine value) => _db.update('Medicine', {
+ 'removed': 1,
+ },
+ where: 'designation = ? AND color = ? AND defaultDose = ?',
+ whereArgs: [
+ value.designation,
+ value.color,
+ value.dosis,
+ ], // TODO: test for null values
+ );
+
+}
+
+extension _Castable on Object {
+ T? castOrNull<T>() {
+ if (this is T) return this as T;
+ return null;
+ }
}
health_data_store/lib/src/types/medicine.dart
@@ -15,6 +15,6 @@ class Medicine with _$Medicine {
/// Sample value: `0xFF42A5F5`
int? color,
/// Default dosis of medication.
- int? dosis,
+ double? dosis,
}) = _Medicine;
}
health_data_store/lib/src/database_manager.dart
@@ -9,6 +9,7 @@ import 'package:sqflite_common/sqlite_api.dart';
/// ## DB scheme
///
/// 
+/// // TODO: replace with updating file once merged
///
/// ## Types
/// Data in the database tries to always use the most common SI-units.
@@ -50,6 +51,8 @@ class DatabaseManager {
'"medID" INTEGER NOT NULL UNIQUE,'
'"designation" TEXT NOT NULL,'
'"defaultDose" REAL,'
+ '"color" INTEGER,'
+ '"removed" BOOLEAN,'
'PRIMARY KEY("medID")'
');');
await _db.execute('CREATE TABLE "Timestamps" ('
@@ -88,4 +91,7 @@ class DatabaseManager {
/// Closes the database.
Future<void> close() => _db.close();
+
+ // TODO: perform cleanup of medicines that are marked as deleted and have no
+ // intakes referencing them.
}
health_data_store/test/src/repositories/medicine_repository_test.dart
@@ -0,0 +1,76 @@
+import 'package:health_data_store/health_data_store.dart';
+import 'package:test/expect.dart';
+import 'package:test/scaffolding.dart';
+
+import '../database_manager_test.dart';
+
+void main() {
+ sqfliteTestInit();
+ test('should initialize', () async {
+ final db = await mockDBManager();
+ addTearDown(db.close);
+ MedicineRepository(db.db);
+ });
+ test('should return no medicines when no are added', () async {
+ final db = await mockDBManager();
+ addTearDown(db.close);
+ final repo = MedicineRepository(db.db);
+ final all = await repo.getAll();
+ expect(all, isEmpty);
+ });
+ test('should store all complete medicines', () async {
+ final db = await mockDBManager();
+ addTearDown(db.close);
+ final repo = MedicineRepository(db.db);
+ await repo.add(Medicine(designation: 'med1', color: 0xFF226A, dosis: 42));
+ await repo.add(Medicine(designation: 'med2', color: 0xAF226B, dosis: 43));
+ final all = await repo.getAll();
+ expect(all, hasLength(2));
+ expect(all, containsAll([
+ isA<Medicine>()
+ .having((p0) => p0.designation, 'designation', 'med1')
+ .having((p0) => p0.color, 'color', 0xFF226A)
+ .having((p0) => p0.dosis, 'dosis', 42),
+ isA<Medicine>()
+ .having((p0) => p0.designation, 'designation', 'med2')
+ .having((p0) => p0.color, 'color', 0xAF226B)
+ .having((p0) => p0.dosis, 'dosis', 43),
+ ]));
+ });
+ test('should store all incomplete medicines', () async {
+ final db = await mockDBManager();
+ addTearDown(db.close);
+ final repo = MedicineRepository(db.db);
+ await repo.add(Medicine(designation: 'med1', color: 0xFF226A,));
+ await repo.add(Medicine(designation: 'med2', dosis: 43));
+ await repo.add(Medicine(designation: 'med3',));
+ final all = await repo.getAll();
+ expect(all, hasLength(3));
+ expect(all, containsAll([
+ isA<Medicine>()
+ .having((p0) => p0.designation, 'designation', 'med1')
+ .having((p0) => p0.color, 'color', 0xFF226A)
+ .having((p0) => p0.dosis, 'dosis', null),
+ isA<Medicine>()
+ .having((p0) => p0.designation, 'designation', 'med2')
+ .having((p0) => p0.color, 'color', null)
+ .having((p0) => p0.dosis, 'dosis', 43),
+ isA<Medicine>()
+ .having((p0) => p0.designation, 'designation', 'med3')
+ .having((p0) => p0.color, 'color', null)
+ .having((p0) => p0.dosis, 'dosis', null),
+ ]));
+ });
+ test('should mark medicines as deleted', () async {
+ final db = await mockDBManager();
+ addTearDown(db.close);
+ final repo = MedicineRepository(db.db);
+ final med1= Medicine(designation: 'med1', color: 0xFF226A, dosis: 42);
+ await repo.add(med1);
+ await repo.add(Medicine(designation: 'med2', color: 0xAF226B, dosis: 43));
+ expect(await repo.getAll(), hasLength(2));
+ await repo.remove(med1);
+ expect(await repo.getAll(), hasLength(1));
+ });
+
+}