Cuma, Eylül 21, 2012

Ödeme Ekranı - Para Üstü Seçimi

Selamlar. Alt.Net google grubunda açtığım ve SambaPOS projesini nasıl daha iyi değerlendirebileceğimi sorduğum bir konuda gelen öneriler neticesinde bazı SambaPOS özelliklerini kodlarken ya da refactoring yaparken yaptıklarımı bloglama gibi bir fikir gündeme geldi. Çok düşündüm ve biryerlerden başlamak adına sıradaki işimi kayda alarak yapmaya karar verdim. Şimdi bir SambaPOS özelliğini hem kodlayacak hem de anlık olarak yaptıklarımı bloga yazacağım.

Buna “Live Development” adını veriyorum. Canlı canlı kodlama yapacağız yani :) Aslında bir anlamda pair programlama yapmış da oluyorum :) Yer yer kısa açıklamalara da yer vererek kullandığım teknolojiler hakkında da bilgiler vermiş olacağım. Belki projenin dökümantasyon eksiğini kapatmak anlamında bir faydası olur.

Burası programın ödeme almak için kullanılan ekranı. Gerekli para birimi, kur, hesap ve para üzeri hesaplama ayarlarını yaptığımız zaman program sol alt kısımda göründüğü gibi belge toplamını çeşitli para birimlerinde hesaplayarak gösteriyor. Eğer müşteri ödemeyi TL olarak değil de Dolar ya da Euro olarak yapmak istiyorsa kullanıcı bu butonlardan birine basarak ödemeyi farklı para birimlerinden alabiliyor. 

Ancak burada şöyle bir durum var. Hesap 17,40 dolar ve müşteri muhtemelen 20 dolar verip para üzeri isteyecek. Müşteriler duruma göre para üstünü dolar ya da TL olarak isteyebiliyor. Bu nedenle tahsilatın hangi para biriminden yapıldığını seçtiğimiz gibi para üstünün de hangi para biriminden yapıldığını seçebilmemiz gerekiyor. 

Bu hesapları yapmak ve ilgili tutarları ilgili kasa hesaplarına aktarmak ile ilgili özellikler zaten yapılmış durumda. Bugünkü işimiz kullanıcının para üstünü hangi para biriminden vereceğini seçebilmesini sağlamak.

Normalde 31.50 hesap varken 50 tuşuna ve Cash tuşuna bastığımız zaman bu 50 Nakit anlamına gelir ve program otomatik olarak para üstünü şekildeki gibi gösterir. Burada direk olarak para üstünü göstermek yerine hangi para biriminden para üstü verdiğimizi seçebilmemiz gerekiyor. 

Öncelikle ödemeyi işlediğimiz kod parçasını inceleyelim.

Seçilen nakit, kredi kartı gibi ödeme tipi PaymentTemplate parametresi olarak fonksiyona geliyor. Ne kadar tahsil edilmesi gerektiğini ve ne kadar tahsil edildiğini GetPaymentValue() ve GetTenderedValue() fonksiyonları ile alıyoruz. Bir yuvarlama işleminden sonra SubmitPaymentAmount() ile ödemeyi kayıt ediyoruz. Bu fonksiyon kullanılan para üstü şablonunu da döndürüyor ve görüntüleyeceğimiz para üstünün para birimini ve kurunu alabilmek için bu değeri DisplayReturningAmount() fonksiyonuna geçiyoruz. Böylece işlem tamamlanmış oluyor. 

Para üstü şablonu (ChangePaymentTemplate) kullanıcının para üstünün hangi para biriminden verilebileceğini belirlemek için yaptığı tanımlar. Yani Dolar ve Euro para üstü vermek isteniyorsa iki tane para üstü şablonu tanımlanacak ve işlem sırasında kullanıcıdan bir tanesini seçmesi istenecek. Şu anki durumda sadece bir para üstü şablonuna izin verildiği ve şablonun tanımlanmış ya da tanımlanmamış olmasına göre işlem yapıldığı için bu SubmitPaymentAmount() fonksiyonundan sonuç olarak dönüyor. Bu nokta problemli çünkü eğer şablon sayısı birden fazlaysa bunu kullanıcıya seçtirmek gerek. 

Kodu şöyle değiştirdim.


Öncelikle fonksiyonun Para Üstünü görüntüleyen kısmını SubmitPaymentAmount() fonksiyonuna taşıdık. GetChangePaymentTemplates() fonksiyonunu ise buraya alarak tanımlanmış tüm para üstü şablonlarını döndürecek şekilde düzenledik. Son olarak da eğer şablon sayısı birden faza ise ChangeTemplates kolleksiyonunu oluşturarak görüntüleyeceğimiz para üstü düğmeleri için gerekli veriyi hazırlıyoruz ve IsChangeOptionsVisible değişkenini true yaparak düğmelerin görüntülenmesini sağlayacağız.

Burada ChangeTemplates kolleksiyonu hakkında kısa bir bilgi verebiliriz. CommandButtonViewModel bir düğme için gerekli veriyi tutan bir jenerik sınıfımız. Düğme başlığını, düğmeye tıklantığında çalışacak ICommand implementasyonunu ve ICommand'a geçilecek parametreyi tutuyor. 

ICommand arabirimini gerçekleyen sınıflar WPF'de düğme gibi Command özelliği içeren kontrollere direk olarak bağlanabilirler. ViewModel e Command olarak tanımladığımız _selectChangePaymentTemplateCommand sınıfının yapılandırılması şöyle.


Çalıştırıldığında OnSelectChangePaymentTemplate() fonksiyonuna Parameter olarak belirlediğimiz PaymetData nesnesini parametre olarak geçerek çalıştıracak. PaymentData o anki tahsilat değerlerini OnChangePaymentTemplate fonksiyonuna geçmek için tanımladığımız bir sınıf. 

Bir para üstü seçildiğinde SubmitPaymentAmount() seçilen para üstü şablonu ve diğer tahsilat verilerini alarak çalışacak.

Kod kısmında yapacaklarımız bu kadar.

Şimdi Para Üstü seçimi düğmelerinin görüntülenmesini sağlayacağız. 

Bu XAML kodu ChangeTemplates kolleksiyonuna bind edilmiş bir ItemsControl kontrolü tanımlar. ChangeTemplates kolleksiyonu tanımlı para üstü şablonlarını içeriyordu. ItemsControl ise kolleksiyon tipinde veriye bağlanan bir kontroldür.

ItemsControl.ItemTemplate bölümünde kolleksiyonun her bir elemanı için olşturulacak kontrolü ve veri bağlantısını tanımlıyoruz. Burada her bir şablon için bir FlexButton yaratılacak ve her bir FlexButton ChangeTemplates kolleksiyonunun içerdiği her bir CommandButtonViewModel nesnesinin özelliklerine bağlanacak (bind). 

ItemsControl.ItemsPanel bölümündeki tanımlama ise oluşan düğmelerin tek bir satırda mevcut alana sığdıracak bir UniformGrid içine ekleneceğini belirliyor. 

En dışarıda ise görünüp görünmediği IsChangeOptionsVisible özelliğine bağlı bir Border var. Bir ağaç yapısı şeklinde. En dışta bir Border, içinde bir ItemsControl ve ItemsControl'e bağlı kolleksiyonun (ChangeTemplates) her bir elemanı için bir FlexButton oluşacak. Border'ı gizlediğimizde içerideki düğmeleri de gizlemiş olacağız.

Sonuç olarak Dolar tahsilatina geçip 4,97 tutarındaki belge için 5 dolarlık bir tahsilat yaptığımızda para üstünün hangi para biriminden verileceği aşağıdaki gibi sorulmuş oluyor.


Burada Dollar Change ya da EuroChange seçeneklerinden birini seçerek para üstünün hangi para biriminden verildiğini belirlemiş oluyoruz.

Tabii para üstü şablonu isimlerini kullandığımız için Dollar Change gibi isimler görüyoruz. Buna göre direk olarak para üstünün ne kadar olduğunu göstermemiz biraz daha pratiklik sağlayacaktır. Bunun için CommandButtonViewModel nesnesini oluşturduğumuz yerde Caption özelliğini para üstünü hesaplayarak atayabiliriz.

Kodumuzun son hali böyle. CommandButtonViewModel sınıfının Caption özelliğine para üstünü hesaplayarak yazıyoruz. Böylelikle kullanıcı ne kadar para üstü vermesi gerektiğini anlamış oluyor. 


Son iki satırda ekran kontrollerine bağladığımız özelliklerde değişiklikler olduğunu ve güncellenmesi gerektiğinden WPF'i haberdar ediyoruz :) Tabi kodu kısa tutmak için böyle yaptım. Normalde ChangeTemplates kolleksiyonunu ObservableCollection tipinde tanımlamak ve her seferinde yeni bir kolleksiyon oluşturmak yerine kolleksiyonu temizleyip yeniden oluşturmak gerek. Ayrıca IsChangeOptionsVisible özelliğinin güncellenmesini özelliğin set metodu içinde yapabiliriz.

Bu ufak değişiklikleri ve kodun son halini incelemek için https://github.com/emreeren/SambaPOS-3/blob/master/Samba.Modules.PaymentModule/PaymentEditorViewModel.cs adresini ziyaret edebilirsiniz.



















9 TL'lik satış 4.97 dolar ediyor. Müşteri 10 dolar veriyor ve para üstünü Euro istiyor. Sonuçta €4.29 para üstü vermemiz gerekiyor. Belgenin alt toplamından göreceğimiz gibi Dolar kasamıza 18,10 TL karşılığı dolar girmiş, Euro kasamızdan da 9,10 TL değerinde Euro çıkmış oluyor. Mükemmel!

Bu arada farkettim bu sınıf bayağı bir büyümüş. Ekran elemanlarını farklı UserController (View) içine
taşıyarak ilgili metodları farklı ViewModel sınıfları içine taşımanın zamanı yaklaşmış...

Başka bir Live Development yazısında görüşmek üzere.

Hiç yorum yok: