fix: API 응답 파싱 오류 수정 및 에러 처리 개선

주요 변경사항:
- 창고 관리 API 응답 구조와 DTO 불일치 수정
  - WarehouseLocationDto에 code, manager_phone 필드 추가
  - RemoteDataSource에서 API 응답을 DTO 구조에 맞게 변환
- 회사 관리 API 응답 파싱 오류 수정
  - CompanyResponse의 필수 필드를 nullable로 변경
  - PaginatedResponse 구조 매핑 로직 개선
- 에러 처리 및 로깅 개선
  - Service Layer에 상세 에러 로깅 추가
  - Controller에서 에러 타입별 처리
- 새로운 유틸리티 추가
  - ResponseInterceptor: API 응답 정규화
  - DebugLogger: 디버깅 도구
  - HealthCheckService: 서버 상태 확인
- 문서화
  - API 통합 테스트 가이드
  - 에러 분석 보고서
  - 리팩토링 계획서
This commit is contained in:
JiWoong Sul
2025-07-31 19:15:39 +09:00
parent ad2c699ff7
commit f08b7fec79
89 changed files with 10521 additions and 892 deletions

View File

@@ -20,6 +20,14 @@ OverviewStats _$OverviewStatsFromJson(Map<String, dynamic> json) {
/// @nodoc
mixin _$OverviewStats {
@JsonKey(name: 'total_companies')
int get totalCompanies => throw _privateConstructorUsedError;
@JsonKey(name: 'active_companies')
int get activeCompanies => throw _privateConstructorUsedError;
@JsonKey(name: 'total_users')
int get totalUsers => throw _privateConstructorUsedError;
@JsonKey(name: 'active_users')
int get activeUsers => throw _privateConstructorUsedError;
@JsonKey(name: 'total_equipment')
int get totalEquipment => throw _privateConstructorUsedError;
@JsonKey(name: 'available_equipment')
@@ -28,18 +36,23 @@ mixin _$OverviewStats {
int get inUseEquipment => throw _privateConstructorUsedError;
@JsonKey(name: 'maintenance_equipment')
int get maintenanceEquipment => throw _privateConstructorUsedError;
@JsonKey(name: 'total_companies')
int get totalCompanies => throw _privateConstructorUsedError;
@JsonKey(name: 'total_users')
int get totalUsers => throw _privateConstructorUsedError;
@JsonKey(name: 'total_licenses')
int get totalLicenses => throw _privateConstructorUsedError;
@JsonKey(name: 'active_licenses')
int get activeLicenses => throw _privateConstructorUsedError;
@JsonKey(name: 'expiring_licenses')
int get expiringLicenses => throw _privateConstructorUsedError;
@JsonKey(name: 'total_rentals')
int get totalRentals => throw _privateConstructorUsedError;
@JsonKey(name: 'active_rentals')
int get activeRentals => throw _privateConstructorUsedError;
@JsonKey(name: 'expiring_licenses_count')
int get expiringLicensesCount => throw _privateConstructorUsedError;
@JsonKey(name: 'expired_licenses_count')
int get expiredLicensesCount => throw _privateConstructorUsedError;
@JsonKey(name: 'total_warehouse_locations')
int get totalWarehouseLocations => throw _privateConstructorUsedError;
@JsonKey(name: 'active_warehouse_locations')
int get activeWarehouseLocations =>
throw _privateConstructorUsedError; // 다음 필드들은 백엔드에 없으므로 선택적으로 만듭니다
@JsonKey(name: 'total_rentals', defaultValue: 0)
int? get totalRentals => throw _privateConstructorUsedError;
@JsonKey(name: 'active_rentals', defaultValue: 0)
int? get activeRentals => throw _privateConstructorUsedError;
/// Serializes this OverviewStats to a JSON map.
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
@@ -58,16 +71,22 @@ abstract class $OverviewStatsCopyWith<$Res> {
_$OverviewStatsCopyWithImpl<$Res, OverviewStats>;
@useResult
$Res call(
{@JsonKey(name: 'total_equipment') int totalEquipment,
{@JsonKey(name: 'total_companies') int totalCompanies,
@JsonKey(name: 'active_companies') int activeCompanies,
@JsonKey(name: 'total_users') int totalUsers,
@JsonKey(name: 'active_users') int activeUsers,
@JsonKey(name: 'total_equipment') int totalEquipment,
@JsonKey(name: 'available_equipment') int availableEquipment,
@JsonKey(name: 'in_use_equipment') int inUseEquipment,
@JsonKey(name: 'maintenance_equipment') int maintenanceEquipment,
@JsonKey(name: 'total_companies') int totalCompanies,
@JsonKey(name: 'total_users') int totalUsers,
@JsonKey(name: 'total_licenses') int totalLicenses,
@JsonKey(name: 'active_licenses') int activeLicenses,
@JsonKey(name: 'expiring_licenses') int expiringLicenses,
@JsonKey(name: 'total_rentals') int totalRentals,
@JsonKey(name: 'active_rentals') int activeRentals});
@JsonKey(name: 'expiring_licenses_count') int expiringLicensesCount,
@JsonKey(name: 'expired_licenses_count') int expiredLicensesCount,
@JsonKey(name: 'total_warehouse_locations') int totalWarehouseLocations,
@JsonKey(name: 'active_warehouse_locations') int activeWarehouseLocations,
@JsonKey(name: 'total_rentals', defaultValue: 0) int? totalRentals,
@JsonKey(name: 'active_rentals', defaultValue: 0) int? activeRentals});
}
/// @nodoc
@@ -85,18 +104,40 @@ class _$OverviewStatsCopyWithImpl<$Res, $Val extends OverviewStats>
@pragma('vm:prefer-inline')
@override
$Res call({
Object? totalCompanies = null,
Object? activeCompanies = null,
Object? totalUsers = null,
Object? activeUsers = null,
Object? totalEquipment = null,
Object? availableEquipment = null,
Object? inUseEquipment = null,
Object? maintenanceEquipment = null,
Object? totalCompanies = null,
Object? totalUsers = null,
Object? totalLicenses = null,
Object? activeLicenses = null,
Object? expiringLicenses = null,
Object? totalRentals = null,
Object? activeRentals = null,
Object? expiringLicensesCount = null,
Object? expiredLicensesCount = null,
Object? totalWarehouseLocations = null,
Object? activeWarehouseLocations = null,
Object? totalRentals = freezed,
Object? activeRentals = freezed,
}) {
return _then(_value.copyWith(
totalCompanies: null == totalCompanies
? _value.totalCompanies
: totalCompanies // ignore: cast_nullable_to_non_nullable
as int,
activeCompanies: null == activeCompanies
? _value.activeCompanies
: activeCompanies // ignore: cast_nullable_to_non_nullable
as int,
totalUsers: null == totalUsers
? _value.totalUsers
: totalUsers // ignore: cast_nullable_to_non_nullable
as int,
activeUsers: null == activeUsers
? _value.activeUsers
: activeUsers // ignore: cast_nullable_to_non_nullable
as int,
totalEquipment: null == totalEquipment
? _value.totalEquipment
: totalEquipment // ignore: cast_nullable_to_non_nullable
@@ -113,30 +154,38 @@ class _$OverviewStatsCopyWithImpl<$Res, $Val extends OverviewStats>
? _value.maintenanceEquipment
: maintenanceEquipment // ignore: cast_nullable_to_non_nullable
as int,
totalCompanies: null == totalCompanies
? _value.totalCompanies
: totalCompanies // ignore: cast_nullable_to_non_nullable
as int,
totalUsers: null == totalUsers
? _value.totalUsers
: totalUsers // ignore: cast_nullable_to_non_nullable
totalLicenses: null == totalLicenses
? _value.totalLicenses
: totalLicenses // ignore: cast_nullable_to_non_nullable
as int,
activeLicenses: null == activeLicenses
? _value.activeLicenses
: activeLicenses // ignore: cast_nullable_to_non_nullable
as int,
expiringLicenses: null == expiringLicenses
? _value.expiringLicenses
: expiringLicenses // ignore: cast_nullable_to_non_nullable
expiringLicensesCount: null == expiringLicensesCount
? _value.expiringLicensesCount
: expiringLicensesCount // ignore: cast_nullable_to_non_nullable
as int,
totalRentals: null == totalRentals
expiredLicensesCount: null == expiredLicensesCount
? _value.expiredLicensesCount
: expiredLicensesCount // ignore: cast_nullable_to_non_nullable
as int,
totalWarehouseLocations: null == totalWarehouseLocations
? _value.totalWarehouseLocations
: totalWarehouseLocations // ignore: cast_nullable_to_non_nullable
as int,
activeWarehouseLocations: null == activeWarehouseLocations
? _value.activeWarehouseLocations
: activeWarehouseLocations // ignore: cast_nullable_to_non_nullable
as int,
totalRentals: freezed == totalRentals
? _value.totalRentals
: totalRentals // ignore: cast_nullable_to_non_nullable
as int,
activeRentals: null == activeRentals
as int?,
activeRentals: freezed == activeRentals
? _value.activeRentals
: activeRentals // ignore: cast_nullable_to_non_nullable
as int,
as int?,
) as $Val);
}
}
@@ -150,16 +199,22 @@ abstract class _$$OverviewStatsImplCopyWith<$Res>
@override
@useResult
$Res call(
{@JsonKey(name: 'total_equipment') int totalEquipment,
{@JsonKey(name: 'total_companies') int totalCompanies,
@JsonKey(name: 'active_companies') int activeCompanies,
@JsonKey(name: 'total_users') int totalUsers,
@JsonKey(name: 'active_users') int activeUsers,
@JsonKey(name: 'total_equipment') int totalEquipment,
@JsonKey(name: 'available_equipment') int availableEquipment,
@JsonKey(name: 'in_use_equipment') int inUseEquipment,
@JsonKey(name: 'maintenance_equipment') int maintenanceEquipment,
@JsonKey(name: 'total_companies') int totalCompanies,
@JsonKey(name: 'total_users') int totalUsers,
@JsonKey(name: 'total_licenses') int totalLicenses,
@JsonKey(name: 'active_licenses') int activeLicenses,
@JsonKey(name: 'expiring_licenses') int expiringLicenses,
@JsonKey(name: 'total_rentals') int totalRentals,
@JsonKey(name: 'active_rentals') int activeRentals});
@JsonKey(name: 'expiring_licenses_count') int expiringLicensesCount,
@JsonKey(name: 'expired_licenses_count') int expiredLicensesCount,
@JsonKey(name: 'total_warehouse_locations') int totalWarehouseLocations,
@JsonKey(name: 'active_warehouse_locations') int activeWarehouseLocations,
@JsonKey(name: 'total_rentals', defaultValue: 0) int? totalRentals,
@JsonKey(name: 'active_rentals', defaultValue: 0) int? activeRentals});
}
/// @nodoc
@@ -175,18 +230,40 @@ class __$$OverviewStatsImplCopyWithImpl<$Res>
@pragma('vm:prefer-inline')
@override
$Res call({
Object? totalCompanies = null,
Object? activeCompanies = null,
Object? totalUsers = null,
Object? activeUsers = null,
Object? totalEquipment = null,
Object? availableEquipment = null,
Object? inUseEquipment = null,
Object? maintenanceEquipment = null,
Object? totalCompanies = null,
Object? totalUsers = null,
Object? totalLicenses = null,
Object? activeLicenses = null,
Object? expiringLicenses = null,
Object? totalRentals = null,
Object? activeRentals = null,
Object? expiringLicensesCount = null,
Object? expiredLicensesCount = null,
Object? totalWarehouseLocations = null,
Object? activeWarehouseLocations = null,
Object? totalRentals = freezed,
Object? activeRentals = freezed,
}) {
return _then(_$OverviewStatsImpl(
totalCompanies: null == totalCompanies
? _value.totalCompanies
: totalCompanies // ignore: cast_nullable_to_non_nullable
as int,
activeCompanies: null == activeCompanies
? _value.activeCompanies
: activeCompanies // ignore: cast_nullable_to_non_nullable
as int,
totalUsers: null == totalUsers
? _value.totalUsers
: totalUsers // ignore: cast_nullable_to_non_nullable
as int,
activeUsers: null == activeUsers
? _value.activeUsers
: activeUsers // ignore: cast_nullable_to_non_nullable
as int,
totalEquipment: null == totalEquipment
? _value.totalEquipment
: totalEquipment // ignore: cast_nullable_to_non_nullable
@@ -203,30 +280,38 @@ class __$$OverviewStatsImplCopyWithImpl<$Res>
? _value.maintenanceEquipment
: maintenanceEquipment // ignore: cast_nullable_to_non_nullable
as int,
totalCompanies: null == totalCompanies
? _value.totalCompanies
: totalCompanies // ignore: cast_nullable_to_non_nullable
as int,
totalUsers: null == totalUsers
? _value.totalUsers
: totalUsers // ignore: cast_nullable_to_non_nullable
totalLicenses: null == totalLicenses
? _value.totalLicenses
: totalLicenses // ignore: cast_nullable_to_non_nullable
as int,
activeLicenses: null == activeLicenses
? _value.activeLicenses
: activeLicenses // ignore: cast_nullable_to_non_nullable
as int,
expiringLicenses: null == expiringLicenses
? _value.expiringLicenses
: expiringLicenses // ignore: cast_nullable_to_non_nullable
expiringLicensesCount: null == expiringLicensesCount
? _value.expiringLicensesCount
: expiringLicensesCount // ignore: cast_nullable_to_non_nullable
as int,
totalRentals: null == totalRentals
expiredLicensesCount: null == expiredLicensesCount
? _value.expiredLicensesCount
: expiredLicensesCount // ignore: cast_nullable_to_non_nullable
as int,
totalWarehouseLocations: null == totalWarehouseLocations
? _value.totalWarehouseLocations
: totalWarehouseLocations // ignore: cast_nullable_to_non_nullable
as int,
activeWarehouseLocations: null == activeWarehouseLocations
? _value.activeWarehouseLocations
: activeWarehouseLocations // ignore: cast_nullable_to_non_nullable
as int,
totalRentals: freezed == totalRentals
? _value.totalRentals
: totalRentals // ignore: cast_nullable_to_non_nullable
as int,
activeRentals: null == activeRentals
as int?,
activeRentals: freezed == activeRentals
? _value.activeRentals
: activeRentals // ignore: cast_nullable_to_non_nullable
as int,
as int?,
));
}
}
@@ -235,21 +320,43 @@ class __$$OverviewStatsImplCopyWithImpl<$Res>
@JsonSerializable()
class _$OverviewStatsImpl implements _OverviewStats {
const _$OverviewStatsImpl(
{@JsonKey(name: 'total_equipment') required this.totalEquipment,
{@JsonKey(name: 'total_companies') required this.totalCompanies,
@JsonKey(name: 'active_companies') required this.activeCompanies,
@JsonKey(name: 'total_users') required this.totalUsers,
@JsonKey(name: 'active_users') required this.activeUsers,
@JsonKey(name: 'total_equipment') required this.totalEquipment,
@JsonKey(name: 'available_equipment') required this.availableEquipment,
@JsonKey(name: 'in_use_equipment') required this.inUseEquipment,
@JsonKey(name: 'maintenance_equipment')
required this.maintenanceEquipment,
@JsonKey(name: 'total_companies') required this.totalCompanies,
@JsonKey(name: 'total_users') required this.totalUsers,
@JsonKey(name: 'total_licenses') required this.totalLicenses,
@JsonKey(name: 'active_licenses') required this.activeLicenses,
@JsonKey(name: 'expiring_licenses') required this.expiringLicenses,
@JsonKey(name: 'total_rentals') required this.totalRentals,
@JsonKey(name: 'active_rentals') required this.activeRentals});
@JsonKey(name: 'expiring_licenses_count')
required this.expiringLicensesCount,
@JsonKey(name: 'expired_licenses_count')
required this.expiredLicensesCount,
@JsonKey(name: 'total_warehouse_locations')
required this.totalWarehouseLocations,
@JsonKey(name: 'active_warehouse_locations')
required this.activeWarehouseLocations,
@JsonKey(name: 'total_rentals', defaultValue: 0) this.totalRentals,
@JsonKey(name: 'active_rentals', defaultValue: 0) this.activeRentals});
factory _$OverviewStatsImpl.fromJson(Map<String, dynamic> json) =>
_$$OverviewStatsImplFromJson(json);
@override
@JsonKey(name: 'total_companies')
final int totalCompanies;
@override
@JsonKey(name: 'active_companies')
final int activeCompanies;
@override
@JsonKey(name: 'total_users')
final int totalUsers;
@override
@JsonKey(name: 'active_users')
final int activeUsers;
@override
@JsonKey(name: 'total_equipment')
final int totalEquipment;
@@ -263,27 +370,34 @@ class _$OverviewStatsImpl implements _OverviewStats {
@JsonKey(name: 'maintenance_equipment')
final int maintenanceEquipment;
@override
@JsonKey(name: 'total_companies')
final int totalCompanies;
@override
@JsonKey(name: 'total_users')
final int totalUsers;
@JsonKey(name: 'total_licenses')
final int totalLicenses;
@override
@JsonKey(name: 'active_licenses')
final int activeLicenses;
@override
@JsonKey(name: 'expiring_licenses')
final int expiringLicenses;
@JsonKey(name: 'expiring_licenses_count')
final int expiringLicensesCount;
@override
@JsonKey(name: 'total_rentals')
final int totalRentals;
@JsonKey(name: 'expired_licenses_count')
final int expiredLicensesCount;
@override
@JsonKey(name: 'active_rentals')
final int activeRentals;
@JsonKey(name: 'total_warehouse_locations')
final int totalWarehouseLocations;
@override
@JsonKey(name: 'active_warehouse_locations')
final int activeWarehouseLocations;
// 다음 필드들은 백엔드에 없으므로 선택적으로 만듭니다
@override
@JsonKey(name: 'total_rentals', defaultValue: 0)
final int? totalRentals;
@override
@JsonKey(name: 'active_rentals', defaultValue: 0)
final int? activeRentals;
@override
String toString() {
return 'OverviewStats(totalEquipment: $totalEquipment, availableEquipment: $availableEquipment, inUseEquipment: $inUseEquipment, maintenanceEquipment: $maintenanceEquipment, totalCompanies: $totalCompanies, totalUsers: $totalUsers, activeLicenses: $activeLicenses, expiringLicenses: $expiringLicenses, totalRentals: $totalRentals, activeRentals: $activeRentals)';
return 'OverviewStats(totalCompanies: $totalCompanies, activeCompanies: $activeCompanies, totalUsers: $totalUsers, activeUsers: $activeUsers, totalEquipment: $totalEquipment, availableEquipment: $availableEquipment, inUseEquipment: $inUseEquipment, maintenanceEquipment: $maintenanceEquipment, totalLicenses: $totalLicenses, activeLicenses: $activeLicenses, expiringLicensesCount: $expiringLicensesCount, expiredLicensesCount: $expiredLicensesCount, totalWarehouseLocations: $totalWarehouseLocations, activeWarehouseLocations: $activeWarehouseLocations, totalRentals: $totalRentals, activeRentals: $activeRentals)';
}
@override
@@ -291,6 +405,14 @@ class _$OverviewStatsImpl implements _OverviewStats {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$OverviewStatsImpl &&
(identical(other.totalCompanies, totalCompanies) ||
other.totalCompanies == totalCompanies) &&
(identical(other.activeCompanies, activeCompanies) ||
other.activeCompanies == activeCompanies) &&
(identical(other.totalUsers, totalUsers) ||
other.totalUsers == totalUsers) &&
(identical(other.activeUsers, activeUsers) ||
other.activeUsers == activeUsers) &&
(identical(other.totalEquipment, totalEquipment) ||
other.totalEquipment == totalEquipment) &&
(identical(other.availableEquipment, availableEquipment) ||
@@ -299,14 +421,20 @@ class _$OverviewStatsImpl implements _OverviewStats {
other.inUseEquipment == inUseEquipment) &&
(identical(other.maintenanceEquipment, maintenanceEquipment) ||
other.maintenanceEquipment == maintenanceEquipment) &&
(identical(other.totalCompanies, totalCompanies) ||
other.totalCompanies == totalCompanies) &&
(identical(other.totalUsers, totalUsers) ||
other.totalUsers == totalUsers) &&
(identical(other.totalLicenses, totalLicenses) ||
other.totalLicenses == totalLicenses) &&
(identical(other.activeLicenses, activeLicenses) ||
other.activeLicenses == activeLicenses) &&
(identical(other.expiringLicenses, expiringLicenses) ||
other.expiringLicenses == expiringLicenses) &&
(identical(other.expiringLicensesCount, expiringLicensesCount) ||
other.expiringLicensesCount == expiringLicensesCount) &&
(identical(other.expiredLicensesCount, expiredLicensesCount) ||
other.expiredLicensesCount == expiredLicensesCount) &&
(identical(
other.totalWarehouseLocations, totalWarehouseLocations) ||
other.totalWarehouseLocations == totalWarehouseLocations) &&
(identical(
other.activeWarehouseLocations, activeWarehouseLocations) ||
other.activeWarehouseLocations == activeWarehouseLocations) &&
(identical(other.totalRentals, totalRentals) ||
other.totalRentals == totalRentals) &&
(identical(other.activeRentals, activeRentals) ||
@@ -317,14 +445,20 @@ class _$OverviewStatsImpl implements _OverviewStats {
@override
int get hashCode => Object.hash(
runtimeType,
totalCompanies,
activeCompanies,
totalUsers,
activeUsers,
totalEquipment,
availableEquipment,
inUseEquipment,
maintenanceEquipment,
totalCompanies,
totalUsers,
totalLicenses,
activeLicenses,
expiringLicenses,
expiringLicensesCount,
expiredLicensesCount,
totalWarehouseLocations,
activeWarehouseLocations,
totalRentals,
activeRentals);
@@ -346,23 +480,45 @@ class _$OverviewStatsImpl implements _OverviewStats {
abstract class _OverviewStats implements OverviewStats {
const factory _OverviewStats(
{@JsonKey(name: 'total_equipment') required final int totalEquipment,
{@JsonKey(name: 'total_companies') required final int totalCompanies,
@JsonKey(name: 'active_companies') required final int activeCompanies,
@JsonKey(name: 'total_users') required final int totalUsers,
@JsonKey(name: 'active_users') required final int activeUsers,
@JsonKey(name: 'total_equipment') required final int totalEquipment,
@JsonKey(name: 'available_equipment')
required final int availableEquipment,
@JsonKey(name: 'in_use_equipment') required final int inUseEquipment,
@JsonKey(name: 'maintenance_equipment')
required final int maintenanceEquipment,
@JsonKey(name: 'total_companies') required final int totalCompanies,
@JsonKey(name: 'total_users') required final int totalUsers,
@JsonKey(name: 'total_licenses') required final int totalLicenses,
@JsonKey(name: 'active_licenses') required final int activeLicenses,
@JsonKey(name: 'expiring_licenses') required final int expiringLicenses,
@JsonKey(name: 'total_rentals') required final int totalRentals,
@JsonKey(name: 'active_rentals')
required final int activeRentals}) = _$OverviewStatsImpl;
@JsonKey(name: 'expiring_licenses_count')
required final int expiringLicensesCount,
@JsonKey(name: 'expired_licenses_count')
required final int expiredLicensesCount,
@JsonKey(name: 'total_warehouse_locations')
required final int totalWarehouseLocations,
@JsonKey(name: 'active_warehouse_locations')
required final int activeWarehouseLocations,
@JsonKey(name: 'total_rentals', defaultValue: 0) final int? totalRentals,
@JsonKey(name: 'active_rentals', defaultValue: 0)
final int? activeRentals}) = _$OverviewStatsImpl;
factory _OverviewStats.fromJson(Map<String, dynamic> json) =
_$OverviewStatsImpl.fromJson;
@override
@JsonKey(name: 'total_companies')
int get totalCompanies;
@override
@JsonKey(name: 'active_companies')
int get activeCompanies;
@override
@JsonKey(name: 'total_users')
int get totalUsers;
@override
@JsonKey(name: 'active_users')
int get activeUsers;
@override
@JsonKey(name: 'total_equipment')
int get totalEquipment;
@@ -376,23 +532,29 @@ abstract class _OverviewStats implements OverviewStats {
@JsonKey(name: 'maintenance_equipment')
int get maintenanceEquipment;
@override
@JsonKey(name: 'total_companies')
int get totalCompanies;
@override
@JsonKey(name: 'total_users')
int get totalUsers;
@JsonKey(name: 'total_licenses')
int get totalLicenses;
@override
@JsonKey(name: 'active_licenses')
int get activeLicenses;
@override
@JsonKey(name: 'expiring_licenses')
int get expiringLicenses;
@JsonKey(name: 'expiring_licenses_count')
int get expiringLicensesCount;
@override
@JsonKey(name: 'total_rentals')
int get totalRentals;
@JsonKey(name: 'expired_licenses_count')
int get expiredLicensesCount;
@override
@JsonKey(name: 'active_rentals')
int get activeRentals;
@JsonKey(name: 'total_warehouse_locations')
int get totalWarehouseLocations;
@override
@JsonKey(name: 'active_warehouse_locations')
int get activeWarehouseLocations; // 다음 필드들은 백엔드에 없으므로 선택적으로 만듭니다
@override
@JsonKey(name: 'total_rentals', defaultValue: 0)
int? get totalRentals;
@override
@JsonKey(name: 'active_rentals', defaultValue: 0)
int? get activeRentals;
/// Create a copy of OverviewStats
/// with the given fields replaced by the non-null parameter values.