From 923c3e0f6a3142425b3cd193d1f6abbdceb51623 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Munsch?= Date: Mon, 11 Sep 2023 09:57:57 +0200 Subject: [PATCH 1/4] oci_migration fix wrong keywords associated with products --- database/migrations/2023_12_06_124752_migrate_oci_tables.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/database/migrations/2023_12_06_124752_migrate_oci_tables.php b/database/migrations/2023_12_06_124752_migrate_oci_tables.php index 801f266..8e07fb7 100644 --- a/database/migrations/2023_12_06_124752_migrate_oci_tables.php +++ b/database/migrations/2023_12_06_124752_migrate_oci_tables.php @@ -24,6 +24,7 @@ use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\File; use Illuminate\Support\Facades\Schema; use Illuminate\Support\Facades\Storage; +use Illuminate\Support\ItemNotFoundException; use Illuminate\Support\Str; use Symfony\Component\Console\Helper\ProgressBar; use Symfony\Component\Console\Output\ConsoleOutput; @@ -140,7 +141,7 @@ return new class extends Migration ->explode(PHP_EOL)->map(fn (string $other_allegation) => Str::of($other_allegation)->squish()) ->unique(); - $MOTKS = Keyword::all(); + $MOTKS = Keyword::query()->where('keyword_cat', 'LIKE', 'product_%')->get(); /** @var \Illuminate\Support\Collection */ $START_SOURCES = $this->getQuery('SOURCE')->get(); /** @var \Illuminate\Support\Collection */ @@ -239,7 +240,7 @@ return new class extends Migration fn (Keyword $keyword) => Str::of($keyword->label)->ascii()->replace(' ', '') == Str::of($motk)->trim()->ascii()->replace(' ', '') ); - } catch (\Exception) { + } catch (ItemNotFoundException) { dump( $motk, $MOTKS->pluck('label') From 0681bf8f0a441afc32456a2cb8727afffb79aa67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Munsch?= Date: Mon, 11 Sep 2023 11:05:17 +0200 Subject: [PATCH 2/4] Oci migration Products comments --- .../2023_12_06_124752_migrate_oci_tables.php | 123 +++++++++++++++--- 1 file changed, 106 insertions(+), 17 deletions(-) diff --git a/database/migrations/2023_12_06_124752_migrate_oci_tables.php b/database/migrations/2023_12_06_124752_migrate_oci_tables.php index 8e07fb7..be8c442 100644 --- a/database/migrations/2023_12_06_124752_migrate_oci_tables.php +++ b/database/migrations/2023_12_06_124752_migrate_oci_tables.php @@ -13,9 +13,12 @@ use App\Lib\Helpers\FileStorageHelper; use App\Models\Brand; use App\Models\Keyword; use App\Models\Product; +use App\Models\ProductComment; use App\Models\User; use Carbon\Carbon; +use Illuminate\Console\OutputStyle; use Illuminate\Contracts\Database\Query\Builder; +use Illuminate\Database\Eloquent\ModelNotFoundException; use Illuminate\Database\Migrations\Migration; use Illuminate\Database\QueryException; use Illuminate\Database\Schema\Blueprint; @@ -27,6 +30,7 @@ use Illuminate\Support\Facades\Storage; use Illuminate\Support\ItemNotFoundException; use Illuminate\Support\Str; use Symfony\Component\Console\Helper\ProgressBar; +use Symfony\Component\Console\Input\ArgvInput; use Symfony\Component\Console\Output\ConsoleOutput; return new class extends Migration @@ -50,6 +54,12 @@ return new class extends Migration 'VEILLE_PROD', 'VEILLE_PROD_COMM', ]; + /** + * Console tabulation (margin left) + * @var integer + */ + private $consoleTabulation = 28; + /** @var \App\Models\User */ private $dummyUser; @@ -64,10 +74,14 @@ return new class extends Migration */ public function up(): void { - // ! DEV: Uncomment this to skip the migration - // return; - $console = new ConsoleOutput(); - $section = $console->section(); + $ouput = new ConsoleOutput(); + $input = new ArgvInput(); + $style = new OutputStyle($input, $ouput); + $section = $ouput->section(); + + if (!$style->confirm('Do this migration or skip ?', false)) { + return; + } // * SEED KEYWORDS As they are needed on runtime. Schema::disableForeignKeyConstraints(); @@ -75,6 +89,7 @@ return new class extends Migration DB::table('keywordables')->truncate(); DB::table('keywords')->truncate(); DB::table('products')->truncate(); + DB::table('product_comments')->truncate(); // * Remove previously uploaded files. File::deleteDirectory(storage_path('app/public/modelfiles/products')); Schema::enableForeignKeyConstraints(); @@ -100,15 +115,16 @@ return new class extends Migration $this->fixForeignKeyActionOnProcesses(); // ! DEV: Comment this after running once, to develop a migration without remigrating every temp table. - // $this->createAndFillTempTables(); + $this->createAndFillTempTables(); // * Migrate PRODUCTS, comment all except the one you want to develop here. - $this->migrateBrands(); - $this->migrateProducts(); - - // ! DEV: Add a die here to develop migration and prevent droping temp tables - // dd(''); + $this->migrateBrands($style); + $this->migrateProducts($style); + $this->migrateProductsComments($style); + if (!$style->confirm('Continue ?')) { + throw new \RuntimeException('Migration stoped'); + } $this->dropTempTables(); $section->clear(); } @@ -127,14 +143,84 @@ return new class extends Migration // - MIGRATION METHODS - /** - * Migrate products - * + * Migrate products comments * + * @param \Illuminate\Console\OutputStyle $style * @return void * @throws \Error In case of failure. * @phpcs:disable Generic.Metrics.CyclomaticComplexity.MaxExceeded + * @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.Found */ - private function migrateProducts(): void + private function migrateProductsComments(OutputStyle $style): void + { + // phpcs:enable + $index = "NUM_COMM"; + $query = $this->getQuery("VEILLE_PROD_COMM")->orderBy($index); + $nbRowsToMigrate = (clone $query)->count(); + $totalRowsToMigrate = $nbRowsToMigrate; + + $console = new ConsoleOutput(); + $console->writeln(''); + $progress = new ProgressBar($console, $nbRowsToMigrate); + $progress->setMessage(str_pad('Migrate Products Comments', $this->consoleTabulation, ' ')); + $progress->setFormat(' - %message% [%bar%] %percent:3s%% %current%/%max% %elapsed:6s%/%estimated:-6s%'); + $skipped = collect(); + + while ($nbRowsToMigrate > 0) { + $progress->display(); + $progress->advance(1); + $row = (clone $query)->skip($totalRowsToMigrate - $nbRowsToMigrate--)->limit(1)->first(); + try { + + /** @var \App\Models\ProductComment $comment */ + $comment = ProductComment::query()->where('id', $row->{$index})->firstOrNew(); + $comment->id = $row->NUM_COMM; + /** @var \App\Models\Product $product */ + $product = Product::query()->where('id', $row->NUM_PROD)->firstOrFail(); + $product->id = $row->NUM_PROD; + + $date_saisie = $row->DATE_SAISIE ? $this->tryToParseCarbon($row->DATE_SAISIE, true) : null; + + $fill = [ + 'product_id' => $product->id, + 'evaluation' => $row->APPRECIATION ?? '', + 'aspect' => $row->ASPECT, + 'taste' => $row->GOUT, + 'odor' => $row->ODEUR, + 'texture' => $row->TEXTURE, + ]; + if ($date_saisie) { + // ? FIXME: IS this pertinent ? + $fill['created_at'] = $date_saisie; + $fill['updated_at'] = $date_saisie; + } + $comment->fill($fill); + if (!DB::transaction(fn () => $comment->saveQuietly())) { + throw new \Error("Failed to save comment {$row->NUM_COMM}"); + } + } catch (ModelNotFoundException $e) { + $model = $e->getModel(); + $skipped->push("No {$model} found for '{$row->NUM_PROD}', skip comment '{$row->NUM_COMM}'"); + } //end try + } //end while + $progress->finish(); + if ($skipped->count() and !$console->writeln('') and $style->confirm('Show errors ?', false)) { + $console->writeln(''); + $skipped->each(fn (string $error) => $console->writeln(str_repeat(' ', 8) . $error)); + } + } + + /** + * Migrate products + * + * + * @param \Illuminate\Console\OutputStyle $style + * @return void + * @throws \Error In case of failure. + * @phpcs:disable Generic.Metrics.CyclomaticComplexity.MaxExceeded + * @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.Found + */ + private function migrateProducts(OutputStyle $style): void { // phpcs:enable $otherAllegations = Str::of(File::get(base_path('database/migrations/other_allegations.txt'))) @@ -170,7 +256,7 @@ return new class extends Migration $console = new ConsoleOutput(); $console->writeln(''); $progress = new ProgressBar($console, $nbRowsToMigrate); - $progress->setMessage(str_pad('Migrate Products', 24, ' ')); + $progress->setMessage(str_pad('Migrate Products', $this->consoleTabulation, ' ')); $progress->setFormat(' - %message% [%bar%] %percent:3s%% %current%/%max% %elapsed:6s%/%estimated:-6s%'); while ($nbRowsToMigrate > 0) { @@ -407,10 +493,13 @@ return new class extends Migration /** * Create unique brands using veille products * + * @param \Illuminate\Console\OutputStyle $style * @return void + * @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.Found */ - private function migrateBrands(): void + private function migrateBrands(OutputStyle $style): void { + // phpcs:enable $query = $this->getQuery("VEILLE_PROD"); /** @var \Illuminate\Support\Collection */ $brands = (clone $query)->pluck('MARQUE')->filter() @@ -418,7 +507,7 @@ return new class extends Migration $console = new ConsoleOutput(); $console->writeln(''); $progress = new ProgressBar($console, $brands->count()); - $progress->setMessage(str_pad('Migrate Brands', 24, ' ')); + $progress->setMessage(str_pad('Migrate Brands', $this->consoleTabulation, ' ')); $progress->setFormat(' - %message% [%bar%] %percent:3s%% %current%/%max% %elapsed:6s%/%estimated:-6s%'); // FIXME: Insert brand->filter and find from where it should be fetched. $brands->each(function ($brandName) use ($progress) { @@ -616,7 +705,7 @@ return new class extends Migration $this->getTableName($tableName), $header ); - $message = str_pad("{$this->tablePrefix} {$tableName}", 24, ' '); + $message = str_pad("{$this->tablePrefix} {$tableName}", $this->consoleTabulation, ' '); $section->write(" - {$message} -> Fetching OCI DATA.."); $content = $this->fetchOciTableContent($tableName, $header); $section->clear(); From 6aab7d4eff67c85cc0eb1b36809add8a3a32e201 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Munsch?= Date: Mon, 11 Sep 2023 11:23:42 +0200 Subject: [PATCH 3/4] Fix product resource with comments --- app/Http/Resources/ProductResource.php | 9 ++++++++- resources/views/documents/product-body.blade.php | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/app/Http/Resources/ProductResource.php b/app/Http/Resources/ProductResource.php index 8e93bb3..278510d 100644 --- a/app/Http/Resources/ProductResource.php +++ b/app/Http/Resources/ProductResource.php @@ -6,6 +6,7 @@ use App\Enums\Products\ClaimEnum; use App\Enums\Products\OriginEnum; use App\Models\Keyword; use App\Models\Product; +use App\Models\ProductComment; use Illuminate\Http\Resources\Json\JsonResource; class ProductResource extends JsonResource @@ -87,7 +88,13 @@ class ProductResource extends JsonResource 'product_range' => $this->product->product_range->label(), 'geo_area' => $this->product->geo_area->label(), 'freeComment' => $this->product->comment, - 'productComments' => $this->product->productComments, + // FIXME: Use dedicaced resources for relations. + 'productComments' => $this->product->productComments->map(function (ProductComment $comment) { + return (object)\array_merge($comment->toArray(), [ + 'created_at' => $comment->created_at->isoFormat('DD\/MM\/YYYY'), + 'updated_at' => $comment->updated_at->isoFormat('DD\/MM\/YYYY'), + ]); + }), 'productKeywords' => $this->product->productKeywords ->map(fn (Keyword $keyword) => $keyword->label) ->implode(', '), diff --git a/resources/views/documents/product-body.blade.php b/resources/views/documents/product-body.blade.php index 6e5907d..6fb7e5c 100644 --- a/resources/views/documents/product-body.blade.php +++ b/resources/views/documents/product-body.blade.php @@ -71,7 +71,7 @@

{{ __('Commentaire libre : ') }}{{ strip_tags($product->freeComment) }}

@endif @foreach ($product->productComments as $productComment) -

{{ __('Commentaire dégustation du : ') }}{{ $productComment->created_at->isoFormat('DD\/MM\/YYYY') }}

+

{{ __('Commentaire dégustation du : ') }}{{ $productComment->created_at }}

From c88583d7271593cc15996373221460bd4309dc41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Munsch?= Date: Mon, 11 Sep 2023 11:28:07 +0200 Subject: [PATCH 4/4] Fix printMultiProductSheet making 2 sheets for the firs product item --- app/Http/Controllers/ProductController.php | 3 +-- app/Models/Product.php | 14 +++++++------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/app/Http/Controllers/ProductController.php b/app/Http/Controllers/ProductController.php index 5e232a6..7c6126e 100644 --- a/app/Http/Controllers/ProductController.php +++ b/app/Http/Controllers/ProductController.php @@ -28,7 +28,6 @@ class ProductController extends Controller */ public function index(IndexFilterRequest $request) { - // DB::enableQueryLog(); /** @var \Illuminate\Database\Eloquent\Builder $brands */ $brandsQuery = Brand::query(); @@ -40,7 +39,6 @@ class ProductController extends Controller $this->sortQuery($productsQuery); $products = $this->paginate($productsQuery); - // dd(DB::getQueryLog(), $products->items()); /** @var array $printMultiProduct Array of id */ $printMultiProduct = session('printMultiProduct') ?? []; @@ -320,6 +318,7 @@ class ProductController extends Controller */ public function printMultiProductSheet() { + // FIXME: This should not use session. /** @var array printMultiProduct */ $printMultiProduct = session('printMultiProduct') ?? []; asort($printMultiProduct); diff --git a/app/Models/Product.php b/app/Models/Product.php index 094a602..6b52924 100644 --- a/app/Models/Product.php +++ b/app/Models/Product.php @@ -319,14 +319,14 @@ class Product extends Model // * If not yet defined, set the first page. if (is_null($pdf)) { $pdf = Product::generateProductPdf($product, $title); + } else { + // * Add another page and add HTML from view to this. + $pdf->getMpdf()->AddPage(); + $pdf->getMpdf()->WriteHTML((string)view( + 'documents.product-body', + ['product' => (object)(new ProductResource($product))->toArray()], + )); } - - // * Add another page and add HTML from view to this. - $pdf->getMpdf()->AddPage(); - $pdf->getMpdf()->WriteHTML((string)view( - 'documents.product-body', - ['product' => (object)(new ProductResource($product))->toArray()], - )); } return $pdf; }
{{ __('Appréciation') }}