refactor: 重構 VendorProduct API 與新增進貨單重複檢查前端邏輯
All checks were successful
ERP-Deploy-Production / deploy-production (push) Successful in 1m9s
ERP-Deploy-Demo / deploy-demo (push) Successful in 1m10s

1. 將 VendorProductController 中的 Eloquent 關聯操作改為透過 ProcurementService 使用 DB 操作,解除跨模組 Model 直接依賴。
2. ProcurementService 加入 vendor product 的資料存取方法。
3. 進貨單建立前端 (GoodsReceipt/Create.tsx) 新增重複進貨檢查與警告對話框邏輯。
This commit is contained in:
2026-02-25 11:11:28 +08:00
parent e406ecd63d
commit ad91b08dbc
11 changed files with 689 additions and 23 deletions

View File

@@ -35,6 +35,7 @@ import {
import axios from 'axios';
import { PurchaseOrderStatus } from '@/types/purchase-order';
import { STATUS_CONFIG } from '@/constants/purchase-order';
import { DuplicateWarningDialog } from './components/DuplicateWarningDialog';
@@ -89,6 +90,11 @@ export default function GoodsReceiptCreate({ warehouses, pendingPurchaseOrders,
const [productSearch, setProductSearch] = useState('');
const [foundProducts, setFoundProducts] = useState<any[]>([]);
// Duplicate Check States
const [warningOpen, setWarningOpen] = useState(false);
const [warnings, setWarnings] = useState<any[]>([]);
const [isCheckingDuplicate, setIsCheckingDuplicate] = useState(false);
const { data, setData, post, processing, errors } = useForm({
type: 'standard', // 'standard', 'miscellaneous', 'other'
warehouse_id: '',
@@ -280,9 +286,30 @@ export default function GoodsReceiptCreate({ warehouses, pendingPurchaseOrders,
});
}, [nextSequences, JSON.stringify(data.items.map(i => ({ m: i.batchMode, c: i.originCountry, s: i.product_code, p: i.product_id }))), data.received_date]);
const submit = (e: React.FormEvent) => {
e.preventDefault();
post(route('goods-receipts.store'));
const submit = async (e: React.FormEvent, force: boolean = false) => {
if (e) e.preventDefault();
// 如果不是強制提交,先檢查重複
if (!force) {
setIsCheckingDuplicate(true);
try {
const response = await axios.post(route('goods-receipts.check-duplicate'), data);
if (response.data.has_warnings) {
setWarnings(response.data.warnings);
setWarningOpen(true);
return; // 停止並顯示警告
}
} catch (error) {
console.error("Duplicate check failed", error);
// 檢查失敗則繼續,或視為阻擋?這裡選擇繼續
} finally {
setIsCheckingDuplicate(false);
}
}
post(route('goods-receipts.store'), {
onSuccess: () => setWarningOpen(false),
});
};
@@ -738,13 +765,21 @@ export default function GoodsReceiptCreate({ warehouses, pendingPurchaseOrders,
size="lg"
className="button-filled-primary px-12 h-14 rounded-xl shadow-lg text-lg font-bold transition-all hover:scale-[1.02] active:scale-[0.98]"
onClick={submit}
disabled={processing || (data.type === 'standard' ? !selectedPO : !selectedVendor)}
disabled={processing || isCheckingDuplicate || (data.type === 'standard' ? !selectedPO : !selectedVendor)}
>
<Save className="mr-2 h-5 w-5" />
{processing ? '處理中...' : '確認進貨'}
{processing || isCheckingDuplicate ? '處理中...' : '確認進貨'}
</Button>
</div>
</div>
<DuplicateWarningDialog
open={warningOpen}
onClose={() => setWarningOpen(false)}
onConfirm={() => submit(null as any, true)}
warnings={warnings}
processing={processing}
/>
</AuthenticatedLayout >
);
}