Normal #11188
客室単価(RoomRate)予約で大人/こども別の売上科目が反映されない問題の対応
Description
Booking.com大人/こども売上科目 対応状況¶
経緯¶
「室料区分」で大人/こども別の売上科目が反映されない不具合を調査。
原因:「室料区分」の予約は部屋単位の合計金額のみ、人数別単価なしで連携されており、
既存の「人数区分」ロジックでは大人/こども別の項目が生成されないため。
Phase1(応急処置):対応済み・テスト完了¶
- 客室単価(室料区分)の予約でも、朝食等の項目を人数基準(大人・こども区別なし)で按分計上するよう
sales.phpを修正 - ステージング環境で以下を確認済み
- 人数按分の計算が正しいこと(合計金額が予約総額と一致)
- 人数0件時のガード(0除算なし)
- 複数泊時の翌日計上を含めた計算
- 既存の人数区分(PersonalRate)予約への影響がないこと(回帰なし)
- 朝食等の紐付けが未設定の既存プランでの後方互換維持
- 制限事項:大人/こどもを区別した単価設定はできず、合計人数での一律按分のみ
Phase2(本対応):設計中¶
画面イメージ¶
| プランID | プラン名 | 料金タイプ | OTA | 施設名 |
|---|---|---|---|---|
| - | - | 人数区分 / 室料区分(ラジオボタン、デフォルト:人数区分) | - | - |
人数区分選択時(既存とほぼ同じ、客室単価列は削除)
| 大人 | こどもA | こどもB | こどもC | こどもD | こどもその他 |
|---|
室料区分選択時(新規UI)
| 宿泊費(+追加) | 大人 | こどもA | こどもB | こどもC | こどもD | こどもその他 |
|---|---|---|---|---|---|---|
| 数量1固定、残額を吸収 | 夕食/朝食/昼食/追加を人数分按分で計上 | 同左 | 同左 | 同左 | 同左 | 同左 |
主な設計方針¶
- 財布共有:予約の合計金額(TotalPerRoomRate)は絶対に変わらない。可変(残額)項目は「宿泊費」1つのみ、それ以外は全て固定額(項目数制限なし)
- 判定基準:予約ごとの計算は、プラン側の設定ではなくOTAから届く実際のデータ(室料区分/人数区分)を優先
- ガード:固定額合計が総額を超えて宿泊費がマイナスになるケースは、既存の人数区分側にも同様の可能性があるため、現時点ではガードなしで統一(必要になれば後日追加)
- 想定外のケースへの対応:プラン設定と実際の予約データの区分が食い違った場合(例:室料区分プランに人数区分予約が来た等)は、既存の「その他プラン」へのフォールバック機構で吸収する
- 既存プランの移行:全既存プランはデフォルトで「人数区分」扱い。従来「客室単価」の「宿泊」に設定されていたものは新方式の「宿泊費」にそのまま引き継ぎ、「客室単価」の「朝食」等は一旦無視(Phase1の設定は使われなくなる)
ALTER TABLE plan_item_map
ADD COLUMN rate_type TINYINT(1) NOT NULL DEFAULT 0
COMMENT '料金タイプ(0:人数区分, 1:室料区分)'
AFTER sales_item_type;
ALTER TABLE plans
ADD COLUMN rate_type TINYINT(1) NOT NULL DEFAULT 0
COMMENT '紐づけ画面のデフォルト表示(0:人数区分, 1:室料区分)。売上計算には使用しない'
AFTER ota_name;
-- ステップ1:事前確認
-- 客室単価と売上アイテムが紐づいているレコードがあるか確認。
SELECT id, plan_id, sales_item_id, customer_type, sales_item_type, rate_type
FROM plan_item_map
WHERE customer_type = '客室単価'
AND deleted_flg = 0
ORDER BY plan_id, sales_item_type;
-- ステップ2:「宿泊」(室料区分の残額アイテム)をrate_type=1に更新
UPDATE plan_item_map
SET rate_type = 1
WHERE customer_type = '客室単価'
AND sales_item_type = '宿泊'
AND deleted_flg = 0;
-- ステップ3:「宿泊」以外(朝食・昼食・夕食・その他)を
-- 「大人」〜「こどもその他」6タイプに複製(rate_type=1)
INSERT INTO plan_item_map
(plan_id, sales_item_id, customer_type, sales_item_type, rate_type, created_us, created_at, updated_us, updated_at, deleted_flg)
SELECT
pim.plan_id, pim.sales_item_id, ct.customer_type, pim.sales_item_type, 1,
'migration', NOW(), 'migration', NOW(), 0
FROM plan_item_map pim
CROSS JOIN (
SELECT '大人' AS customer_type
UNION ALL SELECT 'こどもA'
UNION ALL SELECT 'こどもB'
UNION ALL SELECT 'こどもC'
UNION ALL SELECT 'こどもD'
UNION ALL SELECT 'こどもその他'
) ct
WHERE pim.customer_type = '客室単価'
AND pim.sales_item_type != '宿泊'
AND pim.deleted_flg = 0;
Subtasks
Related issues