Service_Project_Branching #82

Merged
vaibhav.surve merged 20 commits from Service_Project_Branching into main 2025-11-24 06:32:58 +00:00
3 changed files with 123 additions and 95 deletions
Showing only changes of commit 2c98ac359c - Show all commits

View File

@ -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 {

View File

@ -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"],

View File

@ -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