Исключение дублирования контрагентов

Часто бывает, что необходимо обеспечить уникальность контрагентов в базе данных. В системе по умолчанию не организовано ограничение при вводе юридических и физических лиц. Реальная компания имеет свои правила при вводе контрагента.

Рассмотрим популярную ситуацию, когда правило уникальности для контрагента формулируется так: в базе данных не может быть контрагентов, у которых одинаковые ИНН и город в юридическом адресе.

Реализовать это можно через перехват событий на обновление в базе данных.

Внимание!
Некорректное применение приведенного в данной статье сценария может привести к блокировке всех транзакций в БД. Убедитесь, что ваш код работает только для требуемых условий, во всех остальных случаях должна выполняться строка return false; // возврат в норме.

Алгоритм следующий. Перед тем как изменения в объекте будут записаны в базу данных (метод OnPreUpdate), определим тип объекта (IContractor). Если у контрагента указан город в юридическом адресе, ищем с таким же ИНН и городом среди введённых. Если находим, выводим сообщение о не уникальности контрагента. Если город не указан, ищем с таким же ИНН.

Для этого создадим специальный объект в Дизайнере и назовём его "Перехватчики". На вкладке Сценарии карточки этого объекта подключим необходимые пространства в начале сценария:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using EleWise.ELMA.Common.Models;
using EleWise.ELMA.ComponentModel;
using EleWise.ELMA.ConfigurationModel;
using EleWise.ELMA.CRM.Models;
using EleWise.ELMA.Documents.Models;
using EleWise.ELMA.Logging;
using EleWise.ELMA.Model.Common;
using EleWise.ELMA.Model.Entities;
using EleWise.ELMA.Model.Managers;
using EleWise.ELMA.Model.Types.Settings;
using EleWise.ELMA.Runtime.Managers;
using EleWise.ELMA.Runtime.NH.Listeners; 
using EleWise.ELMA.Runtime.Settings;
using EleWise.ELMA.Services;
using NHibernate.Event;

Затем добавим следующий код:

Внимание!
Некорректное применение приведенного в данной статье сценария может привести к блокировке всех транзакций в БД. Убедитесь, что ваш код работает только для требуемых условий, во всех остальных случаях должна выполняться строка return false; // возврат в норме.
[Component] 
public class ReSaveContractor : EntityEventsListener 
{ 
	public override bool OnPreUpdate(PreUpdateEvent @event) 
	{  
		// Определяем тип объекта 
		//---------------------------------------------------------- 
		if(@event.Entity is IContractor) // интерфейс объекта типа Контрагент 
		{ 
			var Kontragent = (IContractor)@event.Entity; 
		  
			if (Kontragent.LegalAddress != null && !string.IsNullOrWhiteSpace(Kontragent.LegalAddress.City)) // Если ввели город в юридическом адресе 
			{ 
				// Ищем по фильтру контрагента указываем ИНН и город и исключаем текущего контрагента 
				var filterString = string.Format(@"(INN is NULL OR INN = ’{0}’) and LegalAddress in (City LIKE ’%{1}%’) and Id <> {2}",Kontragent.INN, Kontragent.LegalAddress.City.Trim(), Kontragent.Id); 
				var findKA = EntityManager<IContractor>.Instance.Find(filterString);      
				if (findKA.Count == 0) 
				{ 
					Logger.Log.Error("==Выход нет дублей "); 
				} 
				else
				{
					throw new Exception("Контрагент уже существует. "+string.Format(@"{0}/CRM/ContractorLegal/Details/{1}", 
					Locator.GetServiceNotNull<CommonSettingsModule>().Settings.ApplicationBaseUrl, 
					findKA.ElementAt(0).Id)+ 
					" Укажите другие ИНН и город."); 
				} 
			} 
			else
			{ 
				// Ищем по фильтру контрагента указываем ИНН и город и исключаем текущего контрагента 
				var filterString = string.Format(@"(INN is NULL OR INN = ’{0}’) and LegalAddress in (City is NULL OR City = ’’) and Id <> {1}",Kontragent.INN, Kontragent.Id); 
				var findKA = EntityManager<IContractor>.Instance.Find(filterString);      
				if (findKA.Count == 0) 
				{ 
					Logger.Log.Error("==Выход нет дублей "); 
				} 
				else
				{
					throw new Exception("Контрагент уже ."+string.Format(@"{0}/CRM/ContractorLegal/Details/{1}", 
					Locator.GetServiceNotNull<CommonSettingsModule>().Settings.ApplicationBaseUrl, 
					findKA.ElementAt(0).Id)+ 
					" Укажите другие ИНН и город."); 
				}      
			}     
		} 
		return false; // возврат в норме 
	} 
}

Здесь можно ещё добавить, что метод OnPreUpdate(PreUpdateEvent @event) вызывается и при создании нового объекта и при изменении существующего. Таким образом любые изменения названия и/или города юридического адреса контрагентов будут отслеживаться системой.

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

Внимание!
Некорректное применение приведенного в данной статье сценария может привести к блокировке всех транзакций в БД. Убедитесь, что ваш код работает только для требуемых условий, во всех остальных случаях должна выполняться строка return false; // возврат в норме.