货币转换和货币格式化

This commit is contained in:
TL 2022-07-28 17:45:45 +08:00
parent 5b5630cd95
commit 22f5683b63
7 changed files with 114 additions and 178 deletions

View File

@ -3,6 +3,8 @@
use Beike\Models\Customer;
use Beike\Models\AdminUser;
use Beike\Repositories\LanguageRepo;
use Beike\Services\CurrencyService;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Str;
use TorMorten\Eventy\Facades\Eventy;
use Illuminate\Support\Facades\Route;
@ -195,9 +197,12 @@ function locale(): string
* @param $price
* @return string
*/
function currency_format($price): string
function currency_format($price, $currency = '', $value = '', $format = true): string
{
return '$' . number_format($price, 2);
if (!$currency) {
$currency = Session::get('currency') ?? system_setting('base.currency');
}
return CurrencyService::getInstance()->format($price, $currency, $value, $format);
}
/**

View File

@ -66,4 +66,10 @@ class CurrencyRepo
{
return Currency::query()->get();
}
public static function enabled()
{
return Currency::query()->where('status', true)->get();
}
}

View File

@ -43,6 +43,18 @@ class SystemSettingRepo
'value' => old('locale', system_setting('base.locale', 'zh_cn')),
'description' => '默认语言设置',
],
[
'name' => 'currency',
'label' => '默认货币',
'type' => 'select',
'required' => true,
'options' => [
['value' => 'CNY', 'label' => '人民币'],
['value' => 'USD', 'label' => '美元']
],
'value' => old('currency', system_setting('base.currency', 'USD')),
'description' => '默认货币设置',
],
[
'name' => 'admin_name',
'label' => '后台目录',

View File

@ -1,12 +1,12 @@
<?php
/**
* TaxService.php
* CurrencyService.php
*
* @copyright 2022 opencart.cn - All Rights Reserved
* @link http://www.guangdawangluo.com
* @author Edward Yang <yangjin@opencart.cn>
* @created 2022-07-21 16:29:54
* @modified 2022-07-21 16:29:54
* @author TL <mengwb@opencart.cn>
* @created 2022-07-28 16:29:54
* @modified 2022-07-28 16:29:54
*/
namespace Beike\Services;
@ -14,195 +14,78 @@ namespace Beike\Services;
use Beike\Models\Address;
use Beike\Models\TaxRate;
use Beike\Models\TaxRule;
use Beike\Repositories\CurrencyRepo;
class TaxService
class CurrencyService
{
private $taxRates = array();
private static $taxRules;
private static $instance;
private $currencies = array();
const AVAILABLE_TYPES = ['shipping', 'payment', 'store'];
public function __construct($data = array())
{
$countryId = system_setting('base.config_country_id');
$zoneId = system_setting('base.config_zone_id');
$shippingAddress = $data['shipping_address'] ?? null;
$paymentAddress = $data['payment_address'] ?? null;
if ($shippingAddress) {
if ($shippingAddress instanceof Address) {
$this->setShippingAddress($shippingAddress->country_id, $shippingAddress->zone_id);
} elseif ($shippingAddress instanceof \ArrayObject) {
$this->setShippingAddress($countryId, $zoneId);
} else {
$this->setShippingAddress($shippingAddress['country_id'], $shippingAddress['zone_id']);
}
} elseif (system_setting('base.config_tax_default') == 'shipping') {
$this->setShippingAddress($countryId, $zoneId);
}
if ($paymentAddress) {
if ($paymentAddress instanceof Address) {
$this->setPaymentAddress($paymentAddress->country_id, $paymentAddress->zone_id);
} elseif ($paymentAddress instanceof \ArrayObject) {
$this->setShippingAddress($countryId, $zoneId);
} else {
$this->setPaymentAddress($paymentAddress['country_id'], $paymentAddress['zone_id']);
}
} elseif (system_setting('base.config_tax_default') == 'payment') {
$this->setPaymentAddress($countryId, $zoneId);
}
$this->setStoreAddress($countryId, $zoneId);
}
public static function getInstance($data = array())
{
return new self($data);
}
private function getTaxRules($type, $countryId, $zoneId)
{
if (self::$taxRules !== null && isset(self::$taxRules["$type-$countryId-$zoneId"])) {
return self::$taxRules["$type-$countryId-$zoneId"];
}
$customerGroupId = (int)system_setting('base.config_customer_group_id');
$sqlBuilder = TaxRule::query()
->leftJoin('tax_rate', 'tax_rule.tax_rate_id', '=', 'tax_rate.tax_rate_id')
->join('tax_rate_to_customer_group', 'tax_rate.tax_rate_id', '=', 'tax_rate_to_customer_group.tax_rate_id')
->leftJoin('zone_to_geo_zone', 'tax_rate.geo_zone_id', '=', 'zone_to_geo_zone.geo_zone_id')
->leftJoin('geo_zone', 'tax_rate.geo_zone_id', '=', 'geo_zone.geo_zone_id')
->select('tax_rule.*', 'tax_rate.*')
->where('tax_rule.based', $type)
->where('tax_rate_to_customer_group.customer_group_id', $customerGroupId)
->where('zone_to_geo_zone.country_id', $countryId)
->where(function ($query) use ($zoneId) {
$query->where('zone_to_geo_zone.zone_id', '=', 0)
->orWhere('zone_to_geo_zone.zone_id', '=', (int)$zoneId);
})
->orderBy('tax_rule.priority');
$data = $sqlBuilder->get();
self::$taxRules["$type-$countryId-$zoneId"] = $data;
return $data;
}
private function setAddress($type, $countryId, $zoneId)
{
if (!in_array($type, self::AVAILABLE_TYPES)) {
throw new \Exception('invalid tax types');
}
$data = $this->getTaxRules($type, $countryId, $zoneId);
foreach ($data as $result) {
$this->taxRates[$result->tax_class_id][$result->tax_rate_id] = array(
'tax_rate_id' => $result->tax_rate_id,
'name' => $result->name,
'rate' => $result->rate,
'type' => $result->type,
'priority' => $result->priority
);
public function __construct() {
foreach (CurrencyRepo::enabled() as $result) {
$this->currencies[$result->code] = $result;
}
}
public function unsetRates()
public static function getInstance()
{
$this->taxRates = array();
if (!self::$instance) {
self::$instance = new self();
}
return self::$instance;
}
public function setShippingAddress($countryId, $zoneId)
public function format($amount, $currency, $value = '', $format = true)
{
$this->setAddress('shipping', $countryId, $zoneId);
$symbol_left = $this->currencies[$currency]->symbol_left;
$symbol_right = $this->currencies[$currency]->symbol_right;
$decimal_place = $this->currencies[$currency]->decimal_place;
if (!$value) {
$value = $this->currencies[$currency]->value;
}
$amount = $value ? (float)$amount * $value : (float)$amount;
$amount = round($amount, (int)$decimal_place);
if (!$format) {
return $amount;
}
$string = '';
if ($amount < 0) {
$string = '-';
}
if ($symbol_left) {
$string .= $symbol_left;
}
$string .= number_format(abs($amount), (int)$decimal_place, __('currency.decimal_point'), __('currency.thousand_point'));
if ($symbol_right) {
$string .= $symbol_right;
}
return $string;
}
public function setPaymentAddress($countryId, $zoneId)
{
$this->setAddress('payment', $countryId, $zoneId);
}
public function setStoreAddress($countryId, $zoneId)
{
$this->setAddress('store', $countryId, $zoneId);
}
/**
* $tax = \App\Models\Library\Tax::getInstance();
* $tax->setShippingAddress(1, 0);
* $tax->calculate(123.45, 9, $tax->config->getValue('config_tax'))
*
* @param $value
* @param $taxClassId
* @param bool|true $calculate
* @return mixed
*/
public function calculate($value, $taxClassId, bool $calculate = true)
{
if ($taxClassId && $calculate) {
$amount = 0;
$taxRates = $this->getRates($value, $taxClassId);
foreach ($taxRates as $taxRate) {
if ($calculate != 'P' && $calculate != 'F') {
$amount += $taxRate['amount'];
} elseif ($taxRate['type'] == $calculate) {
$amount += $taxRate['amount'];
}
}
return $value + $amount;
public function convert($value, $from, $to) {
if (isset($this->currencies[$from])) {
$from = $this->currencies[$from]->value;
} else {
return $value;
$from = 1;
}
}
public function getTax($value, $taxClassId)
{
$amount = 0;
$taxRates = $this->getRates($value, $taxClassId);
foreach ($taxRates as $taxRate) {
$amount += $taxRate['amount'];
}
return $amount;
}
public function getRateName($taxRateId)
{
$taxRate = TaxRate::query()->find($taxRateId);
if ($taxRate) {
return $taxRate->name;
if (isset($this->currencies[$to])) {
$to = $this->currencies[$to]->value;
} else {
return false;
}
}
public function getRates($value, $taxClassId)
{
$taxRateData = array();
if (isset($this->taxRates[$taxClassId])) {
foreach ($this->taxRates[$taxClassId] as $taxRate) {
if (isset($taxRateData[$taxRate['tax_rate_id']])) {
$amount = $taxRateData[$taxRate['tax_rate_id']]['amount'];
} else {
$amount = 0;
}
if ($taxRate['type'] == 'F') {
$amount += $taxRate['rate'];
} elseif ($taxRate['type'] == 'P') {
$amount += ($value / 100 * $taxRate['rate']);
}
$taxRateData[$taxRate['tax_rate_id']] = array(
'tax_rate_id' => $taxRate['tax_rate_id'],
'name' => $taxRate['name'],
'rate' => $taxRate['rate'],
'type' => $taxRate['type'],
'amount' => $amount
);
}
$to = 1;
}
return $taxRateData;
return $value * ($to / $from);
}
}

View File

@ -11,7 +11,7 @@
namespace Beike\Shop\Http\Controllers;
use Beike\Repositories\LanguageRepo;
use Illuminate\Support\Facades\Session;
class LanguageController extends Controller
{

View File

@ -0,0 +1,15 @@
<?php
/**
* currency.php
*
* @copyright 2022 opencart.cn - All Rights Reserved
* @link http://www.guangdawangluo.com
* @author TL <mengwb@opencart.cn>
* @created 2022-07-28 17:21:38
* @modified 2022-07-28 17:21:38
*/
return [
'decimal_point' => '.',
'thousand_point' => ',',
];

View File

@ -0,0 +1,15 @@
<?php
/**
* currency.php
*
* @copyright 2022 opencart.cn - All Rights Reserved
* @link http://www.guangdawangluo.com
* @author TL <mengwb@opencart.cn>
* @created 2022-07-28 17:21:38
* @modified 2022-07-28 17:21:38
*/
return [
'decimal_point' => '.',
'thousand_point' => ',',
];