🌐 言語: 🇻🇳 Tiếng Việt · 🇬🇧 English · 🇯🇵 日本語(現在)
GP247 の通貨(Currency)
はじめに
このドキュメントでは、GP247/S-Cart の 通貨(currency) 機能の仕組みを説明し、ストアオーナーが自分のショップの通貨を 設定する方法を案内します。技術に詳しくない方 向けです。読み終えると、通貨が何で構成されるか、基準通貨(商品価格を 保存する通貨)と表示用の通貨の違い、為替レートの仕組み、お客様がどの通貨で価格を見るか、通貨をどこで作成・編集するか、 価格を狂わせずに 基準通貨を変更 する方法、そして通貨を削除・編集できないことがある理由がわかります。
⭐ gp247/shop バージョン 2.1 から適用されます。 このドキュメントで (v2.1) と付いている項目 — 明示的な基準通貨、 価値を保ったままの基準通貨の変更(rebase)、金額入力欄の横の通貨単位メモ — は、gp247/shop 2.1 からの新機能 です。 ショップでそれより古いバージョンを使っている場合、ほかの部分は当てはまりますが、(v2.1) の項目はまだ表示されないことがあります。
1. GP247 の通貨はどう動きますか?
押さえておきたい重要な点が 6 つあります。
- ショップでは複数の通貨を使えます。 通貨の一覧(例:USD、VND)を登録します。各通貨は 有効(お客様が使える)または 無効(非表示)にできます。
- 商品価格は 1 つの「基準通貨」で保存されます。 商品価格は、基準通貨(base currency — GP247 ではストアの「基準」/ 「bit」単位とも呼びます)で 1 回だけ入力します。ほかの通貨で表示するときは、その通貨の 為替レート(exchange rate) を 使って、システムが 自動で換算 します。
- 基準通貨は明示的です (v2.1)。 基準 として指定される通貨はちょうど 1 つ です(一覧に青い「基準」バッジが付きます)。
基準通貨は 為替レートが常に
1で、常に有効 で、編集・削除がロック されています。変更は 基準通貨を変更 機能 (セクション 4 をご覧ください)でのみ行います。2.1 より前は、為替レートが1の通貨が基準だと「暗黙的に」みなされて いたため、レート1の通貨が 0 個や複数あると混乱しやすい状態でした。 - 通貨ごとに表示形式があります。 含まれるのは:記号(例:
$、₫)、記号の位置(金額の前か後か)、 小数点以下の桁数(precision — 例:USD は 2 桁で10.00、VND は 0 桁で250.000)、桁区切り記号 です。 - ストアには既定の表示通貨があります。 お客様がショップに来たときに最初に表示される通貨です。注意: これは 3 の 基準通貨とは 別の 考え方です。基準通貨は 価格を保存する場所 で、既定の通貨は お客様が最初に見る通貨 です。多くの 場合 2 つは同じですが、同じである必要はありません。ショップで複数の通貨を有効にすると、お客様は画面の切替ボタンで 自分で通貨を切り替えられます。
- 注文は注文時の通貨を記憶します。 お客様が注文すると、注文にはその時点の通貨と為替レートが 保存されます。後で 為替レートを変えても 過去の注文は変わりません。お客様が購入したときのとおりに表示されます。
用語: 為替レート(exchange rate) は、基準価格 を表示中の通貨に換算する数値です。基準通貨のレートは
1です。 例:基準価格が USD(レート1)で、VND のレートを25000にすると → 基準価格2の商品は、VND で見ると50.000 ₫と 表示されます。
2. 通貨の設定手順(順番に進めてください)
ステップ 1 — 通貨の管理画面を開く
-
ショップの 管理画面(admin) にログインします。
-
メニューの 設定 → 通貨(Currency)(通貨のアイコン)を開きます。
成功すると、画面が 2 つに分かれて表示されます:左側に入力フォーム、右側に通貨の一覧 です。現在 基準 の 通貨には、名前の列に青い 「基準」 バッジが付きます (v2.1)。
この画面を開くには
admin_currency権限が必要です。メニューが見当たらない場合は、管理者に権限を付与してもらってください。
ステップ 2 — 新しい通貨を追加する
-
新規追加(Add new) を押します。
-
次の項目を入力します。
- 名前(Name): わかりやすい名前。例:
US DollarまたはViệt Nam Đồng。 - コード(Code): ほかの通貨と 重複しない 短いコード。例:
USD、VND、EUR。 - 記号(Symbol): 表示する記号。例:
$、₫、€。 - 為替レート(Exchange rate): 基準価格から換算する数値で、0 より大きくなければなりません。(基準通貨は常に
1で、 この欄はロックされています — セクション 3 をご覧ください。) - 小数点以下の桁数(Precision): 表示する小数の桁数で、
0から8までです。USD は通常2、VND は通常0です。 - 記号を先頭に表示(Symbol first): はい/いいえを選びます。はい →
$10.00、いいえ →250.000 ₫。 - 桁区切り記号(Thousands separator): 区切りに使う記号。例:
,(英語式)または.(ベトナム式)。 - ステータス(Status): 有効にするとお客様が使えます。無効にすると非表示になります。
- 並び順(Sort): 数字が小さいほど、選択リストの前のほうに表示されます。
- 名前(Name): わかりやすい名前。例:
-
保存 を押します。
成功すると、新しい通貨が右側の一覧に表示されます。
小数点の記号について: システムは小数点の記号を、桁区切り記号の 逆 として自動で決めます。桁区切りを
,にすると 小数点は.になり(例:1,234.50)、桁区切りを.にすると小数点は,になります(例:1.234,50)。
ステップ 3 — ストアの既定の表示通貨を設定する
- 設定 → サイト情報 / ストア(Website Info 画面)を開きます。
- 通貨(Currency) の選択欄を探し、ショップの既定の通貨を選びます。
- 保存します。
これはお客様がショップを開いたときに 最初に表示される 通貨です(価格を保存する基準通貨とは別です)。この欄では 有効な 通貨だけを選べます。
ステップ 4 —(任意)お客様が通貨を切り替えられるようにする
- ショップで 2 つ以上の通貨 を有効にすると、お客様向けの画面のヘッダーまたはフッターに 通貨切替ボタン(currency switcher)が表示されます。お客様が選ぶと、ショップ全体の価格がその通貨で表示し直されます。
- お客様の選択はそのお客様のセッション内で記憶され、ほかのお客様には影響しません。
ステップ 5 — ストアで確認する
- お客様向けの画面(ストアフロント) でショップを開きます。
- 切替ボタンで別の通貨に切り替えてみます。
- 商品とカートの価格の記号と小数点以下の桁数が、設定どおりに変わっているか確認します。
3. 基準通貨 — なぜロックされているのですか? (v2.1)
基準通貨 は、すべての商品価格、原価(cost)、属性の追加料金、特価 がデータベースに保存される単位です。言い換えると、 商品に入力した金額はすべて「基準通貨での金額」とみなされます。商品全体の「ものさし」なので、GP247 2.1 ではしっかり保護して います。
- 基準通貨は常にちょうど 1 つ で、一覧に 「基準」 バッジが付きます。
- 基準通貨の為替レートは常に
1です(編集できません)。ほかのすべてのレートは、基準通貨 に対して 測るからです。 - 基準通貨は常に有効です。
- 基準通貨は直接編集・削除できません。 基準通貨の行の 編集 と 削除 ボタンは非表示/ロックされています。 「ものさし」を別の通貨に移したいときは、セクション 4 の 基準通貨を変更 機能を使います。基準のフラグや為替レートを 手で書き換えないでください。
なぜ手で編集できないのですか? 保存済みの価格の数字に手を付けずに基準通貨だけを変えると、商品全体が「間違った単位で 読まれて」しまいます(「100 USD」のつもりで
100と保存した商品が、急に「100 VND」と読まれてしまいます)。基準通貨を変更 機能なら、これを安全に行えます — すぐ下をご覧ください。
4. 基準通貨の変更(rebase)— 価値を保ったまま (v2.1)
ストアの「価格のものさし」を別の通貨に移したいとき(例:以前は USD で価格を入力していたが、今後は VND で入力したい)は、 基準通貨を変更 機能を使います。ポイントは、どの通貨でもお客様に表示される価格が変わらない よう、システムが 数字を 自動で再計算 することです。商品の価格を 1 つずつ入力し直す必要はありません。
手順
-
設定 → 通貨 を開きます。
-
上部にある 基準通貨を変更(Change base) ボタン(2 本の矢印 ⇄ のアイコン)を押します。警告のダイアログが表示されます。
-
現在の基準通貨 の行を見て、正しい通貨を変更しようとしているか確認します。
-
新しい基準通貨 の欄で、基準にしたい通貨を選びます。一覧には、有効 で まだ基準ではない 通貨だけが表示されます。
-
旧基準通貨の新しいレート の欄を確認します。価格を変えないための値(
1 ÷ 新しい通貨の現在のレート)を、システムが あらかじめ提案して入力 しています。意図的に別の値にしたい場合を除き、提案された値のままにしてください。 -
確認のチェックボックス 「基準通貨を変更することによる影響を理解しました。」(必須)にチェックを入れると、確定ボタンが 使えるようになります。
-
基準通貨を変更 を押して実行します。
成功すると、基準通貨の変更に成功したと表示されます。「基準」 バッジが新しい通貨に移り、ストアフロントの価格は以前と まったく同じままです。
システムが内部で行うこと(簡単な説明)
1 つの安全なトランザクション の中で行います(すべて完了するか、何も変わらないかのどちらかで、中途半端な状態はありません)。
- 基準通貨建ての価格の数字(販売価格、原価、属性の追加料金、特価)に 新しい通貨のレート を掛けます。
- すべての 為替レートを同じ数字で割ります(ほかの通貨も正しく換算されるようにするため)。
- 新しい通貨を基準(レート
1)にし、古い基準通貨には入力した新しいレートを設定します。 - 過去の注文には手を付けません。 注文時の通貨とレートがすでに「固定」されているからです。
この計算方法により、「2 USD ↔ 50.000 ₫」で販売中の商品は、基準を VND に変更した後も「50.000 ₫ ↔ 2 USD」と正しく表示されます。 保存されている数字は変わりますが、お客様に見える価値は変わりません。
5. 金額入力欄の横の通貨単位メモ(管理画面)(v2.1)
商品の金額入力欄はすべて 基準通貨 で入力するため、入力する人はどの通貨で入力しているのか混乱しがちです。2.1 から、 管理画面では各金額入力欄のすぐ横に 通貨コードのメモが自動で表示されます。
- 商品の画面(価格、原価、バリエーションの追加料金、特価など):基準通貨 のコードを表示します。例:
(VND)— 「この欄は基準通貨で入力します」というお知らせです。 - 注文の画面(注文の作成/編集):その注文自身の通貨 のコード(編集時)、または選んでいる通貨(作成時)を表示します。 通貨の違う注文を取り違えないためです。
- 何らかの理由で通貨を判定できない場合、メモは既定のラベルに戻ります(多言語の仕組みで変更できます)。
このメモは 表示上のお知らせ だけで、数字の保存方法は変わりません。これまでどおり基準通貨で入力してください。
6. 通貨はどこに表示されますか?
- お客様向けの画面(ストアフロント): 商品価格、カート、決済 — お客様が選んでいる通貨(既定の通貨、またはお客様が 切り替えた通貨)で表示されます。
- お客様の注文: 注文時 の通貨(注文に保存済み)で表示されます。
- 管理画面 — 注文詳細と注文一覧: 各注文は その注文自身の 通貨で表示されます(換算し直しません)。一覧に複数の通貨が 混ざっていても区別できるよう、記号も表示されます。
- 請求書(invoice): 注文の通貨で表示されます。
7. 大切な注意点
- 為替レートを変えても、過去の注文は変わりません。 確定した注文は購入時の通貨とレートを保持します。変更が影響するのは、 ストアフロントでの 新しい 価格の表示だけです。
- 商品価格は常に基準通貨で入力します。 換算済みの価格を入力しないでください。入力欄の横の通貨コードのメモ (セクション 5)が、どの通貨で入力しているかを知らせてくれます。
- 基準通貨を変えるときは Rebase 機能(セクション 4)を使います。 基準のフラグやレートを手で書き換えないでください。 商品全体の価格が狂わないよう、手での変更はシステムがブロックします。
- 小数点以下の桁数は通貨ごと に決まり、金額ごとではありません。たとえば VND の precision を
0にすると、VND の金額は すべて小数部分なしで表示されます。 - とても小さなレートも正確に保存されます。 システムはレートを小数点以下 6 桁まで保存するので、小さな単位から換算する
大きな通貨(例:レート
0.00004)でも 0 に丸められません。
8. 条件と制約(操作の前に確認)
通貨の画面には、データのチェックといくつかの業務上の制約があります。システムがエラーを出しても驚かないよう、先に確認して おきましょう。
通貨を追加/編集するとき
- 名前は必須 で、最大 100 文字です。通貨の一覧に常にわかりやすいラベルがあるようにするためです。
- コードは必須で、重複できません。最大 10 文字です。コードは通貨を識別する「キー」で(注文はコードで保存されます)、 重複するとデータが混乱するためです。
- 記号は必須 で、最大 20 文字です。お客様に価格を表示するためです。
- 為替レートは必須で、数値かつ 0 より大きくなければなりません。 レートが
0や負の数だと、換算した価格がすべて 0 に なったり、おかしくなったりするためです。 - 小数点以下の桁数は 0 から 8 の整数 です。金額を適切に表示するための制限です(実際の通貨で 8 桁を超える小数が必要な ものはありません)。
- 桁区切り記号は必須 で、最大 2 文字です。
- 並び順は数値で、負の数は使えません。
基準通貨について (v2.1)
- 基準通貨は編集・削除できません。 編集/削除ボタンはロックされ、URL から直接アクセスしようとしてもシステムがブロック します。理由: 基準通貨は商品全体の価格のものさしで、手で編集すると価格がすべて狂うからです。
- 基準通貨のレートは常に
1で、常に有効です。 変更できません。 - 基準通貨を変えたい場合は、基準通貨を変更 機能を使います(セクション 4)。
基準通貨を変更(rebase)するとき (v2.1)
- 基準通貨がすでに存在している 必要があります。
- 新しい基準通貨は有効で、まだ基準ではない通貨でなければなりません。 選択リストは、条件を満たす候補だけに自動で絞られて います。
- 旧基準通貨の新しいレートは 0 より大きく、
1以外の数値でなければなりません。1のままだと 2 つの通貨が等価という 意味になり、基準通貨の変更としては不合理だからです。 - 確認のチェックボックス「…理解しました」にチェックを入れないと、変更ボタンを押せません。商品全体に影響する操作だからです。
通貨を削除するとき
次の場合、システムは 削除をブロック し、理由を表示します(黙って削除することはありません)。ショップを壊したり、 過去の注文のデータを失ったりしないためです。
- 基準通貨である場合 (v2.1) — 基準通貨はすべての価格を保存する通貨で、削除するとすべての商品価格が「宙に浮いた」状態に なります。削除したい場合は、先に別の通貨へ 基準通貨を変更 してください(セクション 4)。
- ストアの既定の表示通貨になっている場合 — 削除すると、ショップに既定で表示する通貨がなくなります。先に既定の通貨を 別の通貨に変更(サイト情報)してから削除してください。
- この通貨を使った注文がすでにある場合 — 削除すると、過去の注文の通貨情報が失われ、金額が正しく表示されなくなります。 注文履歴を守るための重要な制約です。
- 最後の 1 つの有効な通貨である場合 — ショップには使える通貨が少なくとも 1 つ必要です。最後の 1 つを削除すると、 ストアフロントで表示できる通貨がなくなります。
削除の制約は、実際のデータ(基準のフラグ、現在の既定の通貨、実際の注文、有効な通貨の数)から判定され、固定の一覧に 基づくもの ではありません。そのため、長年にわたって通貨を変えてきたショップも含め、どのショップでも正しく働きます。
9. 処理ロジックと通貨関数(開発者向け)
このセクションは 開発者 向けです。一般のユーザーは読み飛ばしてかまいません。
データモデル
- テーブル
shop_currency:name、code(unique)、symbol、exchange_ratedecimal(16,6)、precision(tinyint)、symbol_first(0/1)、thousands、status(0/1)、sort、is_base(tinyInteger、既定値0) — 基準通貨のフラグで、「is_base=1の行はちょうど 1 つ」という不変条件があります (v2.1)。 - 注文の通貨スナップショット:
shop_order.currency(コード)+shop_order.exchange_ratedecimal(16,6)。shop_order_detail.exchange_rateも decimal(16,6) です(小さなレートを正確に保つため、3 つのテーブルで統一)。 - 基準通貨建てで、rebase() が掛け直す 4 つの価格列:
shop_product.price、shop_product.cost、shop_product_attribute.add_price、shop_product_promotion.price_promotion。
使用中の通貨の決定(ストアフロントのみ)
CurrencyMiddleware(front のルートグループにだけ登録され、admin には 登録されません):session('currency')を 読み込みます → 空ならgp247_store_info('currency')(既定の表示通貨)を使います → 有効な通貨の一覧になければ、最初の 有効な通貨を使います →ShopCurrency::setCode()を呼び出して static プロパティに読み込みます。- ストアフロントの通貨切替ルート:
front.currency(currency/{code})→session(['currency' => $code])。 - 管理画面についての注意: admin は
CurrencyMiddlewareを 実行しません。そのため、正しく表示するには、使用中の通貨では なく 注文のスナップショット の通貨(onlyRender)を使う必要があります。
基準通貨と rebase (v2.1) — Models/ShopCurrency.php
getBaseCode(): ?string— 基準通貨の 唯一の信頼できる情報源 です:where('is_base', 1)->value('code')。 以前の「レート1の有効な通貨を探す」方法(誤りやすい)に代わるものです。アップグレードしたサイトでまだ基準を選んで いない場合はnullを返します。- Boot guards(多層防御):
deleting:deleteBlockReason() !== nullの場合に削除をブロックします(Livewire、seeder、tinker など、すべての削除経路に 適用されます)。saving:is_base=1なのにexchange_rate != 1またはstatus != 1の場合に保存をブロックします(基準の不変条件を 守ります)。rebase と seeder はクエリビルダーを使う(モデルイベントを経由しない)ため、このガードに止められることは ありません。
rebase(string $newBaseCode, float $newRateForOldBase): void— 価値を保ったまま 基準を変更し、1 つのトランザクション で実行します(NFR-AVAIL-rebase-atomicity)。r = 新しい通貨の現在のレートとすると、基準通貨建ての 4 つの価格列 × r (DB 層での一括 UPDATE で、カタログを PHP に読み込み ません — RISK-TECH-rebase-bulk-price-update)、すべてのレートを ÷ r、新しい通貨をrate=1, is_base=1、古い通貨をrate=$newRateForOldBase, is_base=0に固定します。価値が保たれることの 証明:すべての通貨 C について(price×r)×(oldRate(C)/r) = price×oldRate(C)。基準がない/対象が不正/レートが不正な場合はInvalidArgumentExceptionを投げます。最後にresetStaticCache()を呼び出します。sqlNumericLiteral(float): string(private)—sprintf('%.6F', $r)で安全な decimal リテラル(指数表記なし、小数点は ドット、scale 6 で切り詰め)を作り、col = col * rに埋め込みます。呼び出し側が管理する値にだけ使います。deleteBlockReason(): ?string— 削除の不変条件(セクション 8)に従ってbase/default/in_use/last_active/nullを返します。codeを基準に判定し、is_baseを最初に確認します (v2.1)。gp247_store_info('currency')を使います (admin はミドルウェアを読み込まないためgetCode()は使いません)。where('status',1)->count()で直接数えます。
Livewire 管理画面 — Admin/Livewire/CurrencyManager.php
- 基準の行では編集と削除を非表示/ロックします。
is_base=1の場合、edit()/save()は拒否します(URL からの直接アクセス 対策)。 - 基準通貨を変更 のモーダル:
rebaseTarget、rebaseOldRate、rebaseConfirmed。updatedRebaseTarget()はrebaseOldRate = 1 / rate(target)を自動で提案します(sprintf('%.6F')の後に trim)。rebase()は検証を行い (rebaseTargetは存在し、status=1、is_base=0であること。rebaseOldRateはnumeric|gt:0|not_in:1。rebaseConfirmedはaccepted)、その後ShopCurrency::rebase()を呼び出します。ドメインのエラーは toast で表示し、 成功すれば flash + リダイレクトします。
ヘルパー関数(Library/Helpers/currency.php)
gp247_currency_render($money, $currency=null, $rate=null, $space=false, $useSymbol=true)— 換算(レートを掛ける)- 書式設定 + 記号。
gp247_currency_render_symbol($money, $currency=null, $space=false, $includeSymbol=true)— 書式設定 + 記号のみで、 換算はしません(金額がすでに正しい通貨の場合。例:注文のスナップショットの金額)。gp247_currency_value($money, $rate=null)— レートで値を換算します。gp247_currency_code()/gp247_currency_rate()/gp247_currency_info()— 使用中の通貨。gp247_currency_format($money)— 使用中の通貨の precision で数値を書式設定します(記号なし)。gp247_currency_all()— 有効な通貨の一覧(並べ替え済み)。gp247_currency_all_active()— 有効な通貨のcode → nameのマップ。gp247_base_currency_code(): ?string(v2.1) —ShopCurrency::getBaseCode()のラッパーです。gp247_money_hint($code = null): string(v2.1) — 金額入力欄の横のメモ:null→ 基準通貨を使い、"(CODE)"を 返します。判定できない場合は i18n ラベルproduct.base_unit_hintに戻ります。
よくある質問(Q&A)
Q1: 商品価格はどの通貨で入力しますか?
→ 基準通貨 — 「基準」バッジが付いた通貨(レート 1)で入力します。ほかの通貨は表示時にシステムが自動で換算します。
2.1 からは、各金額入力欄の横に通貨コードのメモ(例:(VND))が表示され、どの通貨で入力しているかを知らせてくれます。
Q2: 「基準通貨」とショップの「既定の通貨」は何が違いますか?
→ 基準通貨 は 商品価格を保存する場所 です(ものさしで、レートは常に 1、ロックされています)。既定の通貨
(サイト情報で設定)は、お客様がショップに来たときに 最初に見る通貨 です。多くの場合は同じですが、別の考え方です。
Q3: 基準通貨を USD から VND に変えたい場合は?
→ 設定 → 通貨 を開き、基準通貨を変更 を押して新しい通貨を選び、提案されたレートのままにして、確認のチェックを入れて 変更を押します。システムが数字を再計算するので、お客様に見える価格は変わりません。商品の価格を 1 つずつ直す必要は ありません。
Q4: 基準通貨を変えると、商品価格が狂いませんか?
→ 狂いません。基準通貨の変更機能は 価値を保ちます。数字を整合するように掛け直し・割り直すので、どの通貨でも表示価格は そのままです。過去の注文にも手を付けません。
Q5: 基準通貨を編集・削除できないのはなぜですか?
→ 基準通貨は商品全体の価格のものさしで、手で編集すると価格がすべて狂うからです。変えたい場合は、直接編集するのではなく 基準通貨を変更 を使ってください。
Q6: 金額入力欄の横の (VND) というメモは何ですか?
→ その欄がどの通貨で入力するものかを知らせるメモです(商品の画面では 基準通貨、注文の画面では注文の通貨)。表示のため だけのもので、数字の保存方法は変わりません。
Q7: VND の金額の最後に .00 が付いて表示される(例:250.000,00)のはなぜですか?
→ その通貨の 小数点以下の桁数(precision) が 0 以外になっているからです。小数部分を表示しないよう、VND の precision を
0 にしてください。
Q8: 為替レートを変えると、過去の注文は再計算されますか?
→ されません。各注文は注文時の通貨とレートを保存しています。レートの変更が影響するのは、ストアフロントでの 新しい 価格の 表示だけです。
Q9: 通貨を削除できないのはなぜですか?
→ ブロックされるケースのどれかに当てはまっているからです:基準通貨 である、ショップの 既定の通貨 になっている、 その通貨を使った 注文がある、または 最後の有効な通貨 である。システムが具体的な理由を表示します。
Q10: 為替レートを市場に合わせて自動で更新できますか?
→ 現在のバージョンでは、為替レートは通貨の画面で 手動で 入力します。自動でレートを更新する機能は用意されていません。
📅 最終更新: 2026-10-22 · ✍️ 作成者 (Author): GP247