feat: Gestion des secteurs et migration v3.0.4+304

- Ajout système complet de gestion des secteurs avec contours géographiques
- Import des contours départementaux depuis GeoJSON
- API REST pour la gestion des secteurs (/api/sectors)
- Service de géolocalisation pour déterminer les secteurs
- Migration base de données avec tables x_departements_contours et sectors_adresses
- Interface Flutter pour visualisation et gestion des secteurs
- Ajout thème sombre dans l'application
- Corrections diverses et optimisations

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
pierre
2025-08-07 11:01:45 +02:00
parent 6a609fb467
commit 599b9fcda0
662 changed files with 213221 additions and 174243 deletions

2
app/lib/core/data/models/amicale_model.dart Normal file → Executable file
View File

@@ -222,7 +222,7 @@ class AmicaleModel extends HiveObject {
DateTime? updatedAt,
}) {
return AmicaleModel(
id: this.id,
id: id,
name: name ?? this.name,
adresse1: adresse1 ?? this.adresse1,
adresse2: adresse2 ?? this.adresse2,

0
app/lib/core/data/models/client_model.dart Normal file → Executable file
View File

16
app/lib/core/data/models/membre_model.dart Normal file → Executable file
View File

@@ -4,6 +4,22 @@ import 'package:geosector_app/core/data/models/user_model.dart';
part 'membre_model.g.dart';
/// Modèle représentant un membre d'une amicale.
///
/// IMPORTANT : Ce modèle représente TOUS les membres d'une amicale,
/// pas seulement l'utilisateur connecté. Pour l'utilisateur connecté, voir UserModel.
///
/// La box Hive 'membres' contient plusieurs enregistrements (tous les membres de l'amicale).
///
/// Relations avec les autres modèles :
/// - UserModel : représente uniquement l'utilisateur connecté (current user)
/// - UserSectorModel : utilise MembreModel.id pour associer les membres aux secteurs
/// ATTENTION : UserSectorModel.id = MembreModel.id (pas UserModel.id)
///
/// Chaque membre a son propre ID unique qui est utilisé pour :
/// - L'attribution aux secteurs (via UserSectorModel)
/// - La gestion des passages
/// - Les statistiques par membre
@HiveType(typeId: 5) // Utilisation d'un typeId unique
class MembreModel extends HiveObject {
@HiveField(0)

0
app/lib/core/data/models/operation_model.dart Normal file → Executable file
View File

24
app/lib/core/data/models/passage_model.dart Normal file → Executable file
View File

@@ -12,7 +12,7 @@ class PassageModel extends HiveObject {
final int fkOperation;
@HiveField(2)
final int fkSector;
final int? fkSector;
@HiveField(3)
final int fkUser;
@@ -24,7 +24,7 @@ class PassageModel extends HiveObject {
final String fkAdresse;
@HiveField(6)
final DateTime passedAt;
final DateTime? passedAt;
@HiveField(7)
final String numero;
@@ -95,11 +95,11 @@ class PassageModel extends HiveObject {
PassageModel({
required this.id,
required this.fkOperation,
required this.fkSector,
this.fkSector,
required this.fkUser,
required this.fkType,
required this.fkAdresse,
required this.passedAt,
this.passedAt,
required this.numero,
required this.rue,
this.rueBis = '',
@@ -136,7 +136,11 @@ class PassageModel extends HiveObject {
final int fkOperation = rawFkOperation is String ? int.parse(rawFkOperation) : rawFkOperation as int;
final dynamic rawFkSector = json['fk_sector'];
final int fkSector = rawFkSector is String ? int.parse(rawFkSector) : rawFkSector as int;
final int? fkSector = rawFkSector == null
? null
: rawFkSector is String
? int.parse(rawFkSector)
: rawFkSector as int;
final dynamic rawFkUser = json['fk_user'];
final int fkUser = rawFkUser is String ? int.parse(rawFkUser) : rawFkUser as int;
@@ -153,8 +157,10 @@ class PassageModel extends HiveObject {
final dynamic rawNbPassages = json['nb_passages'];
final int nbPassages = rawNbPassages is String ? int.parse(rawNbPassages) : rawNbPassages as int;
// Convertir la date
final DateTime passedAt = DateTime.parse(json['passed_at']);
// Convertir la date (nullable)
final DateTime? passedAt = json['passed_at'] != null
? DateTime.parse(json['passed_at'])
: null;
return PassageModel(
id: id,
@@ -203,7 +209,7 @@ class PassageModel extends HiveObject {
'fk_user': fkUser,
'fk_type': fkType,
'fk_adresse': fkAdresse,
'passed_at': passedAt.toIso8601String(),
'passed_at': passedAt?.toIso8601String(),
'numero': numero,
'rue': rue,
'rue_bis': rueBis,
@@ -293,6 +299,6 @@ class PassageModel extends HiveObject {
@override
String toString() {
return 'PassageModel(id: $id, fkOperation: $fkOperation, fkSector: $fkSector, fkUser: $fkUser, fkType: $fkType, adresse: $fkAdresse, ville: $ville, montant: $montant)';
return 'PassageModel(id: $id, fkOperation: $fkOperation, fkSector: $fkSector, fkUser: $fkUser, fkType: $fkType, adresse: $fkAdresse, ville: $ville, montant: $montant, passedAt: $passedAt)';
}
}

View File

@@ -19,11 +19,11 @@ class PassageModelAdapter extends TypeAdapter<PassageModel> {
return PassageModel(
id: fields[0] as int,
fkOperation: fields[1] as int,
fkSector: fields[2] as int,
fkSector: fields[2] as int?,
fkUser: fields[3] as int,
fkType: fields[4] as int,
fkAdresse: fields[5] as String,
passedAt: fields[6] as DateTime,
passedAt: fields[6] as DateTime?,
numero: fields[7] as String,
rue: fields[8] as String,
rueBis: fields[9] as String,

0
app/lib/core/data/models/region_model.dart Normal file → Executable file
View File

0
app/lib/core/data/models/sector_model.dart Normal file → Executable file
View File

14
app/lib/core/data/models/user_model.dart Normal file → Executable file
View File

@@ -2,6 +2,16 @@ import 'package:hive/hive.dart';
part 'user_model.g.dart';
/// Modèle représentant l'utilisateur actuellement connecté (current user).
///
/// IMPORTANT : Ce modèle est utilisé UNIQUEMENT pour l'utilisateur connecté,
/// pas pour les membres de l'amicale. Pour les membres, utilisez MembreModel.
///
/// La box Hive 'users' ne contient qu'un seul enregistrement : l'utilisateur actuel.
///
/// Relations avec les autres modèles :
/// - MembreModel : représente TOUS les membres d'une amicale (y compris l'utilisateur actuel s'il est membre)
/// - UserSectorModel : associe les membres (pas les users) aux secteurs
@HiveType(typeId: 0)
class UserModel extends HiveObject {
@HiveField(0)
@@ -201,13 +211,13 @@ class UserModel extends HiveObject {
DateTime? dateEmbauche,
}) {
return UserModel(
id: this.id,
id: id,
email: email ?? this.email,
name: name ?? this.name,
username: username ?? this.username,
firstName: firstName ?? this.firstName,
role: role ?? this.role,
createdAt: this.createdAt,
createdAt: createdAt,
lastSyncedAt: lastSyncedAt ?? this.lastSyncedAt,
isActive: isActive ?? this.isActive,
isSynced: isSynced ?? this.isSynced,

0
app/lib/core/data/models/user_sector_model.dart Normal file → Executable file
View File