31 जुल॰ 2025·8 मिनट पढ़ने में

कर और इनवॉइस के लिए बहु-मुद्रा प्राइसिंग डाटा मॉडल

एक बहु-मुद्रा प्राइसिंग डाटा मॉडल सीखें जो एक्सचेंज रेट्स, राउंडिंग, टैक्स और लोकलाइज़्ड इनवॉइस डिस्प्ले को बिना आश्चर्य के संभालता है।

कर और इनवॉइस के लिए बहु-मुद्रा प्राइसिंग डाटा मॉडल

बहु-मुद्रा इनवॉइस में आम तौर पर क्या गलत होता है

बहु-मुद्रा इनवॉइस उबाऊ पर महंगे तरीकों से फेल होते हैं। UI में नंबर सही दिखते हैं, फिर कोई PDF एक्सपोर्ट करता है, अकाउंटिंग उसे इम्पोर्ट करती है, और टोटल लाइन आइटम्स से मेल नहीं खाते।

मूल कारण सरल है: पैसे की गणित केवल एक्सचेंज रेट से गुणा करना नहीं है। टैक्स, राउंडिंग, और जिस क्षण आप रेट कैप्चर करते हैं, वे परिणाम को प्रभावित करते हैं। यदि आपका प्राइसिंग डाटा मॉडल उन विकल्पों को स्पष्ट नहीं करता, तो सिस्टम के अलग भाग "मदद करने" के लिए फिर से गणना कर के अलग उत्तर देंगे।

तीन व्यू को सहमत होना चाहिए, भले ही वे अलग-लग मुद्राएँ दिखाएँ:

  • ग्राहक का दृश्य: ग्राहक मुद्रा में स्पष्ट कीमतें, जिनके टोटल जोड़ते हों।
  • अकाउंटिंग दृश्य: रिपोर्टिंग और रिकंसिलिएशन के लिए सुसंगत आधार राशियाँ।
  • ऑडिट दृश्य: एक पेपर ट्रेल जो दिखाए किस रेट और राउंडिंग नियम ने इनवॉइस बनाया।

गैर-मिलान अक्सर छोटे निर्णयों से आते हैं जो अलग जगहों पर लिए जाते हैं। एक टीम हर लाइन आइटम पर राउंड करती है; दूसरी सिर्फ टोटल राउंड करती है। एक पेज वर्तमान रेट उपयोग करता है; दूसरा इनवॉइस-तिथि रेट। कुछ टैक्स डिस्काउंट से पहले लागू होते हैं, कुछ के बाद। कुछ टैक्स कीमत में शामिल हैं; कुछ ऊपर जोड़े जाते हैं।

एक ठोस उदाहरण: आप EUR में 19.99 का आइटम बेचते हैं, इनवॉइस GBP में करते हैं, और रिपोर्ट USD में करते हैं। यदि आप प्रति लाइन कन्वर्ट कर के 2 दशमलव पर राउंड करते हैं, तो टैक्स टोटल अलग आ सकता है बनाम पहले जोड़कर फिर कन्वर्ट करने पर। दोनों तरीके तर्कसंगत हो सकते हैं, पर केवल एक ही आपका नियम होना चाहिए।

लक्ष्य है पूर्वानुमेय गणनाएँ और स्पष्ट सहेजी गई मानें। हर इनवॉाइस को बिना अटकल लगाए जवाब देना चाहिए: कौन सी राशियाँ दर्ज की गईं, किस मुद्रा में दर्ज हुईं, कौन सा रेट इस्तेमाल हुआ (और कब), क्या राउंड हुआ (और कैसे), और कौन से टैक्स नियम लागू हुए। यह स्पष्टता UI, PDF, एक्सपोर्ट और ऑडिट में टोटल स्थिर रखती है।

स्कीमा डिजाइन से पहले सहमत होने वाले प्रमुख शब्द

टेबल्स खींचने से पहले सुनिश्चित करें कि हर कोई एक ही शब्दों का प्रयोग कर रहा है। अधिकांश बहु-मुद्रा बग तकनीकी नहीं होते, वे "हमने अलग मतलब निकाला" बग होते हैं। एक साफ़ स्कीमा उन परिभाषाओं से शुरू होता है जिन्हें प्रोडक्ट, फाइनेंस और इंजीनियरिंग सब स्वीकार करें।

आपकी डेटाबेस को प्रभावित करने वाली मुद्रा संबंधी शर्तें

प्रत्येक मनी फ्लो के लिए तीन मुद्राओं पर सहमत हों:

  • Transactional currency: वह मुद्रा जो ग्राहक देखता है और जिस पर सहमति देता है (प्राइस लिस्ट, कार्ट, इनवॉइस डिस्प्ले)।
  • Settlement currency: वह मुद्रा जिसमें आपको वास्तव में भुगतान मिलता है (पेमेंट प्रोवाइडर या बैंक जो सेटल करता है)।
  • Reporting currency: डैशबोर्ड और अकाउंटिंग सारांशों के लिए इस्तेमाल होने वाली मुद्रा।

साथ ही minor units पर परिभाषा करें। USD में 2 (सेंट), JPY में 0, KWD में 3 होते हैं। यह मायने रखता है क्योंकि "12.34" को फ़्लोटिंग नंबर के रूप में रखना ड्रिफ्ट करेगा, जबकि minor units में एक इंटीजर (जैसे 1234 सेंट) सटीक रहता है और राउंडिंग पूर्वानुमेय बनाता है।

वह टैक्स शब्द जो कुल राशि बदलते हैं

टैक्स के लिए भी वही स्तर का समझौता चाहिए। तय करें कि कीमतें tax-inclusive हैं (दिखाई गई कीमत पहले से टैक्स शामिल करती है) या tax-exclusive (टैक्स ऊपर जोड़ा जाता है)। साथ ही यह चुनें कि टैक्स प्रति लाइन आइटम पर (फिर जोड़कर) गणना होगा या प्रति इनवॉइस (पहले जोड़कर, फिर टैक्स)। ये चुनाव राउंडिंग को प्रभावित करते हैं और अंतिम देय राशि को कुछ minor units से बदल सकते हैं।

अंत में, तय करें क्या सहेजा जाना चाहिए बनाम क्या व्युत्पन्न किया जा सकता है:

  • जिन चीज़ों को कानूनी और वित्तीय रूप से सहेजना जरूरी है: सहमत कीमतें, लागू टैक्स रेट, अंतिम राउंडेड टोटल, और उपयोग की गई मुद्रा।
  • जो चीज़ें सुरक्षित रूप से फिर से गणना की जा सकती हैं: फ़ॉर्मैटेड स्ट्रिंग्स, डिस्प्ले-ओनली कन्वर्ज़न, और अधिकांश मध्यवर्ती गणित।

कोर मनी फ़ील्ड: क्या सहेजें और कैसे

पहले तय करें कौन से नंबर तथ्य हैं जिन्हें आप सहेजते हैं और कौन से परिणाम हैं जिन्हें आप पुन: गणना कर सकते हैं। दोनों को मिलाना ही ऐसी स्थिति बनाता है जहां इनवॉइस स्क्रीन पर एक टोटल दिखाता है और एक्सपोर्ट में अलग।

पैसे को minor units में इंटीजर के रूप में सहेजें (जैसे सेंट) और हमेशा मुद्रा कोड उसके साथ रखें। बिना मुद्रा के राशि अधूरी जानकारी है। इंटीजर कई लाइनों को जोड़ने पर छोटे फ़्लोटिंग त्रुटियों से बचाता है।

एक व्यावहारिक पैटर्न यह है कि कच्चे इनपुट और рассчит किए गए आउटपुट दोनों रखें। इनपुट बताते हैं उपयोगकर्ता ने क्या दर्ज किया; आउटपुट बताते हैं आपने क्या बिल किया। जब कोई महीनों बाद इनवॉइस पर विवाद करे, तो आपको दोनों चाहिए होते हैं।

इनवॉइस लाइनों के लिए एक साफ, टिकाऊ फ़ील्ड सेट इस तरह दिखता है:

  • unit_price_minor + unit_currency
  • quantity (और आवश्यकता हो तो uom)
  • line_subtotal_minor (tax/discount से पहले)
  • line_discount_minor
  • line_tax_minor (या टैक्स प्रकारों के हिसाब से विभाजित)
  • line_total_minor (लाइन की अंतिम राशि)

राउंडिंग सिर्फ़ UI डिटेल नहीं है। गणनाओं के लिए उपयोग किए गए राउंडिंग मेथड और प्रिसिशन को सहेजें, खासकर अगर आप अलग-अलग minor units वाली मुद्राओं (JPY बनाम USD) या नकद राउंडिंग नियम सर्पोर्ट करते हैं। एक छोटा सा "calculation context" रिकॉर्ड calc_precision, rounding_mode, और क्या राउंडिंग प्रति लाइन होती है या सिर्फ़ इनवॉइस टोटल पर, यह कैप्चर कर सकता है।

डिस्प्ले फ़ॉर्मैटिंग स्टोर्ड वैल्यूज़ से अलग रखें। स्टोर की गई वैल्यूज़ सादे नंबर और कोड हों; फ़ॉर्मैटिंग (करेंसी सिम्बल, सेपरेटर, लोकलाइज़्ड नंबर फॉर्मैट) प्रेज़ेंटेशन लेयर की जिम्मेदारी है। उदाहरण के लिए, 12345 + EUR सहेजें, और UI तय करे कि उसे "€123.45" या "123,45 €" कैसे दिखाना है।

एक्सचेंज रेट्स: टेबल, टाइमस्टैम्प और ऑडिट ट्रेल

एक्सचेंज रेट्स को समय-आधारित डेटा और स्पष्ट स्रोत के रूप में ट्रीट करें। "आज का रेट" कुछ ऐसा नहीं है जिसे आप बाद में सुरक्षित रूप से पुन: गणना कर सकें।

एक व्यावहारिक एक्सचेंज रेट टेबल आमतौर पर शामिल करती है:

  • base_currency (किससे कन्वर्ट, जैसे USD)
  • quote_currency (किसमें कन्वर्ट, जैसे EUR)
  • rate (1 base के प्रति quote, उच्च-प्रिसिशन दशमलव में सहेजा गया)
  • effective_at (वह टाइमस्टैम्प जब रेट वैध है)
  • source (प्रोवाइडर) और source_ref (उनका ID या payload हैश)

ऑडिट में वह स्रोत जानकारी मायने रखती है। अगर कोई ग्राहक किसी राशि पर विवाद करता है, तो आप बिल्कुल बता सकते हैं कि नंबर कहां से आया।

फिर, यह चुनें कि इनवॉइस किस रेट का उपयोग करेगा, और फिर उसी पर टिके रहें। सामान्य विकल्प हैं: ऑर्डर टाइम, शिपमेंट टाइम, या इनवॉइस टाइम का रेट। सबसे अच्छा विकल्प आपके व्यापार पर निर्भर करता है। महत्वपूर्ण हिस्सा है निरंतरता और दस्तावेज़ीकरण।

जो भी नियम चुनें, उपयोग किए गए सटीक रेट को इनवॉइस पर सहेजें (और अक्सर प्रत्येक इनवॉइस लाइन पर भी)। बाद में उसे फिर से ढूँढने पर भरोसा न करें। फ़ील्ड जोड़ें जैसे fx_rate, fx_rate_effective_at, और fx_rate_source ताकि इनवॉइस को बिल्कुल वैसा ही पुनरुत्पन्न किया जा सके।

मिसिंग रेट्स (वीकेंड, अवकाश, प्रोवाइडर आउटेज) के लिए फॉलबैक बिहेवियर स्पष्ट रखें। सामान्य दृष्टिकोण हैं: सबसे हाल का पहले का रेट उपयोग करें, इनवॉइसिंग ब्लॉक करें जब तक रेट उपलब्ध न हो, या मैनुअल रेट की अनुमति दें और अप्रूवल फ्लैग रखें।

उदाहरण: ऑर्डर शनिवार को रखा गया, सोमवार को शिप हुआ, और सोमवार को इनवॉइस किया गया। यदि आपका नियम इनवॉइस समय का रेट है पर आपका प्रोवाइडर वीकेंड रेट प्रकाशित नहीं करता, तो आप शुक्रवार का आख़िरी रेट उपयोग कर सकते हैं और effective_at = Friday 23:59 रिकॉर्ड कर सकते हैं, साथ में source_ref ट्रेसबिलिटी के लिए।

मुद्रा रूपांतरण और राउंडिंग नियम जो सुसंगत रहें

अपना डिप्लॉयमेंट पथ चुनें
क्लाउड पर डिप्लॉय करें या पूर्ण नियंत्रण के लिए सोर्स कोड एक्सपोर्ट करें।
AppMaster आज़माएँ

राउंडिंग की समस्याएँ आमतौर पर स्पष्ट बग नहीं लगतीं। वे 1-सेंट के गैप के रूप में दिखती हैं इनवॉइस टोटल और लाइनों के योग के बीच, या छोटे टैक्स अंतर के रूप में जो आपने दिखाया और जो पेमेंट प्रोवाइडर अपेक्षित करता है के बीच। अच्छे मॉडल राउंडिंग को एक नियम बनाते हैं जिसे आप समझा सकें, न कि एक आश्चर्य जिसे बाद में पैच करना पड़े।

तय करें बिल्कुल कहाँ राउंडिंग होगी

उन पॉइंट्स का चयन करें जहाँ राउंडिंग की अनुमति होगी, और बाकी सभी को उच्च प्रिसिशन पर रखें। सामान्य राउंडिंग पॉइंट्स में शामिल हैं:

  • लाइन एक्सटेंशन (quantity x unit price, डिस्काउंट के बाद)
  • प्रत्येक टैक्स राशि (प्रति लाइन या प्रति इनवॉइस, प्राधिकरण के अनुसार)
  • अंतिम इनवॉइस टोटल

यदि आप इन पॉइंट्स को परिभाषित नहीं करते, तो सिस्टम के अलग भाग सुविधा अनुसार राउंड कर देंगे, और टोटल ड्रिफ्ट करेंगे।

एक ही राउंडिंग मोड का उपयोग करें, टैक्स नियमों के स्पष्ट अपवादों के साथ

एक राउंडिंग मोड चुनें (half-up या bankers rounding) और उसे लगातार लागू करें। ग्राहक को समझाने के लिए half-up आसान है। बड़े वॉल्यूम पर बायस कम करने के लिए bankers rounding उपयोगी हो सकता है। कोई भी काम कर सकता है, पर आपका API, UI, एक्सपोर्ट और अकाउंटिंग रिपोर्ट्स एक ही मोड उपयोग करनी चाहिए।

कन्वर्ज़न और मध्यवर्ती चरणों के दौरान अतिरिक्त प्रिसिशन रखें (उदा., FX रेट्स कई दशमलव के साथ सहेजें), फिर केवल चुने गए राउंडिंग पॉइंट्स पर राउंड करें।

डिस्काउंट के लिए भी एक सिंगल नियम चाहिए: डिस्काउंट टैक्स से पहले लगाना (कूपन के लिए सामान्य) या टैक्स के बाद (कुछ फीस के लिए आवश्यक)। इसे लिखें और एक बार एन्कोड करें।

कुछ क्षेत्रों में टैक्स प्रति लाइन, प्रति टैक्स, या इनवॉइस टोटल पर राउंड करने की कानूनी जरूरत होती है। अपने कोडबेस में एक-ऑफ़ केस हार्डकोड करने के बजाय देश/राज्य/टैक्स-रिज़ीम के हिसाब से एक "rounding policy" सेटिंग स्टोर करें और गणनाएँ उस नीति का पालन करें।

एक सरल जांच: यदि आप वही इनवॉइस कल फिर से उसी सहेजे हुए रेट्स और नीति के साथ बनाएँ, तो आपको हर बार एक ही सेंट मिलना चाहिए।

टैक्स फ़ील्ड: VAT, sales tax और मल्टीपल टैक्स के पैटर्न

अपना इनवॉइस स्कीमा डिज़ाइन करें
एक ही स्थान पर invoice, tax और FX टेबल मॉडल करें — Data Designer के साथ।
AppMaster आज़माएँ

टैक्स तेज़ी से जटिल हो जाते हैं क्योंकि वे खरीदार के स्थान, आपकी बिक्री के प्रकार, और कीमतें नेट हैं या ग्रॉस पर निर्भर करते हैं। एक साफ मॉडल टैक्स को स्पष्ट रखता है, न कि निहित।

टैक्स बेस को अनअम्बिग्यूस बनाएं। यह सहेजें कि जिस कीमत पर आप टैक्स लगा रहे हैं वह नेट (टैक्स ऊपर जोड़ना) है या ग्रॉस (टैक्स शामिल)। फिर आपने जो रेट लागू किया और गणना करके निकाली गई टैक्स राशि दोनों को स्नैपशॉट के रूप में स्टोर करें, ताकि बाद में नियम बदलने पर इतिहास फिर से लिखा न जाए।

प्रति इनवॉइस लाइन कम से कम जो सेट साफ़ रहे:

  • tax_basis (NET या GROSS)
  • tax_rate (दशमलव, उदाहरण 0.20)
  • taxable_amount_minor (वह आधार जिसे आपने वास्तव में टैक्स किया)
  • tax_amount_minor
  • tax_method (PER_LINE या ON_SUBTOTAL)

यदि एक से अधिक टैक्स लागू हो सकते हैं (उदा., VAT के साथ शहर का सरचार्ज), तो एक अलग ब्रेकडाउन टेबल जोड़ें जैसे InvoiceLineTax जिसमें प्रति लागू टैक्स एक रो हो। हर रो में tax_code, tax_rate, taxable_amount_minor, tax_amount_minor, मुद्रा और गणना समय पर प्रयुक्त क्षेत्रघट संकेत (देश, क्षेत्र, पोस्टल कोड जैसा प्रासंगिक हो) शामिल होना चाहिए।

इनवॉइस या इनवॉइस लाइन पर लागू नियम विवरण का स्नैपशॉट रखें, जैसे rule_version या निर्णय इनपुट का एक JSON ब्लॉब (ग्राहक टैक्स स्थिति, reverse charge, छूट)। यदि VAT नियम अगले साल बदलते हैं, पुराने इनवॉइस अभी भी वो दिखाएँ जो आपने वास्तव में चार्ज किया था।

उदाहरण: जर्मनी के ग्राहक को बेची गई एक SaaS सदस्यता पर NET लाइन प्राइस पर 19% VAT और 1% स्थानीय टैक्स लागू हो सकती है। लाइन टोटल्स को बिल किए गए रूप में सहेजें, और ऑडिट व डिस्प्ले के लिए प्रत्येक टैक्स के लिए एक ब्रेकडाउन रो रखें।

चरण-दर-चरण टेबल डिज़ाइन कैसे करें

यह चालाक गणित के बारे में कम और सही समय पर सही तथ्यों को फ्रीज़ करने के बारे में ज़्यादा है। लक्ष्य यह है कि एक इनवॉइस को महीनों बाद खोला जाए और वही संख्याएँ दिखें।

शुरू करें यह तय करके कि प्रोडक्ट कीमतों की ट्रुथ कहाँ रहती है। कई टीमें प्रत्येक प्रोडक्ट के लिए बेस-मुद्रा में कीमत रखती हैं और ऑप्शनली बाजार के अनुसार ओवरराइड्स जोड़ती हैं (उदा., USD और EUR के लिए अलग प्राइस रो)। जो भी आप चुनें, उसे स्कीमा में स्पष्ट रखें ताकि आप "कैटलॉग प्राइस" और "कनवर्टेड प्राइस" को मिलाएँ नहीं।

एक सरल अनुक्रम जो तालिकाओं को समझने में आसान रखता है:

  • Products and pricing: product_id, price_amount_minor, price_currency, effective_from (यदि कीमतें समय के साथ बदलती हैं)।
  • Order and invoice headers: document_currency, customer_locale, billing_country, और टाइमस्टैम्प (issued_at, tax_point_at)।
  • Line items: unit_price_amount_minor, quantity, discount_amount_minor, tax_amount_minor, line_total_amount_minor, और हर स्टोर की गई रकम के लिए मुद्रा।
  • Exchange rate snapshot: उपयोग किया गया सटीक रेट (rate_value, rate_provider, rate_timestamp) जिसका संदर्भ ऑर्डर या इनवॉइस से दे।
  • Tax breakdown records: प्रति टैक्स एक रो (tax_type, rate_percent, taxable_base_minor, tax_amount_minor) साथ में calculation_method旗।

बाद में पुन: गणना पर भरोसा न करें। जब आप इनवॉइस बनाते हैं, तो अंतिम यूनिट प्राइस, डिस्काउंट और टोटल्स को इनवॉइस लाइन आइटम्स पर कॉपी करें, भले ही वे ऑर्डर से आए हों।

ट्रेसबिलिटी के लिए, इनवॉइस पर calculation_version (या calc_hash) जोड़ें और एक छोटा calculation_log टेबल रखें जो रिकॉर्ड करे किसने और क्यों रीकैल्क्यूलेशन ट्रिगर किया (उदा., "rate updated before issuing")।

संख्याओं को तोड़े बिना लोकलाइज़्ड इनवॉइस डिस्प्ले

टैक्स को स्पष्ट रखें
इनवॉइस लाइन और टैक्स ब्रेकडाउन रिकॉर्ड बनाएं जो महीनों बाद भी पढ़ने लायक रहें।
AppMaster आज़माएँ

लोकलाइज़ेशन को इनवॉइस के रूप को बदलना चाहिए, अर्थ को नहीं। सभी गणनाएँ सहेजे हुए संख्यात्मक मानों का उपयोग कर के करें (minor units या फिक्स्ड-प्रिसिशन दशमलव), फिर सबसे अंत में लोकलाइज़्ड फॉर्मैटिंग लागू करें।

इनवॉइस प्रेज़ेंटेशन सेटिंग्स को केवल ग्राहक प्रोफ़ाइल पर न रखें — इन्हें दस्तावेज़ पर स्टोर करें। ग्राहक देश, बिलिंग संपर्क और प्राथमिकताएँ समय के साथ बदलती हैं। एक इनवॉइस कानूनी स्नैपशॉट है। चीज़ें जैसे invoice_language, invoice_locale, और फॉर्मैटिंग फ्लैग (उदा., ट्रेलिंग ज़ीरो दिखाना) डॉक्यूमेंट के साथ सहेजें ताकि छह महीने बाद री-प्रिंट मूल के समान दिखे।

करेंसी सिम्बल डिस्प्ले का मामला है। कुछ लोकल्स में सिम्बल रकम से पहले आता है, कुछ में बाद में; कुछ में स्पेस चाहिए, कुछ में नहीं। सिम्बल प्लेसमेंट, स्पेसिंग, दशमलव सेपरेटर और हजारों समूहबद्ध करने को रेंडर समय पर संभालें, इनवॉइस लोकल और मुद्रा के आधार पर। स्टोर की गई मनी फ़ील्ड में सिम्बल न बेक करें, और फ़ॉर्मैटेड स्ट्रिंग्स को फिर से नंबर में पार्स न करें।

यदि आपको सेकेंडरी करंसी में रिपोर्टिंग चाहिए (आम तौर पर होम करंसी जैसे USD या EUR), तो उसे स्पष्ट रूप से सेकेंडरी टोटल के रूप में दिखाएँ, प्राथमिक दस्तावेज़ मुद्रा की जगह नहीं। दस्तावेज़ मुद्रा कानूनी स्रोत बनी रहती है।

एक व्यावहारिक सेटअप इनवॉइस आउटपुट के लिए:

  • लाइन आइटम्स और टोटल्स दस्तावेज़ मुद्रा में दिखाएँ, invoice-locale फ़ॉर्मैटिंग का उपयोग कर के।
  • वैकल्पिक रूप से सेकेंडरी रिपोर्टिंग टोटल दिखाएँ जिस पर रेट स्रोत और टाइमस्टैम्प लेबल हों।
  • टैक्स ब्रेकडाउन को अलग लाइनों के रूप में दिखाएँ (taxable base, हर टैक्स, कुल टैक्स), न कि एक मिश्रित राशि।
  • PDFs और ईमेल को समान सहेजे हुए टोटल्स से रेंडर करें ताकि संख्याएँ ड्रिफ्ट न करें।

उदाहरण: एक फ्रेंच ग्राहक को CHF में बिल किया जाता है। इनवॉइस लोकल कॉमा दशमलव और मुद्रा को रकम के बाद रखता है, पर गणनाएँ सहेजे हुए CHF राशियों और टैक्स टोटल्स पर ही होती हैं। फॉर्मैट बदलता है; संख्याएँ नहीं।

बचने योग्य सामान्य गलतियाँ और जाल

बहु-मुद्रा इनवॉइस को तोड़ने का सबसे तेज़ तरीका पैसे को एक सामान्य नंबर समझना है। कीमतों, टैक्स और टोटल्स के लिए फ्लोटिंग पॉइंट प्रकार छोटे त्रुटियाँ बनाते हैं जो बाद में "$0.01 से ऑफ" समस्याओं के रूप में दिखती हैं। राशियाँ minor units में इंटीजर के रूप में स्टोर करें (सेंट) या स्पष्ट स्केल के साथ फिक्स्ड दशमलव प्रकार का उपयोग करें, फिर इसे लगातार उपयोग करें।

एक और क्लासिक जाल इतिहास को गलती से बदलना है। अगर आप किसी पुराने इनवॉइस को आज के एक्सचेंज रेट से या अपडेट हुए टैक्स नियम से फिर से गणना करते हैं, तो वह दस्तावेज़ जो ग्राहक ने देखा और भुगतान किया था, वह नहीं रहेगा। इनवॉइस को इश्यू करने के बाद अपरिवर्तनीय रखें: सटीक एक्सचेंज रेट, राउंडिंग नियम, और टैक्स मेथड सहेजें, और स्टोर किए गए टोटल्स को फिर से गणना न करें।

एक ही लाइन आइटम में मुद्राओं को मिलाना भी एक शांत स्कीमा बग है। अगर यूनिट प्राइस EUR में है, डिस्काउंट USD में और टैक्स GBP में गणना की गई, तो आप बाद में गणित समझा नहीं पाएँगे। डिस्प्ले और सेटलमेंट के लिए एक दस्तावेज़ मुद्रा चुनें, और आंतरिक रिपोर्टिंग के लिए एक बेस मुद्रा चुनें (यदि जरूरत हो)। हर स्टोर की गई राशि के साथ स्पष्ट मुद्रा होनी चाहिए।

राउंडिंग की गलतियाँ अक्सर बहुत अधिक चरणों में राउंड करने से आती हैं। यदि आप यूनिट प्राइस पर राउंड करते हैं, फिर लाइन टोटल पर, फिर प्रति लाइन टैक्स पर, फिर सबटोटल पर फिर से, तो टोटल लाइनों के योग से मेल करना बंद कर सकते हैं।

बचने योग्य सामान्य जाल:

  • मनी या एक्सचेंज रेट्स के लिए फ़्लोट्स का बिना फिक्स्ड प्रिसिशन उपयोग
  • पुराने इनवॉइस के लिए फिर से रूपांतरण चलाना बजाय सहेजे गए रेट्स के उपयोग के
  • एक लाइन आइटम में अलग-अलग मुद्राएँ अनुमति देना
  • कई स्टेप्स पर राउंडिंग करने के बजाय स्पष्ट पॉइंट्स पर ही राउंडिंग
  • दस्तावेज़ पर रेट टाइमस्टैम्प, राउंडिंग मोड और टैक्स मेथड न स्टोर करना

उदाहरण: आप CAD में एक इनवॉइस बनाते हैं, EUR-प्राइस्ड सेवा को कन्वर्ट करते हैं, फिर बाद में अपना रेट टेबल अपडेट करते हैं। अगर आप केवल EUR राशि स्टोर करते हैं और डिस्प्ले पर कन्वर्ट करते हैं, तो अगली हफ्ते CAD टोटल बदल जाएगा। EUR राशि, लागू FX रेट (और समय), और इनवॉइस पर उपयोग की गई अंतिम CAD राशियाँ स्टोर करें।

शिप करने से पहले त्वरित चेकलिस्ट

रीवर्क से बचें
ज़ब आवश्यक हो तो क्लीन सोर्स कोड जनरेट करें, बिना गंदे री-राइट के।
शुरू करें

बहु-मुद्रा इनवॉइस को "हो गया" कहने से पहले संगति पर केंद्रित एक अंतिम पास करें। यहां अधिकतर बग जटिल नहीं होते — वे जो आप स्टोर करते हैं, जो आप दिखाते हैं, और जो आप जोड़ते हैं, उन तीनों के बीच मिसमैच से आते हैं।

इसे एक रिलीज़ गेट के रूप में उपयोग करें:

  • प्रत्येक इनवॉइस हेडर पर ठीक एक दस्तावेज़ मुद्रा हो, और इनवॉइस पर सहेजे गए हर टोटल उसी मुद्रा में हों।
  • आप जो भी मौद्रिक मान सहेजते हैं वे minor units में इंटीजर हों, जिसमें लाइन टोटल्स, टैक्स राशि, डिस्काउंट और शिपिंग शामिल हों।
  • इनवॉइस सटीक एक्सचेंज रेट को सहेजे (एक सटीक दशमलव के रूप में), साथ में टाइमस्टैम्प और रेट स्रोत।
  • राउंडिंग नियम दस्तावेजीकृत हों और एक साझा स्थान में लागू हों।
  • अगर एक से अधिक टैक्स लागू हो सकते हैं, तो आप प्रति लाइन टैक्स ब्रेकडाउन स्टोर करें (और ऑप्शनली प्रति अधिकार क्षेत्र), न कि केवल हेडर पर एक टैक्स टोटल।

स्कीमा ठीक होने के बाद, ऑडिटर की तरह गणित का सत्यापन करें। इनवॉइस टोटल्स स्टोर किए गए लाइन टोटल्स और स्टोर किए गए टैक्स राशियों के योग के बराबर होने चाहिए। डिस्प्ले या फॉर्मैटेड स्ट्रिंग्स से टोटल्स फिर से गणना न करें।

एक व्यावहारिक टेस्ट: किसी ऐसे इनवॉइस को चुनें जिसमें कम से कम तीन लाइन हों, एक डिस्काउंट लागू करें, और एक लाइन पर दो टैक्स शामिल हों। फिर उसे किसी दूसरे लोकेल में प्रिंट करें (अलग सेपरेटर और मुद्रा सिम्बल) और पुष्टि करें कि सहेजे हुए नंबर बदलते नहीं हैं।

उदाहरण परिदृश्य: एक ऑर्डर, तीन मुद्राएँ, और टैक्स

बिलिंग तेज़ी से प्रोटोटाइप करें
वेब और मोबाइल UI एक ही लॉजिक से स्पिन-अप करके बिलिंग जल्दी प्रोटोटाइप करें।
प्रोटोटाइप बनाएं

एक US ग्राहक USD में बिल होता है, आपका EU सप्लायर आपको EUR में शुल्क मांगता है, और आपकी फाइनेंस टीम GBP में रिपोर्ट करती है। यही वह जगह है जहाँ मॉडल शांत रहता है या 1-सेंट मिसमैच का ढेर बन जाता है।

ऑर्डर: 3 यूनिट्स एक प्रोडक्ट की।

  • ग्राहक मूल्य: $19.99 प्रति यूनिट (USD)
  • डिस्काउंट: लाइन पर 10%
  • US सेल्स टैक्स: 8.25% (डिस्काउंट के बाद टैक्स लागू)
  • सप्लायर कॉस्ट: EUR 12.40 प्रति यूनिट (EUR)
  • रिपोर्टिंग मुद्रा: GBP

वॉकथ्रू: क्या होता है और कब आप कन्वर्ट करते हैं

एक कन्वर्ज़न क्षण चुनें और उसी पर टिके रहें। कई इनवॉइसिंग सिस्टम्स में, एक सुरक्षित विकल्प इनवॉइस इश्यू समय पर कन्वर्ट करना और फिर उपयोग किए गए सटीक रेट को स्टोर करना है।

इनवॉइस निर्माण पर:

  1. USD लाइन सबटोटल गणना: 3 x 19.99 = 59.97 USD.
  2. डिस्काउंट लागू करें: 59.97 x 10% = 5.997, जिसे 6.00 USD पर राउंड किया गया।
  3. लाइन नेट: 59.97 - 6.00 = 53.97 USD.
  4. टैक्स: 53.97 x 8.25% = 4.452525, जिसे 4.45 USD पर राउंड किया गया।
  5. टोटल: 53.97 + 4.45 = 58.42 USD.

राउंडिंग केवल परिभाषित पॉइंट्स पर होती है (डिस्काउंट, प्रत्येक टैक्स राशि, लाइन टोटल)। उन राउंड किए गए परिणामों को स्टोर करें, और हमेशा स्टोर किए गए मानों को जोड़ें। इससे क्लासिक समस्या बचती है जहां आपका PDF 58.42 दिखाता है पर एक्सपोर्ट 58.43 री-कैल्क्युलेट करता है।

आप बाद में पुनरुत्पादन के लिए क्या स्टोर करते हैं

इनवॉइस (और इनवॉइस लाइनों) पर मुद्रा कोड (USD), minor units में राशियाँ (सेंट), प्रति टैक्स ब्रेकडाउन, और USD से GBP रिपोर्टिंग के लिए उपयोग किए गए एक्सचेंज रेट रिकॉर्ड IDs स्टोर करें। सप्लायर कॉस्ट के लिए EUR कॉस्ट और उसके अपने रेट रिकॉर्ड को भी स्टोर करें यदि आप लागत को GBP में कन्वर्ट करते हैं।

ग्राहक को एक साफ USD इनवॉइस दिखेगा (कीमतें, डिस्काउंट, टैक्स, टोटल)। फाइनेंस USD राशियाँ और फ्रीज़ किए गए GBP समकक्ष और सटीक रेट टाइमस्टैम्प एक्सपोर्ट कर पाएगा ताकि महीने के अंत के नंबर कल रेट्स बदलने पर भी मैच करें।

अगले कदम: लागू करें, टेस्ट करें, और मेंटेनेबल रखें

अपना न्यूनतम स्कीमा एक छोटे कॉन्ट्रैक्ट के रूप में लिखें: कौन सी राशियाँ सहेजी जाती हैं (मूल, कन्वर्टेड, टैक्स), हर राशि किस मुद्रा में है, कौन सा राउंडिंग नियम लागू है, और किस टाइमस्टैम्प ने किसी एक्सचेंज रेट को लॉक किया। इसे नीरस और विशिष्ट रखें।

UI स्क्रीन बनाने से पहले टेस्ट बनाएं। केवल सामान्य इनवॉइसों का परीक्षण न करें। एज-केस जोड़ें जो राउंडिंग शोर को उजागर करने के लिए पर्याप्त छोटे हों और एग्रीगेशन समस्याओं को उजागर करने के लिए पर्याप्त बड़े हों।

एक स्टार्टर सेट टेस्ट केस:

  • बहुत छोटी यूनिट प्राइस (जैसे 0.01) उच्च मात्रा के साथ गुणा
  • डिस्काउंट जो रूपांतरण के बाद रिपीटिंग दशमलव बनाते हैं
  • ऑर्डर तिथि और इनवॉइस तिथि के बीच एक्सचेंज रेट परिवर्तन
  • एक ही इनवॉइस प्रकार पर मिश्रित टैक्स नियम (टैक्स शामिल बनाम टैक्स अलग)
  • रिफंड और क्रेडिट नोट जो मूल राउंडिंग से मेल खाते हों

सहायता टिकटों को छोटा रखने के लिए, एक ऑडिट व्यू जोड़ें जो इनवॉइस पर हर संख्या की व्याख्या करे: सहेजे हुए मान, मुद्रा कोड, एक्सचेंज रेट ID और टाइमस्टैम्प, और उपयोग किया गया राउंडिंग मेथड। जब कोई पूछे "यह टोटल अलग क्यों है?", तो आप सहेजे हुए तथ्यों से जवाब दे सकें।

यदि आप एक आंतरिक बिलिंग टूल बना रहे हैं, तो AppMaster (appmaster.io) जैसी नो-कोड प्लेटफ़ॉर्म आपकी मदद कर सकती है ताकि स्कीमा एक जगह रहे और कैलकुलेशन लॉजिक एक ही पुन: प्रयोज्य वर्कफ़्लो में हो, जिससे वेब और मोबाइल स्क्रीन अलग-अलग गणित न करें।

अंत में, स्वामित्व असाइन करें। तय करें कौन एक्सचेंज रेट्स अपडेट करता है, कौन टैक्स नियम अपडेट करता है, और कौन जारी किए गए इनवॉइस को प्रभावित करने वाले परिवर्तनों को अप्रूव करता है। स्थिरता एक प्रक्रिया है, सिर्फ़ एक स्कीमा नहीं।

शुरू करना आसान
कुछ बनाएं अद्भुत

फ्री प्लान के साथ ऐपमास्टर के साथ प्रयोग करें।
जब आप तैयार होंगे तब आप उचित सदस्यता चुन सकते हैं।

शुरू हो जाओ