Initial commit: unionflow-mobile-apps
Application Flutter complète (sans build artifacts). Signed-off-by: lions dev Team
This commit is contained in:
@@ -0,0 +1,229 @@
|
||||
/// Datasource distant pour le workflow financier (API)
|
||||
library finance_workflow_remote_datasource;
|
||||
|
||||
import 'dart:convert';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||
import 'package:injectable/injectable.dart';
|
||||
import '../../../../core/config/environment.dart';
|
||||
import '../../../../core/error/exceptions.dart';
|
||||
import '../models/transaction_approval_model.dart';
|
||||
import '../models/budget_model.dart';
|
||||
import '../../domain/entities/transaction_approval.dart';
|
||||
import '../../domain/entities/budget.dart';
|
||||
|
||||
@lazySingleton
|
||||
class FinanceWorkflowRemoteDatasource {
|
||||
final http.Client client;
|
||||
final FlutterSecureStorage secureStorage;
|
||||
|
||||
FinanceWorkflowRemoteDatasource({
|
||||
required this.client,
|
||||
required this.secureStorage,
|
||||
});
|
||||
|
||||
/// Headers HTTP avec authentification
|
||||
Future<Map<String, String>> _getHeaders() async {
|
||||
final token = await secureStorage.read(key: 'access_token');
|
||||
return {
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
if (token != null) 'Authorization': 'Bearer $token',
|
||||
};
|
||||
}
|
||||
|
||||
// === APPROBATIONS ===
|
||||
|
||||
Future<List<TransactionApprovalModel>> getPendingApprovals({
|
||||
String? organizationId,
|
||||
}) async {
|
||||
final uri = Uri.parse('${AppConfig.apiBaseUrl}/api/finance/approvals/pending')
|
||||
.replace(queryParameters: {
|
||||
if (organizationId != null) 'organizationId': organizationId,
|
||||
});
|
||||
|
||||
final response = await client.get(uri, headers: await _getHeaders());
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
final List<dynamic> jsonList = json.decode(response.body);
|
||||
return jsonList
|
||||
.map((json) => TransactionApprovalModel.fromJson(json))
|
||||
.toList();
|
||||
} else if (response.statusCode == 401) {
|
||||
throw UnauthorizedException();
|
||||
} else {
|
||||
throw ServerException('Erreur lors de la récupération des approbations');
|
||||
}
|
||||
}
|
||||
|
||||
Future<TransactionApprovalModel> getApprovalById(String approvalId) async {
|
||||
final uri = Uri.parse(
|
||||
'${AppConfig.apiBaseUrl}/api/finance/approvals/$approvalId');
|
||||
|
||||
final response = await client.get(uri, headers: await _getHeaders());
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
return TransactionApprovalModel.fromJson(json.decode(response.body));
|
||||
} else if (response.statusCode == 404) {
|
||||
throw NotFoundException('Approbation non trouvée');
|
||||
} else if (response.statusCode == 401) {
|
||||
throw UnauthorizedException();
|
||||
} else {
|
||||
throw ServerException('Erreur lors de la récupération de l\'approbation');
|
||||
}
|
||||
}
|
||||
|
||||
Future<TransactionApprovalModel> approveTransaction({
|
||||
required String approvalId,
|
||||
String? comment,
|
||||
}) async {
|
||||
final uri =
|
||||
Uri.parse('${AppConfig.apiBaseUrl}/api/finance/approvals/$approvalId/approve');
|
||||
|
||||
final body = json.encode({
|
||||
if (comment != null) 'comment': comment,
|
||||
});
|
||||
|
||||
final response = await client.post(
|
||||
uri,
|
||||
headers: await _getHeaders(),
|
||||
body: body,
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
return TransactionApprovalModel.fromJson(json.decode(response.body));
|
||||
} else if (response.statusCode == 401) {
|
||||
throw UnauthorizedException();
|
||||
} else if (response.statusCode == 403) {
|
||||
throw ForbiddenException('Permission insuffisante pour approuver');
|
||||
} else {
|
||||
throw ServerException('Erreur lors de l\'approbation');
|
||||
}
|
||||
}
|
||||
|
||||
Future<TransactionApprovalModel> rejectTransaction({
|
||||
required String approvalId,
|
||||
required String reason,
|
||||
}) async {
|
||||
final uri =
|
||||
Uri.parse('${AppConfig.apiBaseUrl}/api/finance/approvals/$approvalId/reject');
|
||||
|
||||
final body = json.encode({
|
||||
'reason': reason,
|
||||
});
|
||||
|
||||
final response = await client.post(
|
||||
uri,
|
||||
headers: await _getHeaders(),
|
||||
body: body,
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
return TransactionApprovalModel.fromJson(json.decode(response.body));
|
||||
} else if (response.statusCode == 401) {
|
||||
throw UnauthorizedException();
|
||||
} else if (response.statusCode == 403) {
|
||||
throw ForbiddenException('Permission insuffisante pour rejeter');
|
||||
} else {
|
||||
throw ServerException('Erreur lors du rejet');
|
||||
}
|
||||
}
|
||||
|
||||
// === BUDGETS ===
|
||||
|
||||
Future<List<BudgetModel>> getBudgets({
|
||||
String? organizationId,
|
||||
String? status,
|
||||
int? year,
|
||||
}) async {
|
||||
final uri = Uri.parse('${AppConfig.apiBaseUrl}/api/finance/budgets')
|
||||
.replace(queryParameters: {
|
||||
if (organizationId != null) 'organizationId': organizationId,
|
||||
if (status != null) 'status': status,
|
||||
if (year != null) 'year': year.toString(),
|
||||
});
|
||||
|
||||
final response = await client.get(uri, headers: await _getHeaders());
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
final List<dynamic> jsonList = json.decode(response.body);
|
||||
return jsonList.map((json) => BudgetModel.fromJson(json)).toList();
|
||||
} else if (response.statusCode == 401) {
|
||||
throw UnauthorizedException();
|
||||
} else {
|
||||
throw ServerException('Erreur lors de la récupération des budgets');
|
||||
}
|
||||
}
|
||||
|
||||
Future<BudgetModel> getBudgetById(String budgetId) async {
|
||||
final uri =
|
||||
Uri.parse('${AppConfig.apiBaseUrl}/api/finance/budgets/$budgetId');
|
||||
|
||||
final response = await client.get(uri, headers: await _getHeaders());
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
return BudgetModel.fromJson(json.decode(response.body));
|
||||
} else if (response.statusCode == 404) {
|
||||
throw NotFoundException('Budget non trouvé');
|
||||
} else if (response.statusCode == 401) {
|
||||
throw UnauthorizedException();
|
||||
} else {
|
||||
throw ServerException('Erreur lors de la récupération du budget');
|
||||
}
|
||||
}
|
||||
|
||||
Future<BudgetModel> createBudget({
|
||||
required String name,
|
||||
String? description,
|
||||
required String organizationId,
|
||||
required String period,
|
||||
required int year,
|
||||
int? month,
|
||||
required List<Map<String, dynamic>> lines,
|
||||
}) async {
|
||||
final uri = Uri.parse('${AppConfig.apiBaseUrl}/api/finance/budgets');
|
||||
|
||||
final body = json.encode({
|
||||
'name': name,
|
||||
if (description != null) 'description': description,
|
||||
'organizationId': organizationId,
|
||||
'period': period,
|
||||
'year': year,
|
||||
if (month != null) 'month': month,
|
||||
'lines': lines,
|
||||
});
|
||||
|
||||
final response = await client.post(
|
||||
uri,
|
||||
headers: await _getHeaders(),
|
||||
body: body,
|
||||
);
|
||||
|
||||
if (response.statusCode == 201 || response.statusCode == 200) {
|
||||
return BudgetModel.fromJson(json.decode(response.body));
|
||||
} else if (response.statusCode == 401) {
|
||||
throw UnauthorizedException();
|
||||
} else if (response.statusCode == 403) {
|
||||
throw ForbiddenException('Permission insuffisante pour créer un budget');
|
||||
} else {
|
||||
throw ServerException('Erreur lors de la création du budget');
|
||||
}
|
||||
}
|
||||
|
||||
Future<Map<String, dynamic>> getBudgetTracking({
|
||||
required String budgetId,
|
||||
}) async {
|
||||
final uri = Uri.parse(
|
||||
'${AppConfig.apiBaseUrl}/api/finance/budgets/$budgetId/tracking');
|
||||
|
||||
final response = await client.get(uri, headers: await _getHeaders());
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
return json.decode(response.body) as Map<String, dynamic>;
|
||||
} else if (response.statusCode == 401) {
|
||||
throw UnauthorizedException();
|
||||
} else {
|
||||
throw ServerException('Erreur lors de la récupération du suivi budgétaire');
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user