| @@ -868,12 +868,16 @@ | ||
| 868 | 868 | */ |
| 869 | 869 | private function formatDiscountAmount($discount): string { |
| 870 | 870 | $amount = $discount->group_discount_amount ?? 0; |
| 871 | 871 | if ($discount->group_discount_type === 'percentage') { |
| 872 | - return "{$amount}% off"; | |
| 873 | - } else { | |
| 874 | - return "$" . number_format((float) $amount, 2) . " off"; | |
| 872 | + /* translators: %s: discount percentage. */ | |
| 873 | + return sprintf(__('%s%% off', 'yatra'), $amount); | |
| 875 | 874 | } |
| 875 | + | |
| 876 | + // Was a hardcoded "$" with default separators, so every non-dollar site | |
| 877 | + // showed the wrong currency (and the label could not be translated). | |
| 878 | + /* translators: %s: discount amount, already formatted with the site currency. */ | |
| 879 | + return sprintf(__('%s off', 'yatra'), yatra_format_price((float) $amount, null, false)); | |
| 876 | 880 | } |
| 877 | 881 | |
| 878 | 882 | /** |
| 879 | 883 | * @param array $travelerCounts Array of category_id => count (e.g., ['3' => 4, '5' => 1]) |
| @@ -898,19 +902,32 @@ | ||
| 898 | 902 | |
| 899 | 903 | |
| 900 | 904 | $totalTravelers = array_sum(array_map('intval', $travelerCounts)); |
| 901 | 905 | |
| 902 | - // Build price lookup by category_id | |
| 906 | + // Build price + price-type lookup by category_id | |
| 903 | 907 | $priceByCategory = []; |
| 908 | + $ptByCategory = []; | |
| 904 | 909 | foreach ($priceTypes as $pt) { |
| 905 | - $pt = (object) $pt; | |
| 906 | - $categoryId = $pt->category_id ?? null; | |
| 910 | + $pt = (array) $pt; | |
| 911 | + $categoryId = $pt['category_id'] ?? null; | |
| 907 | 912 | if ($categoryId !== null) { |
| 908 | - $priceByCategory[$categoryId] = (float) ($pt->effective_price ?? $pt->sale_price ?? $pt->original_price ?? 0); | |
| 913 | + $priceByCategory[$categoryId] = (float) ($pt['effective_price'] ?? $pt['sale_price'] ?? $pt['original_price'] ?? 0); | |
| 914 | + $ptByCategory[$categoryId] = $pt; | |
| 909 | 915 | } |
| 910 | 916 | } |
| 911 | 917 | |
| 918 | + // Effective subtotal for a category — delegate to the single source of | |
| 919 | + // truth so the discount base ALWAYS matches CalculationService's charge | |
| 920 | + // (per-person × count, flat per-group, or per-block group pricing). | |
| 921 | + $catSubtotal = function ($categoryId, $count) use ($priceByCategory, $ptByCategory): float { | |
| 922 | + return \Yatra\Services\TripPricingService::categoryLineSubtotal( | |
| 923 | + $ptByCategory[$categoryId] ?? [], | |
| 924 | + (int) $count, | |
| 925 | + (float) ($priceByCategory[$categoryId] ?? 0) | |
| 926 | + ); | |
| 927 | + }; | |
| 912 | 928 | |
| 929 | + | |
| 913 | 930 | foreach ($groupDiscounts as $discount) { |
| 914 | 931 | $discountMode = $discount->discount_mode ?? 'total'; |
| 915 | 932 | |
| 916 | 933 | // Category-based discounts: check each category's count and apply to that category's subtotal |
| @@ -940,10 +957,10 @@ | ||
| 940 | 957 | $discountType = $range->discount_type ?? 'percentage'; |
| 941 | 958 | $discountValue = (float) ($range->discount_amount ?? 0); |
| 942 | 959 | |
| 943 | 960 | // Calculate discount for this category's subtotal only |
| 944 | - $categoryPrice = $priceByCategory[$categoryId] ?? 0; | |
| 945 | - $categorySubtotal = $categoryPrice * $categoryCount; | |
| 961 | + // (flat for per-group, price × count for per-person). | |
| 962 | + $categorySubtotal = $catSubtotal($categoryId, $categoryCount); | |
| 946 | 963 | |
| 947 | 964 | if ($discountType === 'percentage') { |
| 948 | 965 | $categoryDiscount = $categorySubtotal * ($discountValue / 100); |
| 949 | 966 | } else { |
| @@ -970,10 +987,12 @@ | ||
| 970 | 987 | $discountInfo = ''; |
| 971 | 988 | if (!empty($appliedCategories)) { |
| 972 | 989 | $firstCat = $appliedCategories[0]; |
| 973 | 990 | if ($firstCat['discount_type'] === 'percentage') { |
| 991 | + /* translators: %s: discount percentage value. */ | |
| 974 | 992 | $discountInfo = sprintf(__('Group Discount (%s%%)', 'yatra'), $firstCat['discount_value']); |
| 975 | 993 | } else { |
| 994 | + /* translators: %s: formatted discount amount. */ | |
| 976 | 995 | $discountInfo = sprintf(__('Group Discount (%s)', 'yatra'), yatra_format_price($firstCat['discount_value'])); |
| 977 | 996 | } |
| 978 | 997 | } else { |
| 979 | 998 | $discountInfo = __('Group Discount', 'yatra'); |
| @@ -1002,10 +1021,9 @@ | ||
| 1002 | 1021 | |
| 1003 | 1022 | // Calculate total subtotal from all categories |
| 1004 | 1023 | $totalSubtotal = 0; |
| 1005 | 1024 | foreach ($travelerCounts as $catId => $count) { |
| 1006 | - $categoryPrice = $priceByCategory[$catId] ?? 0; | |
| 1007 | - $totalSubtotal += $categoryPrice * $count; | |
| 1025 | + $totalSubtotal += $catSubtotal($catId, $count); | |
| 1008 | 1026 | } |
| 1009 | 1027 | |
| 1010 | 1028 | // Calculate the actual discount amount |
| 1011 | 1029 | $calculatedAmount = $discountType === 'percentage' |
| @@ -1016,10 +1034,12 @@ | ||
| 1016 | 1034 | 'type' => $discountType, |
| 1017 | 1035 | 'value' => $discountValue, |
| 1018 | 1036 | 'amount' => round($calculatedAmount, 2), |
| 1019 | 1037 | 'code' => $discount->code ?? null, |
| 1020 | - 'label' => $discountType === 'percentage' | |
| 1038 | + 'label' => $discountType === 'percentage' | |
| 1039 | + /* translators: %s: discount percentage value. */ | |
| 1021 | 1040 | ? sprintf(__('Group Discount (%s%%)', 'yatra'), $discountValue) |
| 1041 | + /* translators: %s: formatted discount amount. */ | |
| 1022 | 1042 | : sprintf(__('Group Discount (%s)', 'yatra'), yatra_format_price($discountValue)), |
| 1023 | 1043 | ]; |
| 1024 | 1044 | } |
| 1025 | 1045 | } |
| @@ -1043,10 +1063,9 @@ | ||
| 1043 | 1063 | |
| 1044 | 1064 | // Calculate total subtotal from all categories |
| 1045 | 1065 | $totalSubtotal = 0; |
| 1046 | 1066 | foreach ($travelerCounts as $catId => $count) { |
| 1047 | - $categoryPrice = $priceByCategory[$catId] ?? 0; | |
| 1048 | - $totalSubtotal += $categoryPrice * $count; | |
| 1067 | + $totalSubtotal += $catSubtotal($catId, $count); | |
| 1049 | 1068 | } |
| 1050 | 1069 | |
| 1051 | 1070 | // Calculate the actual discount amount |
| 1052 | 1071 | $calculatedAmount = $discountType === 'percentage' |
| @@ -1057,10 +1076,12 @@ | ||
| 1057 | 1076 | 'type' => $discountType, |
| 1058 | 1077 | 'value' => $discountValue, |
| 1059 | 1078 | 'amount' => round($calculatedAmount, 2), |
| 1060 | 1079 | 'code' => $discount->code ?? null, |
| 1061 | - 'label' => $discountType === 'percentage' | |
| 1080 | + 'label' => $discountType === 'percentage' | |
| 1081 | + /* translators: %s: discount percentage value. */ | |
| 1062 | 1082 | ? sprintf(__('Group Discount (%s%%)', 'yatra'), $discountValue) |
| 1083 | + /* translators: %s: formatted discount amount. */ | |
| 1063 | 1084 | : sprintf(__('Group Discount (%s)', 'yatra'), yatra_format_price($discountValue)), |
| 1064 | 1085 | ]; |
| 1065 | 1086 | } |
| 1066 | 1087 | } |
| @@ -1067,9 +1088,9 @@ | ||
| 1067 | 1088 | } |
| 1068 | 1089 | |
| 1069 | 1090 | return null; |
| 1070 | 1091 | } |
| 1071 | - | |
| 1092 | + | |
| 1072 | 1093 | /** |
| 1073 | 1094 | * Calculate coupon discount for booking |
| 1074 | 1095 | * |
| 1075 | 1096 | * @param string $coupon_code Coupon code to apply |
| @@ -1133,9 +1154,10 @@ | ||
| 1133 | 1154 | 'code' => $coupon_code, |
| 1134 | 1155 | 'type' => $discount->type, |
| 1135 | 1156 | 'amount' => (float) $discount->amount, |
| 1136 | 1157 | 'calculated_amount' => round($calculated_discount, 2), |
| 1137 | - 'label' => $discount->type === 'percentage' | |
| 1158 | + 'label' => $discount->type === 'percentage' | |
| 1159 | + /* translators: %s: discount percentage value. */ | |
| 1138 | 1160 | ? sprintf(__('Coupon (%s%%)', 'yatra'), $discount->amount) |
| 1139 | 1161 | : __('Coupon Discount', 'yatra'), |
| 1140 | 1162 | ]; |
| 1141 | 1163 | } |
| @@ -1215,10 +1237,11 @@ | ||
| 1215 | 1237 | |
| 1216 | 1238 | // Check minimum amount |
| 1217 | 1239 | if (!empty($discount->min_amount) && $total < (float) $discount->min_amount) { |
| 1218 | 1240 | return [ |
| 1219 | - 'valid' => false, | |
| 1241 | + 'valid' => false, | |
| 1220 | 1242 | 'message' => sprintf( |
| 1243 | + /* translators: %s: formatted minimum amount. */ | |
| 1221 | 1244 | __('Minimum amount of %s required for this coupon.', 'yatra'), |
| 1222 | 1245 | yatra_format_price((float) $discount->min_amount) |
| 1223 | 1246 | ) |
| 1224 | 1247 | ]; |