feat(expense): refactor expense data handling and response parsing

This commit is contained in:
Vaibhav Surve 2025-07-25 12:00:33 +05:30
parent a83954c5c4
commit 9124b815ef
3 changed files with 96 additions and 35 deletions

View File

@ -72,15 +72,12 @@ class ExpenseController extends GetxController {
if (result != null) {
try {
final List<dynamic> rawList = result['expenses'] ?? [];
final parsed = rawList
.map((e) => ExpenseModel.fromJson(e as Map<String, dynamic>))
.toList();
final expenseResponse = ExpenseResponse.fromJson(result);
expenses.assignAll(expenseResponse.data.data);
expenses.assignAll(parsed);
logSafe("Expenses loaded: ${parsed.length}");
logSafe("Expenses loaded: ${expenses.length}");
logSafe(
"Pagination Info: Page ${result['currentPage']} of ${result['totalPages']} | Total: ${result['totalEntites']}");
"Pagination Info: Page ${expenseResponse.data.currentPage} of ${expenseResponse.data.totalPages} | Total: ${expenseResponse.data.totalEntites}");
} catch (e) {
errorMessage.value = 'Failed to parse expenses: $e';
logSafe("Parse error in fetchExpenses: $e", level: LogLevel.error);

View File

@ -308,27 +308,25 @@ class ApiService {
try {
final response = await _getRequest(uri.toString());
if (response == null) return null;
if (response == null) {
logSafe("Expense list request failed: null response",
level: LogLevel.error);
return null;
}
final parsed = _parseResponseForAllData(response, label: 'Expense List');
// Directly parse and return the entire JSON response
final body = response.body.trim();
if (body.isEmpty) {
logSafe("Expense list response body is empty", level: LogLevel.error);
return null;
}
if (parsed != null && parsed['data'] is Map<String, dynamic>) {
final dataObj = parsed['data'] as Map<String, dynamic>;
if (dataObj['data'] is List) {
return {
'currentPage': dataObj['currentPage'] ?? 1,
'totalPages': dataObj['totalPages'] ?? 1,
'totalEntites': dataObj['totalEntites'] ?? 0,
'expenses': List<dynamic>.from(dataObj['data']),
};
} else {
logSafe("Expense list 'data' is not a list: $dataObj",
level: LogLevel.error);
return null;
}
final jsonResponse = jsonDecode(body);
if (jsonResponse is Map<String, dynamic>) {
logSafe("Expense list response parsed successfully");
return jsonResponse; // Return the entire API response
} else {
logSafe("Unexpected response structure: $parsed",
logSafe("Unexpected response structure: $jsonResponse",
level: LogLevel.error);
return null;
}

View File

@ -1,14 +1,77 @@
import 'dart:convert';
List<ExpenseModel> expenseModelFromJson(String str) {
final jsonData = json.decode(str);
return List<ExpenseModel>.from(
jsonData["data"]["data"].map((x) => ExpenseModel.fromJson(x))
);
/// Parse the entire response
ExpenseResponse expenseResponseFromJson(String str) =>
ExpenseResponse.fromJson(json.decode(str));
String expenseResponseToJson(ExpenseResponse data) =>
json.encode(data.toJson());
class ExpenseResponse {
final bool success;
final String message;
final ExpenseData data;
final dynamic errors;
final int statusCode;
final DateTime timestamp;
ExpenseResponse({
required this.success,
required this.message,
required this.data,
required this.errors,
required this.statusCode,
required this.timestamp,
});
factory ExpenseResponse.fromJson(Map<String, dynamic> json) =>
ExpenseResponse(
success: json["success"],
message: json["message"],
data: ExpenseData.fromJson(json["data"]),
errors: json["errors"],
statusCode: json["statusCode"],
timestamp: DateTime.parse(json["timestamp"]),
);
Map<String, dynamic> toJson() => {
"success": success,
"message": message,
"data": data.toJson(),
"errors": errors,
"statusCode": statusCode,
"timestamp": timestamp.toIso8601String(),
};
}
String expenseModelToJson(List<ExpenseModel> data) =>
json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class ExpenseData {
final int currentPage;
final int totalPages;
final int totalEntites;
final List<ExpenseModel> data;
ExpenseData({
required this.currentPage,
required this.totalPages,
required this.totalEntites,
required this.data,
});
factory ExpenseData.fromJson(Map<String, dynamic> json) => ExpenseData(
currentPage: json["currentPage"],
totalPages: json["totalPages"],
totalEntites: json["totalEntites"],
data: List<ExpenseModel>.from(
json["data"].map((x) => ExpenseModel.fromJson(x))),
);
Map<String, dynamic> toJson() => {
"currentPage": currentPage,
"totalPages": totalPages,
"totalEntites": totalEntites,
"data": List<dynamic>.from(data.map((x) => x.toJson())),
};
}
class ExpenseModel {
final String id;
@ -53,9 +116,12 @@ class ExpenseModel {
supplerName: json["supplerName"],
amount: (json["amount"] as num).toDouble(),
status: Status.fromJson(json["status"]),
nextStatus: List<Status>.from(
json["nextStatus"].map((x) => Status.fromJson(x))),
preApproved: json["preApproved"],
nextStatus: json["nextStatus"] != null
? List<Status>.from(
json["nextStatus"].map((x) => Status.fromJson(x)),
)
: [],
preApproved: json["preApproved"] ?? false,
);
Map<String, dynamic> toJson() => {