laxmidhar / desi-currency
A little toolkit that teaches Laravel to count in rupees — because not every app runs on dollars.
Installs: 3
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/laxmidhar/desi-currency
Requires
- php: ^8.0|^8.1|^8.2|^8.3
- illuminate/support: ^9.0|^10.0|^11.0|^12.0
README
A comprehensive Laravel package for handling Indian currency formatting, conversions, and utilities. Format amounts in Lakhs, Crores, convert to words, parse shorthand notations (1L, 2.5Cr), and much more - all following Indian numbering standards.
✨ Features
- 🇮🇳 Indian Numbering System - Proper comma placement (₹1,23,456.78)
- 💰 Lakh & Crore Formatting - Convert to Lakhs, Crores with ease
- 🔤 Words Conversion - Amount to Indian words (One Lakh Twenty Three Thousand)
- 📝 Shorthand Support - Parse and format 1L, 2.5Cr, 500K notations
- 🔄 Two-way Conversion - Format to shorthand and parse back to numbers
- ✅ Zero Configuration - Works out of the box
- 🎯 Production Ready - Fully tested and optimized
- 📦 Auto-Discovery - Automatically registers with Laravel
📋 Requirements
- PHP 8.0 or higher
- Laravel 9.x, 10.x, 11.x, or 12.x
🚀 Installation
Install via Composer:
composer require laxmidhar/desi-currency
The service provider will be automatically registered via Laravel's package auto-discovery.
📖 Usage
Facade Usage (Recommended)
use Laxmidhar\DesiCurrency\Facades\Currency; // Format in Indian style Currency::format(123456.78); // Output: "₹1,23,456.78" // Convert to words Currency::toWords(150000); // Output: "₹1.5 Lakh" // Shorthand notation Currency::toShorthand(2500000); // Output: "₹25L" // Parse back to number Currency::parse('1.5L'); // Output: 150000
Direct Class Usage
use Laxmidhar\DesiCurrency\Support\CurrencyService; CurrencyService::format(123456.78); CurrencyService::toWords(150000); CurrencyService::toShorthand(2500000);
Dependency Injection
use Laxmidhar\DesiCurrency\Support\CurrencyService; class InvoiceController extends Controller { public function __construct(protected CurrencyService $currency) {} public function show($id) { $invoice = Invoice::find($id); $formatted = $this->currency->format($invoice->total); $inWords = $this->currency->toIndianWords($invoice->total); return view('invoice.show', compact('invoice', 'formatted', 'inWords')); } }
🧩 Available Methods
💰 Core Formatting Methods
format(float $amount, bool $showSymbol = true): string
Format amount using Indian numbering system (₹1,23,456.78).
Parameters:
$amount
- Amount to format$showSymbol
- Whether to include ₹ symbol (default: true)
Examples:
Currency::format(1234.56); // Output: "₹1,234.56" Currency::format(123456.78); // Output: "₹1,23,456.78" Currency::format(12345678.90); // Output: "₹1,23,45,678.90" Currency::format(1234.56, false); // Output: "1,234.56" Currency::format(-5000); // Output: "-₹5,000.00"
Key Features:
- Follows Indian comma placement (last 3 digits, then groups of 2)
- Handles negative amounts
- Always shows 2 decimal places
- Optional currency symbol
formatWhole(float $amount, bool $showSymbol = true): string
Format amount without decimal places.
Parameters:
$amount
- Amount to format$showSymbol
- Whether to include ₹ symbol (default: true)
Examples:
Currency::formatWhole(123456.78); // Output: "₹1,23,457" Currency::formatWhole(1234.50); // Output: "₹1,235" Currency::formatWhole(1000000); // Output: "₹10,00,000" Currency::formatWhole(1234.56, false); // Output: "1,235"
Use Cases:
- Display whole rupees only
- Invoice totals
- Round number displays
- Reports and summaries
formatAccounting(float $amount, bool $showSymbol = true): string
Format for accounting purposes (negative values in parentheses).
Parameters:
$amount
- Amount to format$showSymbol
- Whether to include ₹ symbol (default: true)
Examples:
Currency::formatAccounting(1000); // Output: "₹1,000.00" Currency::formatAccounting(-1000); // Output: "(₹1,000.00)" Currency::formatAccounting(-25000.50); // Output: "(₹25,000.50)"
Use Cases:
- Financial statements
- Balance sheets
- Profit/Loss reports
- Accounting software
🔤 Words & Shorthand Conversion
toWords(float $amount, bool $showSymbol = true): string
Convert amount to readable words format (Lakh, Crore, K).
Parameters:
$amount
- Amount to convert$showSymbol
- Whether to include ₹ symbol (default: true)
Examples:
Currency::toWords(500); // Output: "₹500" Currency::toWords(5000); // Output: "₹5K" Currency::toWords(50000); // Output: "₹50K" Currency::toWords(150000); // Output: "₹1.5 Lakh" Currency::toWords(2500000); // Output: "₹25 Lakh" Currency::toWords(15000000); // Output: "₹1.5 Crore" Currency::toWords(250000000); // Output: "₹25 Crore" Currency::toWords(150000, false); // Output: "1.5 Lakh"
Conversion Logic:
- ≥ 1 Crore (10,000,000): Shows in Crores
- ≥ 1 Lakh (100,000): Shows in Lakhs
- ≥ 1 Thousand (1,000): Shows with K suffix
- < 1 Thousand: Shows as is
toShorthand(float $amount, bool $showSymbol = true): string
Convert to compact shorthand notation (1L, 2.5Cr, 500K).
Parameters:
$amount
- Amount to convert$showSymbol
- Whether to include ₹ symbol (default: true)
Examples:
Currency::toShorthand(500); // Output: "₹500" Currency::toShorthand(5000); // Output: "₹5K" Currency::toShorthand(150000); // Output: "₹1.5L" Currency::toShorthand(2500000); // Output: "₹25L" Currency::toShorthand(15000000); // Output: "₹1.5Cr" Currency::toShorthand(250000000); // Output: "₹25Cr" Currency::toShorthand(-150000); // Output: "-₹1.5L"
Use Cases:
- Dashboard widgets
- Mobile app displays
- Quick summaries
- Data tables
- Charts and graphs
toLakhs(float $amount, int $decimals = 2, bool $showSymbol = true): string
Always format in Lakhs, regardless of amount.
Parameters:
$amount
- Amount to convert$decimals
- Number of decimal places (default: 2)$showSymbol
- Whether to include ₹ symbol (default: true)
Examples:
Currency::toLakhs(50000); // Output: "₹0.50 Lakhs" Currency::toLakhs(150000); // Output: "₹1.50 Lakhs" Currency::toLakhs(2500000); // Output: "₹25.00 Lakhs" Currency::toLakhs(15000000); // Output: "₹150.00 Lakhs" Currency::toLakhs(150000, 1); // Output: "₹1.5 Lakhs" Currency::toLakhs(100000); // Output: "₹1.00 Lakh" Currency::toLakhs(150000, 2, false); // Output: "1.50 Lakhs"
Use Cases:
- Real estate pricing
- Salary negotiations
- Project budgets
- Property valuations
toCrores(float $amount, int $decimals = 2, bool $showSymbol = true): string
Always format in Crores, regardless of amount.
Parameters:
$amount
- Amount to convert$decimals
- Number of decimal places (default: 2)$showSymbol
- Whether to include ₹ symbol (default: true)
Examples:
Currency::toCrores(5000000); // Output: "₹0.50 Crores" Currency::toCrores(15000000); // Output: "₹1.50 Crores" Currency::toCrores(250000000); // Output: "₹25.00 Crores" Currency::toCrores(15000000, 1); // Output: "₹1.5 Crores" Currency::toCrores(10000000); // Output: "₹1.00 Crore" Currency::toCrores(15000000, 2, false); // Output: "1.50 Crores"
Use Cases:
- Company valuations
- Large transactions
- Annual reports
- Government budgets
- Infrastructure projects
toIndianWords(float $amount): string
Convert amount to complete Indian words format.
Parameters:
$amount
- Amount to convert
Examples:
Currency::toIndianWords(123); // Output: "One Hundred Twenty Three Rupees" Currency::toIndianWords(1234.50); // Output: "One Thousand Two Hundred Thirty Four Rupees and Fifty Paise" Currency::toIndianWords(123456); // Output: "One Lakh Twenty Three Thousand Four Hundred Fifty Six Rupees" Currency::toIndianWords(12345678); // Output: "One Crore Twenty Three Lakh Forty Five Thousand Six Hundred Seventy Eight Rupees" Currency::toIndianWords(100.25); // Output: "One Hundred Rupees and Twenty Five Paise" Currency::toIndianWords(-500); // Output: "Negative Five Hundred Rupees"
Use Cases:
- Cheque printing
- Invoice generation
- Legal documents
- Payment receipts
- Bank transactions
🔄 Parsing & Conversion
parse(string $amount): float
Parse Indian currency notation back to numeric value.
Parameters:
$amount
- String amount to parse
Examples:
Currency::parse('1L'); // Output: 100000 Currency::parse('1.5L'); // Output: 150000 Currency::parse('2.5Cr'); // Output: 25000000 Currency::parse('500K'); // Output: 500000 Currency::parse('1 Lakh'); // Output: 100000 Currency::parse('2.5 Crore'); // Output: 25000000 Currency::parse('₹1.5L'); // Output: 150000 Currency::parse('Rs 2.5Cr'); // Output: 25000000 Currency::parse('-1.5L'); // Output: -150000 Currency::parse('1,50,000'); // Output: 150000
Supported Formats:
- Shorthand: 1L, 2.5Cr, 500K
- Words: 1 Lakh, 2.5 Crore
- With symbols: ₹1L, Rs 2Cr
- With commas: 1,50,000
- Negative values: -1.5L
Use Cases:
- User input parsing
- Import data processing
- API integrations
- Form submissions
🔧 Utility Methods
symbol(): string
Get the rupee currency symbol.
Examples:
Currency::symbol(); // Output: "₹" // Usage in views echo Currency::symbol() . '1,000'; // Output: "₹1,000"
splitRupeesPaise(float $amount): array
Split amount into rupees and paise components.
Parameters:
$amount
- Amount to split
Examples:
Currency::splitRupeesPaise(1234.56); // Output: ['rupees' => 1234, 'paise' => 56] Currency::splitRupeesPaise(100.25); // Output: ['rupees' => 100, 'paise' => 25] Currency::splitRupeesPaise(500); // Output: ['rupees' => 500, 'paise' => 0] Currency::splitRupeesPaise(-1234.56); // Output: ['rupees' => -1234, 'paise' => 56] // Usage example $split = Currency::splitRupeesPaise(1234.56); echo "Rupees: {$split['rupees']}, Paise: {$split['paise']}"; // Output: "Rupees: 1234, Paise: 56"
Use Cases:
- Cheque printing
- Detailed invoices
- Payment breakdowns
- Accounting entries
formatWithSuffix(float $amount, string $suffix = '', bool $showSymbol = true): string
Format amount with custom suffix.
Parameters:
$amount
- Amount to format$suffix
- Custom suffix text$showSymbol
- Whether to include ₹ symbol (default: true)
Examples:
Currency::formatWithSuffix(1000, 'per month'); // Output: "₹1,000.00 per month" Currency::formatWithSuffix(50000, 'annual'); // Output: "₹50,000.00 annual" Currency::formatWithSuffix(25000, 'onwards'); // Output: "₹25,000.00 onwards" Currency::formatWithSuffix(100000, 'only'); // Output: "₹1,00,000.00 only" Currency::formatWithSuffix(1000); // Output: "₹1,000.00"
Use Cases:
- Subscription pricing
- Product pricing
- EMI displays
- Offer pricing
isLakhsRange(float $amount): bool
Check if amount is in the Lakhs range (1L to 1Cr).
Parameters:
$amount
- Amount to check
Examples:
Currency::isLakhsRange(50000); // Output: false (less than 1 Lakh) Currency::isLakhsRange(150000); // Output: true (1.5 Lakhs) Currency::isLakhsRange(2500000); // Output: true (25 Lakhs) Currency::isLakhsRange(15000000); // Output: false (1.5 Crores) // Usage example $amount = 250000; if (Currency::isLakhsRange($amount)) { echo Currency::toLakhs($amount); } else { echo Currency::format($amount); }
Use Cases:
- Conditional formatting
- Range-based displays
- Report categorization
isCroresRange(float $amount): bool
Check if amount is in the Crores range (≥1Cr).
Parameters:
$amount
- Amount to check
Examples:
Currency::isCroresRange(5000000); // Output: false (50 Lakhs) Currency::isCroresRange(10000000); // Output: true (1 Crore) Currency::isCroresRange(250000000); // Output: true (25 Crores) // Usage example $amount = 15000000; if (Currency::isCroresRange($amount)) { echo Currency::toCrores($amount); } else { echo Currency::toLakhs($amount); }
Use Cases:
- Large transaction handling
- Report filtering
- Display logic
💡 Practical Examples
E-commerce Product Display
use Laxmidhar\DesiCurrency\Facades\Currency; // Product price formatting $product = Product::find(1); $price = $product->price; // 149900 // For display echo Currency::toShorthand($price); // Output: "₹1.5L" // For detailed view echo Currency::format($price); // Output: "₹1,49,900.00" // For cards/widgets echo Currency::toWords($price); // Output: "₹1.5 Lakh"
Invoice Generation
use Laxmidhar\DesiCurrency\Facades\Currency; $invoice = Invoice::find(1); $total = $invoice->total; // 125750.50 // Invoice total echo Currency::format($total); // Output: "₹1,25,750.50" // Amount in words echo Currency::toIndianWords($total); // Output: "One Lakh Twenty Five Thousand Seven Hundred Fifty Rupees and Fifty Paise" // Split for detailed view $split = Currency::splitRupeesPaise($total); echo "Rupees: {$split['rupees']}, Paise: {$split['paise']}"; // Output: "Rupees: 125750, Paise: 50"
Dashboard Statistics
use Laxmidhar\DesiCurrency\Facades\Currency; // Annual revenue $revenue = 125000000; // 12.5 Crores echo Currency::toShorthand($revenue); // Output: "₹12.5Cr" // Monthly revenue $monthly = $revenue / 12; if (Currency::isCroresRange($monthly)) { echo Currency::toCrores($monthly); } else { echo Currency::toLakhs($monthly); } // Output: "₹1.04 Crores"
Salary Package Display
use Laxmidhar\DesiCurrency\Facades\Currency; $salary = 1800000; // 18 Lakhs per annum // Annual echo Currency::toLakhs($salary) . ' per annum'; // Output: "₹18.00 Lakhs per annum" // Monthly $monthly = $salary / 12; echo Currency::format($monthly) . ' per month'; // Output: "₹1,50,000.00 per month"
User Input Processing
use Laxmidhar\DesiCurrency\Facades\Currency; // User enters "2.5L" in a form $userInput = request('budget'); // "2.5L" // Parse to numeric value $numericValue = Currency::parse($userInput); // Output: 250000 // Store in database $property->budget = $numericValue; $property->save(); // Display back to user echo Currency::toWords($property->budget); // Output: "₹2.5 Lakh"
Financial Reports
use Laxmidhar\DesiCurrency\Facades\Currency; $profit = 5500000; $loss = -1200000; // Profit echo Currency::formatAccounting($profit); // Output: "₹55,00,000.00" // Loss echo Currency::formatAccounting($loss); // Output: "(₹12,00,000.00)" // Summary echo Currency::toShorthand($profit); // Output: "₹55L"
Real Estate Listings
use Laxmidhar\DesiCurrency\Facades\Currency; $properties = Property::all(); foreach ($properties as $property) { $price = $property->price; // Display appropriate format based on range if (Currency::isCroresRange($price)) { echo $property->title . ': ' . Currency::toCrores($price); } else if (Currency::isLakhsRange($price)) { echo $property->title . ': ' . Currency::toLakhs($price); } else { echo $property->title . ': ' . Currency::format($price); } } // Output examples: // "Luxury Villa: ₹2.50 Crores" // "2BHK Apartment: ₹45.00 Lakhs" // "Plot: ₹25,00,000.00"
Blade Templates
{{-- Simple formatting --}} <h3>Price: {{ Currency::format($product->price) }}</h3> {{-- Shorthand for cards --}} <div class="price-tag"> {{ Currency::toShorthand($product->price) }} </div> {{-- Invoice display --}} <div class="invoice-total"> <strong>Total:</strong> {{ Currency::format($invoice->total) }}<br> <small>{{ Currency::toIndianWords($invoice->total) }}</small> </div> {{-- Conditional display --}} @if(Currency::isCroresRange($amount)) <span class="badge">{{ Currency::toCrores($amount) }}</span> @else <span class="badge">{{ Currency::toLakhs($amount) }}</span> @endif
🎯 Best Practices
1. Consistent Display
Use the same format throughout your application for consistency:
// Good: Consistent format echo Currency::toShorthand($amount); // Throughout app // Avoid: Mixing formats randomly echo Currency::format($amount); echo Currency::toWords($amount);
2. Store as Numeric, Display as Formatted
Always store amounts as numeric values in database:
// Storage (numeric) $product->price = 150000; // Display (formatted) echo Currency::toWords($product->price);
3. Handle User Input Properly
Parse user input before storing:
$input = request('amount'); // "1.5L" $numeric = Currency::parse($input); $model->amount = $numeric; // Store: 150000
4. Use Appropriate Format for Context
Choose format based on where it's displayed:
// Dashboards: Shorthand echo Currency::toShorthand($revenue); // Reports: Full format echo Currency::format($revenue); // Invoices: Words echo Currency::toIndianWords($total); // Cards: Words format echo Currency::toWords($amount);
5. Handle Negative Amounts
Always check for negative values:
$balance = -5000; // Use accounting format for negatives echo Currency::formatAccounting($balance); // Output: "(₹5,000.00)"
🧪 Testing
Run the test suite:
composer test
Run tests with coverage:
composer test:coverage
Example Test Cases
use Laxmidhar\DesiCurrency\Facades\Currency; test('formats amount in Indian style', function () { expect(Currency::format(123456.78)) ->toBe('₹1,23,456.78'); }); test('converts to lakhs notation', function () { expect(Currency::toWords(150000)) ->toBe('₹1.5 Lakh'); }); test('parses shorthand notation', function () { expect(Currency::parse('1.5L')) ->toBe(150000.0); }); test('converts to Indian words', function () { expect(Currency::toIndianWords(1234.50)) ->toBe('One Thousand Two Hundred Thirty Four Rupees and Fifty Paise'); });
📊 Comparison with Other Solutions
Feature | Desi Currency | Manual Formatting | Other Packages |
---|---|---|---|
Indian Numbering | ✅ | ❌ | ⚠️ Limited |
Lakh/Crore Support | ✅ | ❌ | ❌ |
Shorthand Parsing | ✅ | ❌ | ❌ |
Words Conversion | ✅ | ❌ | ⚠️ English only |
Zero Config | ✅ | N/A | ❌ |
Laravel Integration | ✅ | N/A | ⚠️ Limited |
🔒 Security
If you discover any security-related issues, please email papu.team7@gmail.com instead of using the issue tracker.
🤝 Contributing
Contributions are welcome! Please follow these steps:
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature
) - Commit your changes (
git commit -m 'Add some amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - Open a Pull Request
Please ensure:
- All tests pass
- Code follows PSR-12 standards
- New features include tests
- Documentation is updated
📝 Changelog
Please see CHANGELOG for recent changes.
📄 License
This package is open-sourced software licensed under the MIT license.
👨💻 Author
Laxmidhar Maharana
Senior Laravel Developer • Open Source Contributor
⭐ Show Your Support
If this package helped you, please give it a ⭐️ on GitHub!
🙏 Acknowledgments
Special thanks to:
- The Laravel community for inspiration
- Contributors who helped improve this package
- Indian developers who understand the pain of currency formatting
📚 Related Packages
- Laravel Helpers - 85+ Helper Functions
- Laravel Money - Money handling
- Laravel Cashier - Subscription billing
🗺️ Roadmap
- Add support for other Indian regional formats
- Currency conversion support
- GST calculations
- Tax computation helpers
- Multi-currency support
- Blade directives for formatting
❓ FAQ
Q: Can I use this for non-Indian currencies?
A: This package is specifically designed for Indian Rupee and Indian numbering system. For other currencies, consider using Laravel Money or similar packages.
Q: Does it handle GST calculations?
A: Not yet, but it's on the roadmap. Current version focuses on formatting and conversion.
Q: Can I customize the decimal places?
A: Yes, methods like toLakhs()
and toCrores()
accept a $decimals
parameter.
Q: Does it work with Blade templates?
A: Yes! You can use the Currency
facade directly in Blade templates as shown in the examples above.
Q: How do I handle very large amounts (Thousands of Crores)?
A: The package handles amounts up to PHP's float limit. For extremely large numbers, consider using BC Math functions.
Made with ❤️ for Indian Developers
Supporting Digital India • Made in India 🇮🇳