feat: 라이선스 관리 기능 개선 및 폼 검증 강화
- LicenseDto 모델 업데이트 - 라이선스 폼 UI 개선 및 검증 로직 강화 - 라이선스 리스트 화면 필터링 기능 추가 - 만료일 관리 기능 개선 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -23,6 +23,16 @@ class LicenseFormController extends ChangeNotifier {
|
||||
int _companyId = 1;
|
||||
int _durationMonths = 12; // 기본값: 12개월
|
||||
String _visitCycle = '미방문'; // 기본값: 미방문
|
||||
|
||||
// 추가 필드 컨트롤러
|
||||
final TextEditingController productNameController = TextEditingController();
|
||||
final TextEditingController licenseKeyController = TextEditingController();
|
||||
final TextEditingController vendorController = TextEditingController();
|
||||
final TextEditingController locationController = TextEditingController();
|
||||
final TextEditingController assignedUserController = TextEditingController();
|
||||
String status = '활성';
|
||||
DateTime? purchaseDate;
|
||||
DateTime? expiryDate;
|
||||
|
||||
// isEditMode setter
|
||||
set isEditMode(bool value) {
|
||||
@@ -52,15 +62,19 @@ class LicenseFormController extends ChangeNotifier {
|
||||
this.useApi = false,
|
||||
MockDataService? dataService,
|
||||
int? licenseId,
|
||||
bool isExtension = false,
|
||||
}) : mockDataService = dataService ?? MockDataService() {
|
||||
if (useApi && GetIt.instance.isRegistered<LicenseService>()) {
|
||||
_licenseService = GetIt.instance<LicenseService>();
|
||||
}
|
||||
|
||||
if (licenseId != null) {
|
||||
if (licenseId != null && !isExtension) {
|
||||
_licenseId = licenseId;
|
||||
_isEditMode = true;
|
||||
loadLicense();
|
||||
// loadLicense()는 별도로 호출됨
|
||||
} else if (licenseId != null && isExtension) {
|
||||
_licenseId = licenseId;
|
||||
_isEditMode = false; // 연장 모드는 새로운 라이선스 생성
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,29 +115,122 @@ class LicenseFormController extends ChangeNotifier {
|
||||
Future<void> loadLicense() async {
|
||||
if (_licenseId == null) return;
|
||||
|
||||
debugPrint('📝 loadLicense 시작 - ID: $_licenseId');
|
||||
|
||||
_isLoading = true;
|
||||
_error = null;
|
||||
notifyListeners();
|
||||
|
||||
try {
|
||||
if (useApi && GetIt.instance.isRegistered<LicenseService>()) {
|
||||
debugPrint('📝 API에서 라이센스 로드 중...');
|
||||
_originalLicense = await _licenseService.getLicenseById(_licenseId!);
|
||||
} else {
|
||||
debugPrint('📝 Mock에서 라이센스 로드 중...');
|
||||
_originalLicense = mockDataService?.getLicenseById(_licenseId!);
|
||||
}
|
||||
|
||||
debugPrint('📝 로드된 라이센스: $_originalLicense');
|
||||
|
||||
if (_originalLicense != null) {
|
||||
// 폼 필드에 데이터 설정
|
||||
productNameController.text = _originalLicense!.productName ?? '';
|
||||
licenseKeyController.text = _originalLicense!.licenseKey;
|
||||
vendorController.text = _originalLicense!.vendor ?? '';
|
||||
locationController.text = _originalLicense!.companyName ?? '';
|
||||
assignedUserController.text = _originalLicense!.assignedUserName ?? '';
|
||||
|
||||
debugPrint('📝 폼 필드 설정 완료:');
|
||||
debugPrint(' - 제품명: ${productNameController.text}');
|
||||
debugPrint(' - 라이선스 키: ${licenseKeyController.text}');
|
||||
debugPrint(' - 벤더: ${vendorController.text}');
|
||||
debugPrint(' - 현위치: ${locationController.text}');
|
||||
debugPrint(' - 할당 사용자: ${assignedUserController.text}');
|
||||
status = _originalLicense!.isActive ? '활성' : '비활성';
|
||||
purchaseDate = _originalLicense!.purchaseDate;
|
||||
expiryDate = _originalLicense!.expiryDate;
|
||||
|
||||
_name = _originalLicense!.productName ?? '';
|
||||
_companyId = _originalLicense!.companyId ?? 1;
|
||||
// durationMonths와 visitCycle은 License 모델에 없으므로 기본값 유지
|
||||
// _durationMonths = _originalLicense!.durationMonths;
|
||||
// _visitCycle = _originalLicense!.visitCycle;
|
||||
|
||||
// remark에서 방문주기 정보 추출 (있는 경우)
|
||||
if (_originalLicense!.remark != null && _originalLicense!.remark!.contains('방문주기:')) {
|
||||
final remarkParts = _originalLicense!.remark!.split('방문주기:');
|
||||
if (remarkParts.length > 1) {
|
||||
_visitCycle = remarkParts[1].trim();
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
_error = e.toString();
|
||||
debugPrint('❌ 라이센스 로드 실패: $e');
|
||||
} finally {
|
||||
_isLoading = false;
|
||||
notifyListeners();
|
||||
debugPrint('📝 loadLicense 완료 - isLoading: false');
|
||||
}
|
||||
}
|
||||
|
||||
// 라이센스 정보 로드 (연장 모드 - 기존 데이터로 새 라이선스 생성)
|
||||
Future<void> loadLicenseForExtension() async {
|
||||
if (_licenseId == null) return;
|
||||
|
||||
debugPrint('📝 loadLicenseForExtension 시작 - ID: $_licenseId');
|
||||
|
||||
_isLoading = true;
|
||||
_error = null;
|
||||
notifyListeners();
|
||||
|
||||
try {
|
||||
License? sourceLicense;
|
||||
if (useApi && GetIt.instance.isRegistered<LicenseService>()) {
|
||||
debugPrint('📝 API에서 라이센스 로드 중 (연장용)...');
|
||||
sourceLicense = await _licenseService.getLicenseById(_licenseId!);
|
||||
} else {
|
||||
debugPrint('📝 Mock에서 라이센스 로드 중 (연장용)...');
|
||||
sourceLicense = mockDataService?.getLicenseById(_licenseId!);
|
||||
}
|
||||
|
||||
debugPrint('📝 로드된 소스 라이센스: $sourceLicense');
|
||||
|
||||
if (sourceLicense != null) {
|
||||
// 연장용으로 기존 데이터 복사 (ID는 null로 새 라이선스 생성)
|
||||
productNameController.text = sourceLicense.productName ?? '';
|
||||
licenseKeyController.text = '${sourceLicense.licenseKey}-EXT-${DateTime.now().millisecondsSinceEpoch}';
|
||||
vendorController.text = sourceLicense.vendor ?? '';
|
||||
locationController.text = sourceLicense.companyName ?? '';
|
||||
assignedUserController.text = sourceLicense.assignedUserName ?? '';
|
||||
|
||||
debugPrint('📝 연장용 폼 필드 설정 완료:');
|
||||
debugPrint(' - 제품명: ${productNameController.text}');
|
||||
debugPrint(' - 라이선스 키: ${licenseKeyController.text}');
|
||||
debugPrint(' - 벤더: ${vendorController.text}');
|
||||
debugPrint(' - 현위치: ${locationController.text}');
|
||||
debugPrint(' - 할당 사용자: ${assignedUserController.text}');
|
||||
status = '활성'; // 연장은 항상 활성으로 시작
|
||||
purchaseDate = DateTime.now(); // 구매일은 오늘
|
||||
// 만료일은 기존 만료일에서 연장 (기본 12개월)
|
||||
expiryDate = sourceLicense.expiryDate?.add(Duration(days: _durationMonths * 30))
|
||||
?? DateTime.now().add(Duration(days: _durationMonths * 30));
|
||||
|
||||
_name = sourceLicense.productName ?? '';
|
||||
_companyId = sourceLicense.companyId ?? 1;
|
||||
|
||||
// remark에서 방문주기 정보 추출 (있는 경우)
|
||||
if (sourceLicense.remark != null && sourceLicense.remark!.contains('방문주기:')) {
|
||||
final remarkParts = sourceLicense.remark!.split('방문주기:');
|
||||
if (remarkParts.length > 1) {
|
||||
_visitCycle = remarkParts[1].trim();
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
_error = e.toString();
|
||||
debugPrint('❌ 라이센스 연장 로드 실패: $e');
|
||||
} finally {
|
||||
_isLoading = false;
|
||||
notifyListeners();
|
||||
debugPrint('📝 loadLicenseForExtension 완료 - isLoading: false');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,14 +247,20 @@ class LicenseFormController extends ChangeNotifier {
|
||||
try {
|
||||
final license = License(
|
||||
id: _isEditMode ? _licenseId : null,
|
||||
licenseKey: 'LIC-${DateTime.now().millisecondsSinceEpoch}',
|
||||
productName: _name,
|
||||
licenseKey: licenseKeyController.text.isNotEmpty
|
||||
? licenseKeyController.text
|
||||
: 'LIC-${DateTime.now().millisecondsSinceEpoch}',
|
||||
productName: productNameController.text,
|
||||
vendor: vendorController.text,
|
||||
companyName: locationController.text,
|
||||
assignedUserName: assignedUserController.text.isNotEmpty
|
||||
? assignedUserController.text
|
||||
: null,
|
||||
companyId: _companyId,
|
||||
// durationMonths와 visitCycle은 License 모델에 없음
|
||||
// 대신 expiryDate를 설정
|
||||
purchaseDate: DateTime.now(),
|
||||
expiryDate: DateTime.now().add(Duration(days: _durationMonths * 30)),
|
||||
remark: '방문주기: $_visitCycle',
|
||||
isActive: status == '활성',
|
||||
purchaseDate: purchaseDate ?? DateTime.now(),
|
||||
expiryDate: expiryDate ?? DateTime.now().add(Duration(days: _durationMonths * 30)),
|
||||
remark: '${_durationMonths}개월,${_visitCycle},방문',
|
||||
);
|
||||
|
||||
if (useApi && GetIt.instance.isRegistered<LicenseService>()) {
|
||||
@@ -210,6 +323,12 @@ class LicenseFormController extends ChangeNotifier {
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
// TextEditingController들 정리
|
||||
productNameController.dispose();
|
||||
licenseKeyController.dispose();
|
||||
vendorController.dispose();
|
||||
locationController.dispose();
|
||||
assignedUserController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user