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)

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ı boyutla