From 0d1bd95ccda1c6561da29403b06fd9cb602802f8 Mon Sep 17 00:00:00 2001 From: Amitav Roy Date: Sun, 5 Jan 2025 11:30:51 +0530 Subject: [PATCH] Seems like the basic query feature is now working for Segment with dynamic rule based query --- .../Rules/MinimumPurchaseValueRule.php | 9 +++++- .../Segment/Rules/SegmentRuleInterface.php | 4 ++- .../Segment/Rules/TotalPurchaseValueRule.php | 12 +++++++- .../Segment/Services/SegmentRuleService.php | 28 ++++++++++++++++++- app/Services/UserService.php | 20 +++++++++++++ 5 files changed, 69 insertions(+), 4 deletions(-) create mode 100644 app/Services/UserService.php diff --git a/app/Domain/Segment/Rules/MinimumPurchaseValueRule.php b/app/Domain/Segment/Rules/MinimumPurchaseValueRule.php index c8d877f..d568462 100644 --- a/app/Domain/Segment/Rules/MinimumPurchaseValueRule.php +++ b/app/Domain/Segment/Rules/MinimumPurchaseValueRule.php @@ -2,9 +2,16 @@ namespace App\Domain\Segment\Rules; +use Illuminate\Database\Eloquent\Builder; + class MinimumPurchaseValueRule implements SegmentRuleInterface { - public function execute(): void {} + public function execute(Builder $query): void + { + $query->whereHas('orders', function ($query) { + $query->where('total_amount', '>', 1000); + }); + } public function getFriendlyName(): string { diff --git a/app/Domain/Segment/Rules/SegmentRuleInterface.php b/app/Domain/Segment/Rules/SegmentRuleInterface.php index 5109154..ac4a941 100644 --- a/app/Domain/Segment/Rules/SegmentRuleInterface.php +++ b/app/Domain/Segment/Rules/SegmentRuleInterface.php @@ -2,9 +2,11 @@ namespace App\Domain\Segment\Rules; +use Illuminate\Database\Eloquent\Builder; + interface SegmentRuleInterface { public function getFriendlyName(): string; - public function execute(): void; + public function execute(Builder $query): void; } diff --git a/app/Domain/Segment/Rules/TotalPurchaseValueRule.php b/app/Domain/Segment/Rules/TotalPurchaseValueRule.php index b911466..4d321dc 100644 --- a/app/Domain/Segment/Rules/TotalPurchaseValueRule.php +++ b/app/Domain/Segment/Rules/TotalPurchaseValueRule.php @@ -2,9 +2,19 @@ namespace App\Domain\Segment\Rules; +use Illuminate\Database\Eloquent\Builder; +use Illuminate\Support\Facades\DB; + class TotalPurchaseValueRule implements SegmentRuleInterface { - public function execute(): void {} + public function execute(Builder $query): void + { + $query->whereHas('orders', function ($query) { + $query->select(DB::raw('SUM(total_amount) as total_sum')) + ->groupBy('user_id') + ->havingRaw('SUM(total_amount) >= ?', [1000]); + }); + } public function getFriendlyName(): string { diff --git a/app/Domain/Segment/Services/SegmentRuleService.php b/app/Domain/Segment/Services/SegmentRuleService.php index 83761a4..b86009c 100644 --- a/app/Domain/Segment/Services/SegmentRuleService.php +++ b/app/Domain/Segment/Services/SegmentRuleService.php @@ -2,8 +2,12 @@ namespace App\Domain\Segment\Services; +use App\Domain\Segment\Models\Segment; use App\Domain\Segment\Rules\MinimumPurchaseValueRule; use App\Domain\Segment\Rules\TotalPurchaseValueRule; +use App\Services\UserService; +use Exception; +use Illuminate\Database\Eloquent\Builder; use Illuminate\Support\Collection; class SegmentRuleService @@ -11,7 +15,7 @@ class SegmentRuleService /** * @return Collection */ - public function getRuleMapping(): Collection + private function getRuleMapping(): Collection { return collect([ 'total_purchase_value' => TotalPurchaseValueRule::class, @@ -37,4 +41,26 @@ public function getRuleNames(): Collection return $ruleNames; } + + /** + * @throws Exception + */ + public function segmentQuery(Segment $segment): Builder + { + $query = app(UserService::class)->getBaseUserQueryForSegment(); + + $rules = collect($segment->rules); + + $rules->each(function ($rule) use ($query) { + $allowedRules = $this->getRuleMapping(); + + if (! $allowedRules->has($rule['rule_name'])) { + throw new Exception('No such rule exist'); + } + + app($allowedRules[$rule['rule_name']])->execute($query); + }); + + return $query; + } } diff --git a/app/Services/UserService.php b/app/Services/UserService.php new file mode 100644 index 0000000..a4564ce --- /dev/null +++ b/app/Services/UserService.php @@ -0,0 +1,20 @@ + + */ + public function getBaseUserQueryForSegment(): Builder + { + return User::query() + ->withSum('orders', 'total_amount') + ->where('role', UserRole::CUSTOMER->value); + } +}