PluginProbe
Yatra – Travel Booking & Tour Operator Software / 3.0.16
Yatra – Travel Booking & Tour Operator Software v3.0.16
3.0.16 3.0.15 3.0.14 3.0.14.1 3.0.14.2 3.0.12 3.0.13 3.0.11 3.0.10 3.0.9 3.0.8 3.0.7 3.0.6 3.0.5 3.0.5.1 3.0.4 3.0.3 3.0.2.9 3.0.2.7 3.0.2.8 3.0.2.6 trunk 1.0.0 2.0.0 2.0.1 All 84 releases
← All changes | app/Services/DiscountService.php +41 -18 3.0.3 → 3.0.16 View file →
@@ -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 ];