dimesum

Ana sayfa / Blog / Para

Para

Çok para birimli giderlerde altı para hatası

· 8 dakika okuma ·

21 Ağustos 2026 tarihli bir denetim, testlerimizin yeşil geçtiği altı para birimi hatası buldu ve nedeni bir belgede sessizce doğruluğunu yitirmiş tek bir cümleydi.

Bir belgedeki güncelliğini yitirmiş tek bir cümle altı para hatasına mal oldu. Dimesum üzerinde 2026-08-21 tarihinde yapılan çok para birimli bir denetim, bunları test paketlerimizin yeşil geçtiği kodda buldu; bunların arasında ¥6,000 tutarındaki bir borcu -₹60.00 olarak gösteren bir talep sayfası da vardı. Cümle şuydu: "gruplar INR'ye sabitlidir". W7'ye kadar doğruydu, yayına alındığı anda yanlış oldu ve bir hafta sonra hâlâ FOLLOWUPS.md içinde duruyordu.

Güncelliğini yitirmiş bir cümle, hiç belge olmamasından daha tehlikelidir. Sonraki bir denetim ona inanır ve kapsadığı yolları atlar, böylece yanlış bir satır sessizliğin asla veremeyeceği bir zararı verir. Boş bir belge sizi kaynağa yönlendirir. Yanlış bir belge sizi bambaşka bir yere yönlendirir.

Gerçekleşen bir takip maddesi, açık kalan bir maddeden daha kötüdür

Dimesum, ertelenen işleri FOLLOWUPS.md içinde tutar; her karar için bir satır ve ertelenme nedeni yer alır. A17 maddesi, grupların INR'ye sabit olduğunu, yurt dışındaki bir seyahatin gerçekleştiği para biriminde kaydedilemeyeceğini ve düzeltmenin bir kurucu kararına bağlı olduğunu söylüyordu. W7 yine de çok para birimliliği yayına aldı: bir gider herhangi bir para biriminde olabilir ve bakiyeler ledger/00005 taşımasıyla (group_id, member_id, currency) anahtarına göre tutulur. Kimse satırın üzerini çizmedi.

Sonraki denetim A17'yi okudu, bu alanın hiç yapılmadığı sonucuna vardı ve uzlaştırma, talep ya da açılış kodunu hiç açmadı. Üç para birimine duyarsız para yolu, tek bir cümlenin gücüyle yayınlanmaya devam etti. Yolda zor bir sorun yoktu. app/amount.py dosyasının belge dizesi de aynı iddiayı taşıyordu, böylece okuyucuya iki kez söylenmiş oldu.

Benimsediğimiz kural

Bir takip maddesinin üzerini, onu kapatan commit içinde çizin. Artık o şekilde çalışmayan bir kodu anlatan bir satır, okumanız gereken dosyadan uzağa yönlendiren bir işarettir ve bu, hiçbir şey söylememekten daha pahalıya mal olur.

Aynı sabit kodlanmış 100 değeri üç farklı dosyada ortaya çıktı

Buradaki para, int64 alt birimleri artı bir ISO 4217 kodudur ve ondalıklı sayılar ona hiç dokunmaz. Tam sayılar yapısı gereği kesindir, dolayısıyla geriye kalan tek riskli aritmetik, ana birim ile alt birim arasındaki dönüşümdür. Alt birim her zaman yüzde bir değildir. JPY'nin alt birimi hiç yoktur, KWD'nin üç ondalığı vardır ve sabit kodlanmış her 100 değeri, kullanıcının evde kaldığına dair bir bahistir.

Python yardımcı bileşenindeki app/amount.py ilk görülen yerdi; denetimden önce, aktif bir kusur olarak değil bir mayın olarak çıkarıldı. Bir cümleden okuduğu değeri 100 ile çarpıyordu, böylece ¥1,200'lük bir fiş 120,000 alt birime dönüşüyordu. Bu ¥120,000 olarak okunur. Alt birimi olmayan bir para biriminde bu sabit, birinin faturasını yüz kat şişirir ve işlev artık bunun yerine istek para biriminin üssünü arıyor.

Sabit kodlanmış 100 çarpanıyla ve ISO 4217 üs tablosuyla dönüştürülen 1,200 yenlik bir fiş ¥1,200 para birimi: JPY ÖNCE minor = major x 100 modüldeki sabit 120000 alt birim ¥120,000 olarak okunur SONRA minor = major x 10^exp JPY üssü = 0 1200 alt birim ¥1,200 olarak okunur
Üs tuzağı tek bir resimde. 100'lük sabit bir çarpan INR için doğrudur ve alt birimi olmayan JPY için 100 kat yanlıştır; aynı sabit, üç ondalığı olan KWD için on kat şaşar.

Denetim, aynı sabiti bir kişinin bir bakiyeyi kabul edip etmeyeceğine karar verdiği sayfada da buldu. /m/{token} adresindeki talep açılış sayfasının arkasındaki formatMinor, 100'e bölüyor ve başına bir rupi işareti yapıştırıyordu. ¥6,000'lık bir borç -₹60.00 olarak yazdırılıyordu: yanlış simge, tutarın yüzde biri. JSON kardeşi /v1/claims de onunla birlikte hata verdi; bir üyenin para birimi başına satırlarını tek satıra düzleştirdi ve haritanın en son yazdığı para birimini tuttu.

Üçüncü dosya internal/ingestion/store.go ve bunu denetim değil, yinelenen kayıt tespitini genişletirken W8 buldu. "Artı veya eksi bir rupi" toleransı 100 sabitiydi, yani paise cinsinden sayılan bir rupi; JPY'nin alt birimi hiç olmadığı halde artı veya eksi ¥100'lük bir bant. Artık üçü de üssü okuyor.

Çıplak tam sayıları karşılaştırmak bir yen'i bir rupi gibi gösterdi

Dimesum'un yinelenenleri ayıklama katmanı, içe aktarılan bir fişin, birinin elle girdiği bir siparişi iki kez borçlandırmaması için yeni bir kaydı son giderlerle karşılaştırır. O tolerans bandının yanındaki sorguda hiç para birimi filtresi yoktu. Böylece ¥1,000 ile ₹1,000 eşleşti ve bir içe aktarma, hiç ilgisi olmayan bir gideri geçersiz kılmayı önerdi. Gruplar ledger/00005'ten beri çok para birimliydi, dolayısıyla bu durum teorik değil erişilebilirdi.

Çıplak alt birimler para birimleri arasında karşılaştırılabilir değildir, toleranslar da değildir. Projeksiyon artık para birimine göre filtreliyor ve bandını, karşılaştırılan para biriminin bir ana biriminden türetiyor.

İki motor "kim kime öder" sorusunu yanıtladı ve ikincisi para birimine duyarsızdı

Pahalı kusur aritmetik değil, yapısaldır. Uzlaştırma yazma yolu, Balance yapısında para birimi alanı olmayan ikinci bir asgari nakit akışı motoru olan internal/platform/simplify üzerinden plan yapıyordu. Para birimi başına sıfır toplam, düz toplamı da sıfır yapar, böylece ¥300,000'lık bir borç ile ₹500'lük bir borç birbirini götürüp hiçe indi ve hiçbir koruma planı reddetmedi. Plan sonra bir yen alacaklısını bir rupi borçlusuyla eşleştirdi.

Yazma işlemi durumu daha da kötüleştirdi. Hizmet, her uzlaştırmaya Currency: g.DefaultCurrency damgasını basıyordu, böylece ¥300,000'lık bir borç bir INR kaydını yetkilendirdi ve yen borcu hiç kapatılamadı.

Aynı dört bakiyenin, para birimine duyarsız simplify motoru ve para birimine duyarlı settle motoru tarafından yönlendirilmesi BAKİYELER Asha +¥300,000 Bhavna -¥300,000 Chetan +₹500 Dev -₹500 simplify: Balance{MemberID, Minor} yapıda para birimi yok, bu yüzden dördü de düz netleşiyor 300000 + (-300000) + 500 + (-500) = 0 plan: Bhavna, Chetan'a öder bir yen borçlusu bir rupi alacaklısına gönderildi settle: Balance{MemberID, money.Amount} para birimine göre böl, sonra her birinin içinde yönlendir JPY: Bhavna, Asha'ya ¥300,000 öder INR: Dev, Chetan'a ₹500 öder uzlaştırma, kapattığı para birimini belirtir simplify düzeltilmedi, silindi
Dört bakiye, iki motor. Para birimi başına sıfır toplam, düz toplamın sıfır olmasını gerektirir, böylece para birimine duyarsız bir motor dengeli bir grup görür ve birbirine hiçbir şey borçlu olmayan iki kişi arasında güvenle bir ödeme yönlendirir.

simplify silindi ve /settle-plan kullanımdan kaldırıldı. Artık tek motor internal/platform/settle: para birimlerini dönüştürülebilir ve dönüştürülemez olarak ayırır, net bakiyeleri bir kez dönüştürür ve dönüştürülemez her para birimini kendi biriminde yönlendirir. Bir uzlaştırma, kapattığı para birimini belirtir ve bir grup birden fazla para birimi tuttuğunda bu alan zorunludur.

Sıfır üst sınır, üst sınır yok olarak okundu

Fazla ödeme koruması, kapattığı borçtan daha büyük bir ödemeyi reddeder. Koruma outstanding > 0 && amount > outstanding şeklinde okuyordu, böylece sıfır üst sınır karşılaştırmayı tamamen atlıyordu. Var olmayan bir borca karşılık ödeme kaydeden biri, kuralın var olma nedeni olan tek durumdur ve süzülüp geçen de bu durumdu.

Düzeltme bir koşul değil, bir tiptir. OutstandingMinor artık bir *int64, böylece "bunu kimse hesaplamadı" ile "yanıt sıfır" aynı şekilde yazılamaz. Nil, kontrolü atlar ve gerçekten bilinmiyor anlamına gelir; defter erişimi olan her çağıran gerçek bir sayı geçirir.

Yeşil bir test paketi neden hiçbir şey kanıtlamadı

Bu yollardaki her fikstür INR kullanıyordu. Para birimine duyarsız bir karşılaştırma, tek para birimli bir testte görünmez, çünkü tek para birimiyle karıştırılacak bir şey yoktur. Test paketleri zayıf değildi, dardı ve onları genişletecek denetim A17 tarafından geri gönderilmişti.

Uçtan uca defter doğrulayıcısı da aynı körlüğü paylaşıyordu, ki asıl akılda tutulması gereken kısım budur. Doğrulayıcı, kayıtları para birimine göre gruplamadan üye başına topluyordu, böylece sağlıklı iki para birimli bir grupta yanlış alarm verdi ve iki kez bozulmuş bir grupta sıfıra topladı. Tehlikeli yön, yanlış negatiftir. Kodla aynı varsayım üzerine kurulmuş bir denetleyici her zaman kodla hemfikir olur.

21 Ağustos 2026 çok para birimli denetiminin bulduğu her kusur, bir yen grubunun aldığı sonuç ve yayına giren düzeltme.
KusurNeredeBir JPY grubunun aldığı sonuçDüzeltme
Üzerinde para birimi olmayan bir Balance yapısıplatform/simplifybir rupi borçlusuyla eşleşen bir yen alacaklısısimplify silindi; settle para birimine göre böler
Her uzlaştırmaya basılan grup varsayılanıuzlaştırma hizmeti¥300,000'lık bir borç bir INR kaydını yetkilendirdibir uzlaştırma, kapattığı para birimini belirtir
Fazla ödeme korumasında outstanding > 0uzlaştırma hizmetisıfır üst sınır, hiç üst sınır olmamaya dönüştü*int64: nil bilinmiyor demek, sıfır sıfır demek
Rupi işaretiyle 100'e bölmeağ geçidi formatMinor¥6,000'lık bir borç -₹60.00 olarak yazdırıldısimge ve ondalıklar para biriminden alınır
Para birimi başına bakiyelerin tek satıra düzleştirilmesi/v1/claimsharitanın en son yazdığı para birimipara birimi başına bir giriş, GET /balances ile eşleşir
Kayıtların üye başına toplanması, para biriminin düşürülmesiuçtan uca defter doğrulayıcısıiki kez bozulmuş bir grubun dengeli olarak raporlanmasıüye ve para birimine göre grupla

Para kodunuzda düz 100 değerini grep'leyin

Onu bu sabit için ve iki tutarı yanında bir para birimi olmadan yan yana koyan her karşılaştırma için arayın. Sonra daha ucuz olanı düzeltin, sonraki altısını önleyeni: bir takip maddesinin üzerini onu kapatan commit içinde çizin. Ve yinelenen bir motoru onarmak yerine silin. "Kim kime öder" sorusuna iki yanıt, birinin yanlış kalmasının yoludur.

Sık sorulan sorular

Çok para birimli gider paylaşımı nedir?

Çok para birimli gider paylaşımı, her gideri gerçekleştiği para biriminde kaydeder ve her şeyi tek bir para birimine dönüştürmek yerine para birimi başına ayrı bir bakiye tutar. Dimesum bakiyeleri grup, üye ve para birimine göre anahtarlar, böylece bir yen borcu ile bir rupi borcu asla tek bir sayıya birleşmez. Dönüştürme, bir uzlaştırma planı için kullanılan bir görünümdür, asla saklanan bir tutar değildir.

Para kodunda sabit kodlanmış 100 neden tehlikelidir?

Sabit kodlanmış bir 100, her para biriminin iki ondalık basamağı olduğunu varsayar, oysa birçoğunun yoktur. JPY'nin alt birimi yoktur, dolayısıyla 100 ile çarpmak ¥1,200'lük bir fişi 120,000 alt birime çevirir, bu bir yuvarlama hatası değil yüz kat şişmedir. KWD'nin üç ondalığı vardır, dolayısıyla aynı sabit on kat şaşar. Bunun yerine ISO 4217 üssünü okuyun.

İki uzlaştırma motorunun çelişmesi nasıl önlenir?

İki motoru uzlaştırmak yerine birini silin, çünkü kim kime öder sorusuna ikinci bir yanıt, ilkinin yanlış kalmasının yoludur. Dimesum, bir denetim ilkinin bakiye tipinde para birimi olmadığını bulana kadar simplify ve settle motorlarını yan yana çalıştırdı; bu da bir planın bir yen alacaklısını bir rupi borçlusuyla eşleştirmesine izin verdi. simplify kaldırıldı ve /settle-plan yamalanmak yerine kullanımdan kaldırıldı.

Test paketi altı para hatasına rağmen neden yeşil kaldı?

Test paketi yeşil kaldı, çünkü etkilenen yollardaki her fikstür tek bir para birimi kullanıyordu ve para birimine duyarsız bir karşılaştırma tek bir para birimi olduğunda başarısız olamaz. Uçtan uca defter doğrulayıcısı da aynı varsayımı taşıyordu: kayıtları para birimine göre gruplamadan üye başına topluyordu, böylece iki kez bozulmuş bir grubu dengeli olarak raporladı. Kodun kendi varsayımı üzerine kurulmuş bir denetleyici, kodla hemfikir olur.

Özellik yayına girdikten sonra bir takip maddesiyle ne yapmalı?

Bir takip maddesinin üzerini, anlattığı işi kapatan commit içinde çizin. Sessizce gerçekleşmiş bir takip maddesi, açık kalan birinden daha kötüdür, çünkü sonraki bir okuyucuyu eskiden anlattığı koddan uzağa yönlendirir. Dimesum, çok para birimliliği yayına aldıktan sonra bir hafta boyunca grupların INR'ye sabit olduğunu söyleyen bir madde bıraktı ve sonraki denetim onun sözüne dayanarak üç para yolunu atladı.