Rupert  Beatty

Rupert Beatty

1660153620

Akaunting: Free and Online Accounting Software

Akaunting™  

Akaunting is a free, open source and online accounting software designed for small businesses and freelancers. It is built with modern technologies such as Laravel, VueJS, Tailwind, RESTful API etc. Thanks to its modular structure, Akaunting provides an awesome App Store for users and developers.

Requirements

  • PHP 8.0 or higher
  • Database (eg: MySQL, PostgreSQL, SQLite)
  • Web Server (eg: Apache, Nginx, IIS)
  • Other libraries

Framework

Akaunting uses Laravel, the best existing PHP framework, as the foundation framework and Module package for Apps.

Installation

  • Install Composer and Npm
  • Clone the repository: git clone https://github.com/akaunting/akaunting.git
  • Install dependencies: composer install ; npm install ; npm run dev
  • Install Akaunting:
php artisan install --db-name="akaunting" --db-username="root" --db-password="pass" --admin-email="admin@company.com" --admin-password="123456"
  • Create sample data (optional): php artisan sample-data:seed

Contributing

Please, be very clear on your commit messages and pull requests, empty pull request messages may be rejected without reason.

When contributing code to Akaunting, you must follow the PSR coding standards. The golden rule is: Imitate the existing Akaunting code.

Please note that this project is released with a Contributor Code of Conduct. By participating in this project you agree to abide by its terms.

Translation

If you'd like to contribute translations, please check out our Crowdin project.

Changelog

Please see Releases for more information what has changed recently.

Security

Please review our security policy on how to report security vulnerabilities.

Credits



Download Details:

Author: Akaunting
Source Code: https://github.com/akaunting/akaunting 
License: GPL-3.0 license

#laravel #php #money 

Akaunting: Free and Online Accounting Software

Money plugin: Adds support for the Money database type in CakePHP 3

Money (DataType)  

Adds support for the Money database type in CakePHP 3.

Install

Using Composer:

composer require gourmet/money:dev-master

You then need to load the plugin. In boostrap.php, something like:

\Cake\Core\Plugin::load('Gourmet/Money', ['bootstrap' => true]);

NOTE: Important to autoload the plugin's bootstrap.php, which will register the new money type.

Usage

In your table, define the money columns like so:

use Cake\Database\Schema\Table as Schema;

class OrdersTable extends Table
{
    protected function _initializeSchema(Schema $schema)
    {
        $schema->columnType('total', 'money');
        return $schema;
    }
}

For more details on DataTypes, read the official CakePHP 3 documentation.

Patches & Features

  • Fork
  • Mod, fix
  • Test - this is important, so it's not unintentionally broken
  • Commit - do not mess with license, todo, version, etc. (if you do change any, bump them into commits of their own that I can ignore when I pull)
  • Pull request - bonus point for topic branches

Bugs & Feedback

http://github.com/gourmet/money/issues

Author: Gourmet
Source Code: https://github.com/gourmet/money 
License: MIT license

#php #money #cakephp 

Money plugin: Adds support for the Money database type in CakePHP 3
Akshara Singh

Akshara Singh

1655895208

In what way does the Localbitcoins clone script generate revenue?

One of the most popular crypto exchanges is Localbitcoins which comes under a P2P-based crypto exchange type. Being an entrepreneur, one can make their dream crypto exchange business a practical one with the help of this Localbitcoins clone script. As you might be aware of the crypto exchange’s various benefits and also the benefits of integrating it with the help of the #localbitcoin clone script. In spite of various unmatched benefits being offered, some #entrepreneurs remain unsolved regarding the revenue patterns. Let’s have a closer look at it,


As it is clear that the Localbitcoins clone script enables you to launch a well-defined P2P crypto exchange with ease. Once after establishing a P2P #crypto exchange, you’ll be all set for beginning your business. After making it through the initial phase and your marketing phase, more users will be starting to flow to your #p2p crypto exchange. That’s where your journey begins. Here are some of the revenue-generating methods,

Revenue generation streams

Fiat deposit/Crypto withdrawal fee

Well, after attaining a reasonable amount of users for your crypto exchange, they’ll be starting to engage themselves with the trading where they’ll be required to deposit some amount of fiat #money in their account. A minimal percentage can be charged for them by the admin of the exchange (you). Once after getting done with their transactions, some may wish to withdraw the bought cryptocurrencies. A certain percentage can also be claimed for this action.

Advertisement fee

You know that P2P crypto exchange is meant for making transactions with high privacy, so the users will be required to post their requirements in the form of ads. For that, a negligible percentage can be claimed from the admin side.


Listing fee

This fast-growing world and technology haven’t settled for any average moves. As it multiplies rapidly, there emerge new cryptocurrencies every day and some of them might prefer to list them on your exchange. In turn, you could offer them a price as a fee for listing their new cryptocurrencies.  


As mentioned above, these are some sort of the ways where this Localbitcoins clone script acts as a pillar for generating revenue for your business. After recognizing its real potential and efficiency all you have to do is to choose the best Localbitcoins clone script. Which enlightens your crypto exchange #business further and takes it to the next level. Obviously, a featured service can be availed by reaching a professional provider. That’s how to experience the above-mentioned revenue one should attain the Localbitcoins clone script from a standard crypto exchange software provider.

Coming to the point, as there is a huge competition among various crypto exchange software providers to offer this Localbitcoins clone script, sorting out the genuine ones among them is quite complicated. Probably it might take weeks just to find a suitable one. Surprisingly, I’ve unloaded all of your burdens by making that research for my own purpose. The result was absolutely shocking. Coinsclone seems to be a perfect fit among others. They have been serving in this industry with their expertise in blockchain tech and have delivered hundreds of projects that turned many business people’s life. Have a look at their individuality >>>> COINSCLONE
 

Reggie  Hudson

Reggie Hudson

1653986520

Tips To Make Money With Rumble in 2022 ($100 Per Day)

Learn how to make money with Rumble in 2022 as a complete beginner. Rumble is a popular video sharing service which has been getting a lot of attention recently. The app promotes itself as one where users can…

#app #money 

Tips To Make Money With Rumble in 2022 ($100 Per Day)
Reggie  Hudson

Reggie Hudson

1653979140

Tips to Make Money with Transcribeme As A Complete Beginner

Learn how to make money with transcribeme as a complete beginner. TranscribeMe offers fast, affordable, and highly accurate human transcription, translation, data annotation, and AI dataset services customized for your…

#app #money 

Tips to Make Money with Transcribeme As A Complete Beginner
Reggie  Hudson

Reggie Hudson

1653971820

Tips to Make Money with Rev.com As A Complete Beginner

Learn how to make money with rev.com as a complete beginner.

Rev is a company that provides transcription, translation, and captioning services to companies such as PBS and Comcast. They do this with both in-house staff, and work-at-home freelancers.

#app #money 

Tips to Make Money with Rev.com As A Complete Beginner
Reggie  Hudson

Reggie Hudson

1653964560

Tips to Make Money on Etoro in 2022

Learn how to make money on Etoro in 2022.

eToro is a bustling online social network where traders can interact, discuss ideas, and share decisions and strategies.

#app #money 

Tips to Make Money on Etoro in 2022
Oral  Brekke

Oral Brekke

1653550140

Lightweight Currency Conversion Library, Successor Of Money.js

Cashify 💸

Lightweight currency conversion library, successor of money.js

Motivation

This package was created, because the popular money.js library:

  • is not maintained (last commit was ~5 years ago)
  • has over 20 open issues
  • does not support TypeScript
  • has implicit globals
  • does not have any unit tests
  • has floating point issues

Highlights

Install

$ npm install cashify

Please note that starting with version 3.0.0 this package is ESM-only and thus requires Node.js v14 or higher.

Usage

With constructor

import {Cashify} from 'cashify';

const rates = {
	GBP: 0.92,
	EUR: 1.00,
	USD: 1.12
};

const cashify = new Cashify({base: 'EUR', rates});

const result = cashify.convert(10, {from: 'EUR', to: 'GBP'});

console.log(result); //=> 9.2

Without constructor

Using the Cashify constructor is not required. Instead, you can just use the convert function:

import {convert} from 'cashify';

const rates = {
	GBP: 0.92,
	EUR: 1.00,
	USD: 1.12
};

const result = convert(10, {from: 'EUR', to: 'GBP', base: 'EUR', rates});

console.log(result); //=> 9.2

Parsing

Cashify supports parsing, so you can pass a string to the amount argument and the from and/or to currency will be automatically detected:

import {Cashify} from 'cashify';

const rates = {
	GBP: 0.92,
	EUR: 1.00,
	USD: 1.12
};

const cashify = new Cashify({base: 'EUR', rates});

// Basic parsing
cashify.convert('€10 EUR', {to: 'GBP'});

// Full parsing
cashify.convert('10 EUR to GBP');

Alternatively, if you just want to parse a string without conversion you can use the parse function which returns an object with parsing results:

import {parse} from 'cashify';

parse('10 EUR to GBP'); //=> {amount: 10, from: 'EUR', to: 'GBP'}

Note: If you want to use full parsing, you need to pass a string in a specific format:

10 usd to pln
12.5 GBP in EUR
3.1415 eur as chf

You can use to, in or as to separate the expression (case insensitive). Used currencies name case doesn't matter, as cashify will automatically convert them to upper case.

Integration with big.js

big.js is a small JavaScript library for arbitrary-precision decimal arithmetic. You can use it with cashify to make sure you won't run into floating point issues:

import {Cashify} from 'cashify';
import Big from 'big.js';

const rates = {
	EUR: 0.8235,
	USD: 1
};

const cashify = new Cashify({base: 'USD', rates});

const result = cashify.convert(1, {
	from: 'USD',
	to: 'EUR',
	BigJs: Big
});

console.log(result); //=> 8.235 (without big.js you would get something like 0.8234999999999999)

Integration with currency.js

currency.js is a small and lightweight library for working with currency values. It integrates well with cashify. In the following example we are using it to format the conversion result:

import {Cashify} from 'cashify';
import currency from 'currency.js';

const rates = {
	GBP: 0.92,
	EUR: 1.00,
	USD: 1.12
};

const cashify = new Cashify({base: 'EUR', rates});

const converted = cashify.convert(8635619, {from: 'EUR', to: 'GBP'}); // => 7944769.48

// Format the conversion result
currency(converted, {symbol: '€', formatWithSymbol: true}).format(); // => €7,944,769.48

API

Cashify({base, rates, BigJs})

Constructor.

base

Type: string

The base currency.

rates

Type: object

An object containing currency rates (for example from an API, such as Open Exchange Rates).

BigJs

Type: big.js constructor

See integration with big.js.

convert(amount, {from, to, base, rates}) with and without constructor

Returns conversion result (number).

amount

Type: number or string

Amount of money you want to convert. You can either use a number or a string. If you choose the second option, you can take advantage of parsing and not specify from and/or to argument(s).

from

Type: string

Currency from which you want to convert. You might not need to specify it if you are using parsing.

to

Type: string

Currency to which you want to convert. You might not need to specify it if you are using parsing.

base

Type: string

The base currency.

rates

Type: object

An object containing currency rates (for example from an API, such as Open Exchange Rates).

BigJs

Type: big.js constructor

See integration with big.js.

parse(expression)

Returns an object, which contains parsing results:

{
	amount: number;
	from: string | undefined;
	to: string | undefined;
}

expression

Type: string

Expression you want to parse, ex. 10 usd to pln or €1.23 eur

Migrating from money.js

With Cashify constructor:

- import fx from 'money';
+ import {Cashify} from 'cashify';

- fx.base = 'EUR';
- fx.rates = {
-	GBP: 0.92,
-	EUR: 1.00,
-	USD: 1.12
- };

+ const rates = {
+	 GBP: 0.92,
+	 EUR: 1.00,
+	 USD: 1.12
+ };

+ const cashify = new Cashify({base: 'EUR', rates});

- fx.convert(10, {from: 'GBP', to: 'EUR'});
+ cashify.convert(10, {from: 'GBP', to: 'EUR'});

With convert function:

- import fx from 'money';
+ import {convert} from 'cashify';

- fx.base = 'EUR';
- fx.rates = {
-	GBP: 0.92,
-	EUR: 1.00,
-	USD: 1.12
- };

+ const rates = {
+	 GBP: 0.92,
+	 EUR: 1.00,
+	 USD: 1.12
+ };

- fx.convert(10, {from: 'GBP', to: 'EUR'});
+ convert(10, {from: 'GBP', to: 'EUR', base: 'EUR', rates});

Floating point issues

When working with currencies, decimals only need to be precise up to the smallest cent value while avoiding common floating point errors when performing basic arithmetic.

Let's take a look at the following example:

import fx from 'money';
import {Cashify} from 'cashify';

const rates = {
	GBP: 0.92,
	USD: 1.12
};

fx.rates = rates;
fx.base = 'EUR';

const cashify = new Cashify({base: 'EUR', rates});

fx.convert(10, {from: 'EUR', to: 'GBP'}); //=> 9.200000000000001
cashify.convert(10, {from: 'EUR', to: 'GBP'}); //=> 9.2

As you can see, money.js doesn't handle currencies correctly and therefore a floating point issues are occuring. Even though there's just a minor discrepancy between the results, if you're converting large amounts, that can add up.

Cashify solves this problem the same way as currency.js - by working with integers behind the scenes. This should be okay for most reasonable values of currencies; if you want to avoid all floating point issues, see integration with big.js.

Related projects

Author: xxczaki
Source Code: https://github.com/xxczaki/cashify 
License: MIT license

#node #npm #convert #money 

Lightweight Currency Conversion Library, Successor Of Money.js
Veronica  Roob

Veronica Roob

1651551780

Brick\Money: A Money and Currency Library for PHP

Brick\Money

A money and currency library for PHP.

Introduction

Working with financial data is a serious matter, and small rounding mistakes in an application may lead to serious consequences in real life. That's why floating-point arithmetic is not suited for monetary calculations.

This library is based on brick/math and handles exact calculations on monies of any size.

Installation

This library is installable via Composer:

composer require brick/money

Requirements

This library requires PHP 7.1 or later.

Although not required, it is recommended that you install the GMP or BCMath extension to speed up calculations.

Project status & release process

While this library is still under development, it is well tested and should be stable enough to use in production environments.

The current releases are numbered 0.x.y. When a non-breaking change is introduced (adding new methods, optimizing existing code, etc.), y is incremented.

When a breaking change is introduced, a new 0.x version cycle is always started.

It is therefore safe to lock your project to a given release cycle, such as 0.5.*.

If you need to upgrade to a newer release cycle, check the release history for a list of changes introduced by each further 0.x.0 version.

Creating a Money

To create a Money, call the of() factory method:

use Brick\Money\Money;

$money = Money::of(50, 'USD'); // USD 50.00
$money = Money::of('19.9', 'USD'); // USD 19.90

Alternatively, you can create a Money from a number of "minor units" (cents), using the ofMinor() method:

use Brick\Money\Money;

$money = Money::ofMinor(1234, 'USD'); // USD 12.34

Basic operations

Money is an immutable class: its value never changes, so it can be safely passed around. All operations on a Money therefore return a new instance:

use Brick\Money\Money;

$money = Money::of(50, 'USD');

echo $money->plus('4.99'); // USD 54.99
echo $money->minus(1); // USD 49.00
echo $money->multipliedBy('1.999'); // USD 99.95
echo $money->dividedBy(4); // USD 12.50

You can add and subtract Money instances as well:

use Brick\Money\Money;

$cost = Money::of(25, 'USD');
$shipping = Money::of('4.99', 'USD');
$discount = Money::of('2.50', 'USD');

echo $cost->plus($shipping)->minus($discount); // USD 27.49

If the two Money instances are not of the same currency, an exception is thrown:

use Brick\Money\Money;

$a = Money::of(1, 'USD');
$b = Money::of(1, 'EUR');

$a->plus($b); // MoneyMismatchException

If the result needs rounding, a rounding mode must be passed as second parameter, or an exception is thrown:

use Brick\Money\Money;
use Brick\Math\RoundingMode;

$money = Money::of(50, 'USD');

$money->plus('0.999'); // RoundingNecessaryException
$money->plus('0.999', RoundingMode::DOWN); // USD 50.99

$money->minus('0.999'); // RoundingNecessaryException
$money->minus('0.999', RoundingMode::UP); // USD 49.01

$money->multipliedBy('1.2345'); // RoundingNecessaryException
$money->multipliedBy('1.2345', RoundingMode::DOWN); // USD 61.72

$money->dividedBy(3); // RoundingNecessaryException
$money->dividedBy(3, RoundingMode::UP); // USD 16.67

Money contexts

By default, monies have the official scale for the currency, as defined by the ISO 4217 standard (for example, EUR and USD have 2 decimal places, while JPY has 0) and increment by steps of 1 minor unit (cent); they internally use what is called the DefaultContext. You can change this behaviour by providing a Context instance. All operations on Money return another Money with the same context. Each context targets a particular use case:

Cash rounding

Some currencies do not allow the same increments for cash and cashless payments. For example, CHF (Swiss Franc) has 2 fraction digits and allows increments of 0.01 CHF, but Switzerland does not have coins of less than 5 cents, or 0.05 CHF.

You can deal with such monies using CashContext:

use Brick\Money\Money;
use Brick\Money\Context\CashContext;
use Brick\Math\RoundingMode;

$money = Money::of(10, 'CHF', new CashContext(5)); // CHF 10.00
$money->dividedBy(3, RoundingMode::DOWN); // CHF 3.30
$money->dividedBy(3, RoundingMode::UP); // CHF 3.35

Custom scale

You can use custom scale monies by providing a CustomContext:

use Brick\Money\Money;
use Brick\Money\Context\CustomContext;
use Brick\Math\RoundingMode;

$money = Money::of(10, 'USD', new CustomContext(4)); // USD 10.0000
$money->dividedBy(7, RoundingMode::UP); // USD 1.4286

Auto scale

If you need monies that adjust their scale to fit the operation result, then AutoContext is for you:

use Brick\Money\Money;
use Brick\Money\Context\AutoContext;

$money = Money::of('1.10', 'USD', new AutoContext()); // USD 1.1
$money->multipliedBy('2.5'); // USD 2.75
$money->dividedBy(8); // USD 0.1375

Note that it is not advised to use AutoContext to represent an intermediate calculation result: in particular, it cannot represent the result of all divisions, as some of them may lead to an infinite repeating decimal, which would throw an exception. For these use cases, RationalMoney is what you need. Head on to the next section!

Advanced calculations

You may occasionally need to chain several operations on a Money, and only apply a rounding mode on the very last step; if you applied a rounding mode on every single operation, you might end up with a different result. This is where RationalMoney comes into play. This class internally stores the amount as a rational number (a fraction). You can create a RationalMoney from a Money, and conversely:

use Brick\Money\Money;
use Brick\Math\RoundingMode;

$money = Money::of('9.5', 'EUR') // EUR 9.50
  ->toRational() // EUR 950/100
  ->dividedBy(3) // EUR 950/300
  ->plus('17.795') // EUR 6288500/300000
  ->multipliedBy('1.196') // EUR 7521046000/300000000
  ->to($money->getContext(), RoundingMode::DOWN) // EUR 25.07

As you can see, the intermediate results are represented as fractions, and no rounding is ever performed. The final to() method converts it to a Money, applying a context and a rounding mode if necessary. Most of the time you want the result in the same context as the original Money, which is what the example above does. But you can really apply any context:

...
  ->to(new CustomContext(8), RoundingMode::UP); // EUR 25.07015334

Note: as you can see in the example above, the numbers in the fractions can quickly get very large. This is usually not a problem—there is no hard limit on the number of digits involved in the calculations—but if necessary, you can simplify the fraction at any time, without affecting the actual monetary value:

...
  ->multipliedBy('1.196') // EUR 7521046000/300000000
  ->simplified() // EUR 3760523/150000

Money allocation

You can easily split a Money into a number of parts:

use Brick\Money\Money;

$money = Money::of(100, 'USD');
[$a, $b, $c] = $money->split(3); // USD 33.34, USD 33.33, USD 33.33

You can also allocate a Money according to a list of ratios. Say you want to distribute a profit of 987.65 CHF to 3 shareholders, having shares of 48%, 41% and 11% of a company:

use Brick\Money\Money;

$profit = Money::of('987.65', 'CHF');
[$a, $b, $c] = $profit->allocate(48, 41, 11); // CHF 474.08, CHF 404.93, CHF 108.64

It plays well with cash roundings, too:

use Brick\Money\Money;
use Brick\Money\Context\CashContext;

$profit = Money::of('987.65', 'CHF', new CashContext(5));
[$a, $b, $c] = $profit->allocate(48, 41, 11); // CHF 474.10, CHF 404.95, CHF 108.60

Note that the ratios can be any (non-negative) integer values and do not need to add up to 100.

When the allocation yields a remainder, both split() and allocate() spread it on the first monies in the list, until the total adds up to the original Money. This is the algorithm suggested by Martin Fowler in his book Patterns of Enterprise Application Architecture. You can see that in the first example, where the first money gets 33.34 dollars while the others get 33.33 dollars.

Money bags (mixed currencies)

You may sometimes need to add monies in different currencies together. MoneyBag comes in handy for this:

use Brick\Money\Money;
use Brick\Money\MoneyBag;

$eur = Money::of('12.34', 'EUR');
$jpy = Money::of(123, 'JPY');

$moneyBag = new MoneyBag();
$moneyBag->add($eur);
$moneyBag->add($jpy);

You can add any kind of money to a MoneyBag: a Money, a RationalMoney, or even another MoneyBag.

Note that unlike other classes, MoneyBag is mutable: its value changes when you call add() or subtract().

What can you do with a MoneyBag? Well, you can convert it to a Money in the currency of your choice, using a CurrencyConverter. Keep reading!

Currency conversion

This library ships with a CurrencyConverter that can convert any kind of money (Money, RationalMoney or MoneyBag) to a Money in another currency:

use Brick\Money\CurrencyConverter;

$exchangeRateProvider = ...;
$converter = new CurrencyConverter($exchangeRateProvider); // optionally provide a Context here

$money = Money::of('50', 'USD');
$converter->convert($money, 'EUR', RoundingMode::DOWN);

The converter performs the most precise calculation possible, internally representing the result as a rational number until the very last step.

To use the currency converter, you need an ExchangeRateProvider. Several implementations are provided, among which:

ConfigurableProvider

This provider starts with a blank state, and allows you to add exchange rates manually:

use Brick\Money\ExchangeRateProvider\ConfigurableProvider;

$provider = new ConfigurableProvider();
$provider->setExchangeRate('EUR', 'USD', '1.0987');
$provider->setExchangeRate('USD', 'EUR', '0.9123');

PDOProvider

This provider reads exchange rates from a database table:

use Brick\Money\ExchangeRateProvider\PDOProvider;
use Brick\Money\ExchangeRateProvider\PDOProviderConfiguration;

$pdo = new \PDO(...);

$configuration = new PDOProviderConfiguration;
$configuration->tableName = 'exchange_rates';
$configuration->sourceCurrencyColumnName = 'source_currency_code';
$configuration->targetCurrencyColumnName = 'target_currency_code';
$configuration->exchangeRateColumnName = 'exchange_rate';

$provider = new PDOProvider($pdo, $configuration);

PDOProvider also supports fixed source or target currency, and dynamic WHERE conditions. Check the PDOProviderConfiguration class for more information.

BaseCurrencyProvider

This provider builds on top of another exchange rate provider, for the quite common case where all your available exchange rates are relative to a single currency. For example, the exchange rates provided by the European Central Bank are all relative to EUR. You can use them directly to convert EUR to USD, but not USD to EUR, let alone USD to GBP.

This provider will combine exchange rates to get the expected result:

use Brick\Money\ExchangeRateProvider\ConfigurableProvider;
use Brick\Money\ExchangeRateProvider\BaseCurrencyProvider;

$provider = new ConfigurableProvider();
$provider->setExchangeRate('EUR', 'USD', '1.1');
$provider->setExchangeRate('EUR', 'GBP', '0.9');

$provider = new BaseCurrencyProvider($provider, 'EUR');
$provider->getExchangeRate('EUR', 'USD'); // 1.1
$provider->getExchangeRate('USD', 'EUR'); // 10/11
$provider->getExchangeRate('GBP', 'USD'); // 11/9

Notice that exchange rate providers can return rational numbers!

Write your own provider

Writing your own provider is easy: the ExchangeRateProvider interface has just one method, getExchangeRate(), that takes the currency codes and returns a number.

Custom currencies

Money supports ISO 4217 currencies by default. You can also use custom currencies by creating a Currency instance. Let's create a Bitcoin currency:

use Brick\Money\Currency;
use Brick\Money\Money;

$bitcoin = new Currency(
    'XBT',     // currency code
    0,         // numeric currency code, useful when storing monies in a database; set to 0 if unused
    'Bitcoin', // currency name
    8          // default scale
);

You can now use this Currency instead of a currency code:

$money = Money::of('0.123', $bitcoin); // XBT 0.12300000

Formatting

Formatting requires the intl extension.

Money objects can be formatted according to a given locale:

$money = Money::of(5000, 'USD');
echo $money->formatTo('en_US'); // $5,000.00
echo $money->formatTo('fr_FR'); // 5 000,00 $US

Alternatively, you can format Money objects with your own instance of NumberFormatter, which gives you room for customization:

$formatter = new \NumberFormatter('en_US', \NumberFormatter::CURRENCY);
$formatter->setSymbol(\NumberFormatter::CURRENCY_SYMBOL, 'US$');
$formatter->setSymbol(\NumberFormatter::MONETARY_GROUPING_SEPARATOR_SYMBOL, '·');
$formatter->setAttribute(\NumberFormatter::MIN_FRACTION_DIGITS, 2);

$money = Money::of(5000, 'USD');
echo $money->formatWith($formatter); // US$5·000.00

Important note: because formatting is performed using NumberFormatter, the amount is converted to floating point in the process; so discrepancies can appear when formatting very large monetary values.

Storing the monies in the database

Persisting the amount

As an integer: in many applications, monies are only ever used with their default scale (e.g. 2 decimal places for USD, 0 for JPY). In this case, the best practice is to store minor units (cents) as an integer field:

And later retrieve it as:

This approach works well with all currencies, without having to worry about the scale. You only have to worry about not overflowing an integer (which would throw an exception), but this is unlikely to happen unless you're dealing with huge amounts of money.

Money::ofMinor($integerAmount, $currencyCode);
$integerAmount = $money->getMinorAmount()->toInt();

As a decimal: for most other cases, storing the amount string as a decimal type is advised:

And later retrieve it as:

Money::of($decimalAmount, $currencyCode);
$decimalAmount = (string) $money->getAmount();

Persisting the currency

As a string: if you only deal with ISO currencies, or custom currencies having a 3-letter currency code, you can store the currency in a CHAR(3). Otherwise, you'll most likely need a VARCHAR. You may also use an ENUM if your application uses a fixed list of currencies.

When retrieving the currency: you can use ISO currency codes directly in Money::of() and Money::ofMinor(). For custom currencies, you'll need to convert them to Currency instances first.

$currencyCode = $money->getCurrency()->getCurrencyCode();

As an integer: if you only deal with ISO currencies, or custom currencies with a numeric code, you may store the currency code as an integer:

When retrieving the currency: you can use numeric codes of ISO currencies directly in Money::of() and Money::ofMinor(). For custom currencies, you'll need to convert them to Currency instances first.

$numericCode = $money->getCurrency()->getNumericCode();

Hardcoded: if your application only ever deals with one currency, you may very well hardcode the currency code and not store it in your database at all.

Using an ORM

If you're using an ORM such as Doctrine, it is advised to store the amount and currency separately, and perform conversion in the getters/setters:

class Entity
{
    private int $price;
    private string $currencyCode;

    public function getPrice() : Money
    {
        return Money::ofMinor($this->price, $this->currencyCode);
    }

    public function setPrice(Money $price) : void
    {
        $this->price = $price->getMinorAmount()->toInt();
        $this->currencyCode = $price->getCurrency()->getCurrencyCode();
    }
}

FAQ

How does this project compare with moneyphp/money?

Please see this discussion.

brick/money for enterprise

Available as part of the Tidelift Subscription.

The maintainers of brick/money and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. Learn more.

Author: brick
Source Code: https://github.com/brick/money
License: MIT License

#php #money 

Brick\Money: A Money and Currency Library for PHP
Veronica  Roob

Veronica Roob

1651544400

Money: PHP Library to Make Working with Money Safer, Easier and Fun

Money

Money PHP

PHP library to make working with money safer, easier, and fun!

"If I had a dime for every time I've seen someone use FLOAT to store currency, I'd have $999.997634" -- Bill Karwin

In short: You shouldn't represent monetary values by a float. Wherever you need to represent money, use this Money value object. Since version 3.0 this library uses strings internally in order to support unlimited integers.

<?php

use Money\Money;

$fiveEur = Money::EUR(500);
$tenEur = $fiveEur->add($fiveEur);

list($part1, $part2, $part3) = $tenEur->allocate([1, 1, 1]);
assert($part1->equals(Money::EUR(334)));
assert($part2->equals(Money::EUR(333)));
assert($part3->equals(Money::EUR(333)));

The documentation is available at http://moneyphp.org

Requirements

This library requires the BCMath PHP extension. There might be additional dependencies for specific feature, e.g. the Swap exchange implementation, check the documentation for more information.

Version 4 requires PHP 8.0. For older version of PHP, use version 3 of this library.

Install

Via Composer

$ composer require moneyphp/money

Features

  • JSON Serialization
  • Big integer support utilizing different, transparent calculation logic upon availability (bcmath, gmp, plain php)
  • Money formatting (including intl formatter)
  • Currency repositories (ISO currencies included)
  • Money exchange (including Swap implementation)

Documentation

Please see the official documentation.

Testing

We try to follow BDD and TDD, as such we use both phpspec and phpunit to test this library.

$ composer test

Running the tests in Docker

Money requires a set of dependencies, so you might want to run it in Docker.

First, build the image locally:

$ docker build -t moneyphp .

Then run the tests:

$ docker run --rm -it -v $PWD:/app -w /app moneyphp vendor/bin/phpunit --exclude-group segmentation

Contributing

We would love to see you helping us to make this library better and better. Please keep in mind we do not use suffixes and prefixes in class names, so not CurrenciesInterface, but Currencies. Other than that, Style CI will help you using the same code style as we are using. Please provide tests when creating a PR and clear descriptions of bugs when filing issues.

Security

If you discover any security related issues, please contact us at team@moneyphp.org.

License

The MIT License (MIT). Please see License File for more information.

Acknowledgements

This library is heavily inspired by Martin Fowler's Money pattern. A special remark goes to Mathias Verraes, without his contributions, in code and via his blog, this library would not be where it stands now.

Author: moneyphp
Source Code: https://github.com/moneyphp/money
License: MIT License

#php #money 

Money: PHP Library to Make Working with Money Safer, Easier and Fun

TbbcMoneyBundle: Bundle is used to integrate the Money library

TbbcMoneyBundle

This bundle is used to integrate the Money library from mathiasverraes into a Symfony project.

This library is based on Fowler's Money pattern

  • This bundle is tested and is stable with Symfony 3.4, 4.3, 4.4, 5.0

Quick Start

use Money\Money;
use Tbbc\MoneyBundle\Form\Type\MoneyType;

// the money library
$fiveEur = Money::EUR(500);
$tenEur = $fiveEur->add($fiveEur);
list($part1, $part2, $part3) = $tenEur->allocate(array(1, 1, 1));
assert($part1->equals(Money::EUR(334)));
assert($part2->equals(Money::EUR(333)));
assert($part3->equals(Money::EUR(333)));

// a service that stores conversion ratios
$pairManager = $this->get('tbbc_money.pair_manager');
$usd = $pairManager->convert($tenEur, 'USD');

// a form integration
$formBuilder->add('price', MoneyType::class);

Features

  • Integrates money library from mathiasverraes
  • Twig filters and PHP helpers for helping with money and currencies in templates
  • A storage system for currency ratios
  • A ratioProvider system for fetching ratio from externals api
  • Symfony form integration
  • Console commands for different operations
  • A configuration parser for specifying website used currencies
  • Access to the history of currency ratio fetched
  • Money formatter i18n

Table of contents

Installation

Use Composer and install with
$ composer require tbbc/money-bundle

If you use Symfony 3 then add the bundle to AppKernel:

    public function registerBundles()
    {
        $bundles = array(
            // ...
            new Tbbc\MoneyBundle\TbbcMoneyBundle(),
        );
    }

For Symfony 4 and higher add the bundle to config/bundles.php (if it was not automatically added during the installation of the package):

    return [
        // ...
        Tbbc\MoneyBundle\TbbcMoneyBundle::class => ['all' => true],
    ];

For Symfony 3, in your config.yml, add the currencies you want to use and the reference currency. For Symfony 4 and higher create a file like config/packages/tbbc_money.yml and add it there.

tbbc_money:
    currencies: ["USD", "EUR"]
    reference_currency: "EUR"
    decimals: 2

In your config.yml or config/packages/tbbc_money.yml, add the form fields presentations

twig:
    form_themes:
        - '@TbbcMoney/Form/fields.html.twig'

You should also register custom Doctrine Money type:

doctrine:
    dbal:
        types:
            money: Tbbc\MoneyBundle\Type\MoneyType

Usage

Money Library integration

use Money\Money;

$fiveEur = Money::EUR(500);
$tenEur = $fiveEur->add($fiveEur);
list($part1, $part2, $part3) = $tenEur->allocate(array(1, 1, 1));
assert($part1->equals(Money::EUR(334)));
assert($part2->equals(Money::EUR(333)));
assert($part3->equals(Money::EUR(333)));

$pair = new CurrencyPair(new Currency('EUR'), new Currency('USD'), 1.2500);
$usd = $pair->convert($tenEur);
$this->assertEquals(Money::USD(1250), $usd);

Form integration

You have 3 new form types (under Tbbc\MoneyBundle\Form\Type namespace):

  • CurrencyType : asks for a currency among currencies defined in config.yml
  • MoneyType : asks for an amount and a currency
  • SimpleMoneyType : asks for an amount and sets the currency to the reference currency set in config.yml

Example :

use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;

// I create my form
$form = $this->createFormBuilder()
    ->add('name', TextType::class)
    ->add('price', MoneyType::class, [
        'data' => Money::EUR(1000), //EUR 10
    ])
    ->add('save', SubmitType::class)
    ->getForm();

Manipulating the form

With MoneyType you can manipulate the form elements with

amount_options for the amount field, and currency_options for the currency field, fx if you want to change the label.

$form = $this->createFormBuilder()
    ->add('price', MoneyType::class, [
        'data' => Money::EUR(1000), //EUR 10
        'amount_options' => array(
            'label' => 'Amount',
        ),
        'currency_options' => array(
            'label' => 'Currency',
        ),
    ])
    ->getForm();

With CurrencyType only currency_options can be used, and with SimpleMoneyType only amount_options can be used.

Saving Money with Doctrine

Solution 1 : two fields in the database

Note that there are 2 columns in the DB table : $priceAmount and $priceCurrency and only one getter/setter : getPrice and setPrice.

The get/setPrice methods are dealing with these two columns transparently.

  • Advantage : your DB is clean and you can do sql sum, group by, sort,... with the amount and the currency in two different columns in your db
  • Disadvantage : it is ugly in the entity.
<?php
namespace App\AdministratorBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Money\Currency;
use Money\Money;

/**
 * TestMoney
 *
 * @ORM\Table("test_money")
 * @ORM\Entity
 */
class TestMoney
{
    /**
     * @var integer
     *
     * @ORM\Column(type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var integer
     *
     * @ORM\Column(name="price_amount", type="integer")
     */
    private $priceAmount;

    /**
     * @var string
     *
     * @ORM\Column(name="price_currency", type="string", length=64)
     */
    private $priceCurrency;

    /**
     * Get id
     *
     * @return integer
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * get Money
     *
     * @return Money
     */
    public function getPrice()
    {
        if (!$this->priceCurrency) {
            return null;
        }
        if (!$this->priceAmount) {
            return new Money(0, new Currency($this->priceCurrency));
        }
        return new Money($this->priceAmount, new Currency($this->priceCurrency));
    }

    /**
     * Set price
     *
     * @param Money $price
     * @return TestMoney
     */
    public function setPrice(Money $price)
    {
        $this->priceAmount = $price->getAmount();
        $this->priceCurrency = $price->getCurrency()->getCode();

        return $this;
    }
}

Solution 2 : use Doctrine type

There is only one string column in your DB table. The money object is manually serialized by the new Doctrine type.

1.25€ is serialized in your DB by 'EUR 125'. This format is stable. It won't change in future releases..

The new Doctrine type name is "money".

  • Advantage : The entity is easy to create and use
  • Disadvantage : it is more difficult to directly request the db in SQL.
<?php
namespace App\AdministratorBundle\Entity;

use Doctrine\ORM\Mapping as ORM;
use Money\Money;

/**
 * TestMoney
 *
 * @ORM\Table("test_money")
 * @ORM\Entity
 */
class TestMoney
{
    /**
     * @var integer
     *
     * @ORM\Column(type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @var Money
     *
     * @ORM\Column(name="price", type="money")
     */
    private $price;

    /**
     * Get id
     *
     * @return integer
     */
    public function getId()
    {
        return $this->id;
    }

    /**
     * get Money
     *
     * @return Money
     */
    public function getPrice()
    {
        return $this->price;
    }

    /**
     * Set price
     *
     * @param Money $price
     * @return TestMoney
     */
    public function setPrice(Money $price)
    {
        $this->price = $price;
        return $this;
    }
}

Conversion manager

Convert an amount into another currency

$pairManager = $this->get("tbbc_money.pair_manager");
$usd = $pairManager->convert($amount, 'USD');

Save a conversion value in a DB

use Money\Money;

$pairManager = $this->get("tbbc_money.pair_manager");
$pairManager->saveRatio('USD', 1.25); // save in ratio file in CSV
$eur = Money::EUR(100);
$usd = $pairManager->convert($amount, 'USD');
$this->assertEquals(Money::USD(125), $usd);

Money formatter

<?php

namespace My\Controller\IndexController;

use Money\Money;
use Money\Currency;

class IndexController extends Controller
{
    public function myAction()
    {
        $moneyFormatter = $this->get('tbbc_money.formatter.money_formatter');
        $price = new Money(123456789, new Currency('EUR'));

        // best method (added in 2.2+ version)
        \Locale::setDefault('fr_FR');
        $formatedPrice = $moneyFormatter->localizedFormatMoney($price);
        // 1 234 567,89 €
        $formatedPrice = $moneyFormatter->localizedFormatMoney($price, 'en');
        // €1,234,567.89

        // old method (before v2.2)
        $formattedPrice = $moneyFormatter->formatMoney($price);
        // 1 234 567,89

        $formattedCurrency = $moneyFormatter->formatCurrency($price);
        // €
    }
}

Twig integration

{{ $amount | money_localized_format('fr') }} => 1 234 567,89 €
{{ $amount | money_localized_format('en_US') }} => €1,234,567.89
{{ $amount | money_localized_format }} => depends on your default locale
{{ $amount | money_format }}
{{ $amount | money_as_float }}
{{ $amount | money_get_currency | currency_symbol }}
{{ $amount | money_get_currency | currency_name }}
{{ $amount | money_convert("USD") | money_format }}
{{ $amount | money_format_currency }}

PHP templating integration

<span class="price"><?php echo $view['tbbc_money']->format($price) ?></span>
<span class="money"><?php echo $view['tbbc_money_currency']->formatCurrencyAsSymbol($price->getCurrency()) ?></span>

Fetching ratio values from remote provider

# save a ratio in the storage
./bin/console tbbc:money:ratio-save USD 1.25

# display ratio list
./bin/console tbbc:money:ratio-list

# fetch all the ratio for all defined currencies from an external API
./bin/console tbbc:money:ratio-fetch

Change the ratio provider

The ratio provider by default is base on the service 'tbbc_money.ratio_provider.ecb'

This bundles contains three ratio providers :

You can change the service to use in the config.yml file :

tbbc_money:
    [...]
    ratio_provider: tbbc_money.ratio_provider.google

Additional rate providers from Exchanger

This project integrates https://github.com/florianv/exchanger library to work with currency exchange rates from various services.

Installation:

composer require "florianv/exchanger" "php-http/message" "php-http/guzzle6-adapter"

Configuration:

First, you need to add services you would like to use into your services.yml file, e.g:

ratio_provider.service.ecb:
  class: Exchanger\Service\EuropeanCentralBank

Second, you need to update ratio provider used by MoneyBundle on your config.yml file:

tbbc_money:
    [...]
    ratio_provider: ratio_provider.service.ecb

Recommended:

Some providers focus on a limited set of currencies, but give better data. You can use several rate providers seamlessly on your project by bundling them into the chain. If some provider does not support certain currency, next provider in the chain would be attempted.

Example of chained providers:

ratio_provider.service.ecb:
  class: Exchanger\Service\EuropeanCentralBank

ratio_provider.service.rcb:
  class: Exchanger\Service\RussianCentralBank

ratio_provider.service.cryptonator:
  class: Exchanger\Service\Cryptonator

ratio_provider.service.array:
  class: Exchanger\Service\PhpArray
  arguments:
    -
      'EUR/USD': 1.157
      'EUR/AUD': 1.628

ratio_provider.service.default:
  class: Exchanger\Service\Chain
  arguments:
    -
      - "@ratio_provider.service.ecb"
      - "@ratio_provider.service.rcb"
      - "@ratio_provider.service.cryptonator"
      - "@ratio_provider.service.array"

As you can see here 4 providers would be attempted one after another until conversion rate is found. Check this page for a fill list of supported services and their configurations: https://github.com/florianv/exchanger/blob/master/doc/readme.md#supported-services

And then you need to assign rate provider on your config.yml file:

tbbc_money:
    [...]
    ratio_provider: ratio_provider.service.default

Create your own ratio provider

A ratio provider is a service that implements the Tbbc\MoneyBundle\Pair\RatioProviderInterface. I recommend that you read the PHP doc of the interface to understand how to implement a new ratio provider.

The new ratio provider has to be registered as a service.

To use the new ratio provider, you should set the service to use in the config.yml by giving the service name.

tbbc_money:
    [...]
    ratio_provider: tbbc_money.ratio_provider.google

automatic currency ratio fetch

Add to your crontab :

1 0 * * * /my_app_dir/bin/console tbbc:money:ratio-fetch > /dev/null

MoneyManager : create a money object from a float

Create a money object from a float can be a bit tricky because of rounding issues.

<?php
$moneyManager = $this->get("tbbc_money.money_manager");
$money = $moneyManager->createMoneyFromFloat('2.5', 'USD');
$this->assertEquals("USD", $money->getCurrency()->getCode());
$this->assertEquals(250, $money->getAmount());

history of currency ratio with the pairHistoryManager

Doctrine is required to use this feature.

In order to get the ratio history, you have to enable it in the configuration and to use Doctrine.

tbbc_money:
    currencies: ["USD", "EUR"]
    reference_currency: "EUR"
    enable_pair_history: true

Then you can use the service :

$pairHistoryManager = $this->get("tbbc_money.pair_history_manager");
$dt = new \DateTime("2012-07-08 11:14:15.638276");

// returns ratio for at a given date
$ratio = $pairHistoryManager->getRatioAtDate('USD',$dt);

// returns the list of USD ratio (relative to the reference value)
$ratioList = $pairHistoryManager->getRatioHistory('USD',$startDate, $endDate);

RatioStorage

Two storages for storing ratios are available : CSV File, or Doctrine By default, TbbcMoneyBundle is configured with CSV File.

If you want to switch to a Doctrine storage, edit your config.yml

tbbc_money:
    storage: doctrine

Update your database schema :

./bin/console doctrine:schema:update --force

With the Doctrine storage, currency ratio will use the default entity manager and will store data inside the tbbc_money_doctrine_storage_ratios

Custom NumberFormatter in MoneyFormatter

The MoneyFormatter::localizedFormatMoney ( service 'tbbc_money.formatter.money_formatter' ) use the php NumberFormatter class ( http://www.php.net/manual/en/numberformatter.formatcurrency.php ) to format money.

You can :

  • give your own \NumberFormatter instance as a parameter of MoneyFormatter::localizedFormatMoney
  • subclass the MoneyFormatter and rewrite the getDefaultNumberFormater method to set a application wide NumberFormatter

Using the TbbcMoneyBundle without Doctrine

You have to disable the pair history service in order to use the TbbcMoneyBundle without Doctrine.

tbbc_money:
    enable_pair_history: true

Note : you can imagine to code your own PairHistoryManager for MongoDB or Propel, it is very easy to do. Don't hesitate to submit a PR with your code and your tests.

Optimizations

In your config.yml, you can :

  • select the templating engine to use. By default, only Twig is loaded.
  • define the decimals count after a unit (ex : 12.25€ : 2 decimals ; 11.5678€ : 4 decimals)
tbbc_money:
    currencies: ["USD", "EUR"]
    reference_currency: "EUR"
    decimals: 2
    enable_pair_history: true
    ratio_provider: tbbc_money.ratio_provider.yahoo_finance

Contributing

  1. Take a look at the list of issues.
  2. Fork
  3. Write a test (for either new feature or bug)
  4. Make a PR

Requirements

  • PHP 5.3.9+
  • Symfony 2.8+

Authors

Philippe Le Van - kitpages.fr - twitter : @plv
Thomas Tourlourat - Wozbe - twitter: @armetiz

Status

Stable

what is functional:

  • integration of the money library
  • configuration parser
  • pairManager
  • Travis CI integration
  • form integration
  • Twig presentation for forms
  • Twig filters
  • commands for ratio creation and ratio display
  • automatic ratio fetch (with 2 ratio providers)
  • history of currency ratio

Author: TheBigBrainsCompany
Source Code: https://github.com/TheBigBrainsCompany/TbbcMoneyBundle 
License: MIT License

#php #money #symfony 

TbbcMoneyBundle: Bundle is used to integrate the Money library

Money: Python Money Class with Optional CLDR Backed Locale Aware

Python Money

Money class with optional CLDR-backed locale-aware formatting and an extensible currency exchange solution.

This is version 1.4.0-dev.

Development:https://github.com/carlospalol/money
Latest release:https://pypi.python.org/pypi/money/

This package is compatible with Python 2.7, 3.4, 3.5, but there are important Differences between Python versions. All code examples use Python 3.5.

Installation

Install the latest release with:

pip install money

For locale-aware formatting, also install the latest version of Babel (2.2 or 2.3 required):

pip install babel

Usage

>>> from money import Money
>>> m = Money(amount='2.22', currency='EUR')
>>> m
EUR 2.22

amount can be any valid value in decimal.Decimal(value) and currency should be a three-letter currency code. Money objects are immutable by convention and hashable. Once created, you can use read-only properties amount (decimal.Decimal) and currency (str) to access its internal components:

>>> m = Money(2, 'USD')
>>> m.amount
Decimal('2')
>>> m.currency
'USD'

Money emulates a numeric type and you can apply most arithmetic and comparison operators between money objects, as well as addition, subtraction, and division with integers (int) and decimal numbers (decimal.Decimal):

>>> m = Money('2.22', 'EUR')
>>> m / 2
EUR 1.11
>>> m + Money('7.77', 'EUR')
EUR 9.99

More formally, with AAA and BBB being different currencies:

 OperatorMoney AAAMoney BBBint, Decimal
Money AAA+, -MoneyN/AMoney
*N/AN/AMoney
/, //DecimalN/AMoney
>, >= <, <=Compares amount.N/AN/A
==FalseFalse

Arithmetic operations with floats are not directly supported. If you need to operate with floats, you must first convert the float to a Decimal, or the Money object to a float (i.e. float(m)). Please be aware of the issues and limitations of floating point arithmetics.

Currency presets

If you use fixed currencies in your code, you may find convenient to create currency-preset Money subclasses:

class EUR(Money):
    def __init__(self, amount='0'):
        super().__init__(amount=amount, currency='EUR')

price = EUR('9.99')

Formatting

Money objects are printed by default with en_US formatting and the currency code.

>>> m = Money('1234.567', 'EUR')
>>> str(m)
'EUR 1,234.57'

Use format(locale=LC_NUMERIC, pattern=None, currency_digits=True, format_type='standard') for locale-aware formatting with currency expansion. format() relies on babel.numbers.format_currency(), and requires Babel to be installed.

>>> m = Money('1234.567', 'USD')
>>> m.format('en_US')
'$1,234.57'
>>> m.format('es_ES')
'1.234,57\xa0$'

The character \xa0 is an unicode non-breaking space. If no locale is passed, Babel will use your system's locale. You can also provide a specific pattern to format():

>>> m = Money('-1234.567', 'USD')
>>> # Regular US format:
>>> m.format('en_US', '¤#,##0.00')
'-$1,234.57'
>>> # Custom negative format:
>>> m.format('en_US', '¤#,##0.00;<¤#,##0.00>')
'<$1,234.57>'
>>> # Spanish format, full currency name:
>>> m.format('es_ES', '#,##0.00 ¤¤¤')
'-1.234,57 dólares estadounidenses'
>>> # Same as above, but rounding (overriding currency natural format):
>>> m.format('es_ES', '#0 ¤¤¤', currency_digits=False)
'-1235 dólares estadounidenses'

For more details on formatting see Babel docs on currency formatting. To learn more about the formatting pattern syntax check out Unicode TR35.

Currency exchange

Currency exchange works by "installing" a backend class that implements the abstract base class (abc) money.exchange.BackendBase. Its API is exposed through money.xrates, along with setup functions xrates.install(pythonpath), xrates.uninstall(), and xrates.backend_name.

A simple proof-of-concept backend money.exchange.SimpleBackend is included:

from decimal import Decimal
from money import Money, xrates

xrates.install('money.exchange.SimpleBackend')
xrates.base = 'USD'
xrates.setrate('AAA', Decimal('2'))
xrates.setrate('BBB', Decimal('8'))

a = Money(1, 'AAA')
b = Money(1, 'BBB')

assert a.to('BBB') == Money('4', 'BBB')
assert b.to('AAA') == Money('0.25', 'AAA')
assert a + b.to('AAA') == Money('1.25', 'AAA')

XMoney

You can use money.XMoney (a subclass of Money), for automatic currency conversion while adding, subtracting, and dividing money objects (+, +=, -, -=, /, //). This is useful when aggregating lots of money objects with heterogeneous currencies. The currency of the leftmost object has priority.

from money import XMoney

# Register backend and rates as above...

a = XMoney(1, 'AAA')
b = XMoney(1, 'BBB')

assert sum([a, b]) == XMoney('1.25', 'AAA')

Exceptions

Found in money.exceptions.

MoneyException(Exception)

Base class for all exceptions.

CurrencyMismatch(MoneyException, ValueError)

Thrown when mixing different currencies, e.g. Money(2, 'EUR') + Money(2, 'USD'). Money objects must be converted first to the same currency, or XMoney could be used for automatic conversion.

InvalidOperandType(MoneyException, TypeError)

Thrown when attempting invalid operations, e.g. multiplication between money objects.

ExchangeError(MoneyException)

Base class for exchange exceptions.

ExchangeBackendNotInstalled(ExchangeError)

Thrown if a conversion is attempted, but there is no backend available.

ExchangeRateNotFound(ExchangeError)

The installed backend failed to provide a suitable exchange rate between the origin and target currencies.

Hierarchy

MoneyException

  • CurrencyMismatch
  • InvalidOperandType

ExchangeError

  • ExchangeBackendNotInstalled
  • ExchangeRateNotFound

Differences between Python versions

ExpressionPython 2.xPython 3.x
round(Money('2.5', 'EUR'))Returns 3.0, a float rounded amount away from zero.Returns EUR 2, a Money object with rounded amount to the nearest even.
Money('0', 'EUR').amount < '0'Returns True. This is the weird but expected behaviour in Python 2.x when comparing Decimal objects with non-numerical objects (Note the '0' is a string). See note in docs.TypeError: unorderable types: decimal.Decimal() > str()

Design decisions

There are several design decisions in money that differ from currently available money class implementations:

Localization

Do not keep any kind of locale conventions database inside this package. Locale conventions are extensive and change over time; keeping track of them is a project of its own. There is already such a project and database (the Unicode Common Locale Data Repository), and an excellent python API for it: Babel.

Currency

There is no need for a currency class. A currency is fully identified by its ISO 4217 code, and localization or exchange rates data are expected to be centralized as databases/services because of their changing nature.

Also:

  • Modulo operator (%): do not override to mean "percentage".
  • Numeric type: you can mix numbers and money in binary operations, and objects evaluate to False if their amount is zero.
  • Global default currency: subclassing is a safer solution.

Contributions

Contributions are welcome. You can use the regular github mechanisms.

To test your changes you will need tox and python 2.7, 3.4, and 3.5. Simply cd to the package root (by setup.py) and run tox.

License

money is released under the MIT license, which can be found in the file LICENSE.

Author: carlospalol
Source Code: https://github.com/carlospalol/money
License: MIT License

#python #money 

Money: Python Money Class with Optional CLDR Backed Locale Aware
Elian  Harber

Elian Harber

1648767480

Decimal: Arbitrary-precision Fixed-point Decimal Numbers in Go

decimal  

Arbitrary-precision fixed-point decimal numbers in go.

Note: Decimal library can "only" represent numbers with a maximum of 2^31 digits after the decimal point.

Features

  • The zero-value is 0, and is safe to use without initialization
  • Addition, subtraction, multiplication with no loss of precision
  • Division with specified precision
  • Database/sql serialization/deserialization
  • JSON and XML serialization/deserialization

Install

Run go get github.com/shopspring/decimal

Requirements

Decimal library requires Go version >=1.7

Usage

package main

import (
    "fmt"
    "github.com/shopspring/decimal"
)

func main() {
    price, err := decimal.NewFromString("136.02")
    if err != nil {
        panic(err)
    }

    quantity := decimal.NewFromInt(3)

    fee, _ := decimal.NewFromString(".035")
    taxRate, _ := decimal.NewFromString(".08875")

    subtotal := price.Mul(quantity)

    preTax := subtotal.Mul(fee.Add(decimal.NewFromFloat(1)))

    total := preTax.Mul(taxRate.Add(decimal.NewFromFloat(1)))

    fmt.Println("Subtotal:", subtotal)                      // Subtotal: 408.06
    fmt.Println("Pre-tax:", preTax)                         // Pre-tax: 422.3421
    fmt.Println("Taxes:", total.Sub(preTax))                // Taxes: 37.482861375
    fmt.Println("Total:", total)                            // Total: 459.824961375
    fmt.Println("Tax rate:", total.Sub(preTax).Div(preTax)) // Tax rate: 0.08875
}

Documentation

http://godoc.org/github.com/shopspring/decimal

Production Usage

  • Spring, since August 14, 2014.
  • If you are using this in production, please let us know!

FAQ

Why don't you just use float64?

Because float64 (or any binary floating point type, actually) can't represent numbers such as 0.1 exactly.

Consider this code: http://play.golang.org/p/TQBd4yJe6B You might expect that it prints out 10, but it actually prints 9.999999999999831. Over time, these small errors can really add up!

Why don't you just use big.Rat?

big.Rat is fine for representing rational numbers, but Decimal is better for representing money. Why? Here's a (contrived) example:

Let's say you use big.Rat, and you have two numbers, x and y, both representing 1/3, and you have z = 1 - x - y = 1/3. If you print each one out, the string output has to stop somewhere (let's say it stops at 3 decimal digits, for simplicity), so you'll get 0.333, 0.333, and 0.333. But where did the other 0.001 go?

Here's the above example as code: http://play.golang.org/p/lCZZs0w9KE

With Decimal, the strings being printed out represent the number exactly. So, if you have x = y = 1/3 (with precision 3), they will actually be equal to 0.333, and when you do z = 1 - x - y, z will be equal to .334. No money is unaccounted for!

You still have to be careful. If you want to split a number N 3 ways, you can't just send N/3 to three different people. You have to pick one to send N - (2/3*N) to. That person will receive the fraction of a penny remainder.

But, it is much easier to be careful with Decimal than with big.Rat.

Why isn't the API similar to big.Int's?

big.Int's API is built to reduce the number of memory allocations for maximal performance. This makes sense for its use-case, but the trade-off is that the API is awkward and easy to misuse.

For example, to add two big.Ints, you do: z := new(big.Int).Add(x, y). A developer unfamiliar with this API might try to do z := a.Add(a, b). This modifies a and sets z as an alias for a, which they might not expect. It also modifies any other aliases to a.

Here's an example of the subtle bugs you can introduce with big.Int's API: https://play.golang.org/p/x2R_78pa8r

In contrast, it's difficult to make such mistakes with decimal. Decimals behave like other go numbers types: even though a = b will not deep copy b into a, it is impossible to modify a Decimal, since all Decimal methods return new Decimals and do not modify the originals. The downside is that this causes extra allocations, so Decimal is less performant. My assumption is that if you're using Decimals, you probably care more about correctness than performance.

Author: Shopspring
Source Code: https://github.com/shopspring/decimal 
License: View license

#go #golang #money 

Decimal: Arbitrary-precision Fixed-point Decimal Numbers in Go

Cashify: Currency Conversion

Cashify 💸

Lightweight currency conversion library, successor of money.js

Motivation

This package was created, because the popular money.js library:

  • is not maintained (last commit was ~5 years ago)
  • has over 20 open issues
  • does not support TypeScript
  • has implicit globals
  • does not have any unit tests
  • has floating point issues

Highlights

Install

$ npm install cashify

Please note that starting with version 3.0.0 this package is ESM-only and thus requires Node.js v14 or higher.

Usage

With constructor

import {Cashify} from 'cashify';

const rates = {
	GBP: 0.92,
	EUR: 1.00,
	USD: 1.12
};

const cashify = new Cashify({base: 'EUR', rates});

const result = cashify.convert(10, {from: 'EUR', to: 'GBP'});

console.log(result); //=> 9.2

Without constructor

Using the Cashify constructor is not required. Instead, you can just use the convert function:

import {convert} from 'cashify';

const rates = {
	GBP: 0.92,
	EUR: 1.00,
	USD: 1.12
};

const result = convert(10, {from: 'EUR', to: 'GBP', base: 'EUR', rates});

console.log(result); //=> 9.2

Parsing

Cashify supports parsing, so you can pass a string to the amount argument and the from and/or to currency will be automatically detected:

import {Cashify} from 'cashify';

const rates = {
	GBP: 0.92,
	EUR: 1.00,
	USD: 1.12
};

const cashify = new Cashify({base: 'EUR', rates});

// Basic parsing
cashify.convert('€10 EUR', {to: 'GBP'});

// Full parsing
cashify.convert('10 EUR to GBP');

Alternatively, if you just want to parse a string without conversion you can use the parse function which returns an object with parsing results:

import {parse} from 'cashify'; parse('10 EUR to GBP'); //=> {amount: 10, from: 'EUR', to: 'GBP'}

Note: If you want to use full parsing, you need to pass a string in a specific format:

10 usd to pln
12.5 GBP in EUR
3.1415 eur as chf

You can use to, in or as to separate the expression (case insensitive). Used currencies name case doesn't matter, as cashify will automatically convert them to upper case.

Integration with big.js

big.js is a small JavaScript library for arbitrary-precision decimal arithmetic. You can use it with cashify to make sure you won't run into floating point issues:

import {Cashify} from 'cashify';
import Big from 'big.js';

const rates = {
	EUR: 0.8235,
	USD: 1
};

const cashify = new Cashify({base: 'USD', rates});

const result = cashify.convert(1, {
	from: 'USD',
	to: 'EUR',
	BigJs: Big
});

console.log(result); //=> 8.235 (without big.js you would get something like 0.8234999999999999)

Integration with currency.js

currency.js is a small and lightweight library for working with currency values. It integrates well with cashify. In the following example we are using it to format the conversion result:

import {Cashify} from 'cashify';
import currency from 'currency.js';

const rates = {
	GBP: 0.92,
	EUR: 1.00,
	USD: 1.12
};

const cashify = new Cashify({base: 'EUR', rates});

const converted = cashify.convert(8635619, {from: 'EUR', to: 'GBP'}); // => 7944769.48

// Format the conversion result
currency(converted, {symbol: '€', formatWithSymbol: true}).format(); // => €7,944,769.48

API

Cashify({base, rates, BigJs})

Constructor.

base

Type: string

The base currency.

rates

Type: object

An object containing currency rates (for example from an API, such as Open Exchange Rates).

BigJs

Type: big.js constructor

See integration with big.js.

convert(amount, {from, to, base, rates}) with and without constructor

Returns conversion result (number).

amount

Type: number or string

Amount of money you want to convert. You can either use a number or a string. If you choose the second option, you can take advantage of parsing and not specify from and/or to argument(s).

from

Type: string

Currency from which you want to convert. You might not need to specify it if you are using parsing.

to

Type: string

Currency to which you want to convert. You might not need to specify it if you are using parsing.

base

Type: string

The base currency.

rates

Type: object

An object containing currency rates (for example from an API, such as Open Exchange Rates).

BigJs

Type: big.js constructor

See integration with big.js.

parse(expression)

Returns an object, which contains parsing results:

{
	amount: number;
	from: string | undefined;
	to: string | undefined;
}

expression

Type: string

Expression you want to parse, ex. 10 usd to pln or €1.23 eur

Migrating from money.js

With Cashify constructor:

- import fx from 'money';
+ import {Cashify} from 'cashify';

- fx.base = 'EUR';
- fx.rates = {
-	GBP: 0.92,
-	EUR: 1.00,
-	USD: 1.12
- };

+ const rates = {
+	 GBP: 0.92,
+	 EUR: 1.00,
+	 USD: 1.12
+ };

+ const cashify = new Cashify({base: 'EUR', rates});

- fx.convert(10, {from: 'GBP', to: 'EUR'});
+ cashify.convert(10, {from: 'GBP', to: 'EUR'});

With convert function:

- import fx from 'money';
+ import {convert} from 'cashify';

- fx.base = 'EUR';
- fx.rates = {
-	GBP: 0.92,
-	EUR: 1.00,
-	USD: 1.12
- };

+ const rates = {
+	 GBP: 0.92,
+	 EUR: 1.00,
+	 USD: 1.12
+ };

- fx.convert(10, {from: 'GBP', to: 'EUR'});
+ convert(10, {from: 'GBP', to: 'EUR', base: 'EUR', rates});

Floating point issues

When working with currencies, decimals only need to be precise up to the smallest cent value while avoiding common floating point errors when performing basic arithmetic.

Let's take a look at the following example:

import fx from 'money';
import {Cashify} from 'cashify';

const rates = {
	GBP: 0.92,
	USD: 1.12
};

fx.rates = rates;
fx.base = 'EUR';

const cashify = new Cashify({base: 'EUR', rates});

fx.convert(10, {from: 'EUR', to: 'GBP'}); //=> 9.200000000000001
cashify.convert(10, {from: 'EUR', to: 'GBP'}); //=> 9.2

As you can see, money.js doesn't handle currencies correctly and therefore a floating point issues are occuring. Even though there's just a minor discrepancy between the results, if you're converting large amounts, that can add up.

Cashify solves this problem the same way as currency.js - by working with integers behind the scenes. This should be okay for most reasonable values of currencies; if you want to avoid all floating point issues, see integration with big.js.

Related projects

Author: xxczaki
Source Code: https://github.com/xxczaki/cashify 
License: MIT License

#node #money #npm #convert 

Cashify: Currency Conversion

13 Very Profitable Business Ideas for Developers

Are you a web developer looking for some business ideas? If so, then this article is perfect for you! We will show you 13 profitable businesses that are perfect for web development. 

There's nothing better than making money off of your skillset, and these ideas will help make sure that happens. Read on to find out how to start building your own successful business today!

https://youtu.be/spsje0jKhRM

#business #startup #startups #entrepreneur #money #webdev 

13 Very Profitable Business Ideas for Developers