번호 자동 부여 대응 및 API 공통 처리 보강
This commit is contained in:
@@ -79,6 +79,10 @@ class _OutboundPageState extends State<OutboundPage> {
|
||||
String? _errorMessage;
|
||||
Set<int> _processingTransactionIds = {};
|
||||
|
||||
String? _routeSelectedNumber;
|
||||
String? _pendingDetailNumber;
|
||||
bool _suppressNextRouteSelection = false;
|
||||
|
||||
late List<String> _statusOptions;
|
||||
final Map<String, LookupItem> _statusLookup = {};
|
||||
LookupItem? _transactionTypeLookup;
|
||||
@@ -256,6 +260,26 @@ class _OutboundPageState extends State<OutboundPage> {
|
||||
controller.transactionType ?? _transactionTypeLookup;
|
||||
_refreshSelection();
|
||||
});
|
||||
final detailNumber = _pendingDetailNumber;
|
||||
if (detailNumber != null) {
|
||||
_pendingDetailNumber = null;
|
||||
OutboundRecord? matched;
|
||||
for (final record in _records) {
|
||||
if (record.transactionNumber == detailNumber) {
|
||||
matched = record;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (matched != null) {
|
||||
final target = matched;
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
if (!mounted) {
|
||||
return;
|
||||
}
|
||||
_showDetailDialog(target);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -580,10 +604,7 @@ class _OutboundPageState extends State<OutboundPage> {
|
||||
),
|
||||
onRowTap: (rowIndex) {
|
||||
final record = visibleRecords[rowIndex];
|
||||
setState(() {
|
||||
_selectedRecord = record;
|
||||
});
|
||||
_showDetailDialog(record);
|
||||
_selectRecord(record, openDetail: true);
|
||||
},
|
||||
),
|
||||
),
|
||||
@@ -748,6 +769,24 @@ class _OutboundPageState extends State<OutboundPage> {
|
||||
return records;
|
||||
}
|
||||
|
||||
void _selectRecord(OutboundRecord? record, {bool openDetail = false}) {
|
||||
if (!mounted) return;
|
||||
setState(() {
|
||||
_selectedRecord = record;
|
||||
});
|
||||
final selectedNumber = record?.transactionNumber;
|
||||
_routeSelectedNumber = selectedNumber;
|
||||
_updateRoute(selected: selectedNumber);
|
||||
if (openDetail && record != null) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
if (!mounted) {
|
||||
return;
|
||||
}
|
||||
_showDetailDialog(record);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
List<String> _buildRecordRow(OutboundRecord record) {
|
||||
final primaryItem = record.items.isNotEmpty ? record.items.first : null;
|
||||
return [
|
||||
@@ -848,18 +887,14 @@ class _OutboundPageState extends State<OutboundPage> {
|
||||
Future<void> _handleCreate() async {
|
||||
final record = await _showOutboundFormDialog();
|
||||
if (record != null) {
|
||||
setState(() {
|
||||
_selectedRecord = record;
|
||||
});
|
||||
_selectRecord(record, openDetail: true);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _handleEdit(OutboundRecord record) async {
|
||||
final updated = await _showOutboundFormDialog(initial: record);
|
||||
if (updated != null) {
|
||||
setState(() {
|
||||
_selectedRecord = updated;
|
||||
});
|
||||
_selectRecord(updated, openDetail: true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1163,6 +1198,10 @@ class _OutboundPageState extends State<OutboundPage> {
|
||||
(params['order'] ?? '').toLowerCase() == 'asc';
|
||||
final pageSizeParam = int.tryParse(params['page_size'] ?? '');
|
||||
final pageParam = int.tryParse(params['page'] ?? '');
|
||||
final selectedParam = params['selected']?.trim();
|
||||
final selectedNumber = selectedParam == null || selectedParam.isEmpty
|
||||
? null
|
||||
: selectedParam;
|
||||
|
||||
final warehouseId = warehouseIdParam;
|
||||
final warehouseLabel = warehouseParam != null && warehouseParam.isNotEmpty
|
||||
@@ -1232,6 +1271,13 @@ class _OutboundPageState extends State<OutboundPage> {
|
||||
_sortAscending = resolvedSortAscending;
|
||||
_pageSize = pageSize;
|
||||
_currentPage = page;
|
||||
_routeSelectedNumber = selectedNumber;
|
||||
if (_suppressNextRouteSelection) {
|
||||
_pendingDetailNumber = null;
|
||||
} else {
|
||||
_pendingDetailNumber = selectedNumber;
|
||||
}
|
||||
_suppressNextRouteSelection = false;
|
||||
_refreshSelection();
|
||||
}
|
||||
|
||||
@@ -1265,6 +1311,16 @@ class _OutboundPageState extends State<OutboundPage> {
|
||||
return;
|
||||
}
|
||||
|
||||
final selectedNumber = _routeSelectedNumber;
|
||||
if (selectedNumber != null) {
|
||||
for (final record in filtered) {
|
||||
if (record.transactionNumber == selectedNumber) {
|
||||
_selectedRecord = record;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final current = _selectedRecord;
|
||||
if (current != null) {
|
||||
OutboundRecord? matched;
|
||||
@@ -1286,7 +1342,7 @@ class _OutboundPageState extends State<OutboundPage> {
|
||||
_selectedRecord = filtered.first;
|
||||
}
|
||||
|
||||
void _updateRoute({int? page, int? pageSize}) {
|
||||
void _updateRoute({int? page, int? pageSize, String? selected}) {
|
||||
if (!mounted) return;
|
||||
final targetPage = page ?? _currentPage;
|
||||
final targetPageSize = pageSize ?? _pageSize;
|
||||
@@ -1336,6 +1392,10 @@ class _OutboundPageState extends State<OutboundPage> {
|
||||
if (targetPageSize != OutboundTableSpec.pageSizeOptions.first) {
|
||||
params['page_size'] = targetPageSize.toString();
|
||||
}
|
||||
final selectedNumber = selected ?? _selectedRecord?.transactionNumber;
|
||||
if (selectedNumber != null && selectedNumber.isNotEmpty) {
|
||||
params['selected'] = selectedNumber;
|
||||
}
|
||||
|
||||
final uri = Uri(
|
||||
path: widget.routeUri.path,
|
||||
@@ -1349,6 +1409,7 @@ class _OutboundPageState extends State<OutboundPage> {
|
||||
if (router == null) {
|
||||
return;
|
||||
}
|
||||
_suppressNextRouteSelection = true;
|
||||
router.go(newLocation);
|
||||
}
|
||||
|
||||
@@ -1510,12 +1571,8 @@ class _OutboundPageState extends State<OutboundPage> {
|
||||
final transactionTypeController = TextEditingController(
|
||||
text: transactionTypeValue,
|
||||
);
|
||||
final transactionNumberController = TextEditingController(
|
||||
text: initial?.transactionNumber ?? '',
|
||||
);
|
||||
final approvalNumberController = TextEditingController(
|
||||
text: initial?.raw?.approval?.approvalNo ?? '',
|
||||
);
|
||||
final assignedTransactionNo = initial?.transactionNumber;
|
||||
final assignedApprovalNo = initial?.raw?.approval?.approvalNo;
|
||||
final approvalNoteController = TextEditingController();
|
||||
|
||||
final drafts =
|
||||
@@ -1530,8 +1587,6 @@ class _OutboundPageState extends State<OutboundPage> {
|
||||
};
|
||||
|
||||
String? writerError;
|
||||
String? transactionNumberError;
|
||||
String? approvalNumberError;
|
||||
String? customerError;
|
||||
String? warehouseError;
|
||||
String? statusError;
|
||||
@@ -1561,10 +1616,6 @@ class _OutboundPageState extends State<OutboundPage> {
|
||||
writerController: writerController,
|
||||
writerSelection: writerSelection,
|
||||
requireWriterSelection: initial == null,
|
||||
transactionNumberController: transactionNumberController,
|
||||
transactionNumberRequired: initial == null,
|
||||
approvalNumberController: approvalNumberController,
|
||||
approvalNumberRequired: initial == null,
|
||||
warehouseSelection: warehouseSelection,
|
||||
statusValue: statusValue.value,
|
||||
selectedCustomers: customerSelection
|
||||
@@ -1575,8 +1626,6 @@ class _OutboundPageState extends State<OutboundPage> {
|
||||
);
|
||||
|
||||
writerError = validation.writerError;
|
||||
transactionNumberError = validation.transactionNumberError;
|
||||
approvalNumberError = validation.approvalNumberError;
|
||||
customerError = validation.customerError;
|
||||
warehouseError = validation.warehouseError;
|
||||
statusError = validation.statusError;
|
||||
@@ -1621,8 +1670,6 @@ class _OutboundPageState extends State<OutboundPage> {
|
||||
|
||||
final remarkText = remarkController.text.trim();
|
||||
final remarkValue = remarkText.isEmpty ? null : remarkText;
|
||||
final transactionNoValue = transactionNumberController.text.trim();
|
||||
final approvalNoValue = approvalNumberController.text.trim();
|
||||
final approvalNoteValue = approvalNoteController.text.trim();
|
||||
final transactionId = initial?.id;
|
||||
|
||||
@@ -1715,7 +1762,10 @@ class _OutboundPageState extends State<OutboundPage> {
|
||||
if (!mounted) {
|
||||
return;
|
||||
}
|
||||
SuperportToast.success(context, '출고 정보가 수정되었습니다.');
|
||||
SuperportToast.success(
|
||||
context,
|
||||
'출고 정보가 수정되었습니다. (${updated.transactionNumber})',
|
||||
);
|
||||
navigator.pop();
|
||||
return;
|
||||
}
|
||||
@@ -1749,7 +1799,6 @@ class _OutboundPageState extends State<OutboundPage> {
|
||||
|
||||
final created = await controller.createTransaction(
|
||||
StockTransactionCreateInput(
|
||||
transactionNo: transactionNoValue,
|
||||
transactionTypeId: transactionTypeLookup.id,
|
||||
transactionStatusId: statusItem.id,
|
||||
warehouseId: warehouseId,
|
||||
@@ -1759,7 +1808,6 @@ class _OutboundPageState extends State<OutboundPage> {
|
||||
lines: createLines,
|
||||
customers: createCustomers,
|
||||
approval: StockTransactionApprovalInput(
|
||||
approvalNo: approvalNoValue,
|
||||
requestedById: createdById,
|
||||
note: approvalNoteValue.isEmpty ? null : approvalNoteValue,
|
||||
),
|
||||
@@ -1770,7 +1818,10 @@ class _OutboundPageState extends State<OutboundPage> {
|
||||
if (!mounted) {
|
||||
return;
|
||||
}
|
||||
SuperportToast.success(context, '출고가 등록되었습니다.');
|
||||
SuperportToast.success(
|
||||
context,
|
||||
'출고가 등록되었습니다. (${created.transactionNumber})',
|
||||
);
|
||||
navigator.pop();
|
||||
} catch (error) {
|
||||
updateSaving(false);
|
||||
@@ -1911,20 +1962,11 @@ class _OutboundPageState extends State<OutboundPage> {
|
||||
width: 240,
|
||||
child: SuperportFormField(
|
||||
label: '트랜잭션번호',
|
||||
required: true,
|
||||
errorText: transactionNumberError,
|
||||
child: ShadInput(
|
||||
controller: transactionNumberController,
|
||||
readOnly: initial != null,
|
||||
enabled: initial == null,
|
||||
placeholder: const Text('예: OUT-2024-0001'),
|
||||
onChanged: (_) {
|
||||
if (transactionNumberError != null) {
|
||||
setState(() {
|
||||
transactionNumberError = null;
|
||||
});
|
||||
}
|
||||
},
|
||||
child: Text(
|
||||
assignedTransactionNo ?? '저장 시 자동 생성',
|
||||
style: assignedTransactionNo == null
|
||||
? theme.textTheme.muted
|
||||
: theme.textTheme.p,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -1932,20 +1974,11 @@ class _OutboundPageState extends State<OutboundPage> {
|
||||
width: 240,
|
||||
child: SuperportFormField(
|
||||
label: '결재번호',
|
||||
required: true,
|
||||
errorText: approvalNumberError,
|
||||
child: ShadInput(
|
||||
controller: approvalNumberController,
|
||||
readOnly: initial != null,
|
||||
enabled: initial == null,
|
||||
placeholder: const Text('예: APP-2024-0001'),
|
||||
onChanged: (_) {
|
||||
if (approvalNumberError != null) {
|
||||
setState(() {
|
||||
approvalNumberError = null;
|
||||
});
|
||||
}
|
||||
},
|
||||
child: Text(
|
||||
assignedApprovalNo ?? '저장 시 자동 생성',
|
||||
style: assignedApprovalNo == null
|
||||
? theme.textTheme.muted
|
||||
: theme.textTheme.p,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -2163,8 +2196,6 @@ class _OutboundPageState extends State<OutboundPage> {
|
||||
writerController.dispose();
|
||||
remarkController.dispose();
|
||||
transactionTypeController.dispose();
|
||||
transactionNumberController.dispose();
|
||||
approvalNumberController.dispose();
|
||||
approvalNoteController.dispose();
|
||||
processedAt.dispose();
|
||||
|
||||
@@ -2418,10 +2449,6 @@ _OutboundFormValidation _validateOutboundForm({
|
||||
required TextEditingController writerController,
|
||||
required InventoryEmployeeSuggestion? writerSelection,
|
||||
required bool requireWriterSelection,
|
||||
required TextEditingController transactionNumberController,
|
||||
required bool transactionNumberRequired,
|
||||
required TextEditingController approvalNumberController,
|
||||
required bool approvalNumberRequired,
|
||||
required InventoryWarehouseOption? warehouseSelection,
|
||||
required String statusValue,
|
||||
required List<InventoryCustomerOption> selectedCustomers,
|
||||
@@ -2430,8 +2457,6 @@ _OutboundFormValidation _validateOutboundForm({
|
||||
}) {
|
||||
var isValid = true;
|
||||
String? writerError;
|
||||
String? transactionNumberError;
|
||||
String? approvalNumberError;
|
||||
String? customerError;
|
||||
String? warehouseError;
|
||||
String? statusError;
|
||||
@@ -2448,18 +2473,6 @@ _OutboundFormValidation _validateOutboundForm({
|
||||
isValid = false;
|
||||
}
|
||||
|
||||
final transactionNumber = transactionNumberController.text.trim();
|
||||
if (transactionNumberRequired && transactionNumber.isEmpty) {
|
||||
transactionNumberError = '거래번호를 입력하세요.';
|
||||
isValid = false;
|
||||
}
|
||||
|
||||
final approvalNumber = approvalNumberController.text.trim();
|
||||
if (approvalNumberRequired && approvalNumber.isEmpty) {
|
||||
approvalNumberError = '결재번호를 입력하세요.';
|
||||
isValid = false;
|
||||
}
|
||||
|
||||
if (warehouseSelection == null) {
|
||||
warehouseError = '창고를 선택하세요.';
|
||||
isValid = false;
|
||||
@@ -2523,8 +2536,6 @@ _OutboundFormValidation _validateOutboundForm({
|
||||
return _OutboundFormValidation(
|
||||
isValid: isValid,
|
||||
writerError: writerError,
|
||||
transactionNumberError: transactionNumberError,
|
||||
approvalNumberError: approvalNumberError,
|
||||
customerError: customerError,
|
||||
warehouseError: warehouseError,
|
||||
statusError: statusError,
|
||||
@@ -2536,8 +2547,6 @@ class _OutboundFormValidation {
|
||||
const _OutboundFormValidation({
|
||||
required this.isValid,
|
||||
this.writerError,
|
||||
this.transactionNumberError,
|
||||
this.approvalNumberError,
|
||||
this.customerError,
|
||||
this.warehouseError,
|
||||
this.statusError,
|
||||
@@ -2546,8 +2555,6 @@ class _OutboundFormValidation {
|
||||
|
||||
final bool isValid;
|
||||
final String? writerError;
|
||||
final String? transactionNumberError;
|
||||
final String? approvalNumberError;
|
||||
final String? customerError;
|
||||
final String? warehouseError;
|
||||
final String? statusError;
|
||||
|
||||
Reference in New Issue
Block a user