From 8e8ef8fe04b4d72e9e25be6793e85042f83bbd6d Mon Sep 17 00:00:00 2001 From: Krzysiej Date: Thu, 8 Jan 2026 17:18:46 +0100 Subject: [PATCH] Increase speed of processing the prices and products. Because this is getting out of hand. --- src/Command/Migrate.php | 33 ++++++++++++++++++++++++++--- src/Command/ScrapeWebsite.php | 20 ++++++++++++++++- src/Controller/IndexController.php | 2 +- src/Controller/PromosController.php | 2 +- src/Models/Product.php | 12 ++++++++--- src/Twig/AppExtension.php | 3 ++- templates/productList.html.twig | 10 ++++----- 7 files changed, 67 insertions(+), 15 deletions(-) diff --git a/src/Command/Migrate.php b/src/Command/Migrate.php index cea7a04..d19b68c 100644 --- a/src/Command/Migrate.php +++ b/src/Command/Migrate.php @@ -24,11 +24,10 @@ class Migrate extends Command public function execute(InputInterface $input, OutputInterface $output): int { - if (true === $input->hasOption(self::RECREATE_OPTION)) { + if ($input->getOption(self::RECREATE_OPTION)) { unlink(__DIR__ . '/../../database.sqlite'); - //sleep(5); + touch(__DIR__ . '/../../database.sqlite'); } - touch(__DIR__ . '/../../database.sqlite'); $capsule = new Capsule; $capsule->addConnection([ 'driver' => 'sqlite', @@ -39,6 +38,7 @@ class Migrate extends Command $this->createProductsTable(); $this->createPricesTable(); $this->createStocksTable(); + $this->updateProductsTableAddPrices(); return Command::SUCCESS; } @@ -94,4 +94,31 @@ class Migrate extends Command }); } } + + public function updateProductsTableAddPrices(): void + { + if (!Capsule::schema()->hasColumn('products', 'priceCurrent')) { + Capsule::schema()->table('products', function (Blueprint $table) { + $table->float('priceCurrent')->default(0); + }); + } + + if (!Capsule::schema()->hasColumn('products', 'priceLowest')) { + Capsule::schema()->table('products', function (Blueprint $table) { + $table->float('priceLowest')->default(0); + }); + } + + if (!Capsule::schema()->hasColumn('products', 'productStandardPrice')) { + Capsule::schema()->table('products', function (Blueprint $table) { + $table->float('productStandardPrice')->default(0); + }); + } + + if (!Capsule::schema()->hasColumn('products', 'lowestProductPrice30Days')) { + Capsule::schema()->table('products', function (Blueprint $table) { + $table->float('lowestProductPrice30Days')->default(0); + }); + } + } } diff --git a/src/Command/ScrapeWebsite.php b/src/Command/ScrapeWebsite.php index 722856a..63c8c4a 100644 --- a/src/Command/ScrapeWebsite.php +++ b/src/Command/ScrapeWebsite.php @@ -33,6 +33,7 @@ class ScrapeWebsite extends Command public function execute(InputInterface $input, OutputInterface $output): int { + $output->writeln('Scrape products'); $progress = new ProgressBar($output); $progress->start(); $products = $this->getProducts(); @@ -42,8 +43,25 @@ class ScrapeWebsite extends Command $progress->advance(); } $progress->finish(); + $output->writeln('Scrape products - DONE'); $output->writeln(''); - $output->writeln('DONE'); + + $output->writeln('Update prices'); + $products = Product::all(); + $progress->setMaxSteps(count($products)); + $progress->start(); + foreach($products as $product) { + $product->priceCurrent = $product->newestPrice->price; + $product->productStandardPrice = $product->newestPrice->productStandardPrice; + $product->lowestProductPrice30Days = $product->newestPrice->lowestProductPrice30Days; + $product->priceLowest = $product->lowestPrice->price; + $product->save(['timestamps' => false]); + $progress->advance(); + } + $progress->finish(); + $output->writeln(''); + $output->writeln('Update prices - DONE'); + $output->writeln('COMMAND - DONE'); return Command::SUCCESS; } diff --git a/src/Controller/IndexController.php b/src/Controller/IndexController.php index f44ddd4..759236c 100644 --- a/src/Controller/IndexController.php +++ b/src/Controller/IndexController.php @@ -14,7 +14,7 @@ final class IndexController extends BaseController if ($this->cache->getItem('list_all')->isHit()) { return $this->render('productList.html.twig', ['listType' => 'all']); } - $products = Product::with(['currentStock', 'price', 'lowestPrice']) + $products = Product::with(['currentStock']) ->orderByDesc('starred') ->orderByDesc('created_by') ->get(); diff --git a/src/Controller/PromosController.php b/src/Controller/PromosController.php index 81c6753..a440cc6 100644 --- a/src/Controller/PromosController.php +++ b/src/Controller/PromosController.php @@ -16,7 +16,7 @@ final class PromosController extends BaseController return $this->render('productList.html.twig', ['listType' => 'promos']); } - $products = Product::whereHas('currentPrice', fn(Builder $query) => $query->whereColumn('price', '<', 'productStandardPrice')) + $products = Product::whereRaw('priceCurrent < productStandardPrice') ->orderByDesc('starred') ->orderByDesc('created_by') ->with(['currentPrice', 'lowestPrice']) diff --git a/src/Models/Product.php b/src/Models/Product.php index 3878df2..3b77e8d 100644 --- a/src/Models/Product.php +++ b/src/Models/Product.php @@ -20,6 +20,10 @@ use function Symfony\Component\Clock\now; * @property string $modelCode * @property string $url * @property int $starred + * @property float $priceCurrent + * @property float $priceLowest + * @property float $productStandardPrice + * @property float $lowestProductPrice30Days */ class Product extends Model { @@ -45,6 +49,10 @@ class Product extends Model { return $this->hasOne(Price::class)->ofMany('price', 'MIN'); } + public function newestPrice(): HasOne + { + return $this->hasOne(Price::class)->latest(); + } public function stock(): HasMany { @@ -53,9 +61,7 @@ class Product extends Model public function currentStock(): HasOne { - return $this->stock()->one()->ofMany()->withDefault(function (Stock $stock) { - $stock->stock = 0; - }); + return $this->stock()->one()->ofMany()->withDefault(fn (Stock $stock) => $stock->stock = 0); } public function toggleStarred(): self diff --git a/src/Twig/AppExtension.php b/src/Twig/AppExtension.php index 7eb9c02..f0b1ac9 100644 --- a/src/Twig/AppExtension.php +++ b/src/Twig/AppExtension.php @@ -31,6 +31,7 @@ class AppExtension extends AbstractExtension new TwigFilter('findByCreatedAtDate', [$this, 'findByCreatedAtDate']), ]; } + public function allCount(): int { return Product::count(); @@ -38,7 +39,7 @@ class AppExtension extends AbstractExtension public function promosCount(): int { - return Product::whereHas('currentPrice', fn(Builder $query) => $query->whereColumn('price', '<', 'productStandardPrice'))->count(); + return Product::whereRaw('priceCurrent < productStandardPrice')->count(); } public function newCount(): int diff --git a/templates/productList.html.twig b/templates/productList.html.twig index 68b31af..0a8f65f 100644 --- a/templates/productList.html.twig +++ b/templates/productList.html.twig @@ -46,13 +46,13 @@ link - {% if product.lowestPrice.price != product.price.last.price %}{{ product.lowestPrice.price | format_currency('PLN', {}, 'pl') }}{% endif %} - {{ product.price.last.price | format_currency('PLN', {}, 'pl') }} + {% if product.priceLowest != product.priceCurrent %}{{ product.priceLowest | format_currency('PLN', {}, 'pl') }}{% endif %} + {{ product.priceCurrent | format_currency('PLN', {}, 'pl') }}
- {% if product.price.last.price != product.price.last.productStandardPrice %}{{ product.price.last.productStandardPrice | format_currency('PLN', {}, 'pl') }} {{ ((1 - product.price.last.price / product.price.last.productStandardPrice)*100)|number_format(0) }}% + {% if product.priceCurrent != product.productStandardPrice %}{{ product.productStandardPrice | format_currency('PLN', {}, 'pl') }} {{ ((1 - product.priceCurrent / product.productStandardPrice)*100)|number_format(0) }}% {% endif %}