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