Özet: Laravel’de iş teslim tarihlerini hesaplamak için hafta sonları ve tatilleri otomatik olarak atlayarak, bir veritabanı tablosu ve Carbon kullanarak nasıl çözüm geliştirilir? Kod örnekleri içerir.
Problemin Tanımı
Bir kamu kurumları için bir kupon yönetim sistemi (VMMS) geliştirirken, her departman için işlem sürelerini hesaplamam gerekiyordu. Basit gibi görünüyor, değil mi? Mevcut tarihe X gün eklemek yeterli. Yanlış.
Kamu kurumları hafta sonları çalışmaz. Tatillerde çalışmaz. Cuma günü verilen bir kuponun, pazartesi sabahına teslim tarihi olmamalıdır eğer pazartesi bir tatil ise. Bu durumları dikkate alan bir teslim tarihleri hesaplayıcısına ihtiyacım vardı.
Yaklaşım
Tatilleri kod içine sabitlemek yerine, onları bir veritabanı tablosunda sakladım. Bu sayede yeni tatiller eklemek için herhangi bir kod değişikliği yapma gereği duyulmuyor; yalnızca yeni bir veritabanı kaydı eklemek yeterli.
Schema::create(, function (Blueprint $table) {
$table->id();
$table->string();
$table->date();
$table->timestamps();
});
Tarih Hesaplama Servisinin Oluşturulması
Tüm tarih hesaplamalarını yönetecek özel bir servis sınıfı oluşturdum:
namespace App\Services;
use Carbon\Carbon;
use App\Models\Holiday;
class DateHelpers
{
protected array $holidays;
public function __construct()
{
$this->holidays = Holiday::pluck()
->map(fn($d) => Carbon::parse($d)->toDateString())
->toArray();
}
public function isNonWorkingDay(Carbon $date): bool
{
return $date->isWeekend()
|| in_array($date->toDateString(), $this->holidays);
}
public function addBusinessDays(Carbon $date, int $days): Carbon
{
$result = $date->copy();
$added = 0;
while ($added $days) {
$result->addDay();
if (!$this->isNonWorkingDay($result)) {
$added++;
}
}
return $result;
}
}
Nasıl Çalışır?
addBusinessDays metodu, gereken iş günlerini sayana kadar, her gün döngü yaparak hafta sonları ve tatilleri atlar. Örneğin, eğer bugün Cuma ise ve 3 iş günü gerekiyorsa:
Cumartesi → atla (hafta sonu)
Pazar → atla (hafta sonu)
Pazartesi → say (1)
Salı → say (2)
Çarşamba → say (3) ← teslim tarihi
Eğer Pazartesi bir tatil ise:
Cumartesi → atla (hafta sonu)
Pazar → atla (hafta sonu)
Pazartesi → atla (tatil)
Salı → say (1)
Çarşamba → say (2)
Perşembe → say (3) ← teslim tarihi
Uygulamada Kullanımı
$dateHelpers = new DateHelpers();
$deadline = $dateHelpers->addBusinessDays(Carbon::now(), 3);
Bir departman bir kupon aldığında – teslim tarihi otomatik olarak hesaplanır ve denetim kaydında saklanır:
AuditTrail::create([
=> $transaction->,
=> $department->,
=> (),
=> ->(::(), ),
]);
Performans İçin Önbellekleme
Tatiller nadiren değiştiği için, her istekte veritabanına hit yapmamak amacıyla tatil listesini önbelleğe aldım:
public function __construct()
{
$this->holidays = ()->(, ()->(), function () {
return ::()
->(() => ::()->())
->();
});
}
Bu, tatiller listesini 24 saat boyunca önbellekler; her gün otomatik olarak yenilenir.
Geçmiş Deadline’ları Kontrol Etme
Carbon’un diffInDays fonksiyonunu kullanarak, bir teslim tarihinin geçip geçmediğini kolayca kontrol edebilirsiniz:
= ::(->)->();
= () ::()->()->(, );
// Negatif = geçmiş, Pozitif = kalan gün, Sıfır = bugün son gün
if ( ) {
// Geçmiş olarak işaretle
}
False parametresi, diffInDays’in geçmiş tarihler için negatif sayılar döndürmesini sağlar; bu da geçmişin tespiti için yararlıdır.
Tatilleri Yönetme
Tatiller veritabanında saklandığı için, yöneticiler bunları basit bir CRUD arayüzü üzerinden yönetebilir:
// Bir tatil ekle
::([
=> ,
=> ,
]);
// Yıl için tüm tatilleri al
::(, ()->)->();
Yeni bir tatil ilan edildiğinde herhangi bir kod dağıtımı gerekmiyor; yalnızca veritabanına eklemek yeterli.
Öğrendiklerim
İş mantığını veritabanından uzak tutun – tarih hesaplamaları PHP’de yer almalıdır, SQL’de değil.
Tatil sorgularını önbelleğe alınız – nadiren değişir ama sıkça sorgulanır.
Carbon’u tutarlı bir şekilde kullanın – Carbon ile ham tarih dizelerini karıştırmak, ince hatalara yol açar.
Kenar durumları test edin – Cuma günkü gönderimler, tatil Pazartesileri ve uzun hafta sonları her zaman test edilmelidir.
Sonuç
Tatil bilincine sahip teslim tarihi hesaplamaları basit görünse de, beklenenden daha fazla kenar durumu vardır. Veritabanı tabanlı tatil tablosuyla bir özel servis sınıfı, mantığı temiz, esnek ve bakımı kolay tutar. Bu desen, iş günü hesaplaması gerektiren herhangi bir sistem için çalışır; izin talepleri, SLA takibi, fatura son tarihleri ve daha fazlası için uygundur.
Kaynak: Orijinal Makale


