Skip to content

Commit

Permalink
Seems like the basic query feature is now working for Segment with dy…
Browse files Browse the repository at this point in the history
…namic rule based query
  • Loading branch information
amitavroy committed Jan 5, 2025
1 parent 8d60310 commit 0d1bd95
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 4 deletions.
9 changes: 8 additions & 1 deletion app/Domain/Segment/Rules/MinimumPurchaseValueRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down
4 changes: 3 additions & 1 deletion app/Domain/Segment/Rules/SegmentRuleInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
12 changes: 11 additions & 1 deletion app/Domain/Segment/Rules/TotalPurchaseValueRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down
28 changes: 27 additions & 1 deletion app/Domain/Segment/Services/SegmentRuleService.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,20 @@

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
{
/**
* @return Collection<string, string>
*/
public function getRuleMapping(): Collection
private function getRuleMapping(): Collection
{
return collect([
'total_purchase_value' => TotalPurchaseValueRule::class,
Expand All @@ -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;
}
}
20 changes: 20 additions & 0 deletions app/Services/UserService.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

namespace App\Services;

use App\Enum\UserRole;
use App\Models\User;
use Illuminate\Database\Eloquent\Builder;

class UserService
{
/**
* @return Builder<User>
*/
public function getBaseUserQueryForSegment(): Builder
{
return User::query()
->withSum('orders', 'total_amount')
->where('role', UserRole::CUSTOMER->value);
}
}

0 comments on commit 0d1bd95

Please sign in to comment.