1111
This commit is contained in:
124
lib/data/datasources/advance_remote_data_source.dart
Normal file
124
lib/data/datasources/advance_remote_data_source.dart
Normal file
@@ -0,0 +1,124 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import '../../core/error/exceptions.dart';
|
||||
import '../../core/network/api_client.dart';
|
||||
import '../dto/advance_request_dto.dart';
|
||||
import '../dto/advance_response_dto.dart';
|
||||
import '../dto/advances_list_response_dto.dart';
|
||||
|
||||
abstract class AdvanceRemoteDataSource {
|
||||
Future<AdvanceResponseDto> createAdvance(AdvanceRequestDto request);
|
||||
Future<AdvancesListResponseDto> getAdvances();
|
||||
}
|
||||
|
||||
class AdvanceRemoteDataSourceImpl implements AdvanceRemoteDataSource {
|
||||
final ApiClient apiClient;
|
||||
|
||||
AdvanceRemoteDataSourceImpl({required this.apiClient});
|
||||
|
||||
@override
|
||||
Future<AdvanceResponseDto> createAdvance(AdvanceRequestDto request) async {
|
||||
try {
|
||||
final response = await apiClient.post(
|
||||
'/SalaryInAdvance',
|
||||
data: request.toJson(),
|
||||
);
|
||||
|
||||
if (response.statusCode == 200 || response.statusCode == 201) {
|
||||
final responseData = response.data;
|
||||
|
||||
if (responseData is Map<String, dynamic>) {
|
||||
return AdvanceResponseDto.fromJson(responseData);
|
||||
} else {
|
||||
throw ServerException(
|
||||
message: 'استجابة غير صحيحة من الخادم',
|
||||
statusCode: response.statusCode,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
throw ServerException(
|
||||
message: 'فشل إنشاء طلب السلفة',
|
||||
statusCode: response.statusCode,
|
||||
);
|
||||
}
|
||||
} on DioException catch (e) {
|
||||
if (e.type == DioExceptionType.connectionTimeout ||
|
||||
e.type == DioExceptionType.receiveTimeout) {
|
||||
throw NetworkException(message: 'انتهت مهلة الاتصال');
|
||||
} else if (e.type == DioExceptionType.connectionError) {
|
||||
throw NetworkException(message: 'لا يوجد اتصال بالانترنيت');
|
||||
} else if (e.response?.statusCode == 500) {
|
||||
throw ServerException(message: 'خطأ في الخادم يرجى المحاولة لاحقا');
|
||||
} else if (e.response != null) {
|
||||
final message =
|
||||
e.response?.data?['message'] ??
|
||||
e.response?.data?['error'] ??
|
||||
'فشل إنشاء طلب السلفة';
|
||||
|
||||
throw ServerException(
|
||||
message: message.toString(),
|
||||
statusCode: e.response?.statusCode,
|
||||
);
|
||||
} else {
|
||||
throw NetworkException(message: 'خطأ في الانترنيت يرجى المحاولة لاحقا');
|
||||
}
|
||||
} catch (e) {
|
||||
if (e is ServerException || e is NetworkException) {
|
||||
rethrow;
|
||||
}
|
||||
print('خطأ غير متوقع: $e');
|
||||
throw ServerException(message: 'خطأ غير متوقع');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<AdvancesListResponseDto> getAdvances() async {
|
||||
try {
|
||||
final response = await apiClient.get('/SalaryInAdvance');
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
final responseData = response.data;
|
||||
|
||||
if (responseData is Map<String, dynamic>) {
|
||||
return AdvancesListResponseDto.fromJson(responseData);
|
||||
} else {
|
||||
throw ServerException(
|
||||
message: 'استجابة غير صحيحة من الخادم',
|
||||
statusCode: response.statusCode,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
throw ServerException(
|
||||
message: 'فشل جلب قائمة السلف',
|
||||
statusCode: response.statusCode,
|
||||
);
|
||||
}
|
||||
} on DioException catch (e) {
|
||||
if (e.type == DioExceptionType.connectionTimeout ||
|
||||
e.type == DioExceptionType.receiveTimeout) {
|
||||
throw NetworkException(message: 'انتهت مهلة الاتصال');
|
||||
} else if (e.type == DioExceptionType.connectionError) {
|
||||
throw NetworkException(message: 'لا يوجد اتصال بالانترنيت');
|
||||
} else if (e.response?.statusCode == 500) {
|
||||
throw ServerException(message: 'خطأ في الخادم يرجى المحاولة لاحقا');
|
||||
} else if (e.response != null) {
|
||||
final message =
|
||||
e.response?.data?['message'] ??
|
||||
e.response?.data?['error'] ??
|
||||
'فشل جلب قائمة السلف';
|
||||
|
||||
throw ServerException(
|
||||
message: message.toString(),
|
||||
statusCode: e.response?.statusCode,
|
||||
);
|
||||
} else {
|
||||
throw NetworkException(message: 'خطأ في الانترنيت يرجى المحاولة لاحقا');
|
||||
}
|
||||
} catch (e) {
|
||||
if (e is ServerException || e is NetworkException) {
|
||||
rethrow;
|
||||
}
|
||||
print('خطأ غير متوقع: $e');
|
||||
throw ServerException(message: 'خطأ غير متوقع');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,10 +4,12 @@ import '../../core/network/api_client.dart';
|
||||
import '../dto/vacation_request_dto.dart';
|
||||
import '../dto/vacation_response_dto.dart';
|
||||
import '../dto/vacation_type_dto.dart';
|
||||
import '../dto/vacations_list_response_dto.dart';
|
||||
|
||||
abstract class VacationRemoteDataSource {
|
||||
Future<VacationResponseDto> createVacation(VacationRequestDto request);
|
||||
Future<VacationTypesResponseDto> getVacationTypes();
|
||||
Future<VacationsListResponseDto> getVacations();
|
||||
}
|
||||
|
||||
class VacationRemoteDataSourceImpl implements VacationRemoteDataSource {
|
||||
@@ -121,4 +123,56 @@ class VacationRemoteDataSourceImpl implements VacationRemoteDataSource {
|
||||
throw ServerException(message: 'خطأ غير متوقع');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<VacationsListResponseDto> getVacations() async {
|
||||
try {
|
||||
final response = await apiClient.get('/Vacation');
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
final responseData = response.data;
|
||||
|
||||
if (responseData is Map<String, dynamic>) {
|
||||
return VacationsListResponseDto.fromJson(responseData);
|
||||
} else {
|
||||
throw ServerException(
|
||||
message: 'استجابة غير صحيحة من الخادم',
|
||||
statusCode: response.statusCode,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
throw ServerException(
|
||||
message: 'فشل جلب قائمة الإجازات',
|
||||
statusCode: response.statusCode,
|
||||
);
|
||||
}
|
||||
} on DioException catch (e) {
|
||||
if (e.type == DioExceptionType.connectionTimeout ||
|
||||
e.type == DioExceptionType.receiveTimeout) {
|
||||
throw NetworkException(message: 'انتهت مهلة الاتصال');
|
||||
} else if (e.type == DioExceptionType.connectionError) {
|
||||
throw NetworkException(message: 'لا يوجد اتصال بالانترنيت');
|
||||
} else if (e.response?.statusCode == 500) {
|
||||
throw ServerException(message: 'خطأ في الخادم يرجى المحاولة لاحقا');
|
||||
} else if (e.response != null) {
|
||||
final message =
|
||||
e.response?.data?['message'] ??
|
||||
e.response?.data?['error'] ??
|
||||
'فشل جلب قائمة الإجازات';
|
||||
|
||||
throw ServerException(
|
||||
message: message.toString(),
|
||||
statusCode: e.response?.statusCode,
|
||||
);
|
||||
} else {
|
||||
throw NetworkException(message: 'خطأ في الانترنيت يرجى المحاولة لاحقا');
|
||||
}
|
||||
} catch (e) {
|
||||
if (e is ServerException || e is NetworkException) {
|
||||
rethrow;
|
||||
}
|
||||
print('خطأ غير متوقع: $e');
|
||||
throw ServerException(message: 'خطأ غير متوقع');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
22
lib/data/dto/advance_request_dto.dart
Normal file
22
lib/data/dto/advance_request_dto.dart
Normal file
@@ -0,0 +1,22 @@
|
||||
class AdvanceRequestDto {
|
||||
final String employeeId;
|
||||
final DateTime date;
|
||||
final double amount;
|
||||
final String reason;
|
||||
|
||||
AdvanceRequestDto({
|
||||
required this.employeeId,
|
||||
required this.date,
|
||||
required this.amount,
|
||||
required this.reason,
|
||||
});
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'employeeId': employeeId,
|
||||
'date': date.toIso8601String(),
|
||||
'amount': amount,
|
||||
'reason': reason,
|
||||
};
|
||||
}
|
||||
}
|
||||
86
lib/data/dto/advance_response_dto.dart
Normal file
86
lib/data/dto/advance_response_dto.dart
Normal file
@@ -0,0 +1,86 @@
|
||||
class AdvanceResponseDto {
|
||||
final int statusCode;
|
||||
final bool isSuccess;
|
||||
final String? message;
|
||||
final AdvanceDataDto? data;
|
||||
|
||||
AdvanceResponseDto({
|
||||
required this.statusCode,
|
||||
required this.isSuccess,
|
||||
this.message,
|
||||
this.data,
|
||||
});
|
||||
|
||||
factory AdvanceResponseDto.fromJson(Map<String, dynamic> json) {
|
||||
return AdvanceResponseDto(
|
||||
statusCode: json['statusCode'] ?? 0,
|
||||
isSuccess: json['isSuccess'] ?? false,
|
||||
message: json['message'],
|
||||
data: json['data'] != null ? AdvanceDataDto.fromJson(json['data']) : null,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class AdvanceDataDto {
|
||||
final String employeeId;
|
||||
final String? employeeFullName;
|
||||
final DateTime date;
|
||||
final double amount;
|
||||
final String? submittedBy;
|
||||
final String? submittedByUser;
|
||||
final String reason;
|
||||
final int state;
|
||||
final String id;
|
||||
final DateTime? createdAt;
|
||||
final DateTime? updatedAt;
|
||||
final DateTime? deletedAt;
|
||||
final bool? isDeleted;
|
||||
|
||||
AdvanceDataDto({
|
||||
required this.employeeId,
|
||||
this.employeeFullName,
|
||||
required this.date,
|
||||
required this.amount,
|
||||
this.submittedBy,
|
||||
this.submittedByUser,
|
||||
required this.reason,
|
||||
required this.state,
|
||||
required this.id,
|
||||
this.createdAt,
|
||||
this.updatedAt,
|
||||
this.deletedAt,
|
||||
this.isDeleted,
|
||||
});
|
||||
|
||||
factory AdvanceDataDto.fromJson(Map<String, dynamic> json) {
|
||||
return AdvanceDataDto(
|
||||
employeeId: json['employeeId']?.toString() ?? '',
|
||||
employeeFullName: json['employeeFullName'],
|
||||
date: _parseDateTime(json['date'])!,
|
||||
amount: (json['amount'] is int) ? (json['amount'] as int).toDouble() : (json['amount'] as num).toDouble(),
|
||||
submittedBy: json['submittedBy'],
|
||||
submittedByUser: json['submittedByUser'],
|
||||
reason: json['reason']?.toString() ?? '',
|
||||
state: json['state'] ?? 0,
|
||||
id: json['id']?.toString() ?? '',
|
||||
createdAt: _parseDateTime(json['createdAt']),
|
||||
updatedAt: _parseDateTime(json['updatedAt']),
|
||||
deletedAt: _parseDateTime(json['deletedAt']),
|
||||
isDeleted: json['isDeleted'],
|
||||
);
|
||||
}
|
||||
|
||||
static DateTime? _parseDateTime(dynamic value) {
|
||||
if (value == null) return null;
|
||||
if (value is DateTime) return value;
|
||||
if (value is String) {
|
||||
try {
|
||||
return DateTime.parse(value);
|
||||
} catch (e) {
|
||||
print('Error parsing date: $value - $e');
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
54
lib/data/dto/advances_list_response_dto.dart
Normal file
54
lib/data/dto/advances_list_response_dto.dart
Normal file
@@ -0,0 +1,54 @@
|
||||
import 'advance_response_dto.dart';
|
||||
|
||||
class AdvancesListResponseDto {
|
||||
final int statusCode;
|
||||
final bool isSuccess;
|
||||
final String? message;
|
||||
final AdvancesListDataDto? data;
|
||||
|
||||
AdvancesListResponseDto({
|
||||
required this.statusCode,
|
||||
required this.isSuccess,
|
||||
this.message,
|
||||
this.data,
|
||||
});
|
||||
|
||||
factory AdvancesListResponseDto.fromJson(Map<String, dynamic> json) {
|
||||
return AdvancesListResponseDto(
|
||||
statusCode: json['statusCode'] ?? 0,
|
||||
isSuccess: json['isSuccess'] ?? false,
|
||||
message: json['message'],
|
||||
data: json['data'] != null ? AdvancesListDataDto.fromJson(json['data']) : null,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class AdvancesListDataDto {
|
||||
final List<AdvanceDataDto> items;
|
||||
final int pageNumber;
|
||||
final int pageSize;
|
||||
final int totalCount;
|
||||
final int totalPages;
|
||||
|
||||
AdvancesListDataDto({
|
||||
required this.items,
|
||||
required this.pageNumber,
|
||||
required this.pageSize,
|
||||
required this.totalCount,
|
||||
required this.totalPages,
|
||||
});
|
||||
|
||||
factory AdvancesListDataDto.fromJson(Map<String, dynamic> json) {
|
||||
return AdvancesListDataDto(
|
||||
items: json['items'] != null
|
||||
? (json['items'] as List)
|
||||
.map((item) => AdvanceDataDto.fromJson(item))
|
||||
.toList()
|
||||
: [],
|
||||
pageNumber: json['pageNumber'] ?? 1,
|
||||
pageSize: json['pageSize'] ?? 15,
|
||||
totalCount: json['totalCount'] ?? 0,
|
||||
totalPages: json['totalPages'] ?? 1,
|
||||
);
|
||||
}
|
||||
}
|
||||
54
lib/data/dto/vacations_list_response_dto.dart
Normal file
54
lib/data/dto/vacations_list_response_dto.dart
Normal file
@@ -0,0 +1,54 @@
|
||||
import 'vacation_response_dto.dart';
|
||||
|
||||
class VacationsListResponseDto {
|
||||
final int statusCode;
|
||||
final bool isSuccess;
|
||||
final String? message;
|
||||
final VacationsListDataDto? data;
|
||||
|
||||
VacationsListResponseDto({
|
||||
required this.statusCode,
|
||||
required this.isSuccess,
|
||||
this.message,
|
||||
this.data,
|
||||
});
|
||||
|
||||
factory VacationsListResponseDto.fromJson(Map<String, dynamic> json) {
|
||||
return VacationsListResponseDto(
|
||||
statusCode: json['statusCode'] ?? 0,
|
||||
isSuccess: json['isSuccess'] ?? false,
|
||||
message: json['message'],
|
||||
data: json['data'] != null ? VacationsListDataDto.fromJson(json['data']) : null,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class VacationsListDataDto {
|
||||
final List<VacationDataDto> items;
|
||||
final int pageNumber;
|
||||
final int pageSize;
|
||||
final int totalCount;
|
||||
final int totalPages;
|
||||
|
||||
VacationsListDataDto({
|
||||
required this.items,
|
||||
required this.pageNumber,
|
||||
required this.pageSize,
|
||||
required this.totalCount,
|
||||
required this.totalPages,
|
||||
});
|
||||
|
||||
factory VacationsListDataDto.fromJson(Map<String, dynamic> json) {
|
||||
return VacationsListDataDto(
|
||||
items: json['items'] != null
|
||||
? (json['items'] as List)
|
||||
.map((item) => VacationDataDto.fromJson(item))
|
||||
.toList()
|
||||
: [],
|
||||
pageNumber: json['pageNumber'] ?? 1,
|
||||
pageSize: json['pageSize'] ?? 15,
|
||||
totalCount: json['totalCount'] ?? 0,
|
||||
totalPages: json['totalPages'] ?? 1,
|
||||
);
|
||||
}
|
||||
}
|
||||
109
lib/data/repositories/advance_repository_impl.dart
Normal file
109
lib/data/repositories/advance_repository_impl.dart
Normal file
@@ -0,0 +1,109 @@
|
||||
import 'package:dartz/dartz.dart';
|
||||
import '../../core/error/exceptions.dart';
|
||||
import '../../core/error/failures.dart';
|
||||
import '../datasources/advance_remote_data_source.dart';
|
||||
import '../dto/advance_request_dto.dart';
|
||||
import '../../domain/models/advance_request_model.dart';
|
||||
import '../../domain/models/advances_list_response_model.dart';
|
||||
import '../../domain/repositories/advance_repository.dart';
|
||||
|
||||
class AdvanceRepositoryImpl implements AdvanceRepository {
|
||||
final AdvanceRemoteDataSource remoteDataSource;
|
||||
|
||||
AdvanceRepositoryImpl({required this.remoteDataSource});
|
||||
|
||||
@override
|
||||
Future<Either<Failure, AdvanceResponseModel>> createAdvance(
|
||||
AdvanceRequestModel request,
|
||||
) async {
|
||||
try {
|
||||
final dto = AdvanceRequestDto(
|
||||
employeeId: request.employeeId,
|
||||
date: request.date,
|
||||
amount: request.amount,
|
||||
reason: request.reason,
|
||||
);
|
||||
|
||||
final responseDto = await remoteDataSource.createAdvance(dto);
|
||||
|
||||
// Convert DTO to Model
|
||||
final responseModel = AdvanceResponseModel(
|
||||
statusCode: responseDto.statusCode,
|
||||
isSuccess: responseDto.isSuccess,
|
||||
message: responseDto.message,
|
||||
data: responseDto.data != null
|
||||
? AdvanceDataModel(
|
||||
employeeId: responseDto.data!.employeeId,
|
||||
employeeFullName: responseDto.data!.employeeFullName,
|
||||
date: responseDto.data!.date,
|
||||
amount: responseDto.data!.amount,
|
||||
submittedBy: responseDto.data!.submittedBy,
|
||||
submittedByUser: responseDto.data!.submittedByUser,
|
||||
reason: responseDto.data!.reason,
|
||||
state: responseDto.data!.state,
|
||||
id: responseDto.data!.id,
|
||||
createdAt: responseDto.data!.createdAt,
|
||||
updatedAt: responseDto.data!.updatedAt,
|
||||
deletedAt: responseDto.data!.deletedAt,
|
||||
isDeleted: responseDto.data!.isDeleted,
|
||||
)
|
||||
: null,
|
||||
);
|
||||
|
||||
return Right(responseModel);
|
||||
} on ServerException catch (e) {
|
||||
return Left(ServerFailure(e.message));
|
||||
} on NetworkException catch (e) {
|
||||
return Left(NetworkFailure(e.message));
|
||||
} catch (e) {
|
||||
return Left(ServerFailure('خطأ غير متوقع: $e'));
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Either<Failure, AdvancesListResponseModel>> getAdvances() async {
|
||||
try {
|
||||
final responseDto = await remoteDataSource.getAdvances();
|
||||
|
||||
// Convert DTO to Model
|
||||
final responseModel = AdvancesListResponseModel(
|
||||
statusCode: responseDto.statusCode,
|
||||
isSuccess: responseDto.isSuccess,
|
||||
message: responseDto.message,
|
||||
data: responseDto.data != null
|
||||
? AdvancesListDataModel(
|
||||
items: responseDto.data!.items
|
||||
.map((dto) => AdvanceDataModel(
|
||||
employeeId: dto.employeeId,
|
||||
employeeFullName: dto.employeeFullName,
|
||||
date: dto.date,
|
||||
amount: dto.amount,
|
||||
submittedBy: dto.submittedBy,
|
||||
submittedByUser: dto.submittedByUser,
|
||||
reason: dto.reason,
|
||||
state: dto.state,
|
||||
id: dto.id,
|
||||
createdAt: dto.createdAt,
|
||||
updatedAt: dto.updatedAt,
|
||||
deletedAt: dto.deletedAt,
|
||||
isDeleted: dto.isDeleted,
|
||||
))
|
||||
.toList(),
|
||||
pageNumber: responseDto.data!.pageNumber,
|
||||
pageSize: responseDto.data!.pageSize,
|
||||
totalCount: responseDto.data!.totalCount,
|
||||
totalPages: responseDto.data!.totalPages,
|
||||
)
|
||||
: null,
|
||||
);
|
||||
|
||||
return Right(responseModel);
|
||||
} on ServerException catch (e) {
|
||||
return Left(ServerFailure(e.message));
|
||||
} on NetworkException catch (e) {
|
||||
return Left(NetworkFailure(e.message));
|
||||
} catch (e) {
|
||||
return Left(ServerFailure('خطأ غير متوقع: $e'));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import '../dto/vacation_request_dto.dart';
|
||||
import '../../domain/models/vacation_request.dart';
|
||||
import '../../domain/models/vacation_response_model.dart';
|
||||
import '../../domain/models/vacation_type_model.dart';
|
||||
import '../../domain/models/vacations_list_response_model.dart';
|
||||
import '../../domain/repositories/vacation_repository.dart';
|
||||
|
||||
class VacationRepositoryImpl implements VacationRepository {
|
||||
@@ -90,4 +91,52 @@ class VacationRepositoryImpl implements VacationRepository {
|
||||
return Left(ServerFailure('خطأ غير متوقع: $e'));
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Either<Failure, VacationsListResponseModel>> getVacations() async {
|
||||
try {
|
||||
final responseDto = await remoteDataSource.getVacations();
|
||||
|
||||
// Convert DTO to Model
|
||||
final responseModel = VacationsListResponseModel(
|
||||
statusCode: responseDto.statusCode,
|
||||
isSuccess: responseDto.isSuccess,
|
||||
message: responseDto.message,
|
||||
data: responseDto.data != null
|
||||
? VacationsListDataModel(
|
||||
items: responseDto.data!.items
|
||||
.map((dto) => VacationDataModel(
|
||||
employeeId: dto.employeeId,
|
||||
employeeFullName: dto.employeeFullName,
|
||||
startDate: dto.startDate,
|
||||
endDate: dto.endDate,
|
||||
reason: dto.reason,
|
||||
submittedBy: dto.submittedBy,
|
||||
submittedByUser: dto.submittedByUser,
|
||||
state: dto.state,
|
||||
type: dto.type,
|
||||
id: dto.id,
|
||||
createdAt: dto.createdAt,
|
||||
updatedAt: dto.updatedAt,
|
||||
deletedAt: dto.deletedAt,
|
||||
isDeleted: dto.isDeleted,
|
||||
))
|
||||
.toList(),
|
||||
pageNumber: responseDto.data!.pageNumber,
|
||||
pageSize: responseDto.data!.pageSize,
|
||||
totalCount: responseDto.data!.totalCount,
|
||||
totalPages: responseDto.data!.totalPages,
|
||||
)
|
||||
: null,
|
||||
);
|
||||
|
||||
return Right(responseModel);
|
||||
} on ServerException catch (e) {
|
||||
return Left(ServerFailure(e.message));
|
||||
} on NetworkException catch (e) {
|
||||
return Left(NetworkFailure(e.message));
|
||||
} catch (e) {
|
||||
return Left(ServerFailure('خطأ غير متوقع: $e'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user