feat: WebSocket temps réel + Finance Workflow + corrections
- Task #6: WebSocket /ws/dashboard + Kafka events (5 topics) * Backend: KafkaEventProducer, KafkaEventConsumer * Mobile: WebSocketService (reconnection, heartbeat, typed events) * DashboardBloc: Auto-refresh depuis WebSocket events - Finance Workflow: approbations + budgets (backend + mobile) * Backend: entities, services, resources, migrations Flyway V6 * Mobile: features finance_workflow complète avec BLoC - Corrections DI: interfaces IRepository partout * IProfileRepository, IOrganizationRepository, IMembreRepository * GetIt configuré avec @injectable - Spec-Kit: constitution + templates mis à jour * .specify/memory/constitution.md enrichie * Templates agent, plan, spec, tasks, checklist - Nettoyage: fichiers temporaires supprimés Signed-off-by: lions dev Team
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
/// Model de données Budget avec sérialisation JSON
|
||||
library budget_model;
|
||||
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
import '../../domain/entities/budget.dart';
|
||||
|
||||
part 'budget_model.g.dart';
|
||||
|
||||
@JsonSerializable(explicitToJson: true)
|
||||
class BudgetModel extends Budget {
|
||||
@JsonKey(
|
||||
fromJson: _linesFromJson,
|
||||
toJson: _linesToJson,
|
||||
)
|
||||
@override
|
||||
final List<BudgetLine> lines;
|
||||
|
||||
const BudgetModel({
|
||||
required super.id,
|
||||
required super.name,
|
||||
super.description,
|
||||
required super.organizationId,
|
||||
required super.period,
|
||||
required super.year,
|
||||
super.month,
|
||||
required super.status,
|
||||
this.lines = const [],
|
||||
required super.totalPlanned,
|
||||
super.totalRealized,
|
||||
super.currency,
|
||||
required super.createdBy,
|
||||
required super.createdAt,
|
||||
super.approvedAt,
|
||||
super.approvedBy,
|
||||
required super.startDate,
|
||||
required super.endDate,
|
||||
super.metadata,
|
||||
}) : super(lines: lines);
|
||||
|
||||
static List<BudgetLine> _linesFromJson(List<dynamic>? json) =>
|
||||
json?.map((e) => BudgetLineModel.fromJson(e as Map<String, dynamic>)).toList() ?? [];
|
||||
|
||||
static List<Map<String, dynamic>> _linesToJson(List<BudgetLine>? lines) =>
|
||||
lines?.map((l) => BudgetLineModel(
|
||||
id: l.id,
|
||||
category: l.category,
|
||||
name: l.name,
|
||||
description: l.description,
|
||||
amountPlanned: l.amountPlanned,
|
||||
amountRealized: l.amountRealized,
|
||||
notes: l.notes,
|
||||
).toJson()).toList() ?? [];
|
||||
|
||||
factory BudgetModel.fromJson(Map<String, dynamic> json) =>
|
||||
_$BudgetModelFromJson(json);
|
||||
|
||||
Map<String, dynamic> toJson() => _$BudgetModelToJson(this);
|
||||
|
||||
factory BudgetModel.fromEntity(Budget entity) {
|
||||
return BudgetModel(
|
||||
id: entity.id,
|
||||
name: entity.name,
|
||||
description: entity.description,
|
||||
organizationId: entity.organizationId,
|
||||
period: entity.period,
|
||||
year: entity.year,
|
||||
month: entity.month,
|
||||
status: entity.status,
|
||||
lines: entity.lines,
|
||||
totalPlanned: entity.totalPlanned,
|
||||
totalRealized: entity.totalRealized,
|
||||
currency: entity.currency,
|
||||
createdBy: entity.createdBy,
|
||||
createdAt: entity.createdAt,
|
||||
approvedAt: entity.approvedAt,
|
||||
approvedBy: entity.approvedBy,
|
||||
startDate: entity.startDate,
|
||||
endDate: entity.endDate,
|
||||
metadata: entity.metadata,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@JsonSerializable()
|
||||
class BudgetLineModel extends BudgetLine {
|
||||
const BudgetLineModel({
|
||||
required super.id,
|
||||
required super.category,
|
||||
required super.name,
|
||||
super.description,
|
||||
required super.amountPlanned,
|
||||
super.amountRealized,
|
||||
super.notes,
|
||||
});
|
||||
|
||||
factory BudgetLineModel.fromJson(Map<String, dynamic> json) =>
|
||||
_$BudgetLineModelFromJson(json);
|
||||
|
||||
Map<String, dynamic> toJson() => _$BudgetLineModelToJson(this);
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/// Model de données TransactionApproval avec sérialisation JSON
|
||||
library transaction_approval_model;
|
||||
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
import '../../domain/entities/transaction_approval.dart';
|
||||
|
||||
part 'transaction_approval_model.g.dart';
|
||||
|
||||
@JsonSerializable(explicitToJson: true)
|
||||
class TransactionApprovalModel extends TransactionApproval {
|
||||
@JsonKey(
|
||||
fromJson: _approversFromJson,
|
||||
toJson: _approversToJson,
|
||||
)
|
||||
@override
|
||||
final List<ApproverAction> approvers;
|
||||
|
||||
const TransactionApprovalModel({
|
||||
required super.id,
|
||||
required super.transactionId,
|
||||
required super.transactionType,
|
||||
required super.amount,
|
||||
super.currency,
|
||||
required super.requesterId,
|
||||
required super.requesterName,
|
||||
super.organizationId,
|
||||
required super.requiredLevel,
|
||||
required super.status,
|
||||
this.approvers = const [],
|
||||
super.rejectionReason,
|
||||
required super.createdAt,
|
||||
super.expiresAt,
|
||||
super.completedAt,
|
||||
super.metadata,
|
||||
}) : super(approvers: approvers);
|
||||
|
||||
static List<ApproverAction> _approversFromJson(List<dynamic>? json) =>
|
||||
json?.map((e) => ApproverActionModel.fromJson(e as Map<String, dynamic>)).toList() ?? [];
|
||||
|
||||
static List<Map<String, dynamic>> _approversToJson(List<ApproverAction>? approvers) =>
|
||||
approvers?.map((a) => ApproverActionModel(
|
||||
approverId: a.approverId,
|
||||
approverName: a.approverName,
|
||||
approverRole: a.approverRole,
|
||||
decision: a.decision,
|
||||
comment: a.comment,
|
||||
decidedAt: a.decidedAt,
|
||||
).toJson()).toList() ?? [];
|
||||
|
||||
factory TransactionApprovalModel.fromJson(Map<String, dynamic> json) =>
|
||||
_$TransactionApprovalModelFromJson(json);
|
||||
|
||||
Map<String, dynamic> toJson() => _$TransactionApprovalModelToJson(this);
|
||||
|
||||
factory TransactionApprovalModel.fromEntity(TransactionApproval entity) {
|
||||
return TransactionApprovalModel(
|
||||
id: entity.id,
|
||||
transactionId: entity.transactionId,
|
||||
transactionType: entity.transactionType,
|
||||
amount: entity.amount,
|
||||
currency: entity.currency,
|
||||
requesterId: entity.requesterId,
|
||||
requesterName: entity.requesterName,
|
||||
organizationId: entity.organizationId,
|
||||
requiredLevel: entity.requiredLevel,
|
||||
status: entity.status,
|
||||
approvers: entity.approvers,
|
||||
rejectionReason: entity.rejectionReason,
|
||||
createdAt: entity.createdAt,
|
||||
expiresAt: entity.expiresAt,
|
||||
completedAt: entity.completedAt,
|
||||
metadata: entity.metadata,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@JsonSerializable()
|
||||
class ApproverActionModel extends ApproverAction {
|
||||
const ApproverActionModel({
|
||||
required super.approverId,
|
||||
required super.approverName,
|
||||
required super.approverRole,
|
||||
required super.decision,
|
||||
super.comment,
|
||||
super.decidedAt,
|
||||
});
|
||||
|
||||
factory ApproverActionModel.fromJson(Map<String, dynamic> json) =>
|
||||
_$ApproverActionModelFromJson(json);
|
||||
|
||||
Map<String, dynamic> toJson() => _$ApproverActionModelToJson(this);
|
||||
}
|
||||
Reference in New Issue
Block a user