logo

Preventing contractor duplication

It is often necessary to ensure that each contractor in the database is unique. By default, the system has no restrictions when creating contractors. In reality, companies have their own rules for creating contractors.

Here is an example: the database cannot contain several contractors with the same taxpayer number and city.

Attention!
Using the script in this article incorrectly may result in locking all the transactions in the database. Make sure that your code is executed correctly for the required conditions; in all other cases, the line return false; // return to normal must be executed.

This can be implemented by intercepting database changing events.

Before the changes in the object will be written to the database (OnPreUpdate method), define the object type (IContractor). If a city is specified for the contractor, search the same taxpayer number and city among the existing contractors. If matches are found, show a notification that the contractor is not unique. If the city is not specified, search the same taxpayer number.

For this, create a special object in the Designer and name it Interceptor. On the scripts tab of this object, add a script:

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;

Add the following code:

Attention!
Using the script in this article incorrectly may result in locking all the transactions in the database. Make sure that your code is executed correctly for the required conditions; in all other cases, the line return false; // return to normal must be executed.
[Component]
public class ReSaveContractor : EntityEventsListener
{
    public override bool OnPreUpdate(PreUpdateEvent @event)
    { 
        // Define the object type
        //----------------------------------------------------------
        if(@event.Entity is IContractor) // interface of the Contractor type object
        {
            var Contractor = (IContractor)@event.Entity;
           
            if (Contractor.LegalAddress != null && !string.IsNullOrWhiteSpace(Contractor.LegalAddress.City)) // If a city is specified
            {
                // Search by the contractor filter, specify the taxpayer number and city, and exclude the current contractor
                var filterString = string.Format(@"(INN is NULL OR INN = ’{0}’) and LegalAddress in (City LIKE ’%{1}%’) and Id <> {2}",Contractor.INN, Contractor.LegalAddress.City.Trim(), Contractor.Id); 
                var findKA = EntityManager<IContractor>.Instance.Find(filterString);     
                if (findKA.Count == 0)
                {
                    Logger.Log.Error("==Output no duplicates");
                }
                else
                {
                    throw new Exception("Contractor already exists. "+string.Format(@"{0}/CRM/ContractorLegal/Details/{1}",
                    Locator.GetServiceNotNull<CommonSettingsModule>().Settings.ApplicationBaseUrl,
                    findKA.ElementAt(0).Id)+
                    " Specify different taxpayer number and city.");
                }
            }
            else
            {
                // Search a contractor by the filter, specify taxpayer number and exclude the current contractor
                var filterString = string.Format(@"(INN is NULL OR INN = ’{0}’) and LegalAddress in (City is NULL OR City = ’’) and Id <> {1}",Contractor.INN, Contractor.Id);
                var findKA = EntityManager<IContractor>.Instance.Find(filterString);     
                if (findKA.Count == 0)
                {
                    Logger.Log.Error("==Output no duplicates");
                }
                else
                {
                    throw new Exception("Contractor already ."+string.Format(@"{0}/CRM/ContractorLegal/Details/{1}",
                    Locator.GetServiceNotNull<CommonSettingsModule>().Settings.ApplicationBaseUrl,
                    findKA.ElementAt(0).Id)+
                    " Specify different taxpayer number and city.");
                }     
            }    
        }
        return false; // return to normal
    }
}

The OnPreUpdate(PreUpdateEvent @event) method is called when creating a new object or changing an existing one. Thus, any changes in the name and/or city in contractors will be tracked by the system.

Another important aspect of this code: when searching for existing contractors, you must exclude the current contractor, even when creating a new one, since the search takes the server cache into account.

Attention!
Using the script in this article incorrectly may result in locking all the transactions in the database. Make sure that your code is executed correctly for the required conditions; in all other cases, the line return false; // return to normal must be executed.