feat: enhance payment request data models for null safety and improve filter options handling in PaymentRequestController
This commit is contained in:
parent
fc78806af2
commit
2c98ac359c
@ -32,13 +32,14 @@ class PaymentRequestController extends GetxController {
|
||||
Future<void> fetchPaymentRequestFilterOptions() async {
|
||||
try {
|
||||
final response = await ApiService.getExpensePaymentRequestFilterApi();
|
||||
if (response != null) {
|
||||
projects.assignAll(response.data.projects);
|
||||
payees.assignAll(response.data.payees);
|
||||
categories.assignAll(response.data.expenseCategory);
|
||||
currencies.assignAll(response.data.currency);
|
||||
statuses.assignAll(response.data.status);
|
||||
createdBy.assignAll(response.data.createdBy);
|
||||
|
||||
if (response != null && response.data != null) {
|
||||
projects.assignAll(response.data!.projects ?? []);
|
||||
payees.assignAll(response.data!.payees ?? []);
|
||||
categories.assignAll(response.data!.expenseCategory ?? []);
|
||||
currencies.assignAll(response.data!.currency ?? []);
|
||||
statuses.assignAll(response.data!.status ?? []);
|
||||
createdBy.assignAll(response.data!.createdBy ?? []);
|
||||
} else {
|
||||
logSafe("Payment request filter API returned null",
|
||||
level: LogLevel.warning);
|
||||
@ -63,7 +64,7 @@ class PaymentRequestController extends GetxController {
|
||||
isLoading.value = false;
|
||||
}
|
||||
|
||||
// ---------------- Load More ----------------
|
||||
// ---------------- Load More ----------------
|
||||
Future<void> loadMorePaymentRequests() async {
|
||||
if (isLoading.value || !_hasMoreData) return;
|
||||
|
||||
@ -74,7 +75,7 @@ class PaymentRequestController extends GetxController {
|
||||
isLoading.value = false;
|
||||
}
|
||||
|
||||
// ---------------- Internal API Call ----------------
|
||||
// ---------------- Internal API Call ----------------
|
||||
Future<void> _fetchPaymentRequestsFromApi() async {
|
||||
try {
|
||||
final response = await ApiService.getExpensePaymentRequestListApi(
|
||||
@ -84,17 +85,17 @@ class PaymentRequestController extends GetxController {
|
||||
searchString: searchString.value,
|
||||
);
|
||||
|
||||
if (response != null && response.data.data.isNotEmpty) {
|
||||
final data = response?.data;
|
||||
final reqList = data?.data ?? [];
|
||||
|
||||
if (response != null && data != null && reqList.isNotEmpty) {
|
||||
if (_pageNumber == 1) {
|
||||
// First page, replace the list
|
||||
paymentRequests.assignAll(response.data.data);
|
||||
paymentRequests.assignAll(reqList);
|
||||
} else {
|
||||
// Append next page items at the end
|
||||
paymentRequests.addAll(response.data.data);
|
||||
paymentRequests.addAll(reqList);
|
||||
}
|
||||
|
||||
// If returned data is less than page size, no more data
|
||||
if (response.data.data.length < _pageSize) {
|
||||
if (reqList.length < _pageSize) {
|
||||
_hasMoreData = false;
|
||||
}
|
||||
} else {
|
||||
|
||||
@ -13,21 +13,23 @@ class PaymentRequestResponse {
|
||||
required this.data,
|
||||
});
|
||||
|
||||
bool success;
|
||||
String message;
|
||||
PaymentRequestData data;
|
||||
bool? success;
|
||||
String? message;
|
||||
PaymentRequestData? data;
|
||||
|
||||
factory PaymentRequestResponse.fromJson(Map<String, dynamic> json) =>
|
||||
PaymentRequestResponse(
|
||||
success: json["success"],
|
||||
message: json["message"],
|
||||
data: PaymentRequestData.fromJson(json["data"]),
|
||||
data: json["data"] != null
|
||||
? PaymentRequestData.fromJson(json["data"])
|
||||
: null,
|
||||
);
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
"success": success,
|
||||
"message": message,
|
||||
"data": data.toJson(),
|
||||
"data": data?.toJson(),
|
||||
};
|
||||
}
|
||||
|
||||
@ -39,25 +41,27 @@ class PaymentRequestData {
|
||||
required this.data,
|
||||
});
|
||||
|
||||
int currentPage;
|
||||
int totalPages;
|
||||
int totalEntities;
|
||||
List<PaymentRequest> data;
|
||||
int? currentPage;
|
||||
int? totalPages;
|
||||
int? totalEntities;
|
||||
List<PaymentRequest>? data;
|
||||
|
||||
factory PaymentRequestData.fromJson(Map<String, dynamic> json) =>
|
||||
PaymentRequestData(
|
||||
currentPage: json["currentPage"],
|
||||
totalPages: json["totalPages"],
|
||||
totalEntities: json["totalEntities"],
|
||||
data: List<PaymentRequest>.from(
|
||||
json["data"].map((x) => PaymentRequest.fromJson(x))),
|
||||
data: json["data"] != null
|
||||
? List<PaymentRequest>.from(
|
||||
json["data"].map((x) => PaymentRequest.fromJson(x)))
|
||||
: [],
|
||||
);
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
"currentPage": currentPage,
|
||||
"totalPages": totalPages,
|
||||
"totalEntities": totalEntities,
|
||||
"data": List<dynamic>.from(data.map((x) => x.toJson())),
|
||||
"data": data?.map((x) => x.toJson()).toList(),
|
||||
};
|
||||
}
|
||||
|
||||
@ -82,23 +86,23 @@ class PaymentRequest {
|
||||
required this.isExpenseCreated,
|
||||
});
|
||||
|
||||
String id;
|
||||
String title;
|
||||
String description;
|
||||
String? id;
|
||||
String? title;
|
||||
String? description;
|
||||
dynamic recurringPayment;
|
||||
String paymentRequestUID;
|
||||
String payee;
|
||||
Currency currency;
|
||||
num amount;
|
||||
DateTime dueDate;
|
||||
Project project;
|
||||
ExpenseCategory expenseCategory;
|
||||
ExpenseStatus expenseStatus;
|
||||
bool isAdvancePayment;
|
||||
DateTime createdAt;
|
||||
CreatedBy createdBy;
|
||||
bool isActive;
|
||||
bool isExpenseCreated;
|
||||
String? paymentRequestUID;
|
||||
String? payee;
|
||||
Currency? currency;
|
||||
num? amount;
|
||||
DateTime? dueDate;
|
||||
Project? project;
|
||||
ExpenseCategory? expenseCategory;
|
||||
ExpenseStatus? expenseStatus;
|
||||
bool? isAdvancePayment;
|
||||
DateTime? createdAt;
|
||||
CreatedBy? createdBy;
|
||||
bool? isActive;
|
||||
bool? isExpenseCreated;
|
||||
|
||||
factory PaymentRequest.fromJson(Map<String, dynamic> json) => PaymentRequest(
|
||||
id: json["id"],
|
||||
@ -107,15 +111,28 @@ class PaymentRequest {
|
||||
recurringPayment: json["recurringPayment"],
|
||||
paymentRequestUID: json["paymentRequestUID"],
|
||||
payee: json["payee"],
|
||||
currency: Currency.fromJson(json["currency"]),
|
||||
currency: json["currency"] != null
|
||||
? Currency.fromJson(json["currency"])
|
||||
: null,
|
||||
amount: json["amount"],
|
||||
dueDate: DateTime.parse(json["dueDate"]),
|
||||
project: Project.fromJson(json["project"]),
|
||||
expenseCategory: ExpenseCategory.fromJson(json["expenseCategory"]),
|
||||
expenseStatus: ExpenseStatus.fromJson(json["expenseStatus"]),
|
||||
dueDate: json["dueDate"] != null
|
||||
? DateTime.parse(json["dueDate"])
|
||||
: null,
|
||||
project:
|
||||
json["project"] != null ? Project.fromJson(json["project"]) : null,
|
||||
expenseCategory: json["expenseCategory"] != null
|
||||
? ExpenseCategory.fromJson(json["expenseCategory"])
|
||||
: null,
|
||||
expenseStatus: json["expenseStatus"] != null
|
||||
? ExpenseStatus.fromJson(json["expenseStatus"])
|
||||
: null,
|
||||
isAdvancePayment: json["isAdvancePayment"],
|
||||
createdAt: DateTime.parse(json["createdAt"]),
|
||||
createdBy: CreatedBy.fromJson(json["createdBy"]),
|
||||
createdAt: json["createdAt"] != null
|
||||
? DateTime.parse(json["createdAt"])
|
||||
: null,
|
||||
createdBy: json["createdBy"] != null
|
||||
? CreatedBy.fromJson(json["createdBy"])
|
||||
: null,
|
||||
isActive: json["isActive"],
|
||||
isExpenseCreated: json["isExpenseCreated"],
|
||||
);
|
||||
@ -127,15 +144,15 @@ class PaymentRequest {
|
||||
"recurringPayment": recurringPayment,
|
||||
"paymentRequestUID": paymentRequestUID,
|
||||
"payee": payee,
|
||||
"currency": currency.toJson(),
|
||||
"currency": currency?.toJson(),
|
||||
"amount": amount,
|
||||
"dueDate": dueDate.toIso8601String(),
|
||||
"project": project.toJson(),
|
||||
"expenseCategory": expenseCategory.toJson(),
|
||||
"expenseStatus": expenseStatus.toJson(),
|
||||
"dueDate": dueDate?.toIso8601String(),
|
||||
"project": project?.toJson(),
|
||||
"expenseCategory": expenseCategory?.toJson(),
|
||||
"expenseStatus": expenseStatus?.toJson(),
|
||||
"isAdvancePayment": isAdvancePayment,
|
||||
"createdAt": createdAt.toIso8601String(),
|
||||
"createdBy": createdBy.toJson(),
|
||||
"createdAt": createdAt?.toIso8601String(),
|
||||
"createdBy": createdBy?.toJson(),
|
||||
"isActive": isActive,
|
||||
"isExpenseCreated": isExpenseCreated,
|
||||
};
|
||||
@ -150,11 +167,11 @@ class Currency {
|
||||
required this.isActive,
|
||||
});
|
||||
|
||||
String id;
|
||||
String currencyCode;
|
||||
String currencyName;
|
||||
String symbol;
|
||||
bool isActive;
|
||||
String? id;
|
||||
String? currencyCode;
|
||||
String? currencyName;
|
||||
String? symbol;
|
||||
bool? isActive;
|
||||
|
||||
factory Currency.fromJson(Map<String, dynamic> json) => Currency(
|
||||
id: json["id"],
|
||||
@ -179,8 +196,8 @@ class Project {
|
||||
required this.name,
|
||||
});
|
||||
|
||||
String id;
|
||||
String name;
|
||||
String? id;
|
||||
String? name;
|
||||
|
||||
factory Project.fromJson(Map<String, dynamic> json) => Project(
|
||||
id: json["id"],
|
||||
@ -202,13 +219,14 @@ class ExpenseCategory {
|
||||
required this.description,
|
||||
});
|
||||
|
||||
String id;
|
||||
String name;
|
||||
bool noOfPersonsRequired;
|
||||
bool isAttachmentRequried;
|
||||
String description;
|
||||
String? id;
|
||||
String? name;
|
||||
bool? noOfPersonsRequired;
|
||||
bool? isAttachmentRequried;
|
||||
String? description;
|
||||
|
||||
factory ExpenseCategory.fromJson(Map<String, dynamic> json) => ExpenseCategory(
|
||||
factory ExpenseCategory.fromJson(Map<String, dynamic> json) =>
|
||||
ExpenseCategory(
|
||||
id: json["id"],
|
||||
name: json["name"],
|
||||
noOfPersonsRequired: json["noOfPersonsRequired"],
|
||||
@ -236,13 +254,13 @@ class ExpenseStatus {
|
||||
required this.isSystem,
|
||||
});
|
||||
|
||||
String id;
|
||||
String name;
|
||||
String displayName;
|
||||
String description;
|
||||
String? id;
|
||||
String? name;
|
||||
String? displayName;
|
||||
String? description;
|
||||
dynamic permissionIds;
|
||||
String color;
|
||||
bool isSystem;
|
||||
String? color;
|
||||
bool? isSystem;
|
||||
|
||||
factory ExpenseStatus.fromJson(Map<String, dynamic> json) => ExpenseStatus(
|
||||
id: json["id"],
|
||||
@ -276,13 +294,13 @@ class CreatedBy {
|
||||
required this.jobRoleName,
|
||||
});
|
||||
|
||||
String id;
|
||||
String firstName;
|
||||
String lastName;
|
||||
String email;
|
||||
String photo;
|
||||
String jobRoleId;
|
||||
String jobRoleName;
|
||||
String? id;
|
||||
String? firstName;
|
||||
String? lastName;
|
||||
String? email;
|
||||
String? photo;
|
||||
String? jobRoleId;
|
||||
String? jobRoleName;
|
||||
|
||||
factory CreatedBy.fromJson(Map<String, dynamic> json) => CreatedBy(
|
||||
id: json["id"],
|
||||
|
||||
@ -14,7 +14,6 @@ import 'package:marco/controller/permission_controller.dart';
|
||||
import 'package:marco/helpers/utils/permission_constants.dart';
|
||||
import 'package:marco/helpers/widgets/my_refresh_indicator.dart';
|
||||
|
||||
|
||||
class PaymentRequestMainScreen extends StatefulWidget {
|
||||
const PaymentRequestMainScreen({super.key});
|
||||
|
||||
@ -70,19 +69,29 @@ class _PaymentRequestMainScreenState extends State<PaymentRequestMainScreen>
|
||||
final now = DateTime.now();
|
||||
|
||||
final filtered = paymentController.paymentRequests.where((e) {
|
||||
return query.isEmpty ||
|
||||
e.title.toLowerCase().contains(query) ||
|
||||
e.payee.toLowerCase().contains(query);
|
||||
final title = e.title?.toLowerCase() ?? "";
|
||||
final payee = e.payee?.toLowerCase() ?? "";
|
||||
|
||||
return query.isEmpty || title.contains(query) || payee.contains(query);
|
||||
}).toList()
|
||||
..sort((a, b) => b.dueDate.compareTo(a.dueDate));
|
||||
..sort((a, b) {
|
||||
final aDate = a.dueDate ?? DateTime(1900);
|
||||
final bDate = b.dueDate ?? DateTime(1900);
|
||||
return bDate.compareTo(aDate);
|
||||
});
|
||||
|
||||
DateTime startOfMonth = DateTime(now.year, now.month, 1);
|
||||
DateTime previousMonthEnd = DateTime(now.year, now.month, 0);
|
||||
|
||||
return isHistory
|
||||
? filtered
|
||||
.where((e) => e.dueDate.isBefore(DateTime(now.year, now.month, 1)))
|
||||
.toList()
|
||||
: filtered
|
||||
.where((e) => e.dueDate.isAfter(DateTime(now.year, now.month, 0)))
|
||||
.toList();
|
||||
? filtered.where((e) {
|
||||
final d = e.dueDate;
|
||||
return d != null && d.isBefore(startOfMonth);
|
||||
}).toList()
|
||||
: filtered.where((e) {
|
||||
final d = e.dueDate;
|
||||
return d != null && d.isAfter(previousMonthEnd);
|
||||
}).toList();
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user