CANIAS Dinamik İskonto Kullanımı | TROIA

CANIAS: Dinamik İskonto Yapısı — Uygulama ve Deneyimler

Merhaba, CANIAS’ta dinamik iskonto yapısını oldukça kullanışlı buluyorum. Aşağıda bir müşteride kurduğum çözümü adım adım anlattım — hem mimari hem de pratik kullanım açısından. Blogda paylaşmak için sadeleştirdim; isteyenler kendi ihtiyaçlarına göre genişletebilir.

Temel fikir

Müşterileri ve malzemeleri “iskonto türüne” göre sınıflandırıp, sistemin dinamik iskonto tablolarına (IASDYNAMICP ve IASDYNAMICPCR) otomatik kayıt üretecek şekilde bir tasarım yaptım. Böylece: hangi müşteri türü hangi malzeme türünde hangi iskonto tipini alacak — bu kurala göre her gece veya manuel tetikleme ile sisteme gerekli kayıtlar yazılıyor.

Veritabanı ve tablolar

Aşağıdaki temel değişiklikleri ve yeni tabloları tanımladım:

  • IASDYNAMICP tablosuna yeni alan: MALZEMEISKONTOTIPI
  • MALZEMEMUSTERIISKONTO tablosu — müşteri tipi, malzeme tipi ve uygulanacak iskonto tipi kaydı.
  • MALZEMEISKONTOSCRIPT tablosu — hangi kurallara göre malzemelere iskonto tipi atanacağı burada tanımlanıyor.

MALZEMEMUSTERIISKONTO

-- Tanımların saklandığı tablo
	[CLIENT] [varchar](2) NOT NULL,
	[COMPANY] [varchar](3) NOT NULL,
	[MUSTERIISKONTOTIPI] [varchar](2) NOT NULL,
	[MALZEMEISKONTOTIPI] [varchar](2) NOT NULL,
	[ISKONTOKODU] [varchar](3) NOT NULL,
	[CREATEDBY] [nvarchar](30) NULL,
	[CREATEDAT] [datetime] NULL,
	[CHANGEDBY] [nvarchar](30) NULL,
	[CHANGEDAT] [datetime] NULL

MALZEMEISKONTOSCRIPT

-- Kuralların saklandığı tablo
	[CLIENT] [varchar](2) NOT NULL,
	[COMPANY] [varchar](3) NOT NULL,
	[ALAN1] [varchar](80) NULL,
	[OPERATOR1] [varchar](10) NULL,
	[DEGER1] [nvarchar](80) NULL,
	[ALAN2] [varchar](80) NULL,
	[OPERATOR2] [varchar](10) NULL,
	[DEGER2] [nvarchar](80) NULL,
	[MALZEMEISKONTOTIPI] [varchar](2) NOT NULL,
	[CREATEDBY] [nvarchar](30) NULL,
	[CREATEDAT] [datetime] NULL,
	[CHANGEDBY] [nvarchar](30) NULL,
	[CHANGEDAT] [datetime] NULL

UI — Yönetim ekranı

Yönetim için dört sekmeli bir ekran geliştirdim. Ekran şu işleri yapıyor:

  1. Sekme 1 — Müşteri İskonto Tip Ataması: Müşterilere/müşteri tiplerine iskonto tipleri atanıyor. Buradan manuel tetikleme de yapılabilir.
  2. Sekme 2 — Malzeme Kural Tanımları: Malzemelere hangi kurallarla iskonto tipi atanacağı tanımlanıyor (MALZEMEISKONTOSCRIPT). Buradan manuel güncelleme de başlatılabilir.
  3. Sekme 3 — İskonto Tanımlarını Görüntüleme: Oluşan eşleşmeler ve atanan iskontolar listeleniyor.
  4. Sekme 4 — Malzemeleri Listeleme: Sistemdeki malzemeler, tanımlanan iskonto kriterlerine göre filtrelenip listelenebiliyor.

Stored Procedures (SP) ve otomasyon

İki ana SP yazdım. Bunlar günlük olarak çalışıyor ancak istenirse yönetim ekranından manuel de tetiklenebiliyor:

1) PRC_ERP_MALZEMEISKONTOTIPIAYARLA.sql

Tanımı: MALZEMEISKONTOSCRIPT tablosundaki kurallara göre malzemelere iskonto tipi atayan SP. Bu prosedür kuralları okur, malzeme setlerini çıkarır ve MALZEMEMUSTERIISKONTO tablosunu günceller.


  create PROCEDURE [dbo].[PRC_ERP_MALZEMEISKONTOTIPIAYARLA]
AS
BEGIN
	DECLARE @sql NVARCHAR(MAX),
			@whereClause NVARCHAR(MAX);

	DECLARE script_cursor CURSOR FOR
	SELECT COMPANY
		 , ALAN1
		 , OPERATOR1
		 , DEGER1
		 , ALAN2
		 , OPERATOR2
		 , DEGER2
		 , MALZEMEISKONTOTIPI
	FROM MALZEMEISKONTOSCRIPT
	WHERE CLIENT = '00'
	ORDER BY COMPANY, CREATEDAT;

	DECLARE @company VARCHAR(50), 
			@alan1 VARCHAR(80), 
			@operator1 VARCHAR(10), 
			@deger1 nVARCHAR(80),
			@alan2 VARCHAR(80), 
			@operator2 VARCHAR(10), 
			@deger2 nVARCHAR(80), 
			@iskontotipi VARCHAR(2);

	OPEN script_cursor
	FETCH NEXT FROM script_cursor INTO @company, @alan1, @operator1, @deger1, @alan2, @operator2, @deger2, @iskontotipi

	WHILE @@FETCH_STATUS = 0
	BEGIN
		SET @whereClause = @alan1 + ' ' + @operator1 + ' N''' + @deger1 + ''''
    
		IF ISNULL(@deger2, '') != ''
			SET @whereClause = @whereClause + ' AND ' + @alan2 + ' ' + @operator2 + ' N''' + @deger2 + ''''
    
		SET @sql = 'UPDATE IASMATMOP SET CHANGEDBY = ''IT-MLZ-DISC-TYPE'', CHANGEDAT = GETDATE(), 
		MALZEMEISKONTOKODU = ''' + @iskontotipi + ''' 
		WHERE CLIENT = ''00'' AND COMPANY = ''' + @company + ''' 
		  AND MALZEMEISKONTOKODU <> ''' + @iskontotipi + ''' 
		  AND ' + @whereClause
		-- PRINT @sql;
		EXEC sp_executesql @sql
		FETCH NEXT FROM script_cursor INTO @company, @alan1, @operator1, @deger1, @alan2, @operator2, @deger2, @iskontotipi
	END;

	CLOSE script_cursor;
	DEALLOCATE script_cursor;
	

END;

2) PRC_ERP_DYNAMICPISKONTOAYARLA.sql

Tanımı: Sistemde iskontosu tanımlı müşteri ve malzemelere göre IASDYNAMICP ve IASDYNAMICPCR tablolarına CANIAS’a uygun dinamik iskonto kayıtlarını oluşturur. Mevcut iskontolar kontrol edilir; varsa ve değişmişse silinip yeniden oluşturur. Hiç yoksa sıfırdan oluşturur.


  create PROCEDURE [dbo].[PRC_ERP_DYNAMICPISKONTOAYARLA]
   @FirmaKodu			VARCHAR(3),
   @MusteriNo			VARCHAR(30)
AS BEGIN
   DECLARE @MusteriIskontoTanimAdedi	INT, 
   		   @MusteriIskontoMevcutAdet	INT, 
		   @musteri_fetch_status		INT,
   		   @iskonto_fetch_status		INT,
		   @MalzemeIskontoTipi			VARCHAR(2),
		   @MusteriIskontoTipi			VARCHAR(2),
   		   @IskontoKodu					VARCHAR(3),	
		   @sonDynamicRelKey			VARCHAR(15),
		   @yeniDynamicRelKey			VARCHAR(15),
		   @yeniRelDesc					VARCHAR(80),
		   @yeniCriteriaText			NVARCHAR(MAX);
   		
   DECLARE musteri_cursor CURSOR FOR
   	SELECT DISTINCT c.CUSTOMER
   				  , c.MUSTERIISKONTOTIPI
   	FROM IASCUSTOMER c WITH (NOLOCK)
   		INNER JOIN MALZEMEMUSTERIISKONTO b WITH (NOLOCK) ON b.CLIENT = '00'
   			AND b.COMPANY = @FirmaKodu
   			AND b.MUSTERIISKONTOTIPI = c.MUSTERIISKONTOTIPI
   	WHERE c.CLIENT = '00'
   		AND c.COMPANY = @FirmaKodu
   		AND c.ISLOCKED = 0
   		AND c.ISDELETE = 0
   		AND c.CUSTOMER LIKE @MusteriNo
		AND c.ISCUSTORVEND = 3
		AND ISNULL(c.MUSTERIISKONTOTIPI, '') <> '';
   OPEN musteri_cursor
   FETCH NEXT FROM musteri_cursor INTO @MusteriNo, @MusteriIskontoTipi;
   SET @musteri_fetch_status = @@FETCH_STATUS;
   WHILE @musteri_fetch_status = 0
   BEGIN
   	PRINT 'Musteri: ' + @MusteriNo;
   	SELECT @MusteriIskontoTanimAdedi = COUNT(*)
   	FROM IASCUSTOMER c WITH (NOLOCK)
   		INNER JOIN MUSTERIISKONTOTIPI b WITH (NOLOCK) ON b.CLIENT = '00'
   			AND b.COMPANY = @FirmaKodu
   			AND b.MUSTERIISKONTOTIPI = c.MUSTERIISKONTOTIPI
   	WHERE c.CLIENT = '00'
   		AND c.COMPANY = @FirmaKodu
   		AND c.CUSTOMER = @MusteriNo;
   	SELECT @MusteriIskontoMevcutAdet = COUNT(*)
   	FROM IASDYNAMICP p WITH (NOLOCK)
   		INNER JOIN MUSTERIISKONTOTIPI b WITH (NOLOCK) ON b.CLIENT = '00'
   			AND b.COMPANY = @FirmaKodu
   			AND b.MALZEMEISKONTOTIPI = p.MALZEMEISKONTOKODU
   			AND b.ISKONTOKODU = p.DISCKEY1
   	WHERE p.CLIENT = '00'
   		AND p.COMPANY = @FirmaKodu
   		AND p.CUSTOMER = @MusteriNo
   		AND p.ISDELETE = 0
   		AND ISNULL(p.ARACGRUBU, '') = ''
   		AND ISNULL(p.GOBEKKODU, '') = ''
   		AND ISNULL(p.MALZEMEISKONTOKODU, '') <> '';
   	IF @MusteriIskontoTanimAdedi = @MusteriIskontoMevcutAdet BEGIN
   		PRINT N'Her sey esitse bir isleme gerek yok.';
   	END;
   	ELSE BEGIN
   		PRINT N'Herhangi bir esitsizlik soz konusu ise hepsini sil yeniden olustur en temizi...';
		-- Once [IASDYNAMICP]
		DELETE p
		FROM IASDYNAMICP p 
			WHERE p.CLIENT = 'RR'
			  AND p.COMPANY = @FirmaKodu
			  AND p.CUSTOMER = @MusteriNo
			  AND p.ISDELETE = 0
   			  AND ISNULL(p.MALZEMEISKONTOKODU, '') <> '';
		PRINT N'  Silinen IASDYNAMICP kayit sayisi: ' + CAST(@@ROWCOUNT AS VARCHAR(10));

		UPDATE p SET p.CLIENT = 'RR', p.CHANGEDBY = 'IT-AUTO-DISC', p.CHANGEDAT = GETDATE()
		FROM IASDYNAMICP p 
			WHERE p.CLIENT = '00'
			  AND p.COMPANY = @FirmaKodu
			  AND p.CUSTOMER = @MusteriNo
			  AND p.ISDELETE = 0
   			  AND ISNULL(p.MALZEMEISKONTOKODU, '') <> '';
		PRINT N'  Guncellenen IASDYNAMICP kayit sayisi: ' + CAST(@@ROWCOUNT AS VARCHAR(10));

		-- Sonra [IASDYNAMICPCR]			  
		DELETE pcr
		FROM IASDYNAMICP p
			INNER JOIN IASDYNAMICPCR pcr ON pcr.CLIENT = 'RR'
				AND pcr.COMPANY = @FirmaKodu
				AND pcr.DYNAMICRELKEY = p.DYNAMICRELKEY
		WHERE p.CLIENT = 'RR'
			AND p.COMPANY = @FirmaKodu
			AND p.CUSTOMER = @MusteriNo
			AND p.ISDELETE = 0
   			AND ISNULL(p.MALZEMEISKONTOKODU, '') <> '';
		PRINT N'  Silinen IASDYNAMICPCR kayit sayisi: ' + CAST(@@ROWCOUNT AS VARCHAR(10));

		UPDATE pcr SET pcr.CLIENT = 'RR', pcr.CHANGEDBY = 'IT-AUTO-DISC', pcr.CHANGEDAT = GETDATE()		
		FROM IASDYNAMICP p
			INNER JOIN IASDYNAMICPCR pcr ON pcr.CLIENT = '00'
				AND pcr.COMPANY = @FirmaKodu
				AND pcr.DYNAMICRELKEY = p.DYNAMICRELKEY
		WHERE p.CLIENT = 'RR'
			AND p.COMPANY = @FirmaKodu
			AND p.CUSTOMER = @MusteriNo
			AND p.ISDELETE = 0
   			AND ISNULL(p.MALZEMEISKONTOKODU, '') <> '';
		PRINT N'  Guncellenen IASDYNAMICPCR kayit sayisi: ' + CAST(@@ROWCOUNT AS VARCHAR(10));
			
   		DECLARE iskonto_cursor CURSOR FOR
		   SELECT b.MALZEMEISKONTOTIPI
				, b.ISKONTOKODU
		   FROM MUSTERIISKONTOTIPI b
		   WHERE b.CLIENT = '00'
			   AND b.COMPANY = @FirmaKodu
			   AND b.MUSTERIISKONTOTIPI = @MusteriIskontoTipi;   		
   		OPEN iskonto_cursor
   		FETCH NEXT FROM iskonto_cursor INTO @MalzemeIskontoTipi, @IskontoKodu;
   		SET @iskonto_fetch_status = @@FETCH_STATUS;
   		WHILE @iskonto_fetch_status = 0
   		BEGIN
   			PRINT '  -> Iskonto: ' + @MalzemeIskontoTipi + ' - ' + @IskontoKodu;
			SET @yeniRelDesc				= @MusteriNo + '[' + 'MlzIskTp:' + @MalzemeIskontoTipi + ']';
			SET @yeniCriteriaText			= '  IASSALHEAD_CUSTOMER == ''' + @MusteriNo + ''' &&   IASSALITEM_MALZEMEISKONTOKODU == ''' + @MalzemeIskontoTipi + '''';
			
			SELECT TOP 1 @sonDynamicRelKey = DYNAMICRELKEY
											FROM IASDYNAMICP
											WHERE CLIENT = '00'
												AND COMPANY = @FirmaKodu
												AND CUSTOMER = @MusteriNo
											ORDER BY DYNAMICRELKEY DESC;
			IF @sonDynamicRelKey IS NULL
				SET @yeniDynamicRelKey = @MusteriNo + '0001'
			ELSE
				SET @yeniDynamicRelKey = @MusteriNo + RIGHT('0000' + CAST(CAST(RIGHT(@sonDynamicRelKey, 4) AS INT) + 1 AS VARCHAR), 4);

			-- Once [IASDYNAMICP]
			INSERT INTO [dbo].[IASDYNAMICP]
					   ([CLIENT]
					   ,[COMPANY]
					   ,[VALIDFROM]
					   ,[VALIDUNTIL]
					   ,[CREATEDBY]
					   ,[CHANGEDBY]
					   ,[CREATEDAT]
					   ,[CHANGEDAT]
					   ,[ISDELETE]
					   ,[QUANTITY1]
					   ,[QUANTITY2]
					   ,[QUANTITY3]
					   ,[QUANTITY4]
					   ,[QUANTITY5]
					   ,[QUANTITY6]
					   ,[PRICE1]
					   ,[PRICE2]
					   ,[PRICE3]
					   ,[PRICE4]
					   ,[PRICE5]
					   ,[PRICE6]
					   ,[DISCKEY1]
					   ,[DISCKEY2]
					   ,[DISCKEY3]
					   ,[DISCKEY4]
					   ,[DISCKEY5]
					   ,[ISVATINCLUSIVE]
					   ,[SALPUNIT]
					   ,[RELPRIO]
					   ,[ISBONUS]
					   ,[BONUSSCALE1]
					   ,[BONUSSCALE2]
					   ,[BONUSSCALE3]
					   ,[BONUSSCALE4]
					   ,[BONUSSCALE5]
					   ,[BONUSSCALE6]
					   ,[BONUSQUAN1]
					   ,[BONUSQUAN2]
					   ,[BONUSQUAN3]
					   ,[BONUSQUAN4]
					   ,[BONUSQUAN5]
					   ,[BONUSQUAN6]
					   ,[BONUSRATE1]
					   ,[BONUSRATE2]
					   ,[BONUSRATE3]
					   ,[BONUSRATE4]
					   ,[BONUSRATE5]
					   ,[BONUSRATE6]
					   ,[ISPRICEDISC]
					   ,[TYPERATE]
					   ,[DYNAMICRELKEY]
					   ,[RELDESC]
					   ,[CRITERIATEXT]
					   ,[ISRUNCODE]
					   ,[CODE]
					   ,[CUSTOMER]
					   ,[MATERIAL]
					   ,[MALZEMEISKONTOKODU])
				 VALUES
					   ('00'
					   ,@FirmaKodu
					   ,'1975-01-01'
					   ,'2030-01-01'
					   ,'IT-AUTO-DISC'
					   ,'IT-AUTO-DISC'
					   ,GETDATE()
					   ,GETDATE()
					   ,0.0
					   ,0.0
					   ,0.0
					   ,0.0
					   ,0.0
					   ,0.0
					   ,0.0
					   ,0.00
					   ,0.00
					   ,0.00
					   ,0.00
					   ,0.00
					   ,0.00
					   ,@IskontoKodu
					   ,''
					   ,''
					   ,''
					   ,''
					   ,0
					   ,1
					   ,2
					   ,0
					   ,0.00
					   ,0.00
					   ,0.00
					   ,0.00
					   ,0.00
					   ,0.00
					   ,0.0
					   ,0.0
					   ,0.0
					   ,0.0
					   ,0.0
					   ,0.0
					   ,0.00
					   ,0.00
					   ,0.00
					   ,0.00
					   ,0.00
					   ,0.00
					   ,0
					   ,0
					   ,@yeniDynamicRelKey
					   ,@yeniRelDesc
					   ,@yeniCriteriaText
					   ,0
					   ,''
					   ,@MusteriNo
					   ,''
					   ,@MalzemeIskontoTipi);
			
			-- Sonra [IASDYNAMICPCR]
			INSERT INTO [dbo].[IASDYNAMICPCR]
						([CLIENT]
						,[COMPANY]
						,[DYNAMICRELKEY]
						,[LOGIC]
						,[PREFIX]
						,[FIELDNAME]
						,[OPERATOR]
						,[VALUE]
						,[SUFFIX]
						,[ISACTIVE]
						,[CRITERIANUM]
						,[ISHEAD]
						,[FIELDTYPE]
						,[ISVARIANT]
						,[VARIANTKEY]
						,[VOPTIONS]
						,[ZOOMTBL]
						,[OPERATORVAR]
						,[VALIDFROM]
						,[VALIDUNTIL]
						,[CREATEDBY]
						,[CREATEDAT]
						,[CHANGEDBY]
						,[CHANGEDAT])
					VALUES
						('00'
						,@FirmaKodu
						,@yeniDynamicRelKey
						,0
						,0
						,'CUSTOMER'
						,0
						,@MusteriNo
						,0
						,1
						,10
						,1
						,'STRING'
						,0
						,''
						,''
						,''
						,0
						,'1975-01-01'
						,'2030-01-01'
						,'IT-AUTO-DISC'
						,GETDATE()
						,'IT-AUTO-DISC'
						,GETDATE());

			INSERT INTO [dbo].[IASDYNAMICPCR]
						   ([CLIENT]
						   ,[COMPANY]
						   ,[DYNAMICRELKEY]
						   ,[LOGIC]
						   ,[PREFIX]
						   ,[FIELDNAME]
						   ,[OPERATOR]
						   ,[VALUE]
						   ,[SUFFIX]
						   ,[ISACTIVE]
						   ,[CRITERIANUM]
						   ,[ISHEAD]
						   ,[FIELDTYPE]
						   ,[ISVARIANT]
						   ,[VARIANTKEY]
						   ,[VOPTIONS]
						   ,[ZOOMTBL]
						   ,[OPERATORVAR]
						   ,[VALIDFROM]
						   ,[VALIDUNTIL]
						   ,[CREATEDBY]
						   ,[CREATEDAT]
						   ,[CHANGEDBY]
						   ,[CHANGEDAT])
					 VALUES
						   ('00'
						   ,@FirmaKodu
						   ,@yeniDynamicRelKey
						   ,2
						   ,0
						   ,'MALZEMEISKONTOKODU'
						   ,0
						   ,@MalzemeIskontoTipi
						   ,0
						   ,1
						   ,20
						   ,0
						   ,'STRING'
						   ,0
						   ,''
						   ,''
						   ,''
						   ,0
						   ,'1975-01-01'
						   ,'2030-01-01'
						   ,'IT-AUTO-DISC'
						   ,GETDATE()
						   ,'IT-AUTO-DISC'
						   ,GETDATE());
   			FETCH NEXT FROM iskonto_cursor INTO @MalzemeIskontoTipi, @IskontoKodu;
   			SET @iskonto_fetch_status = @@FETCH_STATUS;
   		END   		
   		CLOSE iskonto_cursor;
   		DEALLOCATE iskonto_cursor;
   	END;
      FETCH NEXT FROM musteri_cursor INTO @MusteriNo, @MusteriIskontoTipi;
      SET @musteri_fetch_status = @@FETCH_STATUS;
   END;
   CLOSE musteri_cursor;
   DEALLOCATE musteri_cursor;
END;
Not: Her iki SP için de işlem hacmine göre batchleme ve transaction kontrolleri önemlidir. Büyük veri setlerinde blok blok çalışıp kademeli commit/rollback yaklaşımı kullanmak güvenli olur.

Çalışma şekli — Zamanlama ve tetikleme

– Günlük otomasyon: Her gece bir job PRC_ERP_MALZEMEISKONTOTIPIAYARLA prosedürünü çalıştırır, malzeme
iskonto tipi atamalarını yapar. Ardından PRC_ERP_DYNAMICPISKONTOAYARLA çalışarak IASDYNAMICP kayıtlarını üretir.

Bu yapı CANIAS’ta dinamik ve kontrol edilebilir ve daha esnek bir iskonto yönetimi sağladı.

Selamlar…

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top