ponshu-room-lite/lib/services/pricing_helper.dart

95 lines
3.1 KiB
Dart

/// 価格設定のヘルパー関数群
///
/// 店員の感覚に寄り添った価格処理を提供します:
/// - スマート丸め処理 (キリの良い価格に自動調整)
/// - サイズ別価格の自動計算
/// - 価格表示フォーマット (カンマ区切り、円表記)
class PricingHelper {
/// サイズ別の価格比率
///
/// 店員が感覚的に使っている「一合を基準にした比率」
static const sizeRatios = {
'45ml': 0.40, // 一合の約1/4
'90ml': 0.65, // 一合の半分弱
'180ml': 1.0, // 基準 (一合)
};
/// スマート丸め処理
///
/// 店員が手作業でやる「端数を切る」処理を自動化。
/// 価格帯に応じて、キリの良い単位に丸めます:
/// - 500円未満: 50円単位 (例: 720円 → 700円)
/// - 500円以上: 100円単位 (例: 1,170円 → 1,200円)
///
/// [rawPrice] 計算された生の価格
/// 戻り値: 丸められた価格
static int smartRound(double rawPrice) {
if (rawPrice <= 0) return 0;
if (rawPrice < 500) {
// 500円未満 → 50円単位
return ((rawPrice / 50).round() * 50).toInt();
} else {
// 500円以上 → 100円単位
return ((rawPrice / 100).round() * 100).toInt();
}
}
/// サイズ別価格の計算
///
/// 一合価格を基準に、各サイズの価格を自動計算します。
///
/// [basePrice] 一合 (180ml) の価格
/// [size] サイズ (45ml, 90ml, 180ml)
/// 戻り値: 計算・丸め処理された価格
static int calculateSizePrice(int basePrice, String size) {
final ratio = sizeRatios[size] ?? 1.0;
final rawPrice = basePrice * ratio;
return smartRound(rawPrice);
}
/// 価格フォーマット (カンマ区切り)
///
/// 内部データ (int) を表示用文字列に変換します:
/// - 3桁ごとにカンマを挿入
/// - 「円」は付けない (表示側で追加)
///
/// [price] 価格 (int)
/// 戻り値: カンマ区切りの文字列 (例: "1,800")
static String formatPrice(int price) {
if (price <= 0) return '0';
return price.toString().replaceAllMapped(
RegExp(r'(\d{1,3})(?=(\d{3})+(?!\d))'),
(Match m) => '${m[1]},',
);
}
/// 価格パース (カンマ除去)
///
/// ユーザー入力 (カンマ付き文字列) を int に変換します。
///
/// [priceString] 価格文字列 (例: "1,800" or "1800")
/// 戻り値: パースされた価格 (失敗時は null)
static int? parsePrice(String priceString) {
final cleaned = priceString.replaceAll(',', '').trim();
return int.tryParse(cleaned);
}
/// サイズ表示名
///
/// 内部ID (45ml) を表示用の名称に変換します。
///
/// [size] サイズID
/// 戻り値: 表示名 (例: "45ml")
static String getSizeDisplayName(String size) {
// 現状はそのまま返すが、将来的に「グラス (45ml)」などに拡張可能
return size;
}
/// 利用可能なサイズ一覧
///
/// MVPで提供するサイズの一覧。
/// デモでは3種類に絞る。
static List<String> get availableSizes => ['45ml', '90ml', '180ml'];
}