Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 20 additions & 1 deletion app/Application/Services/CartAppService.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,16 @@
namespace App\Application\Services;

use App\Domain\Cart\Model\Cart;
use App\Domain\Cart\Repositories\CartRepositoryInterface;
use App\Domain\Cart\Services\CartService as DomainCartService;
use App\Domain\Product\Repositories\ProductRepositoryInterface;

class CartAppService
{
public function __construct(
private DomainCartService $cartService,
private ProductRepositoryInterface $productRepository
private ProductRepositoryInterface $productRepository,
private CartRepositoryInterface $cartRepository
) {}

public function createUserCart(int $userId): Cart
Expand Down Expand Up @@ -147,4 +149,21 @@ public function transferGuestCartToUser(string $guestToken, int $userId): Cart
// Если у пользователя нет корзины, просто привязываем гостевую
return $this->cartService->assignCartToUser($guestCart, $userId);
}

public function cleanupExpiredCarts(): void
{
$this->cartService->cleanupExpiredCarts();
}

public function getExpiredCartsCount(int $days = 30): int
{
$expirationDate = now()->subDays($days);
return $this->cartRepository->countExpiredBefore($expirationDate);
}

public function getExpiredCarts(int $days = 30): array
{
$expirationDate = now()->subDays($days);
return $this->cartRepository->findExpiredBefore($expirationDate);
}
}
56 changes: 56 additions & 0 deletions app/Console/Commands/CheckExpiredCarts.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php

namespace App\Console\Commands;

use App\Domain\Cart\Repositories\CartRepositoryInterface;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Log;

class CheckExpiredCarts extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'carts:check
{--days=30 : Check carts older than this number of days}
{--show : Show details of expired carts}';

/**
* The console command description.
*
* @var string
*/
protected $description = 'Check for expired carts without deleting them';

/**
* Execute the console command.
*/
public function handle(CartRepositoryInterface $cartRepository): int
{
$days = (int) $this->option('days');
$showDetails = $this->option('show');

$expirationDate = now()->subDays($days);

$this->info("Checking for carts expired before {$expirationDate->format('Y-m-d H:i:s')}");

// В реальной реализации нужно добавить метод в репозиторий для подсчета
// $expiredCount = $cartRepository->countExpiredBefore($expirationDate);

$this->info("Found approximately X expired carts (implementation needed)");

if ($showDetails) {
$this->line('Detailed list would be shown here');
// В реальной реализации: $expiredCarts = $cartRepository->findExpiredBefore($expirationDate);
}

Log::info('Expired carts check completed', [
'days' => $days,
'expiration_date' => $expirationDate,
]);

return Command::SUCCESS;
}
}
71 changes: 71 additions & 0 deletions app/Console/Commands/CleanupExpiredCarts.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<?php

namespace App\Console\Commands;

use App\Application\Services\CartAppService;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Log;

class CleanupExpiredCarts extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'carts:cleanup
{--days=30 : Delete carts older than this number of days}
{--dry-run : Show what would be deleted without actually deleting}';

/**
* The console command description.
*
* @var string
*/
protected $description = 'Clean up expired carts from the database';

/**
* Execute the console command.
*/
public function handle(CartAppService $cartAppService): int
{
$days = (int) $this->option('days');
$isDryRun = $this->option('dry-run');

$this->info('Starting expired carts cleanup...');
$this->line("Looking for carts expired more than {$days} days ago");

if ($isDryRun) {
$this->info('DRY RUN: No actual changes will be made');
}

try {
// Вызываем сервис для очистки
if (!$isDryRun) {
$cartAppService->cleanupExpiredCarts();
$this->info('Successfully cleaned up expired carts');
} else {
$this->info('Dry run completed. Would have cleaned up expired carts');
}

// Логируем выполнение
Log::info('Expired carts cleanup completed', [
'days' => $days,
'dry_run' => $isDryRun,
'timestamp' => now(),
]);

return Command::SUCCESS;

} catch (\Exception $e) {
$this->error("Error during carts cleanup: {$e->getMessage()}");

Log::error('Expired carts cleanup failed', [
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString(),
]);

return Command::FAILURE;
}
}
}
12 changes: 12 additions & 0 deletions app/Domain/Cart/Repositories/CartRepositoryInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,16 @@ public function findByGuestToken(string $guestToken): ?Cart;
public function save(Cart $cart): Cart;
public function delete(string $cartId): void;
public function cleanupExpired(): void;

/**
* Count expired carts before specific date
*/
public function countExpiredBefore(\DateTimeInterface $date): int;

/**
* Find expired carts before specific date
*
* @return Cart[]
*/
public function findExpiredBefore(\DateTimeInterface $date): array;
}
24 changes: 20 additions & 4 deletions app/Infrastructure/Eloquent/Repositories/CartRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use App\Domain\Cart\Repositories\CartRepositoryInterface;
use App\Infrastructure\Eloquent\Models\Cart as EloquentCart;
use App\Infrastructure\Eloquent\Models\CartItem as EloquentCartItem;
use DateTimeInterface;

class CartRepository implements CartRepositoryInterface
{
Expand Down Expand Up @@ -88,10 +89,6 @@ public function delete(string $cartId): void
EloquentCart::destroy($cartId);
}

public function cleanupExpired(): void
{
EloquentCart::where('expires_at', '<=', now())->delete();
}

private function toEntity(EloquentCart $model): Cart
{
Expand All @@ -118,4 +115,23 @@ private function toEntity(EloquentCart $model): Cart
$model->updated_at
);
}

public function cleanupExpired(): void
{
EloquentCart::where('expires_at', '<=', now())->delete();
}

public function countExpiredBefore(DateTimeInterface $date): int
{
return EloquentCart::where('expires_at', '<=', $date)->count();
}

public function findExpiredBefore(DateTimeInterface $date): array
{
return EloquentCart::with('items')
->where('expires_at', '<=', $date)
->get()
->map(fn($model) => $this->toEntity($model))
->toArray();
}
}
3 changes: 2 additions & 1 deletion app/Providers/AppServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,8 @@ private function registerApplicationServices(): void
$this->app->singleton(CartAppService::class, function ($app) {
return new CartAppService(
$app->make(CartService::class),
$app->make(ProductRepositoryInterface::class)
$app->make(ProductRepositoryInterface::class),
$app->make(CartRepositoryInterface::class)
);
});

Expand Down
15 changes: 15 additions & 0 deletions bootstrap/app.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware;
use Illuminate\Console\Scheduling\Schedule;

return Application::configure(basePath: dirname(__DIR__))
->withRouting(
Expand All @@ -14,6 +15,20 @@
->withMiddleware(function (Middleware $middleware) {
//
})
->withSchedule(function (Schedule $schedule) {

// Ежедневная очистка корзин в 2:00 ночи
$schedule->command('carts:cleanup --days=30')
->dailyAt('02:00')
->onOneServer()
->appendOutputTo(storage_path('logs/cart-cleanup.log'));

// Еженедельная проверка по понедельникам в 1:00
$schedule->command('carts:check --days=30')
->weeklyOn(1, '01:00')
->appendOutputTo(storage_path('logs/cart-check.log'));

})
->withExceptions(function (Exceptions $exceptions) {
//
})->create();