- Konu sahibi
- #1
İptal edilen alış faturasıyla stoğu geri almak için ürünün mevcut miktarını doğrudan artırmak yerine, faturaya bağlı ters yönlü bir stok hareketi oluşturun. Alış faturası stok girişiyse iptal işleminde aynı ürün, miktar, depo ve birim maliyet bilgileriyle stok çıkışı yapılmalıdır. Fatura daha önce stok hareketi oluşturmadan iptal edildiyse ikinci kez hareket üretmeyin. İşlemi veritabanı işlemi içinde yürütürseniz fatura durumu, stok hareketi ve stok bakiyesi birlikte güncellenir; işlem yarıda kalırsa yalnızca fatura iptal edilmiş, stok ise eski durumda kalmış olmaz.
Alış faturası kaydedildiğinde tipik akış şöyledir: ürün stoğa girer, stok miktarı artar ve faturaya bağlı bir stok hareketi oluşur. Fatura daha sonra iptal edildiğinde bu girişin etkisi ortadan kaldırılmalıdır. Bu nedenle iptal hareketi, alış hareketinin karşılığı olarak stoktan çıkış yönünde kaydedilir.
Örneğin 10 adet ürün alış faturasıyla stoğa girdiyse stok miktarı 10 artar. Fatura iptal edildiğinde yapılacak işlem stok miktarını tekrar 10 azaltmaktır. Buradaki amaç faturayı silmek değil, oluşturduğu stok etkisini tersine çevirmektir.
Stok miktarını yalnızca ürün kartındaki miktar alanını değiştirerek düzeltmeyin. Böyle bir işlem mevcut stok hareketleriyle bakiye arasındaki ilişkiyi koparır; hangi faturanın stoğu değiştirdiği ve iptalin ne zaman yapıldığı izlenemez hâle gelir.
İptal kodu çalışmadan önce fatura için aşağıdaki bilgileri okuyun:
Stok hareketi varsa iptal sırasında yeni hareketin, mümkünse orijinal hareketin kimliğine bağlanması gerekir. Bunun için stok hareketi tablosunda örneğin
İşlemi kullanıcı arayüzünde tek bir “İptal” komutuyla başlatabilirsiniz; ancak sunucu veya veritabanı tarafında aşağıdaki sıranın korunması gerekir.
İptal edilecek alış miktarı mevcut stoktan büyükse iki farklı iş kuralı olabilir. Uygulama, stok eksiye düşmeye izin veriyorsa iptal tamamlanabilir ve negatif stok ayrıca raporlanabilir. Eksi stok yasaksa işlem durdurulmalı ve kullanıcıya ürünün bir kısmının satıldığı, başka depoya aktarıldığı veya manuel stok düzeltmesi yapıldığı açıkça gösterilmelidir.
Bu durumda faturayı sessizce iptal edip stok miktarını kısmen azaltmak doğru değildir. Kısmi düşüm, fatura ile stok hareketinin artık aynı işlemi temsil etmemesine yol açar. İşletme kuralınız kısmi iptale izin veriyorsa bu durum ayrı bir “kısmi iade” veya “kısmi iptal” süreci olarak modellenmelidir.
Aşağıdaki örnek, bileşen veya veritabanı kütüphanesinden bağımsız bir akışı göstermek için hazırlanmış varsayımsal Object Pascal kodudur.
İptal hareketinin miktarı negatif olarak saklanıyorsa alış iptalinde
Örnekteki
Gerçek uygulamada sorguların aynı transaction bağlantısı üzerinden çalıştığından emin olun. Fatura güncellemesi bir bağlantıda, stok hareketi başka bir bağlantıda çalışıyorsa dış transaction her iki işlemi korumayabilir. Ayrıca eş zamanlı iki kullanıcının aynı faturayı iptal etmesini önlemek için fatura satırlarını veya fatura kaydını kilitleyen veritabanı yaklaşımı kullanılmalıdır.
İşlem başarılı döndüğünde yalnızca ekranda “İptal edildi” mesajını göstermek yeterli değildir. Fatura durumunu, hareket sayısını ve bakiye değişimini ayrı ayrı kontrol edin. Aşağıdaki ayrım, karşılaşılan sonucun nasıl yorumlanacağını gösterir.
Tablodaki ilk satır, işlemin teknik olarak tamamlandığını gösterir; ancak bu durum faturanın muhasebe veya vergi kayıtları açısından tüm sonuçlarının düzeldiğini tek başına kanıtlamaz. Stok hareketi ile fatura iptali farklı modüllerde tutuluyorsa cari, muhasebe ve belge numarası bağlantıları da işletmenin kurallarına göre ayrıca ele alınmalıdır.
Kontrolde sorun çıkarsa destek kaydına yalnızca “stok düzelmedi” yazmayın. Fatura ID veya numarası, ürün ID, depo ID, fatura satırındaki miktar, önceki ve sonraki stok bakiyesi, oluşan hareketlerin ID değerleri, işlem zamanı ve kullanıcı bilgilerini birlikte iletin. İstenen işlem de açık olmalıdır: örneğin “Fatura iptal durumunda, kaynak faturaya bağlı tek bir ters stok hareketi oluşturulması ve bakiye ile hareket toplamının yeniden eşleştirilmesi.”
Sadece toplam miktarı azaltmak, her stok yapısında yeterli değildir. Ürünlerde seri numarası, lot, son kullanma tarihi veya depo bazlı maliyet tutuluyorsa iptal hareketi orijinal alış girişindeki aynı ayrıntılarla oluşturulmalıdır. Aksi hâlde toplam miktar doğru görünse bile belirli seri veya lot bakiyesi yanlış kalabilir.
Ağırlıklı ortalama maliyet kullanılıyorsa stok miktarının yanı sıra toplam stok maliyeti de ters hareketten etkilenir. FIFO veya parti bazlı maliyet kullanılıyorsa iptal hareketinin hangi alış katmanını tersine çevirdiği açıkça belirtilmelidir. Bu nedenle stok miktarı düzeldiği hâlde maliyet raporunun düzeldiği varsayılmamalıdır. Maliyet yönteminize göre stok değerinin de yeniden hesaplanması gerekir.
İptalden sonra ürünün bir bölümü satılmışsa, alış girişinin tamamını geri almak stokta negatif bakiye veya maliyet tutarsızlığı oluşturabilir. Böyle bir durumda doğrudan tam iptal yerine işletmenizin tanımladığı iade, kısmi iptal, sayım düzeltmesi ya da muhasebe düzeltme süreci uygulanmalıdır.
İptal işleminde stok neden azaltılır?
Alış faturası kaydedildiğinde tipik akış şöyledir: ürün stoğa girer, stok miktarı artar ve faturaya bağlı bir stok hareketi oluşur. Fatura daha sonra iptal edildiğinde bu girişin etkisi ortadan kaldırılmalıdır. Bu nedenle iptal hareketi, alış hareketinin karşılığı olarak stoktan çıkış yönünde kaydedilir.
Örneğin 10 adet ürün alış faturasıyla stoğa girdiyse stok miktarı 10 artar. Fatura iptal edildiğinde yapılacak işlem stok miktarını tekrar 10 azaltmaktır. Buradaki amaç faturayı silmek değil, oluşturduğu stok etkisini tersine çevirmektir.
Stok miktarını yalnızca ürün kartındaki miktar alanını değiştirerek düzeltmeyin. Böyle bir işlem mevcut stok hareketleriyle bakiye arasındaki ilişkiyi koparır; hangi faturanın stoğu değiştirdiği ve iptalin ne zaman yapıldığı izlenemez hâle gelir.
Önce faturanın mevcut durumunu kontrol edin
İptal kodu çalışmadan önce fatura için aşağıdaki bilgileri okuyun:
- Faturanın gerçekten alış faturası olup olmadığı.
- Faturanın daha önce iptal edilip edilmediği.
- Faturaya bağlı stok hareketinin oluşturulup oluşturulmadığı.
- Fatura satırlarının ürün, miktar, depo ve birim maliyet bilgileri.
- Faturadaki ürün miktarının mevcut stokta hâlâ bulunup bulunmadığı.
Stok hareketi varsa iptal sırasında yeni hareketin, mümkünse orijinal hareketin kimliğine bağlanması gerekir. Bunun için stok hareketi tablosunda örneğin
KaynakTipi, KaynakId veya TersHareketId gibi alanlar kullanılabilir. Alan adları uygulamanızın veri modeline göre değişir; önemli olan iptal hareketinin hangi faturaya ve hangi ilk stok girişine ait olduğunun kaybolmamasıdır.İptal akışını hangi sırayla uygulamalısınız?
İşlemi kullanıcı arayüzünde tek bir “İptal” komutuyla başlatabilirsiniz; ancak sunucu veya veritabanı tarafında aşağıdaki sıranın korunması gerekir.
- Faturanın kimliğini ve oturum açan kullanıcının işlem yetkisini doğrulayın.
- Faturanın durumunu okuyun. Durum zaten iptalse işlem yapmadan başarılı sonucu döndürün veya kullanıcıya faturanın daha önce iptal edildiğini bildirin.
- Fatura satırlarını ve bu satırlara bağlı stok girişlerini okuyun.
- İptal nedeniyle stoktan düşülecek miktarın geçerli olup olmadığını kontrol edin. Depo, ürün ve birim bilgileri orijinal hareketten alınmalıdır.
- Her fatura satırı için ters yönlü bir stok hareketi oluşturun.
- Stok bakiyesini, uygulamanızın tasarımına göre hareket toplamından yeniden hesaplayın veya güvenli bir güncelleme ile azaltın.
- Fatura durumunu “İptal” olarak değiştirin ve iptal tarihi, kullanıcı ve açıklama bilgilerini kaydedin.
- Tüm değişiklikleri aynı veritabanı işlemi içinde kesinleştirin.
- İşlem başarısız olursa değişiklikleri geri alın ve kullanıcıya fatura numarasıyla birlikte hata bilgisini gösterin.
Stokta yeterli miktar yoksa ne yapılmalı?
İptal edilecek alış miktarı mevcut stoktan büyükse iki farklı iş kuralı olabilir. Uygulama, stok eksiye düşmeye izin veriyorsa iptal tamamlanabilir ve negatif stok ayrıca raporlanabilir. Eksi stok yasaksa işlem durdurulmalı ve kullanıcıya ürünün bir kısmının satıldığı, başka depoya aktarıldığı veya manuel stok düzeltmesi yapıldığı açıkça gösterilmelidir.
Bu durumda faturayı sessizce iptal edip stok miktarını kısmen azaltmak doğru değildir. Kısmi düşüm, fatura ile stok hareketinin artık aynı işlemi temsil etmemesine yol açar. İşletme kuralınız kısmi iptale izin veriyorsa bu durum ayrı bir “kısmi iade” veya “kısmi iptal” süreci olarak modellenmelidir.
Delphi’de transaction ile örnek uygulama
Aşağıdaki örnek, bileşen veya veritabanı kütüphanesinden bağımsız bir akışı göstermek için hazırlanmış varsayımsal Object Pascal kodudur.
Faturalar, FaturaSatirlari, StokHareketleri ve Stoklar tablo adları örnektir; kendi veri erişim katmanınızdaki sorgu ve parametre nesneleriyle uyarlamalısınız.İptal hareketinin miktarı negatif olarak saklanıyorsa alış iptalinde
-Miktar yazılır. Hareket yönü ayrı bir alanla tutuluyorsa miktarı pozitif bırakıp Cikis yönünü kaydetmek de mümkündür. Aynı kayıtta hem negatif miktar hem de çıkış yönünü yanlış yorumlayacak şekilde kullanmayın.
Kod:
procedure TFaturaService.AlisFaturasiniIptalEt(const AFaturaID: Integer);
var
FaturaDurumu: string;
UrunID, DepoID: Integer;
Miktar, BirimMaliyet: Currency;
begin
FDConnection1.StartTransaction;
try
FaturaDurumu := QryDurumOku(AFaturaID);
if SameText(FaturaDurumu, 'IPTAL') then
begin
FDConnection1.Commit;
Exit;
end;
if not SameText(FaturaDurumu, 'KAYITLI') then
raise Exception.Create('Bu fatura iptal edilebilecek durumda değil.');
QrySatirlar.Close;
QrySatirlar.ParamByName('FATURA_ID').AsInteger := AFaturaID;
QrySatirlar.Open;
while not QrySatirlar.Eof do
begin
UrunID := QrySatirlar.FieldByName('URUN_ID').AsInteger;
DepoID := QrySatirlar.FieldByName('DEPO_ID').AsInteger;
Miktar := QrySatirlar.FieldByName('MIKTAR').AsCurrency;
BirimMaliyet := QrySatirlar.FieldByName('BIRIM_MALIYET').AsCurrency;
if not StokHareketiVar(AFaturaID, UrunID, DepoID, 'ALIS') then
raise Exception.CreateFmt(
'Ürün için alış stok hareketi bulunamadı: %d', [UrunID]);
if TersHareketDahaOnceOlusturuldu(AFaturaID, UrunID, DepoID) then
raise Exception.CreateFmt(
'Ürün için iptal hareketi zaten mevcut: %d', [UrunID]);
StokHareketiEkle(
AFaturaID,
UrunID,
DepoID,
'CIKIS',
Miktar,
BirimMaliyet,
'Alış faturası iptali');
StokBakiyesiAzalt(UrunID, DepoID, Miktar);
QrySatirlar.Next;
end;
FaturaDurumunuGuncelle(AFaturaID, 'IPTAL');
FaturaLoguEkle(AFaturaID, 'Alış faturası iptal edildi');
FDConnection1.Commit;
except
FDConnection1.Rollback;
raise;
end;
end;
Örnekteki
StokHareketiVar ve TersHareketDahaOnceOlusturuldu kontrolleri önemlidir. Bunlar olmadan aynı faturanın düğmesine iki kez basılması veya ağ kopması sonrasında işlemin yeniden denenmesi, stoktan iki kez çıkış yapılmasına neden olabilir.Gerçek uygulamada sorguların aynı transaction bağlantısı üzerinden çalıştığından emin olun. Fatura güncellemesi bir bağlantıda, stok hareketi başka bir bağlantıda çalışıyorsa dış transaction her iki işlemi korumayabilir. Ayrıca eş zamanlı iki kullanıcının aynı faturayı iptal etmesini önlemek için fatura satırlarını veya fatura kaydını kilitleyen veritabanı yaklaşımı kullanılmalıdır.
İptalden sonra sonucu nasıl doğrulamalısınız?
İşlem başarılı döndüğünde yalnızca ekranda “İptal edildi” mesajını göstermek yeterli değildir. Fatura durumunu, hareket sayısını ve bakiye değişimini ayrı ayrı kontrol edin. Aşağıdaki ayrım, karşılaşılan sonucun nasıl yorumlanacağını gösterir.
| Görülen durum | Anlamı | Sonraki işlem |
|---|---|---|
| Fatura iptal, bir ters hareket var, stok beklenen miktarda azalmış | İptal akışı tamamlanmış görünüyor | İptal kullanıcısı, tarihi ve hareket bağlantısını denetim kaydında saklayın |
| Fatura iptal, ters hareket yok | Fatura durumu stok işleminden kopmuş olabilir | Faturayı tekrar otomatik iptal etmeyin; eksik hareketi ve transaction kayıtlarını inceleyin |
| İki veya daha fazla ters hareket var | İptal işlemi tekrarlanmış veya idempotency kontrolü yok | Fatura, hareket ve kullanıcı kayıtlarını karşılaştırıp düzeltme hareketini kontrollü oluşturun |
| Stok beklenenden fazla azalmış | Miktar birden fazla kez düşülmüş veya yanlış depo kullanılmış olabilir | Ürün, depo, miktar ve kaynak fatura bağlantısını kontrol edin |
| Stok eksiye düşmüş | İptal edilen miktarın tamamı mevcut stokta bulunmuyor olabilir | Satış, transfer, sayım ve önceki düzeltme hareketlerini inceleyin |
Kontrolde sorun çıkarsa destek kaydına yalnızca “stok düzelmedi” yazmayın. Fatura ID veya numarası, ürün ID, depo ID, fatura satırındaki miktar, önceki ve sonraki stok bakiyesi, oluşan hareketlerin ID değerleri, işlem zamanı ve kullanıcı bilgilerini birlikte iletin. İstenen işlem de açık olmalıdır: örneğin “Fatura iptal durumunda, kaynak faturaya bağlı tek bir ters stok hareketi oluşturulması ve bakiye ile hareket toplamının yeniden eşleştirilmesi.”
Maliyet ve seri-lot bilgilerini ihmal etmeyin
Sadece toplam miktarı azaltmak, her stok yapısında yeterli değildir. Ürünlerde seri numarası, lot, son kullanma tarihi veya depo bazlı maliyet tutuluyorsa iptal hareketi orijinal alış girişindeki aynı ayrıntılarla oluşturulmalıdır. Aksi hâlde toplam miktar doğru görünse bile belirli seri veya lot bakiyesi yanlış kalabilir.
Ağırlıklı ortalama maliyet kullanılıyorsa stok miktarının yanı sıra toplam stok maliyeti de ters hareketten etkilenir. FIFO veya parti bazlı maliyet kullanılıyorsa iptal hareketinin hangi alış katmanını tersine çevirdiği açıkça belirtilmelidir. Bu nedenle stok miktarı düzeldiği hâlde maliyet raporunun düzeldiği varsayılmamalıdır. Maliyet yönteminize göre stok değerinin de yeniden hesaplanması gerekir.
İptalden sonra ürünün bir bölümü satılmışsa, alış girişinin tamamını geri almak stokta negatif bakiye veya maliyet tutarsızlığı oluşturabilir. Böyle bir durumda doğrudan tam iptal yerine işletmenizin tanımladığı iade, kısmi iptal, sayım düzeltmesi ya da muhasebe düzeltme süreci uygulanmalıdır.