Обсудить задачу

Почему в 1С растут дубли контрагентов и как это лечится

Дубли контрагентов в 1С почти никогда не появляются из-за «глюка обмена». У них есть конкретная причина, и она обычно одна и та же.

Почему вообще появляются дубли

Обмен ищет, есть ли уже такой контрагент. Вопрос в том, по какому признаку он ищет. Если по названию, то любое расхождение в строке создаёт новую запись: лишний пробел, кавычки другого вида, «ООО» в начале вместо конца, сокращение вместо полного наименования.

Дальше это множится само: менеджер видит два одинаковых контрагента, выбирает наугад, документы расходятся по разным карточкам, отчёты перестают сходиться.

Проверка занимает минуту: отсортируйте контрагентов по названию и посмотрите соседние строки. Если видите пары, отличающиеся пробелом или регистром, — сопоставление идёт по тексту.

Как понять, по какому полю идёт сопоставление

Смотреть надо не в описание обмена, а в данные. У записей, созданных обменом, проверьте, заполнен ли идентификатор из внешней системы — GUID, XML_ID или служебное поле. Если у половины записей он пустой, обмен их не по нему искал.

  • Заполнен у всех записей — сопоставление по идентификатору, причина дублей в другом
  • Заполнен частично — часть записей заведена руками или другим обменом
  • Пустой почти везде — сопоставление идёт по названию, это и есть источник дублей
PHPПоиск компании по GUID из 1С
// Сопоставление по идентификатору вместо названия.
// Ключ — GUID из 1С: он не меняется при переименовании контрагента,
// а название меняется регулярно. Отсюда и берутся дубли.
function findCompany(string $guid): ?int
{
    $res = CCrmCompany::GetListEx(
        [],
        ['=UF_GUID_1C' => $guid, 'CHECK_PERMISSIONS' => 'N'],
        false,
        ['nTopCount' => 1],
        ['ID'],
    );

    $row = $res->Fetch();

    return $row ? (int) $row['ID'] : null;
}

Что делать, если сопоставление по названию

Переводить на идентификатор. GUID в 1С не меняется при переименовании контрагента, а название меняется регулярно — этим они и отличаются.

  • Проставить идентификатор существующим записям — по совпадению названий, вручную разобрав спорные
  • Перевести обмен на поиск по идентификатору
  • Свести уже накопленные дубли, объединив документы
  • Добавить в обмен проверку: если запись найдена по названию, но идентификатор не совпал — не создавать новую, а писать в лог

Последний пункт важнее, чем кажется: он превращает молчаливое размножение записей в заметную ошибку, которую видно сразу, а не через полгода.

PHPИдемпотентность: повторный запуск не переписывает всё подряд
// Обновляем только то, что реально изменилось.
// Хэш всего набора полей дешевле, чем сравнение поля за полем,
// и переживает добавление новых полей без правки кода.
$hash = md5(json_encode($fields, JSON_UNESCAPED_UNICODE));

if ($existing !== null && $existing['UF_HASH_1C'] === $hash) {
    return $existing['ID'];   // ничего не поменялось — не трогаем запись
}

$fields['UF_HASH_1C'] = $hash;

Чем это оборачивается на объёме

В одном из разборов мы вычистили 20 174 мусорные компании, оставшиеся от старого типового обмена. После перехода на сопоставление по GUID дубли по названию сократились до четырёх пар — их разобрали руками.

Признак сопоставленияЧто происходит при переименованииРиск дублей
НазваниеСоздаётся новая записьВысокий
ИННЗапись находится, но филиалы и ИП с одним ИНН слипаютсяСредний
GUID из 1СЗапись находится, данные обновляютсяНизкий

Если дубли уже накопились

Разовая чистка без исправления причины даёт отсрочку на месяц-другой. Разбираем причину, чиним сопоставление и только потом сводим накопленное.

Посмотреть услугу: обмены с 1С Обсудить задачу