GP247における通貨

🌐 言語: 🇻🇳 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 つあります。

  1. ショップでは複数の通貨を使えます。 通貨の一覧(例:USD、VND)を登録します。各通貨は 有効(お客様が使える)または 無効(非表示)にできます。
  2. 商品価格は 1 つの「基準通貨」で保存されます。 商品価格は、基準通貨(base currency — GP247 ではストアの「基準」/ 「bit」単位とも呼びます)で 1 回だけ入力します。ほかの通貨で表示するときは、その通貨の 為替レート(exchange rate) を 使って、システムが 自動で換算 します。
  3. 基準通貨は明示的です (v2.1)。 基準 として指定される通貨はちょうど 1 つ です(一覧に青い「基準」バッジが付きます)。 基準通貨は 為替レートが常に 1 で、常に有効 で、編集・削除がロック されています。変更は 基準通貨を変更 機能 (セクション 4 をご覧ください)でのみ行います。2.1 より前は、為替レートが 1 の通貨が基準だと「暗黙的に」みなされて いたため、レート 1 の通貨が 0 個や複数あると混乱しやすい状態でした。
  4. 通貨ごとに表示形式があります。 含まれるのは:記号(例:$、₫)、記号の位置(金額の前か後か)、 小数点以下の桁数(precision — 例:USD は 2 桁で 10.00、VND は 0 桁で 250.000)、桁区切り記号 です。
  5. ストアには既定の表示通貨があります。 お客様がショップに来たときに最初に表示される通貨です。注意: これは 3 の 基準通貨とは 別の 考え方です。基準通貨は 価格を保存する場所 で、既定の通貨は お客様が最初に見る通貨 です。多くの 場合 2 つは同じですが、同じである必要はありません。ショップで複数の通貨を有効にすると、お客様は画面の切替ボタンで 自分で通貨を切り替えられます。
  6. 注文は注文時の通貨を記憶します。 お客様が注文すると、注文にはその時点の通貨と為替レートが 保存されます。後で 為替レートを変えても 過去の注文は変わりません。お客様が購入したときのとおりに表示されます。

用語: 為替レート(exchange rate) は、基準価格 を表示中の通貨に換算する数値です。基準通貨のレートは 1 です。 例:基準価格が USD(レート 1)で、VND のレートを 25000 にすると → 基準価格 2 の商品は、VND で見ると 50.000 ₫ と 表示されます。


2. 通貨の設定手順(順番に進めてください)

ステップ 1 — 通貨の管理画面を開く

  1. ショップの 管理画面(admin) にログインします。

  2. メニューの 設定 → 通貨(Currency)(通貨のアイコン)を開きます。

    成功すると、画面が 2 つに分かれて表示されます:左側に入力フォーム、右側に通貨の一覧 です。現在 基準 の 通貨には、名前の列に青い 「基準」 バッジが付きます (v2.1)。

この画面を開くには admin_currency 権限が必要です。メニューが見当たらない場合は、管理者に権限を付与してもらってください。

ステップ 2 — 新しい通貨を追加する

  1. 新規追加(Add new) を押します。

  2. 次の項目を入力します。

    • 名前(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): 数字が小さいほど、選択リストの前のほうに表示されます。
  3. 保存 を押します。

    成功すると、新しい通貨が右側の一覧に表示されます。

小数点の記号について: システムは小数点の記号を、桁区切り記号の 逆 として自動で決めます。桁区切りを , にすると 小数点は . になり(例:1,234.50)、桁区切りを . にすると小数点は , になります(例:1.234,50)。

ステップ 3 — ストアの既定の表示通貨を設定する

  1. 設定 → サイト情報 / ストア(Website Info 画面)を開きます。
  2. 通貨(Currency) の選択欄を探し、ショップの既定の通貨を選びます。
  3. 保存します。

これはお客様がショップを開いたときに 最初に表示される 通貨です(価格を保存する基準通貨とは別です)。この欄では 有効な 通貨だけを選べます。

ステップ 4 —(任意)お客様が通貨を切り替えられるようにする

  • ショップで 2 つ以上の通貨 を有効にすると、お客様向けの画面のヘッダーまたはフッターに 通貨切替ボタン(currency switcher)が表示されます。お客様が選ぶと、ショップ全体の価格がその通貨で表示し直されます。
  • お客様の選択はそのお客様のセッション内で記憶され、ほかのお客様には影響しません。

ステップ 5 — ストアで確認する

  1. お客様向けの画面(ストアフロント) でショップを開きます。
  2. 切替ボタンで別の通貨に切り替えてみます。
  3. 商品とカートの価格の記号と小数点以下の桁数が、設定どおりに変わっているか確認します。

3. 基準通貨 — なぜロックされているのですか? (v2.1)

基準通貨 は、すべての商品価格、原価(cost)、属性の追加料金、特価 がデータベースに保存される単位です。言い換えると、 商品に入力した金額はすべて「基準通貨での金額」とみなされます。商品全体の「ものさし」なので、GP247 2.1 ではしっかり保護して います。

  • 基準通貨は常にちょうど 1 つ で、一覧に 「基準」 バッジが付きます。
  • 基準通貨の為替レートは常に 1 です(編集できません)。ほかのすべてのレートは、基準通貨 に対して 測るからです。
  • 基準通貨は常に有効です。
  • 基準通貨は直接編集・削除できません。 基準通貨の行の 編集 と 削除 ボタンは非表示/ロックされています。 「ものさし」を別の通貨に移したいときは、セクション 4 の 基準通貨を変更 機能を使います。基準のフラグや為替レートを 手で書き換えないでください。

なぜ手で編集できないのですか? 保存済みの価格の数字に手を付けずに基準通貨だけを変えると、商品全体が「間違った単位で 読まれて」しまいます(「100 USD」のつもりで 100 と保存した商品が、急に「100 VND」と読まれてしまいます)。基準通貨を変更 機能なら、これを安全に行えます — すぐ下をご覧ください。


4. 基準通貨の変更(rebase)— 価値を保ったまま (v2.1)

ストアの「価格のものさし」を別の通貨に移したいとき(例:以前は USD で価格を入力していたが、今後は VND で入力したい)は、 基準通貨を変更 機能を使います。ポイントは、どの通貨でもお客様に表示される価格が変わらない よう、システムが 数字を 自動で再計算 することです。商品の価格を 1 つずつ入力し直す必要はありません。

手順

  1. 設定 → 通貨 を開きます。

  2. 上部にある 基準通貨を変更(Change base) ボタン(2 本の矢印 ⇄ のアイコン)を押します。警告のダイアログが表示されます。

  3. 現在の基準通貨 の行を見て、正しい通貨を変更しようとしているか確認します。

  4. 新しい基準通貨 の欄で、基準にしたい通貨を選びます。一覧には、有効 で まだ基準ではない 通貨だけが表示されます。

  5. 旧基準通貨の新しいレート の欄を確認します。価格を変えないための値(1 ÷ 新しい通貨の現在のレート)を、システムが あらかじめ提案して入力 しています。意図的に別の値にしたい場合を除き、提案された値のままにしてください。

  6. 確認のチェックボックス 「基準通貨を変更することによる影響を理解しました。」(必須)にチェックを入れると、確定ボタンが 使えるようになります。

  7. 基準通貨を変更 を押して実行します。

    成功すると、基準通貨の変更に成功したと表示されます。「基準」 バッジが新しい通貨に移り、ストアフロントの価格は以前と まったく同じままです。

システムが内部で行うこと(簡単な説明)

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_rate decimal(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_rate decimal(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