PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.6.5
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.6.5
1.6.5 1.6.4 1.6.3 1.6.2 1.6.1 1.6.0 1.5.4 1.5.5 1.5.3 1.5.2 1.5.1 1.5.0 1.4.2 1.4.1 1.4.0 1.3.28 1.3.27 1.3.26 1.3.25 1.3.23 1.3.22 1.3.21 1.3.20 1.3.19 trunk All 48 releases
← All changes | app/Services/BulkProductInsertService.php +52 -10 1.6.1 → 1.6.5 View file →
@@ -7,8 +7,10 @@
7 7 use FluentCart\App\Helpers\Helper;
8 8 use FluentCart\App\Models\ProductDetail;
9 9 use FluentCart\App\Models\ProductVariation;
10 10 use FluentCart\Framework\Support\Arr;
11 +use FluentCart\App\Http\Rules\RequiredWhenRule;
12 +use FluentCart\App\Http\Rules\WhenFilledRule;
11 13 use FluentCart\Framework\Validator\Validator;
12 14
13 15 class BulkProductInsertService
14 16 {
@@ -111,13 +113,53 @@
111 113
112 114 return Helper::installmentTimesError(Arr::get($allData, "variants.$index.other_info"));
113 115 },
114 116 ],
115 - 'variants.*.other_info.repeat_interval' => 'nullable|required_if:variants.*.other_info.payment_type,subscription|sanitizeText|in:yearly,half_yearly,quarterly,monthly,weekly,daily',
117 + // Conditional requirements here are closures, not `required_if`, and
118 + // the attributes carrying one have no `nullable`: filterExcludeables()
119 + // drops EVERY rule — closures included — when `nullable` meets a falsy
120 + // value, which is what left these requirements dead. WhenFilledRule
121 + // therefore carries the value checks that `nullable` used to guard.
122 + //
123 + // manage_setup_fee keeps `nullable` on purpose: it is an optional flag
124 + // that both services already default to 'no', so demanding it would
125 + // reject payloads that simply omit it.
126 + 'variants.*.other_info.repeat_interval' => [
127 + RequiredWhenRule::make(
128 + 'variants.*.other_info.payment_type',
129 + 'subscription',
130 + __('Interval is required for subscriptions.', 'fluent-cart')
131 + ),
132 + WhenFilledRule::in(
133 + ['yearly', 'half_yearly', 'quarterly', 'monthly', 'weekly', 'daily'],
134 + __('Interval must be a valid frequency.', 'fluent-cart')
135 + ),
136 + ],
116 137 'variants.*.other_info.trial_days' => 'nullable|numeric|min:0|max:365',
117 - 'variants.*.other_info.manage_setup_fee' => 'nullable|required_if:variants.*.other_info.payment_type,subscription|sanitizeText|in:no,yes',
118 - 'variants.*.other_info.signup_fee' => 'nullable|required_if:variants.*.other_info.manage_setup_fee,yes|numeric|min:0',
119 - 'variants.*.other_info.signup_fee_name' => 'nullable|required_if:variants.*.other_info.manage_setup_fee,yes|sanitizeText|maxLength:100',
138 + 'variants.*.other_info.manage_setup_fee' => 'nullable|sanitizeText|in:no,yes',
139 + 'variants.*.other_info.signup_fee' => [
140 + RequiredWhenRule::make(
141 + 'variants.*.other_info.manage_setup_fee',
142 + 'yes',
143 + __('Setup Fee Amount is required.', 'fluent-cart')
144 + ),
145 + WhenFilledRule::numericAtLeast(
146 + 0,
147 + __('Setup Fee must be a number.', 'fluent-cart'),
148 + __('Setup Fee must be 0 or more.', 'fluent-cart')
149 + ),
150 + ],
151 + 'variants.*.other_info.signup_fee_name' => [
152 + RequiredWhenRule::make(
153 + 'variants.*.other_info.manage_setup_fee',
154 + 'yes',
155 + __('Setup Fee Name is required.', 'fluent-cart')
156 + ),
157 + WhenFilledRule::text(
158 + 100,
159 + __('Setup Fee Name must be plain text of 100 characters or fewer.', 'fluent-cart')
160 + ),
161 + ],
120 162 ];
121 163
122 164 $messages = [
123 165 'post_title.required' => __('Title is required.', 'fluent-cart'),
@@ -134,17 +176,12 @@
134 176 'variants.*.item_price.numeric' => __('Price must be a number.', 'fluent-cart'),
135 177 'variants.*.item_price.min' => __('Price must be a positive number.', 'fluent-cart'),
136 178 'variants.*.other_info.payment_type.required' => __('Payment Type is required.', 'fluent-cart'),
137 179 'variants.*.other_info.payment_type.in' => __('Payment Type must be onetime or subscription.', 'fluent-cart'),
138 - 'variants.*.other_info.repeat_interval.required_if' => __('Interval is required for subscriptions.', 'fluent-cart'),
139 - 'variants.*.other_info.repeat_interval.in' => __('Interval must be a valid frequency.', 'fluent-cart'),
140 180 'variants.*.other_info.trial_days.numeric' => __('Trial days must be a number.', 'fluent-cart'),
141 181 'variants.*.other_info.trial_days.min' => __('Trial days must be 0 or more.', 'fluent-cart'),
142 182 'variants.*.other_info.trial_days.max' => __('Trial days may not be greater than 365.', 'fluent-cart'),
143 183 'variants.*.other_info.manage_setup_fee.in' => __('Setup fee option must be yes or no.', 'fluent-cart'),
144 - 'variants.*.other_info.signup_fee.required_if' => __('Setup Fee Amount is required.', 'fluent-cart'),
145 - 'variants.*.other_info.signup_fee.numeric' => __('Setup Fee must be a number.', 'fluent-cart'),
146 - 'variants.*.other_info.signup_fee_name.required_if' => __('Setup Fee Name is required.', 'fluent-cart'),
147 184 ];
148 185
149 186 $validator = Validator::make($data, $rules, $messages);
150 187
@@ -494,13 +531,18 @@
494 531 }
495 532
496 533 /**
497 534 * Sanitize a price value to ensure it's a valid integer (cents).
535 + *
536 + * The value ARRIVES in cents — this only normalizes float artifacts and
537 + * rejects negatives. CSV imports carry dollars, so Importer.vue converts
538 + * at parse time, keeping this endpoint on the same cents contract as every
539 + * other write. See dev-docs/PRICING-AND-TAX.md §6.
498 540 */
499 541 protected function sanitizePrice($value): int
500 542 {
501 543 if (is_numeric($value)) {
502 - return absint(round(floatval($value) * 100));
544 + return absint(Helper::roundCent($value));
503 545 }
504 546
505 547 return 0;
506 548 }