// MDM SORP — Dedup review & merge (6.7). const { useState, useEffect, useMemo, useRef, useCallback, createContext, useContext } = React; function DedupScreen({ navigate }) { const { t, lang } = useI18n(); const toast = useToast(); const cands = [ { id: "p_2002", short: "Schaeffler Middle East FZE", full: "Schaeffler Middle East FZE", trn: "100229876500003", country: "AE", city: "Dubai (JAFZA)", phone: "+971 4 805-1888", email: "sales.me@schaeffler.com", created: "2024-08-14", source: "amo", conf: 0.93, deals: 4, refs: 12, docs: 7 }, { id: "p_2003", short: "Schaffler M.E. Trading LLC", full: "Schaffler M.E. Trading LLC", trn: "100229876500003", country: "AE", city: "Dubai", phone: "+971-4-805 1888", email: "trade@schaffler-me.com", created: "2024-12-02", source: "drive", conf: 0.41, deals: 1, refs: 3, docs: 2 }, ]; const [survivor, setSurvivor] = useState("p_2002"); const [picks, setPicks] = useState({ short: "p_2002", full: "p_2002", trn: "p_2002", country: "p_2002", city: "p_2002", phone: "p_2002", email: "both", }); const fields = [ { key: "short", label: lang === "ru" ? "Краткое имя" : "Short name" }, { key: "full", label: lang === "ru" ? "Полное наименование" : "Full legal name" }, { key: "trn", label: "TRN", mono: true, same: true }, { key: "country", label: t("party_country") }, { key: "city", label: t("party_address") }, { key: "phone", label: t("party_phone"), mono: true }, { key: "email", label: t("party_email"), special: ["both"] }, ]; return (

{t("dedup_title")}

4 пары · 2 высокий приоритет
{/* Candidate pair indicator */}
Пара #1 из 4 · Совпадение по TRN · ИИ confidence 94%
{/* Header row */}
{cands.map(c => (
{c.short}
{c.id} · создано {c.created}
Сделок{c.deals}
Связей{c.refs}
Документов{c.docs}
))}
Превью результата
Одна запись {cands.find(c => c.id === survivor)?.short}.
Перенесётся: 5 сделок · 15 связей · 9 документов.
Дубль помечается tombstone (откат 30 дней).
{/* Field-by-field rows */} {fields.map(f => { const v0 = cands[0][f.key] || "—"; const v1 = cands[1][f.key] || "—"; const same = v0 === v1; return (
{f.label} {!same && {t("dedup_conflict")}} {same && }
{cands.map(c => (
setPicks(p => ({ ...p, [f.key]: c.id }))}> {c[f.key] || "—"}
))}
{f.special?.includes("both") && picks[f.key] === "both" ? обе : {cands.find(c => c.id === picks[f.key])?.[f.key] || cands.find(c => c.id === survivor)?.[f.key] || "—"} } {f.key === "email" && ( )}
); })}

Что произойдёт после слияния

Сделки
Все ссылки deal.supplier и deal_item.supplier переадресуются на p_2002.
Документы
Drive-папка /Suppliers/Schaffler остаётся, индекс перемаппится.
Tombstone
p_2003 не удаляется. Запись остаётся в БД с флагом merged_into=p_2002.
Откат
30 дней через журнал · «Восстановить запись». Все связи откатываются обратно.
); } window.DedupScreen = DedupScreen;