This commit is contained in:
DDD1542
2026-04-09 18:38:08 +09:00
parent ef50c89b05
commit 1b4555f0af
3 changed files with 147 additions and 61 deletions
@@ -807,7 +807,7 @@ export default function SupplierManagementPage() {
};
// 품목 검색
const searchItems = async () => {
const searchItems = useCallback(async () => {
setItemSearchLoading(true);
try {
const filters: any[] = [];
@@ -827,7 +827,14 @@ export default function SupplierManagementPage() {
return divCodes.some((code: string) => PURCHASE_CODES.includes(code));
}));
} catch { /* skip */ } finally { setItemSearchLoading(false); }
};
}, [itemSearchKeyword, priceItems]);
// 실간 검색 (2글자 이상)
useEffect(() => {
if (!itemSelectOpen) return;
if (itemSearchKeyword.length > 0 && itemSearchKeyword.length < 2) return;
searchItems();
}, [itemSearchKeyword, itemSelectOpen]); // eslint-disable-line react-hooks/exhaustive-deps
// 품목 선택 완료 → 상세 입력 모달로 전환
const goToItemDetail = () => {
@@ -1090,7 +1097,7 @@ export default function SupplierManagementPage() {
// 단가 upsert
const priceRows = (itemPrices[itemKey] || []).filter((p) =>
(p.base_price && Number(p.base_price) > 0) || p.start_date
p.base_price || p.start_date || p.currency_code || p.base_price_type
);
const usedPriceIds = new Set<string>();
for (let pi = 0; pi < priceRows.length; pi++) {
@@ -1160,7 +1167,7 @@ export default function SupplierManagementPage() {
}
const priceRows = (itemPrices[itemKey] || []).filter((p) =>
(p.base_price && Number(p.base_price) > 0) || p.start_date
p.base_price || p.start_date || p.currency_code || p.base_price_type
);
for (const price of priceRows) {
await apiClient.post(`/table-management/tables/${PRICE_TABLE}/add`, {
@@ -1192,40 +1199,63 @@ export default function SupplierManagementPage() {
}
};
// 품목 매핑 삭제
// 품목 매핑 해제 (소프트 삭제 — supplier_id를 null 처리)
const handlePriceItemDelete = async () => {
if (priceCheckedIds.length === 0) return;
const ok = await confirm(`선택한 ${priceCheckedIds.length}개 품목 매핑제하시겠습니까?`, {
description: "관련된 단가 정보도 함께 삭제됩니다.",
variant: "destructive", confirmText: "제",
const ok = await confirm(`선택한 ${priceCheckedIds.length}개 품목의 연결제하시겠습니까?`, {
description: "해당 품목의 공급업체 연결이 해제됩니다. (데이터는 유지)",
variant: "destructive", confirmText: "제",
});
if (!ok) return;
try {
for (const mappingId of priceCheckedIds) {
const itemIds = priceCheckedIds.map((mid) => {
const group = Object.values(priceGroups).find((g) => g.master.id === mid);
return group?.master.item_id || group?.master.item_number || "";
}).filter(Boolean);
for (const itemId of itemIds) {
// 해당 품목의 모든 매핑 조회 → supplier_id null 처리
const mapRes = await apiClient.post(`/table-management/tables/${MAPPING_TABLE}/data`, {
page: 1, size: 500,
dataFilter: { enabled: true, filters: [
{ columnName: "supplier_id", operator: "equals", value: selectedSupplier!.supplier_code },
{ columnName: "item_id", operator: "equals", value: itemId },
]}, autoFilter: true,
});
const allMappings = mapRes.data?.data?.data || mapRes.data?.data?.rows || [];
for (const m of allMappings) {
await apiClient.put(`/table-management/tables/${MAPPING_TABLE}/edit`, {
originalData: { id: m.id },
updatedData: { supplier_id: null },
});
}
// 해당 품목의 모든 단가 조회 → supplier_id null 처리
try {
const priceRes = await apiClient.post(`/table-management/tables/${PRICE_TABLE}/data`, {
page: 1, size: 500,
dataFilter: { enabled: true, filters: [{ columnName: "mapping_id", operator: "equals", value: mappingId }] },
autoFilter: true,
dataFilter: { enabled: true, filters: [
{ columnName: "supplier_id", operator: "equals", value: selectedSupplier!.supplier_code },
{ columnName: "item_id", operator: "equals", value: itemId },
]}, autoFilter: true,
});
const prices = priceRes.data?.data?.data || priceRes.data?.data?.rows || [];
if (prices.length > 0) {
await apiClient.delete(`/table-management/tables/${PRICE_TABLE}/delete`, {
data: prices.map((p: any) => ({ id: p.id })),
for (const p of prices) {
await apiClient.put(`/table-management/tables/${PRICE_TABLE}/edit`, {
originalData: { id: p.id },
updatedData: { supplier_id: null },
});
}
} catch { /* skip */ }
}
await apiClient.delete(`/table-management/tables/${MAPPING_TABLE}/delete`, {
data: priceCheckedIds.map((id) => ({ id })),
});
toast.success(`${priceCheckedIds.length}개 품목 매핑이 삭제되었습니다.`);
toast.success(`${priceCheckedIds.length}개 품목의 연결이 해제되었습니다.`);
setPriceCheckedIds([]);
const cid = selectedSupplierId;
setSelectedSupplierId(null);
setTimeout(() => setSelectedSupplierId(cid), 50);
} catch {
toast.error("제에 실패했습니다.");
toast.error("연결 해제에 실패했습니다.");
}
};