feat: 회사 관리 기능 개선 및 지점 평면화 DTO 추가

- CompanyBranchFlatDto 모델 추가로 지점 데이터 처리 개선
- 회사 서비스에 브랜치 평면화 기능 추가
- 회사 폼 컨트롤러 기능 확장
- 회사 리스트 화면 UI 개선

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
JiWoong Sul
2025-08-09 02:16:57 +09:00
parent 8302ff37cc
commit f8e8a95391
9 changed files with 682 additions and 208 deletions

View File

@@ -9,6 +9,7 @@ import 'package:superport/data/models/common/paginated_response.dart';
import 'package:superport/data/models/company/company_dto.dart';
import 'package:superport/data/models/company/company_list_dto.dart';
import 'package:superport/data/models/company/branch_dto.dart';
import 'package:superport/data/models/company/company_branch_flat_dto.dart';
abstract class CompanyRemoteDataSource {
Future<PaginatedResponse<CompanyListDto>> getCompanies({
@@ -48,6 +49,8 @@ abstract class CompanyRemoteDataSource {
Future<void> deleteBranch(int companyId, int branchId);
Future<List<BranchListDto>> getCompanyBranches(int companyId);
Future<List<CompanyBranchFlatDto>> getCompanyBranchesFlat();
}
@LazySingleton(as: CompanyRemoteDataSource)
@@ -343,6 +346,36 @@ class CompanyRemoteDataSourceImpl implements CompanyRemoteDataSource {
}
}
@override
Future<List<CompanyBranchFlatDto>> getCompanyBranchesFlat() async {
try {
final response = await _apiClient.get('${ApiEndpoints.companies}/branches');
if (response.statusCode == 200) {
final responseData = response.data;
if (responseData != null && responseData['success'] == true && responseData['data'] != null) {
final List<dynamic> dataList = responseData['data'];
return dataList.map((item) =>
CompanyBranchFlatDto.fromJson(item as Map<String, dynamic>)
).toList();
} else {
throw ApiException(
message: responseData?['error']?['message'] ?? 'Failed to load company branches',
statusCode: response.statusCode,
);
}
} else {
throw ApiException(
message: 'Failed to load company branches',
statusCode: response.statusCode,
);
}
} catch (e) {
if (e is ApiException) rethrow;
throw ApiException(message: e.toString());
}
}
@override
Future<bool> checkDuplicateCompany(String name) async {
try {

View File

@@ -0,0 +1,18 @@
import 'package:freezed_annotation/freezed_annotation.dart';
part 'company_branch_flat_dto.freezed.dart';
part 'company_branch_flat_dto.g.dart';
/// /companies/branches API의 평면화된 응답을 위한 DTO
@freezed
class CompanyBranchFlatDto with _$CompanyBranchFlatDto {
const factory CompanyBranchFlatDto({
@JsonKey(name: 'company_id') required int companyId,
@JsonKey(name: 'company_name') required String companyName,
@JsonKey(name: 'branch_id') int? branchId,
@JsonKey(name: 'branch_name') String? branchName,
}) = _CompanyBranchFlatDto;
factory CompanyBranchFlatDto.fromJson(Map<String, dynamic> json) =>
_$CompanyBranchFlatDtoFromJson(json);
}

View File

@@ -0,0 +1,249 @@
// coverage:ignore-file
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
part of 'company_branch_flat_dto.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
T _$identity<T>(T value) => value;
final _privateConstructorUsedError = UnsupportedError(
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
CompanyBranchFlatDto _$CompanyBranchFlatDtoFromJson(Map<String, dynamic> json) {
return _CompanyBranchFlatDto.fromJson(json);
}
/// @nodoc
mixin _$CompanyBranchFlatDto {
@JsonKey(name: 'company_id')
int get companyId => throw _privateConstructorUsedError;
@JsonKey(name: 'company_name')
String get companyName => throw _privateConstructorUsedError;
@JsonKey(name: 'branch_id')
int? get branchId => throw _privateConstructorUsedError;
@JsonKey(name: 'branch_name')
String? get branchName => throw _privateConstructorUsedError;
/// Serializes this CompanyBranchFlatDto to a JSON map.
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
/// Create a copy of CompanyBranchFlatDto
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
$CompanyBranchFlatDtoCopyWith<CompanyBranchFlatDto> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $CompanyBranchFlatDtoCopyWith<$Res> {
factory $CompanyBranchFlatDtoCopyWith(CompanyBranchFlatDto value,
$Res Function(CompanyBranchFlatDto) then) =
_$CompanyBranchFlatDtoCopyWithImpl<$Res, CompanyBranchFlatDto>;
@useResult
$Res call(
{@JsonKey(name: 'company_id') int companyId,
@JsonKey(name: 'company_name') String companyName,
@JsonKey(name: 'branch_id') int? branchId,
@JsonKey(name: 'branch_name') String? branchName});
}
/// @nodoc
class _$CompanyBranchFlatDtoCopyWithImpl<$Res,
$Val extends CompanyBranchFlatDto>
implements $CompanyBranchFlatDtoCopyWith<$Res> {
_$CompanyBranchFlatDtoCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
/// Create a copy of CompanyBranchFlatDto
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? companyId = null,
Object? companyName = null,
Object? branchId = freezed,
Object? branchName = freezed,
}) {
return _then(_value.copyWith(
companyId: null == companyId
? _value.companyId
: companyId // ignore: cast_nullable_to_non_nullable
as int,
companyName: null == companyName
? _value.companyName
: companyName // ignore: cast_nullable_to_non_nullable
as String,
branchId: freezed == branchId
? _value.branchId
: branchId // ignore: cast_nullable_to_non_nullable
as int?,
branchName: freezed == branchName
? _value.branchName
: branchName // ignore: cast_nullable_to_non_nullable
as String?,
) as $Val);
}
}
/// @nodoc
abstract class _$$CompanyBranchFlatDtoImplCopyWith<$Res>
implements $CompanyBranchFlatDtoCopyWith<$Res> {
factory _$$CompanyBranchFlatDtoImplCopyWith(_$CompanyBranchFlatDtoImpl value,
$Res Function(_$CompanyBranchFlatDtoImpl) then) =
__$$CompanyBranchFlatDtoImplCopyWithImpl<$Res>;
@override
@useResult
$Res call(
{@JsonKey(name: 'company_id') int companyId,
@JsonKey(name: 'company_name') String companyName,
@JsonKey(name: 'branch_id') int? branchId,
@JsonKey(name: 'branch_name') String? branchName});
}
/// @nodoc
class __$$CompanyBranchFlatDtoImplCopyWithImpl<$Res>
extends _$CompanyBranchFlatDtoCopyWithImpl<$Res, _$CompanyBranchFlatDtoImpl>
implements _$$CompanyBranchFlatDtoImplCopyWith<$Res> {
__$$CompanyBranchFlatDtoImplCopyWithImpl(_$CompanyBranchFlatDtoImpl _value,
$Res Function(_$CompanyBranchFlatDtoImpl) _then)
: super(_value, _then);
/// Create a copy of CompanyBranchFlatDto
/// with the given fields replaced by the non-null parameter values.
@pragma('vm:prefer-inline')
@override
$Res call({
Object? companyId = null,
Object? companyName = null,
Object? branchId = freezed,
Object? branchName = freezed,
}) {
return _then(_$CompanyBranchFlatDtoImpl(
companyId: null == companyId
? _value.companyId
: companyId // ignore: cast_nullable_to_non_nullable
as int,
companyName: null == companyName
? _value.companyName
: companyName // ignore: cast_nullable_to_non_nullable
as String,
branchId: freezed == branchId
? _value.branchId
: branchId // ignore: cast_nullable_to_non_nullable
as int?,
branchName: freezed == branchName
? _value.branchName
: branchName // ignore: cast_nullable_to_non_nullable
as String?,
));
}
}
/// @nodoc
@JsonSerializable()
class _$CompanyBranchFlatDtoImpl implements _CompanyBranchFlatDto {
const _$CompanyBranchFlatDtoImpl(
{@JsonKey(name: 'company_id') required this.companyId,
@JsonKey(name: 'company_name') required this.companyName,
@JsonKey(name: 'branch_id') this.branchId,
@JsonKey(name: 'branch_name') this.branchName});
factory _$CompanyBranchFlatDtoImpl.fromJson(Map<String, dynamic> json) =>
_$$CompanyBranchFlatDtoImplFromJson(json);
@override
@JsonKey(name: 'company_id')
final int companyId;
@override
@JsonKey(name: 'company_name')
final String companyName;
@override
@JsonKey(name: 'branch_id')
final int? branchId;
@override
@JsonKey(name: 'branch_name')
final String? branchName;
@override
String toString() {
return 'CompanyBranchFlatDto(companyId: $companyId, companyName: $companyName, branchId: $branchId, branchName: $branchName)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$CompanyBranchFlatDtoImpl &&
(identical(other.companyId, companyId) ||
other.companyId == companyId) &&
(identical(other.companyName, companyName) ||
other.companyName == companyName) &&
(identical(other.branchId, branchId) ||
other.branchId == branchId) &&
(identical(other.branchName, branchName) ||
other.branchName == branchName));
}
@JsonKey(includeFromJson: false, includeToJson: false)
@override
int get hashCode =>
Object.hash(runtimeType, companyId, companyName, branchId, branchName);
/// Create a copy of CompanyBranchFlatDto
/// with the given fields replaced by the non-null parameter values.
@JsonKey(includeFromJson: false, includeToJson: false)
@override
@pragma('vm:prefer-inline')
_$$CompanyBranchFlatDtoImplCopyWith<_$CompanyBranchFlatDtoImpl>
get copyWith =>
__$$CompanyBranchFlatDtoImplCopyWithImpl<_$CompanyBranchFlatDtoImpl>(
this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$$CompanyBranchFlatDtoImplToJson(
this,
);
}
}
abstract class _CompanyBranchFlatDto implements CompanyBranchFlatDto {
const factory _CompanyBranchFlatDto(
{@JsonKey(name: 'company_id') required final int companyId,
@JsonKey(name: 'company_name') required final String companyName,
@JsonKey(name: 'branch_id') final int? branchId,
@JsonKey(name: 'branch_name') final String? branchName}) =
_$CompanyBranchFlatDtoImpl;
factory _CompanyBranchFlatDto.fromJson(Map<String, dynamic> json) =
_$CompanyBranchFlatDtoImpl.fromJson;
@override
@JsonKey(name: 'company_id')
int get companyId;
@override
@JsonKey(name: 'company_name')
String get companyName;
@override
@JsonKey(name: 'branch_id')
int? get branchId;
@override
@JsonKey(name: 'branch_name')
String? get branchName;
/// Create a copy of CompanyBranchFlatDto
/// with the given fields replaced by the non-null parameter values.
@override
@JsonKey(includeFromJson: false, includeToJson: false)
_$$CompanyBranchFlatDtoImplCopyWith<_$CompanyBranchFlatDtoImpl>
get copyWith => throw _privateConstructorUsedError;
}

View File

@@ -0,0 +1,25 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'company_branch_flat_dto.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
_$CompanyBranchFlatDtoImpl _$$CompanyBranchFlatDtoImplFromJson(
Map<String, dynamic> json) =>
_$CompanyBranchFlatDtoImpl(
companyId: (json['company_id'] as num).toInt(),
companyName: json['company_name'] as String,
branchId: (json['branch_id'] as num?)?.toInt(),
branchName: json['branch_name'] as String?,
);
Map<String, dynamic> _$$CompanyBranchFlatDtoImplToJson(
_$CompanyBranchFlatDtoImpl instance) =>
<String, dynamic>{
'company_id': instance.companyId,
'company_name': instance.companyName,
'branch_id': instance.branchId,
'branch_name': instance.branchName,
};