- Konu sahibi
- #1
Alış faturası kaydedildiğinde stok miktarını artırmanın güvenli yolu, fatura başlığı ve satırlarıyla birlikte stok güncellemesini aynı veritabanı işlemi içinde yapmaktır. Her fatura satırındaki miktarı ilgili stok kartına ekleyin; işlem başarılı olursa tamamını onaylayın, herhangi bir satırda hata oluşursa faturayı ve stok değişikliğini birlikte geri alın. Böylece fatura kaydedilmiş görünüp stokun eksik artması veya aynı faturanın ikinci kez stoğa eklenmesi önlenir.
Stok güncellemesini yalnızca kullanıcı arayüzündeki “Kaydet” düğmesinin sonunda yapmak yerine, fatura kaydetme işleminin parçası olan tek bir yordamda gerçekleştirin. Bu yordamın sırası genel olarak şöyledir:
Örnek olarak aşağıdaki alanların bulunduğu varsayılsın:
Bir satırda 12 adet ürün varsa stok güncellemesi kavramsal olarak şu işlemdir:
Bu sorgu, mevcut stok miktarını silip yeni değer yazmaz; mevcut değerin üzerine satır miktarını ekler. Örneğin mevcut miktar 40, fatura miktarı 12 ise sonuç 52 olur. Ancak bu sonuç yalnızca sorgunun bir kez ve doğru belge için çalıştırıldığını gösterir; faturanın muhasebe açısından doğru olduğunu veya ürün maliyetinin güncellendiğini tek başına kanıtlamaz.
Aşağıdaki örnek FireDAC kullanır. Tablo adları ve alanlar örnektir; kendi veritabanınızdaki adlarla değiştirilmelidir. Fatura satırlarının daha önce bellekte tutulduğu ve
Bu örnekte
Kullandığınız veritabanı
Sadece
Kullanıcı faturayı yeniden açıp tekrar kaydettiğinde yukarıdaki yordam doğrudan çağrılırsa stok ikinci kez artar. Bunun önüne geçmek için faturada stok hareketinin uygulanıp uygulanmadığını belirten bir alan tutabilir veya kaynak belge kimliğini stok hareketi tablosunda benzersiz yapabilirsiniz.
Örneğin mantık şu şekilde kurulabilir:
Fatura kaydedildikten sonra kontrolü yalnızca ekranda “kayıt başarılı” mesajı göstererek yapmayın. Fatura satırındaki miktarı, stok kartının önceki miktarını ve oluşan hareket kaydını birlikte karşılaştırın.
Örneğin stok miktarı 40 iken 12 adetlik alış faturası kaydedildiğinde beklenen yeni miktar 52'dir. Sonuç 40 ise stok güncelleme sorgusu çalışmamış veya yanlış stok kartını hedeflemiş olabilir. Sonuç 64 ise aynı fatura iki kez işlenmiş olma ihtimali vardır. Sonuç 52 olduğu hâlde hareket kaydı yoksa toplam miktar doğru görünür, fakat denetim izi eksiktir.
Tablodaki beklenen miktar kontrolü, yalnızca aritmetik bir doğrulamadır. Miktarın doğru çıkması; alış fiyatının, KDV bilgilerinin, depo bilgisinin veya seri-lot takibinin de doğru işlendiği anlamına gelmez. Bu alanlar kullanılıyorsa aynı fatura işlemi içinde ayrıca doğrulanmalı ve kaydedilmelidir.
Tek bir
Seri numaralı ürünlerde fatura miktarı 5 ise beş ayrı seri kaydı beklenebilir; lot takipli ürünlerde ise miktar lotlara dağıtılmalıdır. Bu bilgiler eksikse toplam stok artmış görünse bile hangi serinin veya lotun depoya girdiği belirlenemez. Dolayısıyla ana stok güncellemesinden önce ilgili takip bilgilerinin zorunlu olup olmadığını kontrol edin.
Stok artışı hangi aşamada yapılmalı?
Stok güncellemesini yalnızca kullanıcı arayüzündeki “Kaydet” düğmesinin sonunda yapmak yerine, fatura kaydetme işleminin parçası olan tek bir yordamda gerçekleştirin. Bu yordamın sırası genel olarak şöyledir:
- Fatura başlığını ve satırlarını doğrulayın.
- Veritabanı işlemini başlatın.
- Fatura başlığını kaydedin ve fatura numarasını alın.
- Fatura satırlarını kaydedin.
- Her satırın miktarını ilgili stok kartına ekleyin.
- Gerekliyse stok hareketi kaydı oluşturun.
- Bütün adımlar başarılıysa işlemi onaylayın; hata oluşursa geri alın.
Gerekli veri yapısı
Örnek olarak aşağıdaki alanların bulunduğu varsayılsın:
StocktablosundaIDveQuantityalanları bulunuyor.PurchaseInvoicetablosu fatura başlığını,PurchaseInvoiceLinetablosu fatura satırlarını tutuyor.- Fatura satırında
StockIDveQuantityalanları var. - Fatura türü alış faturası, belge durumu da kayda alınmış anlamına gelen bir değer taşıyor.
Bir satırda 12 adet ürün varsa stok güncellemesi kavramsal olarak şu işlemdir:
SQL:
UPDATE Stock
SET Quantity = Quantity + :Quantity
WHERE ID = :StockID
Bu sorgu, mevcut stok miktarını silip yeni değer yazmaz; mevcut değerin üzerine satır miktarını ekler. Örneğin mevcut miktar 40, fatura miktarı 12 ise sonuç 52 olur. Ancak bu sonuç yalnızca sorgunun bir kez ve doğru belge için çalıştırıldığını gösterir; faturanın muhasebe açısından doğru olduğunu veya ürün maliyetinin güncellendiğini tek başına kanıtlamaz.
Delphi’de transaction ile uygulama
Aşağıdaki örnek FireDAC kullanır. Tablo adları ve alanlar örnektir; kendi veritabanınızdaki adlarla değiştirilmelidir. Fatura satırlarının daha önce bellekte tutulduğu ve
ALines listesindeki her kaydın stok kartı ile miktarı içerdiği varsayılmıştır.
Kod:
type
TInvoiceLine = record
StockID: Integer;
Quantity: Double;
end;
procedure TInvoiceService.SavePurchaseInvoice(
const AInvoiceNo: string;
const ALines: TArray<TInvoiceLine>);
var
LInvoiceID: Integer;
LLine: TInvoiceLine;
Q: TFDQuery;
begin
if Length(ALines) = 0 then
raise Exception.Create('Fatura en az bir satır içermelidir.');
for LLine in ALines do
begin
if LLine.StockID <= 0 then
raise Exception.Create('Geçersiz stok kartı.');
if LLine.Quantity <= 0 then
raise Exception.Create('Stok miktarı sıfırdan büyük olmalıdır.');
end;
Q := TFDQuery.Create(nil);
try
Q.Connection := FDConnection1;
FDConnection1.StartTransaction;
try
Q.SQL.Text :=
'INSERT INTO PurchaseInvoice (InvoiceNo, InvoiceType, Status) ' +
'VALUES (:InvoiceNo, :InvoiceType, :Status) ' +
'RETURNING ID';
Q.ParamByName('InvoiceNo').AsString := AInvoiceNo;
Q.ParamByName('InvoiceType').AsString := 'PURCHASE';
Q.ParamByName('Status').AsString := 'POSTED';
Q.Open;
LInvoiceID := Q.FieldByName('ID').AsInteger;
Q.Close;
for LLine in ALines do
begin
Q.SQL.Text :=
'INSERT INTO PurchaseInvoiceLine ' +
'(InvoiceID, StockID, Quantity) ' +
'VALUES (:InvoiceID, :StockID, :Quantity)';
Q.ParamByName('InvoiceID').AsInteger := LInvoiceID;
Q.ParamByName('StockID').AsInteger := LLine.StockID;
Q.ParamByName('Quantity').AsFloat := LLine.Quantity;
Q.ExecSQL;
Q.SQL.Text :=
'UPDATE Stock ' +
'SET Quantity = Quantity + :Quantity ' +
'WHERE ID = :StockID';
Q.ParamByName('Quantity').AsFloat := LLine.Quantity;
Q.ParamByName('StockID').AsInteger := LLine.StockID;
Q.ExecSQL;
if Q.RowsAffected <> 1 then
raise Exception.CreateFmt(
'Stok kartı güncellenemedi. StokID: %d',
[LLine.StockID]);
end;
FDConnection1.Commit;
except
FDConnection1.Rollback;
raise;
end;
finally
Q.Free;
end;
end;
Bu örnekte
StartTransaction ile başlayan işlem, fatura başlığını, fatura satırlarını ve stok güncellemelerini kapsar. Commit yalnızca bütün satırlar başarıyla işlendiğinde çalışır. Örneğin üçüncü satırda stok kartı bulunamazsa Rollback çağrılır; önceki iki satırın stok artışı da faturanın kendisi de kalıcı olmaz.Kullandığınız veritabanı
RETURNING ID sözdizimini desteklemiyorsa fatura kimliğini veritabanınıza uygun yöntemle alın. Bu ayrıntı veritabanına göre değişir; fatura numarasını metin olarak kullanıp satırları ona bağlamak da mümkündür, ancak benzersiz bir sayısal kimlik kullanmak yanlış faturaya satır eklenmesi riskini azaltır.Stok hareketi kaydı neden ayrıca tutulmalı?
Sadece
Stock.Quantity alanını artırmak, güncel toplamı verir; fakat bu artışın hangi faturadan, hangi tarihte ve hangi miktarla geldiğini göstermez. ERP uygulamalarında genellikle stok hareketi tablosu da tutulur. Örnek bir hareket kaydında şu bilgiler bulunabilir:- Stok kartı kimliği
- Hareket türü: alış
- Miktar
- Kaynak belge türü ve kimliği
- Hareket tarihi
- Kullanıcı veya işlem yapan uygulama
Stock.Quantity güncellemek yerine hareket kaydı eklenip toplamın bu hareketlerden üretilmesi tercih edilebilir. Mevcut sisteminiz toplam miktarı stok kartında saklıyorsa iki yöntemi aynı işlem içinde uygulayın: hem stok miktarını güncelleyin hem de stok hareketini ekleyin. Biri başarılı, diğeri başarısız kalmamalıdır.Aynı faturanın iki kez stoğa eklenmesini önleme
Kullanıcı faturayı yeniden açıp tekrar kaydettiğinde yukarıdaki yordam doğrudan çağrılırsa stok ikinci kez artar. Bunun önüne geçmek için faturada stok hareketinin uygulanıp uygulanmadığını belirten bir alan tutabilir veya kaynak belge kimliğini stok hareketi tablosunda benzersiz yapabilirsiniz.
Örneğin mantık şu şekilde kurulabilir:
- Faturanın durumu taslaksa stok artırılmaz.
- Fatura ilk kez kayda alınıp kesinleştiriliyorsa stok artırılır ve belge durumu “işlendi” yapılır.
- Belge durumu zaten “işlendi” ise stok güncellemesi tekrar çalıştırılmaz.
- Fatura iptal ediliyorsa alış miktarı yeniden eklenmez; ters yönde bir stok hareketi oluşturulur.
Sonucu nasıl kontrol etmelisiniz?
Fatura kaydedildikten sonra kontrolü yalnızca ekranda “kayıt başarılı” mesajı göstererek yapmayın. Fatura satırındaki miktarı, stok kartının önceki miktarını ve oluşan hareket kaydını birlikte karşılaştırın.
Örneğin stok miktarı 40 iken 12 adetlik alış faturası kaydedildiğinde beklenen yeni miktar 52'dir. Sonuç 40 ise stok güncelleme sorgusu çalışmamış veya yanlış stok kartını hedeflemiş olabilir. Sonuç 64 ise aynı fatura iki kez işlenmiş olma ihtimali vardır. Sonuç 52 olduğu hâlde hareket kaydı yoksa toplam miktar doğru görünür, fakat denetim izi eksiktir.
| Görülen sonuç | Olası anlamı | İzlenecek yol |
|---|---|---|
| Stok beklenen miktar kadar arttı | Güncelleme bir kez başarılı olmuş olabilir | Fatura durumu ve stok hareketi kaydını da doğrulayın |
| Stok hiç artmadı | Kod çalışmamış, transaction geri alınmış veya yanlış StockID kullanılmış olabilir | Fatura satırındaki StockID, miktar ve işlem hata kaydını inceleyin |
| Stok iki kez arttı | Aynı belge yeniden işlenmiş olabilir | Belge durumu ile kaynak fatura kimliğine ait hareketleri kontrol edin; fazladan hareket için ters kayıt uygulayın |
| Fatura var, bazı satırlar yok | Transaction kullanılmamış veya kayıtlar farklı işlemlerde yapılmış olabilir | Fatura ve stok kayıtlarını tek transaction altında birleştirin |
Depo, seri ve lot takibi varsa
Tek bir
Stock.Quantity alanı, birden fazla depoya veya seri-lot takibine sahip sistemler için yeterli olmayabilir. Bu durumda stok miktarı ürün kartında değil, en azından ürün-depo veya ürün-lot düzeyinde tutulmalıdır. Alış faturasında depo seçilmişse miktarı genel stok alanına değil, seçilen depoya ait kayda ekleyin.Seri numaralı ürünlerde fatura miktarı 5 ise beş ayrı seri kaydı beklenebilir; lot takipli ürünlerde ise miktar lotlara dağıtılmalıdır. Bu bilgiler eksikse toplam stok artmış görünse bile hangi serinin veya lotun depoya girdiği belirlenemez. Dolayısıyla ana stok güncellemesinden önce ilgili takip bilgilerinin zorunlu olup olmadığını kontrol edin.
Uygulamada dikkat edilmesi gerekenler
- Miktar alanını
Integeryerine küsuratlı ürünler içinDoubleveya veritabanındaki uygun kesinlikte sayısal türle tutun. - Stok güncellemesini string birleştirmeyle değil, parametreli sorguyla yapın.
- Fatura başlığı, satırları, stok toplamı ve stok hareketini aynı transaction içine alın.
- Stok kartı bulunamazsa veya güncelleme beklenen satır sayısını etkilemezse işlemi hata kabul edin.
- Kesinleşmemiş, iptal edilmiş veya iade niteliğindeki belgelerin yönünü alış faturasıyla aynı kabul etmeyin.
- Faturayı tekrar kaydetme durumunda belge durumu veya benzersiz kaynak belge kontrolü kullanın.
Quantity = Quantity + fatura_miktarı güncellemesini transaction içinde çalıştırmaktır. ERP uygulamasında güvenilir çözüm ise buna fatura durumu, stok hareketi, tekrar işleme kontrolü ve gerekiyorsa depo-seri-lot ayrımını eklemektir.