chnages has been made and net salary is being displayed

This commit is contained in:
Daniah Ayad Al-sultani
2026-02-11 14:31:03 +03:00
parent 1002937045
commit a7930d19e5
23 changed files with 691 additions and 141 deletions

View File

@@ -7,6 +7,7 @@ import '../dto/attendance_record_dto.dart';
import '../dto/overtime_dto.dart';
import '../dto/reward_dto.dart';
import '../dto/punishment_dto.dart';
import '../dto/salary_response_dto.dart';
abstract class AttendanceRemoteDataSource {
Future<AttendanceResponseDto> login({
@@ -25,6 +26,11 @@ abstract class AttendanceRemoteDataSource {
Future<List<OvertimeDto>> getExtraHours({required String employeeId});
Future<List<RewardDto>> getRewards({required String employeeId});
Future<List<PunishmentDto>> getPunishments({required String employeeId});
Future<SalaryResponseDto> calculateSalary({
required String employeeId,
required int month,
required int year,
});
}
class AttendanceRemoteDataSourceImpl implements AttendanceRemoteDataSource {
@@ -286,4 +292,66 @@ class AttendanceRemoteDataSourceImpl implements AttendanceRemoteDataSource {
throw ServerException(message: 'خطأ غير متوقع');
}
}
@override
Future<SalaryResponseDto> calculateSalary({
required String employeeId,
required int month,
required int year,
}) async {
try {
final response = await apiClient.get(
'/SalaryRecord/calculate',
queryParameters: {
'EmployeeId': employeeId,
'Month': month,
'Year': year,
},
);
print('Salary Response Status: ${response.statusCode}');
if (response.statusCode == 200 || response.statusCode == 201) {
final responseData = response.data;
print(
'Salary Response Data: $responseData (${responseData.runtimeType})',
);
if (responseData is Map<String, dynamic>) {
return SalaryResponseDto.fromJson(responseData);
} else if (responseData is num) {
// Handle case where API returns raw number
return SalaryResponseDto(
isSuccess: true,
message: 'Success',
data: SalaryDataDto(netAmount: responseData.toDouble()),
);
} else if (responseData is String &&
double.tryParse(responseData) != null) {
// Handle case where API returns raw numeric string
return SalaryResponseDto(
isSuccess: true,
message: 'Success',
data: SalaryDataDto(netAmount: double.parse(responseData)),
);
} else {
throw ServerException(
message: 'استجابة غير صحيحة من الخادم: $responseData',
statusCode: response.statusCode,
);
}
} else {
throw ServerException(
message: 'فشل في حساب الراتب (Status: ${response.statusCode})',
statusCode: response.statusCode,
);
}
} on DioException catch (e) {
throw ServerException(
message: e.message ?? 'Unknown error',
statusCode: e.response?.statusCode,
);
} catch (e) {
throw ServerException(message: 'خطأ غير متوقع');
}
}
}

View File

@@ -3,9 +3,14 @@ import '../../core/error/exceptions.dart';
import '../../core/network/api_client.dart';
import '../dto/login_dto.dart';
import '../dto/login_response_dto.dart';
import '../dto/change_password_request_dto.dart';
import '../dto/change_password_response_dto.dart';
abstract class AuthRemoteDataSource {
Future<LoginResponseDto> login(LoginDto dto);
Future<ChangePasswordResponseDto> changePassword(
ChangePasswordRequestDto dto,
);
}
class AuthRemoteDataSourceImpl implements AuthRemoteDataSource {
@@ -72,4 +77,37 @@ class AuthRemoteDataSourceImpl implements AuthRemoteDataSource {
throw ServerException(message: 'خطأ غير متوقع');
}
}
@override
Future<ChangePasswordResponseDto> changePassword(
ChangePasswordRequestDto dto,
) async {
try {
final response = await apiClient.post(
'/Auth/change-password',
data: dto.toJson(),
);
if (response.statusCode == 200) {
return ChangePasswordResponseDto.fromJson(response.data);
} else {
throw ServerException(
message: response.data['message'] ?? 'فشل تغيير كلمة المرور',
statusCode: response.statusCode,
);
}
} on DioException catch (e) {
final message =
e.response?.data?['message'] ??
e.response?.data?['error'] ??
'فشل تغيير كلمة المرور';
throw ServerException(
message: message,
statusCode: e.response?.statusCode,
);
} catch (e) {
if (e is ServerException) rethrow;
throw ServerException(message: 'خطأ غير متوقع: $e');
}
}
}

View File

@@ -0,0 +1,13 @@
class ChangePasswordRequestDto {
final String oldPassword;
final String newPassword;
ChangePasswordRequestDto({
required this.oldPassword,
required this.newPassword,
});
Map<String, dynamic> toJson() {
return {'oldPassword': oldPassword, 'newPassword': newPassword};
}
}

View File

@@ -0,0 +1,36 @@
import 'login_response_dto.dart';
class ChangePasswordResponseDto {
final int statusCode;
final bool isSuccess;
final String message;
final LoginDataDto? data;
ChangePasswordResponseDto({
required this.statusCode,
required this.isSuccess,
required this.message,
this.data,
});
factory ChangePasswordResponseDto.fromJson(Map<String, dynamic> json) {
return ChangePasswordResponseDto(
statusCode: json['statusCode'] ?? 0,
isSuccess: json['isSuccess'] ?? false,
message: json['message'] ?? '',
data:
json['data'] != null && json['data'] is Map<String, dynamic>
? LoginDataDto.fromJson(json['data'])
: null,
);
}
Map<String, dynamic> toJson() {
return {
'statusCode': statusCode,
'isSuccess': isSuccess,
'message': message,
'data': data?.toJson(),
};
}
}

View File

@@ -0,0 +1,36 @@
class SalaryResponseDto {
final bool isSuccess;
final String message;
final SalaryDataDto? data;
SalaryResponseDto({
required this.isSuccess,
required this.message,
this.data,
});
factory SalaryResponseDto.fromJson(Map<String, dynamic> json) {
return SalaryResponseDto(
isSuccess: json['isSuccess'] ?? json['IsSuccess'] ?? false,
message: json['message'] ?? json['Message'] ?? '',
data:
json['data'] != null
? SalaryDataDto.fromJson(json['data'])
: json['Data'] != null
? SalaryDataDto.fromJson(json['Data'])
: null,
);
}
}
class SalaryDataDto {
final double netAmount;
SalaryDataDto({required this.netAmount});
factory SalaryDataDto.fromJson(Map<String, dynamic> json) {
return SalaryDataDto(
netAmount: (json['netAmount'] ?? json['NetAmount'] ?? 0.0).toDouble(),
);
}
}

View File

@@ -4,6 +4,7 @@ import '../../domain/models/attendance_response_model.dart';
import '../../domain/models/attendance_model.dart';
import '../../domain/models/overtime_model.dart';
import '../../domain/models/extra_payment_model.dart';
import '../../domain/models/salary_model.dart';
import '../../domain/repositories/attendance_repository.dart';
import '../datasources/attendance_remote_data_source.dart';
@@ -131,4 +132,19 @@ class AttendanceRepositoryImpl implements AttendanceRepository {
)
.toList();
}
@override
Future<SalaryModel> calculateSalary({
required String employeeId,
required int month,
required int year,
}) async {
final dto = await remoteDataSource.calculateSalary(
employeeId: employeeId,
month: month,
year: year,
);
return SalaryModel(netAmount: dto.data?.netAmount ?? 0.0);
}
}

View File

@@ -8,6 +8,10 @@ import '../../domain/models/login_request.dart';
import '../../domain/models/login_response_model.dart';
import '../../domain/repositories/auth_repository.dart';
import '../dto/change_password_request_dto.dart';
import '../../domain/models/change_password_request.dart';
import '../../domain/models/general_response_model.dart';
class AuthRepositoryImpl implements AuthRepository {
final AuthRemoteDataSource remoteDataSource;
final UserLocalDataSource localDataSource;
@@ -71,4 +75,45 @@ class AuthRepositoryImpl implements AuthRepository {
return Left(ServerFailure('خطأ غير متوقع: $e'));
}
}
@override
Future<Either<Failure, GeneralResponseModel>> changePassword(
ChangePasswordRequest request,
) async {
try {
final dto = ChangePasswordRequestDto(
oldPassword: request.oldPassword,
newPassword: request.newPassword,
);
final responseDto = await remoteDataSource.changePassword(dto);
// Re-cache token and employeeId if provided in response
if (responseDto.data != null) {
if (responseDto.data!.token != null) {
await localDataSource.cacheUserToken(responseDto.data!.token!);
}
if (responseDto.data!.employeeId != null) {
await localDataSource.cacheEmployeeId(responseDto.data!.employeeId!);
}
}
final model = GeneralResponseModel(
statusCode: responseDto.statusCode,
isSuccess: responseDto.isSuccess,
message: responseDto.message,
data:
responseDto
.isSuccess, // Use isSuccess as data for the boolean model
);
return Right(model);
} on ServerException catch (e) {
return Left(ServerFailure(e.message));
} on NetworkException catch (e) {
return Left(NetworkFailure(e.message));
} catch (e) {
return Left(ServerFailure('خطأ غير متوقع: $e'));
}
}
}