1C:Enterprise EĞİTİM
DERS 2
1C:Enterprise Ders 2-1
Satın alınan malzemelerin fiyatlarının saklanması
Biz ne zaman yeni bir GoodsReceipt evrakı oluşturduğumuzda satın aldığımız malzemeleri kaydediyoruz. Şimdiye kadar bu evrakın tablo sekmesinde bulunan öznitelikler:
- – Malzeme
- – Miktar
Biz önemli bir şeyi kaçırmış gibi görünüyoruz – biz bu işlemi belli miktarda para ile gerçekleştirdik. Şimdi tablo sekmesine bilgi veren yeni bir öznitelik eklemeli ve her satır için bedel kayıt etmeliyiz.
İkincil veri
Şimdi her satır için ödediğimiz bedeli ve evrakın toplam bedelini bilmemiz iyi olurdu. Satır başına toplam şu formülle hesaplanabilir: Birim fiyat * Miktar ve genel toplam tüm satır bedellerinin toplamı. Bu bilgiye “ikincil veri” denir ve yeni bir bilgi içermez – biz verileri zaten başka ir biçimde tanıyoruz ama diğer formda (şu anki durumda zaten bilinen iki değeri çarparak elde ediyoruz).
Biz ikincil veri ile nasıl çalışabiliriz?
Tamam, şimdi burada hiçbir kullanıcın ikincil veriyi değiştirmesine izin vermemeliyiz. Aksi takdirde:
- – Kullanıcılara gereksiz iş yaptırırız
- – Kullanıcıların yapabileceği hata ile veri bütünlüğünü tehlikeye atarız
Bunun yerine, bu tür verilerin otomatik olarak hesaplanması gerekir.
Diğer anahtar soru şu: ikincil verileri infobase de depolamaya gerçekten ihtiyacımız var mı? Eğer biz bu verileri sadece hesaplayıp gösterirsek, bunları kurtarmak için zahmet etmeye gerek yok mudur?
Yani, burada iki yol var, biz ikincil verileri hesaplayıp saklarız (bu durumda “kalıcı” olur) veya bu verileri göstermemiz gerektiğinde hesaplarız (bu durumda “sanal” olur).
Her iki yaklaşımı deneyelim ve güçlü veya zayıf yönlerini görelim.
Kalıcı ikincil veri
Eğer bir kullanıcı gerçek zamanlı olarak toplamları görseydi, bu çok iyi olurdu, yani fiyat veya miktar değiştirildiğinde bu verileri tekrar hesaplamalıyız. Şimdi tablo sekmesindeki her satır için toplam fiyatı nasıl hesaplayacağımızı görelim.
Bu kaynak kod:
&AtClient
Procedure MaterialsQuantityOnChange(Item)
ThisForm.Items.Materials.CurrentData.Total =
ThisForm.Items.Materials.CurrentData.Quantity *
ThisForm.Items.Materials.CurrentData.Price;
EndProcedure
Bu iyi çalışıyor ama veri bütünlüğü ne durumda? Biz kullanıcıların “Toplam” özniteliğini değiştirmesini engelledik, değil mi?
Hayır, açıkçası henüz bunu yapmadık. Bir sadece formu yaptık, ancak bu kısıtlamayı aşmak için birçok yol vardır. Bunun bir örnek üzerinde nasıl olduğunu görelim.
Not, toplamları bozmak için bundan daha çok yol vardır – bu sadece bir örnek.
Belirtilmesi gereken bir diğer önemli şey bilgisayar korsanları veya her türlü istenmeyen misafirler için bizim verileri korumaya çalışmanın mümkün olmayışıdır. Veri tabanı güvenlik ihlalleri mümkündür, ama çok daha olası senaryo birilerinin tesadüfi hatasıdır.
Sadece sonsuz hata olabileceğini düşünüyorum ve biz bu durumda ikincil veriyi hatalı almış olacağız. Herhangi bir evrak güncelleme işlemi sırasında hataları kontrol etsek ve evrakı durdursak güzel olmaz mıydı? Tüm evraklar için olay işleyicileri kontrolü 1C: Enterprise içinde nerede bulunuyor?
Evrak olay işleyicileri
Bazı 1C: Enterprise nesneleri her zaman bazı özel nesne eylemleri ile olay oluşturabilir. Geliştiriciler olay işleyicisi oluşturabilir ve kaynak kodda ihtiyaç durduğu herhangi bir yerde kullanabilir. Bu olaylarla ilgili iyi bir olay ortaya çıktığında her zaman eylem gerçekleşir ve bizim ihtiyacımız olan kodu çalıştırır. Bunun sonucu olarak asla hata oluşmasına izin vermez ve olay ortaya çıktığında eylem mutlaka gerçekleşir.
Herhangi bir olayı yakalamak ve olay işleyicisini uygulamak için iki yol vardır:
- – Nesne modülünde olay için abone olun;
- – Global bir abonelik oluşturun ve ortak bir modül işleyicisine uygulayın
Biz geçerli tek nesne için “yerel” olay işleyicilerini uygulamak için ilk seçeneği kullanalım. Eğer bir olayı birden fazla nesnenin olay işleyicileri için kullanmaya ihtiyacınız varsa, global abonelikleri kullanabilirsiniz. Ayrıca global abonelikleri tek bir nesne içinde kullanabilirsiniz.
Burada evrak için “yerel” abonelikleri bulabilirsiniz:
Kaynak kod her iki durumda da aynıdır. Şimdi global abonelikleri kullanarak nasıl işleyici oluşturacağız, düşünelim. Bu durumda, olay işleyicisi yalnızca ortak bir modül olarak kullanılabilir, Yani önce birbirimizi tanıyalım.
Genel modüller
Şimdiye kadar kaynak kodları form modülleri içine yazıp saklıyorduk – burası formlar için olay işleyicilerinin uygulandığı yerdi. Gerçek dünya sistemlerinde, Bizim oldukça sık ihtiyacımız olan bir kaynak kodun birden fazla yerde kullanılması. Örneğin, toplam hesabı kodunun birden fazla evrak içinde uygulanması. Biz aynı kodu iki kez tekrar edebiliriz, ama daha iyi bir çözüm kodu başka bir yere yerleştirmektir – her iki belge için erişilebilecek bir yere. Burası genel modüller.
Gerektiği kadar çok genel modüller oluşturulabilir ve istemci, sunucu veya her ikisi tarafından erişilebilir.
Genel modül prosedür ve fonksiyonlarının dışarıdan erişilebilir olması için, “Export” kelimesini prosedür veya fonksiyon tanımının sonuna eklememiz gerekir. Ayrıca tek modül içerisinde birden çok prosedür veya fonksiyon yazılabilir. Şu anda “Export” kelimesini kullanmaya ihtiyacımız yoktur.
İhtiyacımız olan olay aboneliğini oluşturalım.
Ve sonuç olarak olay işleyicisi:
Procedure GoodsReceiptMaterialsTotalBeforeWrite(
Source,
Cancel,
WriteMode,
PostingMode) Export
For Each Material In Source.Materials Do
Material.Total = Material.Price * Material.Quantity;
EndDo;
EndProcedure;
Evrakların toplam fiyatı
Şimdi, toplamları hesaplayalım ve evrak toplamını kaydedelim. Öncelikle evrak için yeni bir öznitelik eklemek lazım:
Sonra bu yeni özniteliği evrak formuna ekleyelim (tablo sekmesinin altına koyalım):
Şimdi aynı olay işleyicisi içindeki döngüde evrak toplamını hesaplamak için birkaç değişiklik yapalım. Bu değişiklik şunun gibi olabilir:
Procedure GoodsReceiptMaterialsTotalBeforeWrite(
Source,
Cancel,
WriteMode,
PostingMode) Export
Source.Total = 0;
For Each Material In Source.Materials Do
Material.Total = Material.Price * Material.Quantity;
Source.Total = Source.Total + Material.Total;
EndDo;
EndProcedure
Yukarıdaki parametre kodu kaynak olarak DocumentObject.GoodsReceipt içerir, yani bizim evrak toplamını almak için “Source.Total” kullanmamız yeterlidir. Sonra evrakı açıp, kaydediyoruz ve tekrar açıp neler olduğunu görelim:
Yani, evrak toplamı hesaplandı ve infobase e kaydedildi. Ama şu an biz herhangi bir satırın fiyat veya miktar değerini değiştirirsek toplam değişmeden kalır. Hadi bunu düzeltelim.
Bizim tablo sekmesi için döngüye ihtiyacımız var, genel toplam hesaplama, tam olarak GoodsReceiptMaterialsTotalBeforeWrite modülündeki gibi geliyor kulağa. Bunu kullanabilir miyiz? Evet, ama tüm parametrelere ihtiyacımız yok, bu yüzden şu şekilde tekrar yazalım:
Procedure GoodsReceiptMaterialsTotalBeforeWrite(
Source,
Cancel,
WriteMode,
PostingMode) Export
CalcTotals(Source);
EndProcedure
Procedure CalcTotals(Document) Export
Document.Total = 0;
For Each Material In Document.Materials Do
Material.Total = Material.Price * Material.Quantity;
Document.Total = Document.Total + Material.Total;
EndDo;
EndProcedure
Yani başka bir prosedür ekledik ve tüm toplam hesaplama döngüsünü taşıdık, GoodsReceiptMaterialsTotalBeforeWrite prosedürünü bırakarak. Unutmayın, modülü dışarıdan erişilebilir hale getirmek için mutlaka “Export” kelimesini eklemeliyiz.
Şimdi formun modülüne geçerek bu prosedürün parametresinin türünü DocumentsObject.GoodsReceipt olarak yazıyoruz. Şimdi bu prosedürü GoodsReceipt evrakının nesne modülünden çağıralım:
&AtClient
Procedure MaterialsQuantityOnChange(Item)
//ThisForm.Items.Materials.CurrentData.Total =
// ThisForm.Items.Materials.CurrentData.Quantity *
// ThisForm.Items.Materials.CurrentData.Price;
Subscriptions.CalcTotals(ThisForm.Object);
EndProcedure
Bu prosedür geçerli satır için hesaplama yapmak üzere kodlanmıştı biz burada tablo sekmesinin tümü için hesap yapacak prosedürü çağırdık. Bu prosedür tüm satırlar için tekrar toplam hesaplayacak ve sonra genel toplamı hesaplayacak.
Unutmayın, prosedür ismini modülün bir parçası olarak kullanıyoruz, örneğin, “Subscriptions.CalcTotals”. Aksi takdirde, prosedür modül dışında erişilebilir olmayacaktır. Ancak sözdizimi denetimi yaparsak, bu hata iletisini görürüz:
Bu hata mesajı bize diyor ki, biz bu çağrıyı ince istemci de yapıyoruz ama bu prosedür ya mevcut değil ya da erişilebilir değil. Diğer bir deyişle, istemci bu prosedürü göremiyor.
İstemci veya sunucu kodunun prosedür ve fonksiyonlarının erişim ayarlarını etkileyebilen şeyler vardır. İstemci için bu modül ve prosedürleri görünür hale getirmek için, “İstemci” onay kutusunu modül özellikleri panelinde işaretlememiz gerekir.
Şimdi, tüm toplamlar hesaplanacak ve infobase de saklanacak.
1C:Enterprise Ders 2-2
Sanal ikincil veri
Şimdi Toplam özniteliğini silelim ve işlem anında tüm hesaplamaları yapalım.
Ayrıca tüm belge için genel toplam hesaplamak gerekiyor. Bu kalıcı olarak genel toplam hesaplamaya çok benziyor, bu sefer forma tek başına öznitelik eklemek gerekir.
Bilmemiz gerek bir şey daha var. Toplam özniteliğinin tablo sekmesi için saklandığını fark etmiş olmalısınız, öznitelikler form listesi gibi gözüküyordu.
Bunun anlamı Platform tablo sekmesindeki her bir kalıcı öznitelik için nasıl toplam hesaplanacağını biliyor. Bu yüzden formda sadece herhangi bir yere TotalTotal özniteliği koyalım ve otomatik olarak hesaplanan genel toplamı alalım.
İkincil veri: Sanal’a karşı Kalıcı
Biz hangisini seçmeliyiz – birincil veya ikincil veri? Maalesef, bu sorunun cevabı basit değil.
Burada önemli olan şey ikincil veriyi sürekli olarak hesaplıyoruz ve açıkçası, bu hesaplama kaynakları tüketir. İkincil veri hesaplanırken, sistem yavaşlar ve tepki süresi artar. Kalıcı ve sanal veriler arasındaki fark bizim ne zaman sistemi yavaşlatmak veya hangi kaynakları tüketmek istediğimizle alakalıdır.
Birincil veri değiştiğinde kalıcı ikincil veri hesaplanır, yazma işlemi sırasında (evrak kaydetme ve daha fazlası). Sanal ikincil veri hesaplama ise veri okuma sırasında gerçekleşir (form yenileme, rapor doldurma ve daha fazlası).
Not, kalıcı ikincil veri, sanal ikincil veriye göre daha az hesaplanır (çünkü veri okuma işlemi yazma işleminden daha çok yapılır), ama hesaplanması daha karmaşık.
Göz önünde bulundurulması gereken bir şey daha geliştiricinin sahip olduğu kaynaklar. Kalıcı ikincil veri hesaplaması ve düzenlemesi daha çok zaman alır. Geliştiriciler bu hata olasılığını azaltmak için kodu daha kolaylaştırmaya izin vermelidir. Bu anlamda, sanal ikincil veri daha doğal ve daha az dağınık bir görünüme sahiptir.
Sonuçta, bunu şimdiden söylemek çok zor, gerçek hayatta ikincil veri için hangi türü seçmemiz gerektiğine. Bu nedenle, en pratik tavsiyem şu olacaktır: öncelikle bazı özellikleri göstermek için ve sistem hızlandırılması için sanal ikincil veri kullanın. Daha sonra kalıcı ikincil veri. (sadece bu özel işlem için). Unutmayın, okuma hız arttırır yazma ise yavaşlatır, eğer her şeyi doğru yaptıysanız, bu yavaşlamayı kimse fark etmeyecektir.
Hizmetler (Services) evrakı
Şimdi satışlarımızı kaydetmeye başlayalım. Biz ev aletleri için tamir hizmeti satacağız. Bu hizmet işlemi onarımı gerçekleştirmek için kullandığımız bir veya birden fazla hizmet ve malzeme içerebilir. Yani, en açık şekilde satış evrakı yapısı aşağıdaki şekilde olacaktır:
Kaydetmek için müşterilerin ve hizmetleri gerçekleştiren teknisyenlerin kim olduğuna ihtiyacımız var. Bunun için “Customer” ve “Technician” alanlarını kullanacağız. Her iki özniteliğinde CatalogRef türünde olması gerekiyor, yani şu an ihtiyaçlarımıza göre iki yeni kart listesi oluşturalım: Customers ve Employees.
Ayrıca kullanılan malzemelerinde nereden alındığını bilmeliyiz, yani bizim “CatalogRef.Warehouses” türünde başka bir özniteliğe de ihtiyacımız var. Lütfen unutmayın, bir onarım için tüm malzemelerin anı depodan alındığını varsayıyoruz. Eğer böyle olmazsa, tablo sekmesine her satır için depo özniteliği eklememiz gerekecek.
Sonra iki ayrı tablo sekmesi yapalım – Materials ve Services – kullandığımız malzeme ve hizmetlerin listesinin kayıt edilmesi için bu tablo sekmeleri kullanılacaktır. Services evrakının tablo sekmesi Service isminde ve CatalogRef türünde bir öznitelik içermelidir, yani bizim bir kart listesine daha ihtiyacımız var.
Bu iki tablo sekmesinin birçok ortak noktası var:
- – İkisi de Price ve Quantity özniteliklerini içerir;
- – Her ikisinde de toplam fiyat hesaplamalıyız (her tablo sekmesi için tüm belge toplamı gibi).
Burada tek farklı olan tablo sekmelerinin Materials veya Services kart listelerine referans yapıyor olması. Eğer bu iki kart listesini birleştirmek istersek ne olur?
Materials ve Services kart listelerini tek kart listesinde birleştirmek
Diğer bir deyişle, sattığımız şey ne olursa olsun her şeyi saklamak için bu kart listesini kullanabilir- bir malzeme veya bir hizmet. Temel olarak, zaten yapmamız gereken tek şey var, Malzeme (Materials) kart listesini yeniden adlandırma:
Kart listeleri hiyerarşiyi destekler, yani kart listesi içindeki öğeleri klasörler içinde düzenli bir biçimde saklayabiliriz. Böylece malzeme ve hizmetleri birbirinden ayırmış oluruz.
Şimdi, Evraktaki ikinci tablo sekmesinden kurtulup Satış evrakının yapısını düzenlersek:
Gerçek hayatta 1C uygulamaları geliştirirken, bazı kararlar vermeliyiz, hangi yaklaşım daha iyi çalışır – farklı metadata nesneleri içindeki kayıtları ayıran, olsa bile bazı farklılıklar vardır. Bunun doğru ya da yanlış diye bir cevabı yoktur. Varlıkları ayırmak genellikle daha doğru ve okunabilir kod ile sonuçlanır, ama dezavantajları olabilir, performans sorunları da dâhil olmak üzere. İki metadata nesnesini birleştirirsek genellikle daha karmaşık bir görünür ve yeni işlevler eklemek daha fazla zaman alabilir ancak bazı durumlarda daha verimli çalışabilirsiniz.
Yani, hangi yaklaşımın daha iyi olacağını önceden bilemeyiz. Deneyim ve sezgilerimizden sonra karar vermek daha iyi olacaktır, eğer yanlış yol seçildiyse, biz metadata nesnesini yeniden yapılandırmalıyız ve kodu daha anlaşılır hale getirmeliyiz, ya da optimizasyon ile daha hızlı çalışması için bunu yapmalıyız.
Depo stok bakiyesi
Satış belgesi kullanımını ortak bir senaryo ile ele alalım:
- – İstemci ofise bulaşık makinesi kurulması için bir çağrı oluşturur;
- – İlgili kişi aşağıdaki malzeme ve hizmetler ile Satış evrakını doldurur ve çağrıya cevap verir:
- – Services:
- – Service call; (Servis araması)
- – Unpacking; (Paketten çıkarma)
- – Installation; (Kurulum)
- – Materials:
- – 1 dishwasher branch tailpiece with nuts and washers (1-1/2-in x 8-in) (somun ve civatalar)
- – Disposal connector with clamps (boru bağlayıcı kelepçeler)
- – 1 angle ball valve (açılı vana)
- – 1 x 3-way brass adapter (3/8-in O.D.) (pirinç adaptör)
- – 1 x 16-in and 1 x 60-in braided stainless steel flex connector (örgülü paslanmaz çelik kelepçe)
- – Teflon tape (teflon bant)
- – Receptionist tells the overall price of the service to the client; (ilgili kişi toplam fiyatın ne kadar olduğunu belirtir)
- – Receptionist checks the availability of technicians and arranges a scheduled time; (ilgili kişi teknisyenin durumu kontrol eder ve saatli tarife belirler)
- – Receptionist posts the document and tells a technician to fulfill the order; (ilgili kişi evrakı teknisyene gönderir ve her yeri doldurmasını ister)
- – Technician drops by to a warehouse, picks up all necessary materials and goes to the client’s place… (teknisyen depoya gider, gerekli malzemeleri alır ve müşterinin ofisine gider)
- – Services:
Bekleyin… Eğer depoda hiç “3-way brass adapter (pirinç adaptör)” kalmamışsa?
Bu durumda teknisyen planlanan zamanı kaçıracak (çünkü teknisyenin öncelikle yeni adaptör almaya gitmesi gerekiyor), müşteri hüsrana uğrayacak, web sitemize olumsuz geri bildirimler yazacak, başka bir şirketi arayacak ve bizim olacak olan parayı kaybedeceğiz.
Yani, kesinlikle siparişi tamamlamak için bir depoda yeterli malzeme olup olmadığını kontrol etmek için bir yol bulmalıyız. Bu prosedüre bakiye kontrolü denir ve ihtiyacımız olan malzemeler için geçerli deponun bakiyesi kontrol edilir.
Ama bu bakiyeyi nereden alacağız? Diğer yandan, ihtiyacımız olan tüm bilgilere sahibiz: GoodsReceipt evrakı ile satın aldığımız tüm malzemelere ait bilgileri kaydediyoruz. Ama biz elimizde kalan adaptör sayısını nasıl hesaplayabiliriz, düşünelim? Özetle şimdiye kadar aldığımız bütün adaptörlerin toplamına ihtiyacımız var (GoodsReceipt evrakı ve bu evrakın tablo sekmesindeki satırlar), hizmet için kullandığımız tüm adaptörler (Services evrakı ve bu evrakın tablo sekmesindeki satırlar) ve daha sonra birinci evraktakilerden ikinci evraktakiler çıkarılır. Bu bir sürü iş gibi kulağa geliyor ve en kötüsü hesaplama daha fazla zaman alacak – biz sisteme yeni bir evrak ekleyelim.
Her malzeme için mevcut bakiye bilgisi saklamak için başka bir yere ihtiyacımız var. Böylece Services evrakı doldurulma anında biz bakiye kontrolü yapabiliriz.
1C: Enterprise bu amaç için özel olarak uygulanan metadata nesnelerini destekler – birikim kayıtları.
Birikim kayıt temelleri
Bu soruya hızlı bir cevap vermek gerektiğinde “birikim kayıtları” cevabını verebiliriz: “kaç tane malzeme var”.
Birikim kayıtları ikincil verileri saklar, yani hiç yeni bilgi yok – hepsini önceden biliyoruz, kaydı sadece başka bir form içinde saklar – bu birincil veri kullanarak hesaplama yapmaktan daha uygundur.
Birikim kayıtlarına kullanıcılar direkt ekleme yapamaz. Genellikle, bir kullanıcı evrak kaydettiğinde otomatik olarak doldurulur. Nasıl çalıştığını görelim:
Yukarıdaki resimde gördüğünüz gibi, bu birikim kaydı boyutlar (depo ve malzeme) arasında kaynakları özetliyor (miktar sütunu). SQL’e aşina olanlar için, bu işlem aşağıdaki gibi teslim edilebilir:
SELECT SUM(Quantity) FROM
Birikim kayıt boyutları
Birikim kayıtları temelde boyutlara göre nasıl dilimlendi, diğer bir deyişle – kaç tane birikim kaydı var. Boyutlar genellikle CatalogRef türünde olsa da herhangi bir türde olabilir.
Birikim kayıt kaynakları bakiye tablosunu özetler. Kaynaklar sadece “Number” türünde olabilir, ancak Number sayısal olan her şeyi temsil edebilir: miktar, ağırlık, uzunluk, hacim ve daha fazlası.
Hiç boyut kullanmayabiliriz. Bu durumda, bakiye kayıt tablosu sadece bir kayıt içerir. Bu satır tüm depolar ve tüm malzemeler üzerinde tüm kaynakları özetler, yani tüm depolarda tüm malzemelerin toplam tutarını alır:
Biz sadece Depo (Warehouse) boyutu eklediğimizde, birikim kayıt kaynakları ikiye bölecektir:
Veya sadece Malzeme (Materials) boyutu oluşturulduğunda kaynaklar üçe bölünecektir:
Belli ki, tüm tabloların bizim ihtiyacımıza uygun bir değeri yok. Yani boyutları doğru kullanmadığımızda kayıtlar o kadarda anlamlı olmuyor. Diğer yandan tüm depolar için toplam malzeme sayısını işimize yarayabilir. (Sadece Malzeme boyutu olduğunda) ve her depo için her malzemenin kaydını tutmak bakiye kaydı için gayet anlamlı (iki boyut).
Peki, boyutların yapısını nasıl seçebiliriz?
1C:Enterprise Ders 2-3
Birikim kayıt boyutları seçimi
Hizmet belgesi doldururken, tablo sekmesindeki her satır için depoda yeterli malzeme olup olmadığını kontrol etmeliyiz. Bunu yapmak için her bir depo için bakiye sorgusu çalıştırmamız gerekiyor – malzeme çifti. Biz “WHERE” koşulu altında iki tane öznitelik için koşul kullanmalıyız. Bu sorgu tek satır varsa koşulu en hızlı biçimde yürütür.
Yani, en iyi sonucu almak için, “WHERE” ifadesi içindeki her koşul için bir boyut olmalı. Veya (bir başka açıdan) tüm boyutlar için “WHERE” ifadesini kullanmalıyız.
Şimdi bakiye kontrolü yapılması için kullanılacak depo ve malzeme için boyut ayarlarını kontrol edelim:
Unutmayın, Platform’un bakiyeyi doğru bulabilmesi için boyutlar ne olursa olsun doğru seçilmelidir, ama bu sonuç almak için gerekli olacak süreyi önemli ölçüde değiştirebilir. Biz birkaç boyut kullandığımız da (yukarıdaki tabloda 5.satırdaki) Platform “WHERE” koşuluna uygun olan kayıtları toplayarak özetleyecek ve bize sunacaktır. Ama yukarıdaki tablodaki 1-3 satırlara uygun hiçbir kayıt yoksa ne olur? Bu durumda, Platform kaydedilen tüm evraklar için tüm tablo sekmelerinin tam kopyasını saklayan bir tablo kullanır.
Bu tabloya “Ana tablo (Main table)” denir ve bu tablo kaynakları boyutlarına göre gruplandırılmış Bakiye tablosundan farklıdır. Resim olarak yeni bir tablo gönderdiğimizde, kayıt işlemi şöyle olacaktır:
Önemli bir fark daha Ana tablo ve Bakiye tablosunun okuma ve yazılması hakkında önemli farklılık vardır, oysa Bakiye tablosu hiçbir şekilde düzenlenemez (ama tabii okunabilir). Sadece Platform Bakiye tablosunu düzenleyebilir. Biz direk olarak değişiklik yapamayız – ancak Ana tabloyu değiştirerek yapabiliriz.
Tamam, şimdi bizim kaydedicimizi oluşturalım.
Birikim kaydedici oluşturma
Süreç oldukça basittir. Sadece boyutlar ve kaynakların türlerinin doğru seçildiğinden emin olun:
- – Malzeme (Material): CatalogRef.MaterialsAndServices
- – Depo (Warehouse): CatalogRef.Warehouses
- – Miktar (Quantity): Number (10, 2)
Not, biz şu an “Bakiyeler” için kaydedici oluşturduk. Burada bir diğer kayıt türü de “Turnovers” vardır. Bu kayıt türü farklı çalışır ve daha sonra değineceğiz
Kart listeleri hiyerarşiyi destekler, yani kart listesi içindeki öğeleri klasörler içinde düzenli bir biçimde saklayabiliriz. Böylece malzeme ve hizmetleri birbirinden ayırmış oluruz.
Şimdi, Evraktaki ikinci tablo sekmesinden kurtulup Satış evrakının yapısını düzenlersek:
Birikim kayıtlarının öznitelikleri
Her metadata nesne gibi, birikim kayıtlarının öznitelikleri de herhangi bir sayıda olabilir. Örneğin, BalanceOfMaterials birikim kaydındaki her malzeme için fiyatları depolamak isteyebiliriz.
Bu öznitelik AR Ana tablosunda kullanılabilir olacak ama AR Bakiye tablosunda kullanılabilir olmayacaktır. Bakiye tablosu boyutlar ve kaynakları depolar, yani öznitelikler Bakiye tablosunda hiçbir anlam ifade etmeyecektir.
Basit bir örnek üzerinde düşünelim. AR’ye iki kayıt ekleyelim:
Bakiye tablosu içinde bir kayıt için miktar toplanmış olacak (Miktar = 10 + 20 = 30). Ama bu 30 malzemenin fiyatı ne kadar? Biz şu an bunu bilmiyoruz. Bazıları 12 dolar, diğerleri- 10,5 dolar. Diğer bir deyişle, toplam değerleri için fiyat tanımsızdır.
Bu nedenle, Sorgu Oluşturucu’da kullanılabilir alanlar listesinde toplamları görmek ve Sanal Bakiye tablosundan seçmek mümkün olmayacaktır.
Yani, Her AR Ana tablo kaydı için ek bilgiler kaydetmek için öznitelikler kullanılır. Bu bilgiler Bakiye tablosunda mevcut değildir.
GoodsReceipt evrakının kaydedilmesi
Evrak formunda benzer bazı butonlar olduğunu görmüşsünüzdür: “Save”, “Post” ve “Post and close”:
“Save” butonu evrakı sadece infobase’e kaydeder. “Post” butonu ise evrakı hem infobase’e kaydeder ve aynı zamanda AR kayıtları için olay işleyicilerini çalıştırır. Yani “Post” butonu, ilgili evrakı kaydetmek ve bu evrak ile ilgili kayıtları doldurmak anlamına gelir.
Yani, kullanıcı evrakı doldurmaktan çıkmak için Save butonuna basar (sadece mevcut durumu korumak için) ve evrak tamamen hazır olduğunda Post butonuna basar.
Unutmayın, evrak kaydedilirken kaydediciye herhangi bir sayı gönderebilir. Örneğin, evrakın birkaç tablo sekmesi olabiliyor ve kayıt içine her bir tablo sekmesinden öğe gönderebilir. Ya da birden fazla kayıt için bir tablodaki bilgiler gönderilmek istenebilir, bunların her biri belirli bir görev için kendi yapısına en uygun olandır.
Platform evraktaki tablo sekmesindeki satırları kaydediciye nasıl gönderir, görelim.
Hareket Yapılandırıcı tarafından oluşturulan koda daha yakından göz atalım.
Procedure Posting(Cancel, Mode)
//{{__REGISTER_REGISTERRECORDS_WIZARD
// This fragment was built by the wizard.
// Warning! All manually made changes will be lost next time you use the wizard.
// register BalanceOfMaterials Receipt
RegisterRecords.BalanceOfMaterials.Write = True;
For Each CurRowMaterials In Materials Do
Record = RegisterRecords.BalanceOfMaterials.Add();
Record.RecordType = AccumulationRecordType.Receipt;
Record.Period = Date;
Record.Material = CurRowMaterials.Material;
Record.Warehouse = Warehouse;
Record.Quantity = CurRowMaterials.Quantity;
EndDo;
//}}__REGISTER_REGISTERRECORDS_WIZARD
EndProcedure
Not; AR tablolarının doğrudan yazılmaya açık olmadığını unutmayın. Bu yüzden, bu kod şu satırı içerir:
RegisterRecords.BalanceOfMaterials.Write = True;
Bunun anlamı, Platform, GoodsReceipt evrakındaki kayıtları BalanceOfMaterials AR’sine kaydetmesi için izin verilmesidir (şu onay kutusu seçili olan),
Platform bu nesne yapısına evrakı bellekte kaydetti.
Eğer RegisterRecords.BalanceOfMaterials. Write’i True olarak ayarladıysak evrak kaydedilirken her şey BalanceOfMaterials AR’sine yazılır. Bu yüzden malzeme tablo sekmesini kayıtlar ile doldurmamız gerekiyor, ama kayıt için açıkça yazmaya gerek yoktur (bunu yapabiliyor olmamıza rağmen) – Platform bununla ilgilenir.
Sonra kodun malzeme tablo sekmesi döngüsü:
For Each CurRowMaterials In Materials Do
Bu döngü içinde, kod yeni kayıt oluşturmak içinBalanceOfMaterials AR kayıt setine neler yazılacağını sorar (nesne modülü içinde olduğumuz için ThisObject kodunu yazmayabiliriz):
Record = RegisterRecords.BalanceOfMaterials.Add();
Sonra kayıt tablo sekmesinin satırlarındaki veriler ile doldurulur ve kayıt türü “RecordType” AccumulationRecordType.Receipt olarak ayarlanır. Bunun anlamı bu verilerin bakiyelere eklenecek (toplanacak) olduklarıdır.
1C:Enterprise Ders 2-4
Services evrakının kaydedilmesi
Services evrakı için aynı kaydetme prosedürünü hayata geçirelim. Bakiye tablosundaki malzeme bakiyelerinden çıkartmak için kayıt türünü (Expense) seçmeyi unutmayın.
Şimdi kaydetme olay işleyicisi uygulandığında neler olduğunu görelim, şu Services evrakını kaydedelim:
BalanceOfMaterials AR’si için Ana Tabloda elde ettiğimiz şey şu:
GoodsReceipt evrakının tüm malzemeleri Bakiye tablosuna eklenecektir, Services evrakının tüm malzemeleri ise düşülecektir. BalanceOfMaterials AR’sinin Bakiye tablosunda ne göreceğiz bakalım:
Ana depomuzda 25 (+ 10 + 20- 5) tane uzatma kablosu (extension cords) ve 47 (+ 50- 3) tane PVC boru (PVC pipes) kalmış.
Malzeme ve hizmet farklılaştırılması
Dikkate alınması gereken birkaç şey daha var:
- – GoodsReceipt evrakının tablo sekmesi doldurulurken, kullanıcı malzeme yerine hizmet ekleyebilir. Bu kesinlikle herhangi bir anlam ifade etmiyor ve biz bunu engellemeliyiz.
- – Services evrakları sadece malzeme değil bazen de hizmet içerir. Ama biz Hizmetler için Bakiye tablosu kaydetmek istemiyoruz. Yani böyle bir şey yok.
Oysa biz bu kart listesi birleştirme dersini daha önce gördük, şimdi olumsuzlukları görebiliriz – bazı durumları farklı şekilde tedavi etmek bir zorunluluk olabiliyor. Hadi, bunu şimdi yapalım.
Her şeyden önce bizim bir malzemeyi kullanmak için gerekli olan servisin ne olduğunu öğrenmemiz gerekiyor. MaterialsAndServices kart listesi için oluşturduğumuz hiyerarşi yapısı burada bize yardım etmeyecek, çünkü kaynak kod veri bilgisine temel olamaz (kullanıcı veriyi değiştirdiğinde, kodun çalışmaması).
Yani, MaterialsAndServices kart listesi öğelerini malzeme veya hizmet olarak işaretlememiz gerekiyor. Diğer bir deyişle, bu kart listesi için yeni bir öznitelik eklemek lazım. Ama bunun türü ne olmalı?
En iyi seçim Sayım (Enumeration).
Sayımlar (Enumerations)
Sayımlar, uygulama içinde tanımlanan değerlerin listesidir (infobase’de saklanan verilerin yerine). Sadece geliştiriciler Sayımları değiştirebilir, yani herhangi bir kaynak kod içinde kullanılması gereken ve değiştirilemez olan değerler listesi olarak düşünebiliriz. Sayımlar kullanılmak istediğinde:
- – Liste değerleri sabittir, yani kullanıcılar listedeki herhangi bir öğeyi silip düzenleyememesi veya yeni öğe ekleyememesi gerektiğinde;
- – Kaynak kodun seçilmiş farklı değerlere göre çalışması gerektiğinde;
Eğer listenizin yalnızca bir kısmı sabit olacaksa, kart listelerinin önceden tanımlı öğelerinde ekleyebilirsiniz. Böylece kullanıcılar yeni öğeler ekleyip silebilirler.
Sayımlar için birkaç örnek:
- – Cinsiyet:
- – Bay;
- – Bayan;
- – Araba gövde tipi:
- – Hatchback;
- – Sedan;
- – SUV;
- – …
- – Turist konaklama türleri:
- – Kamp parkı;
- – Butik otel;
- – B$B;
- – Hotel;
- – Resort;
- – …
Sayım oluşturma gayet açıktır. Bizim yeni bir sayım eklememiz ve şu iki değeri girmemiz gerekiyor: Malzeme (Material) ve Hizmet (Service):
Sonrasında, biz MaterialsAndServices kart listesinin her öğesi için Malzeme veya Hizmet olduğunu işaretlememiz gerekiyor. Bunu yapmak kart listesine yeni bir öznitelik eklemek gerekiyor:
Ve kart listesinin her öğesi için uygun türü belirtelim:
1C:Enterprise Ders 2-5
GoodsReceipt evrakına kullanıcıların hizmet eklemesini önleme
Bakalım, burada ne yapabiliriz.
GoodsReceipt evrakının Malzeme tablo sekmesine yeni bir hizmet satırı ekleyen kodun bir parçası:
&AtClient
Procedure AddAService(Command)
// Insert handler contents.
NewLine = Object.Materials.Add();
NewLine.Material = AddAServiceServer();
EndProcedure
&AtServer
Function AddAServiceServer()
Return(
Catalogs.MaterialsAndServices.FindByAttribute(
“MaterialOrService”,
Enums.MaterialOrService.Service)
);
EndFunction
GoodsReceipt nesne modülünde evrak kaydedilmeden önce tablo sekmesine hizmet olarak eklenen satır var mı diye kontrol yapan ve evrakın yazılmasını engelleyen bir parça kaynak kod:
Procedure BeforeWrite(Cancel, WriteMode, PostingMode)
For Each Material In Materials Do
If Material.Material.MaterialOrService = Enums.MaterialOrService.Service Then
Message(
“The document is not saved.
|You cannot use services in GoodsReceipt documents.
|Please, delete all services from the Materials tabular section.“
);
Cancel = True;
Return;
EndIf;
EndDo;
EndProcedure
Services evrakının BalanceOfMaterials AR’sine hizmet yazmasını önleme
Henüz çözülmemiş bir sorun olarak BalanceOfMaterials AR’sine Services evrakının Hizmet eklemesinin önlenmesi var. Bizim bunu engellememiz gerekir (çünkü hizmet bakiyesi diye bir şey yoktur).
Yazdırma Yapılandırıcı ile oluşturulan MaterialsAndServices tablo sekmesinin satırlarının BalanceOfMaterials AR’sine gönderildiği kod:
Procedure Posting(Cancel, Mode)
RegisterRecords.BalanceOfMaterials.Write = True;
For Each CurRowMaterialsAndServices In MaterialsAndServices Do
Record = RegisterRecords.BalanceOfMaterials.Add();
Record.RecordType = AccumulationRecordType.Expense;
Record.Period = Date;
Record.Material = CurRowMaterialsAndServices.MaterialOrService;
Record.Warehouse = Warehouse;
Record.Quantity = CurRowMaterialsAndServices.Quantity;
EndDo;
EndProcedure
Bizim döngü içinde her CurRowMaterialsAndServices verisi için MaterialOrService özniteliğinin Enums.MaterialOrService. Service eşit olmadığını kontrol etmemiz ve eğer eşit ise Continue komutu ile o veriyi AR’ye göndermeden atlamamız gerekiyor:
Procedure Posting(Cancel, Mode)
RegisterRecords.BalanceOfMaterials.Write = True;
For Each CurRowMaterialsAndServices In MaterialsAndServices Do
If CurRowMaterialsAndServices.MaterialOrService.MaterialOrService =
Enums.MaterialOrService.Service Then
Continue;
EndIf;
Record = RegisterRecords.BalanceOfMaterials.Add();
Record.RecordType = AccumulationRecordType.Expense;
Record.Period = Date;
Record.Material = CurRowMaterialsAndServices.MaterialOrService;
Record.Warehouse = Warehouse;
Record.Quantity = CurRowMaterialsAndServices.Quantity;
EndDo;
EndProcedure
Continue komutu her çalıştığında döngünün bir sonraki elemanına atlatacaktır, yani tüm satırlar için işlem yapılmayacaktır.
Bakiye kontrol
Az öncede belirttiğimiz gibi, siparişi tamamlamak için depoda yeterli malzeme olduğunu kontrol etmeliyiz (Services evrakının kaydedilmesi). Basitçe, biz bunu üç yolla yapabiliriz: biz bunu tablo sekmesini birikim kaydına yazmadan önce veya sonra kontrol edebiliriz. İkinci yolu kullanmanızı tavsiye ederiz. Çünkü bu yolun çoğu durumda daha etkili olduğu kanıtlanmıştır.
Bizim şimdi bir kayıt içine veri yazmaya ve negatif bakiye olup olmadığını kontrol etmeye ihtiyacımız var.
Eğer Services evrakının Kaydetme Olay işleyicisinin kaynak koduna göz atarsanız, birikim kaydına ait açık bir kod bulamazsınız. Kod AR kayıtlarını doldurur ancak asla Infobase içine yazmaz. Bunun yerine, Platform’a otomatik olarak yazmasını söyleyen bir satır vardır:
RegisterRecords.BalanceOfMaterials.Write = True;
Bunun anlamı, Platform evrakın Kaydedilmesi olay işleyicisinden **sonra** bu kodu yürütmesidir, bu yüzden bakiye kontrolü kodunu koymak için bir yer yoktur. Ama burada basit bir ipucu: eğer biz birikim kayıt kayıtlarını açıkça yazarsak, Platform onları zaten yazılmış olarak görür ve bir kez daha yazmaz.
Sonuç olarak olay işleyici kodu şöyle ortaya çıkar:
Procedure Posting(Cancel, Mode)
// 1. Filling out BalanceOfMaterials recordset
RegisterRecords.BalanceOfMaterials.Write = True;
For Each CurRowMaterialsAndServices In MaterialsAndServices Do
If CurRowMaterialsAndServices.MaterialOrService.MaterialOrService =
Enums.MaterialOrService.Service Then
Continue;
EndIf;
Record = RegisterRecords.BalanceOfMaterials.Add();
Record.RecordType = AccumulationRecordType.Expense;
Record.Period = Date;
Record.Material = CurRowMaterialsAndServices.MaterialOrService;
Record.Warehouse = Warehouse;
Record.Quantity = CurRowMaterialsAndServices.Quantity;
EndDo;
//2. Writing down BalanceOfMaterials recordset
RegisterRecords.BalanceOfMaterials.LockForUpdate = True;
RegisterRecords.Write();
//3. Checking if there any negative balance records
Query = New Query;
Query.Text =
“SELECT
| BalanceOfMaterialsBalance.Material AS Material,
| BalanceOfMaterialsBalance.Warehouse AS Warehouse,
| BalanceOfMaterialsBalance.QuantityBalance AS QuantityBalance
|FROM
| AccumulationRegister.BalanceOfMaterials.Balance AS BalanceOfMaterialsBalance
|WHERE
| BalanceOfMaterialsBalance.QuantityBalance < 0″;
QueryResult = Query.Execute();
SelectionDetailRecords = QueryResult.Select();
// 4. If the result is not empty, cancel the document’s posting
If SelectionDetailRecords.Count() = 0 Then
Return;
EndIf;
Cancel = True;
//5. divpare the error message and display it.
MessageText =
“There is not enough materials on the “ +
ThisObject.Warehouse.Description +
“. See the list of deficits below:” +
MessageText;
While SelectionDetailRecords.Next() Do
MessageText =
MessageText + Chars.CR + Chars.LF +
SelectionDetailRecords.Material.Description + “: “ +
SelectionDetailRecords.QuantityBalance;
EndDo;
Message(MessageText);
EndProcedure
Nasıl çalıştığına bir göz atalım.
- BalanceOfMaterials kayıtları doldurulur
Kodun bir kısmı Gönderme prosedürünün önceki versiyonundan gelmektedir. BalanceOfMaterials kayıtlarını MaterialsAndServices tablo sekmesi içeriği ile doldurur, hizmetleri atlayarak.
- BalanceOfMaterials kayıtları yazılır (kaydetmek)
İlk satırda bunları Infobase’e yazarken verileri kilitler. Bu ayarın ayrıntılı olarak açıklanması bu dersin kapsamı dışındadır, bu yüzden sadece şunu hatırlayın: her zaman kayıt yazıldıktan sonra bakiye kontrolü yapmak istiyorsanız, bu seçeneği kullanmalısınız. Aksi takdirde, kullanıcılar kilitlenme ve hata mesajları almaya başlayabilir, özellikle de sistem ağır iş yükü altında çalışırken.
İkinci satır açıkça tüm kayıtları yazılacağını söyler. Bizim uygulamamızda sadece BalanceOfMaterials birikim kayıtlarına kaydedilir. Açıkça kayıtları yazdıktan sonra, Platform bunu otomatik olarak tekrarlamayacaktır.
- Herhangi bir negatif bakiye olup olmadığını kontrol etmek
Eğer bizim Services evrakımız depoda bulunandan daha çok malzeme miktarı içeriyorsa Bakiye Tablosunda negatif bakiye elde edeceğiz. Bu sorgu, bu kayıtları alır. Unutmayın, biz Services evrakının tablo sekmesindeki tüm kayıtlar için bakiye tablosunu negatif değerlere bakmaksızın okuyoruz. Biz Services evrakının tablo sekmesinde kullandığımız malzemeler için kısıtlama yapacak koşulu nasıl ekleyebiliriz? Bu konu bir sonraki dersimizde kesinlikle başlayacağımız bir konudur.
- Sonuç kümesi boş olmadığında, evrak kaydının durdurulması
Eğer sorgu hiçbir kayıt döndürmezse, negatif olan hiçbir bakiye kaydı yoktur. Bu durumda prosedürü yürütmeye ihtiyacımız yok ve sadece prosedürden çıkış yaparız.
Eğer sorgu en az bir kayıt döndürürse, biz evrak kaydını durdururuz, çünkü en az bir malzeme depomuzda kalmamıştır. Yani Cancel parametresini True olarak ayarlarız. Prosedür yürütülmeye devam edecek, ancak iş bittikten sonra Platform evrak kaydını durduracak ve kullanıcıya hata mesajı gösterecektir.
Eğer biz Cancel parametresini True yapacaksak, burada önemli bir şey var, tüm veri değişiklikleri geri alınır ve Infobase evrak gönderilmeden önceki haline geri dönecektir. Diğer bir deyişle, evrak kaydedilmeyecek, hiç tablo kaydı yapılmayacaktır (örneğin; birikim kayıt) – hiçbir şey. Infobase’e tekrardan bu evrak hiç yokmuş gibi bakacağız
Bu işlemi geri almaya “temizlik” denir ve otomatik olarak Platform ve DBMS tarafından yapılır. Hareketleri ve davranışları bu dersin kapsama alanı dışındadır. Şimdi şunları göz önünde tutmalıyız:
- – Bazı olay işleyicileri Cancel parametresine sahiptir;
- – Eğer eyleme devam etmek istemiyorsanız, bu parametreyi True olarak ayarlamanız gerekiyor (çünkü burada yanlış bir şey olduğunu bulduk);
- – Cancel parametresi True olarak ayarlandıktan sonra, geçerli prosedür yürütülmeye devam eder;
- – Prosedürün yürütülmesi tamamlandıktan sonra, Platform geçerli eylemi durdurur ve bu eylem sırasında yapılan tüm veri değişiklikleri geri alınır.
- – Bundan sonra, Platform kullanıcıya bir hata mesajı gösterecektir.
- Hata mesajı oluşturulur ve görüntülenir
Burada, bazı negatif bakiyesi olan kayıtlar vardır. Bu yüzden kullanıcıyı bildirmemiz lazım. Kodun parçası gösterilecek mesajı oluşturur ve görüntüler.
Nasıl çalıştığını görelim.