added time working
This commit is contained in:
@@ -88,6 +88,74 @@ class AutomationEngine
|
||||
return;
|
||||
}
|
||||
|
||||
$cfg = $auto->trigger_config ?? [];
|
||||
$step = (float) ($cfg['step_toman'] ?? 0);
|
||||
if ($step <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$window = (string) ($cfg['price_window'] ?? 'calendar_day');
|
||||
$dir = (string) ($cfg['direction'] ?? 'both');
|
||||
|
||||
if ($window === 'calendar_day') {
|
||||
$this->tryPriceFireCalendarDay($auto, $current, $step, $dir, $cfg);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->tryPriceFireFromLast($auto, $current, $step, $dir);
|
||||
}
|
||||
|
||||
/** تغییر از شروع امروز تا الان؛ حداکثر یکبار در روز */
|
||||
private function tryPriceFireCalendarDay(
|
||||
Automation $auto,
|
||||
float $current,
|
||||
float $step,
|
||||
string $dir,
|
||||
array $cfg
|
||||
): void {
|
||||
$today = now('Asia/Tehran')->toDateString();
|
||||
$dayKey = (string) ($cfg['day_key'] ?? '');
|
||||
$dayOpen = (float) ($cfg['day_open'] ?? 0);
|
||||
$dayFired = (bool) ($cfg['day_fired'] ?? false);
|
||||
|
||||
if ($dayKey !== $today || $dayOpen <= 0) {
|
||||
$cfg['day_key'] = $today;
|
||||
$cfg['day_open'] = $current;
|
||||
$cfg['day_fired'] = false;
|
||||
Automation::query()->where('id', $auto->id)->update([
|
||||
'trigger_config' => $cfg,
|
||||
'last_anchor_price' => $current,
|
||||
]);
|
||||
$auto->trigger_config = $cfg;
|
||||
$auto->last_anchor_price = $current;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ($dayFired) {
|
||||
return;
|
||||
}
|
||||
|
||||
$delta = $current - $dayOpen;
|
||||
if (! $this->priceDirectionMet($dir, $delta, $step)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// برای اعلان قیمت روزانه معمولاً سر ضرب به همه میرود
|
||||
$this->enqueueAudience($auto, 0);
|
||||
$cfg['day_fired'] = true;
|
||||
Automation::query()->where('id', $auto->id)->update([
|
||||
'trigger_config' => $cfg,
|
||||
'last_anchor_price' => $current,
|
||||
]);
|
||||
$auto->trigger_config = $cfg;
|
||||
$auto->last_anchor_price = $current;
|
||||
}
|
||||
|
||||
/** پلهای از آخرین ارسال */
|
||||
private function tryPriceFireFromLast(Automation $auto, float $current, float $step, string $dir): void
|
||||
{
|
||||
$anchor = $auto->last_anchor_price;
|
||||
if ($anchor === null || (float) $anchor <= 0) {
|
||||
Automation::query()->where('id', $auto->id)->update(['last_anchor_price' => $current]);
|
||||
@@ -96,20 +164,8 @@ class AutomationEngine
|
||||
return;
|
||||
}
|
||||
|
||||
$cfg = $auto->trigger_config ?? [];
|
||||
$step = (float) ($cfg['step_toman'] ?? 0);
|
||||
if ($step <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$delta = $current - (float) $anchor;
|
||||
$dir = (string) ($cfg['direction'] ?? 'both');
|
||||
$moved = match ($dir) {
|
||||
'up' => $delta >= $step,
|
||||
'down' => $delta <= -$step,
|
||||
default => abs($delta) >= $step,
|
||||
};
|
||||
if (! $moved) {
|
||||
if (! $this->priceDirectionMet($dir, $delta, $step)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -129,6 +185,15 @@ class AutomationEngine
|
||||
$auto->last_anchor_price = $current;
|
||||
}
|
||||
|
||||
private function priceDirectionMet(string $dir, float $delta, float $step): bool
|
||||
{
|
||||
return match ($dir) {
|
||||
'up' => $delta >= $step,
|
||||
'down' => $delta <= -$step,
|
||||
default => abs($delta) >= $step,
|
||||
};
|
||||
}
|
||||
|
||||
private function runSchedule(): void
|
||||
{
|
||||
$rows = Automation::query()
|
||||
@@ -140,11 +205,12 @@ class AutomationEngine
|
||||
if (! $this->inWindow($auto)) {
|
||||
continue;
|
||||
}
|
||||
$everyDays = max(1, (int) (($auto->trigger_config ?? [])['every_days'] ?? 1));
|
||||
foreach ($this->channels($auto) as $channel) {
|
||||
if (! $this->hourMatches($auto, $channel)) {
|
||||
continue;
|
||||
}
|
||||
if ($this->alreadyRanThisHour($auto, $channel)) {
|
||||
if (! $this->scheduleDue($auto, $channel, $everyDays)) {
|
||||
continue;
|
||||
}
|
||||
$this->sendAudienceNow($auto, $channel);
|
||||
@@ -153,6 +219,22 @@ class AutomationEngine
|
||||
}
|
||||
}
|
||||
|
||||
/** آیا از آخرین اجرای موفق این کانال، حداقل N روز گذشته؟ */
|
||||
private function scheduleDue(Automation $auto, string $channel, int $everyDays): bool
|
||||
{
|
||||
$at = $channel === AutomationCatalog::CHANNEL_SMS
|
||||
? $auto->last_sms_run_at
|
||||
: $auto->last_in_app_run_at;
|
||||
if (! $at) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$lastDay = $at->copy()->timezone('Asia/Tehran')->startOfDay();
|
||||
$today = now('Asia/Tehran')->startOfDay();
|
||||
|
||||
return $lastDay->diffInDays($today) >= $everyDays;
|
||||
}
|
||||
|
||||
private function processDelayedJobs(): void
|
||||
{
|
||||
$jobs = AutomationDelayedJob::query()
|
||||
@@ -215,7 +297,8 @@ class AutomationEngine
|
||||
if ($exists) {
|
||||
continue;
|
||||
}
|
||||
if ($delayHours === 0 && $this->hourMatches($auto, $channel) && $this->sender->maySend($auto, $customer, $channel)) {
|
||||
if ($delayHours === 0 && $this->sender->maySend($auto, $customer, $channel)) {
|
||||
// سر ضرب: بلافاصله، بدون انتظار ساعت کانال
|
||||
$this->sender->send($auto, $customer, $channel);
|
||||
continue;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user