From 49912abd3abcfd6504f4c97e4bff6d7300925c84 Mon Sep 17 00:00:00 2001 From: Brandon Shipley Date: Fri, 3 Oct 2025 02:16:24 -0700 Subject: [PATCH] product variants table split off from category variants table, variant values table updated to reflect --- ...29054627_CreateProductCategoryVariants.php | 2 +- ...06074703_CreateProductSkuVariantValues.php | 2 +- .../20250922045018_CreateProductVariants.php | 62 ++++++++++ src/Controller/ProductSkusController.php | 55 ++++++--- src/Controller/ProductsController.php | 7 +- src/Model/Entity/ProductSkuVariantValue.php | 6 +- src/Model/Entity/ProductVariant.php | 39 ++++++ .../Table/ProductCategoryVariantsTable.php | 4 +- .../Table/ProductSkuVariantValuesTable.php | 14 +-- src/Model/Table/ProductSkusTable.php | 14 +++ src/Model/Table/ProductVariantsTable.php | 115 ++++++++++++++++++ src/Model/Table/ProductsTable.php | 4 +- .../ProductCategoryVariantOptionsFixture.php | 10 +- .../ProductCategoryVariantsFixture.php | 4 +- .../ProductSkuVariantValuesFixture.php | 2 +- tests/Fixture/ProductVariantsFixture.php | 52 ++++++++ tests/Fixture/ProductsFixture.php | 7 ++ .../ProductCategoryVariantsControllerTest.php | 3 + .../Controller/ProductSkusControllerTest.php | 9 +- .../Model/Table/ProductVariantsTableTest.php | 108 ++++++++++++++++ .../Model/Table/ProductsTableTest.php | 4 +- 21 files changed, 477 insertions(+), 46 deletions(-) create mode 100644 config/Migrations/20250922045018_CreateProductVariants.php create mode 100644 src/Model/Entity/ProductVariant.php create mode 100644 src/Model/Table/ProductVariantsTable.php create mode 100644 tests/Fixture/ProductVariantsFixture.php create mode 100644 tests/TestCase/Model/Table/ProductVariantsTableTest.php diff --git a/config/Migrations/20250629054627_CreateProductCategoryVariants.php b/config/Migrations/20250629054627_CreateProductCategoryVariants.php index 8e35324..c8e240e 100644 --- a/config/Migrations/20250629054627_CreateProductCategoryVariants.php +++ b/config/Migrations/20250629054627_CreateProductCategoryVariants.php @@ -45,7 +45,7 @@ class CreateProductCategoryVariants extends AbstractMigration $table->addIndex([ 'product_id', ], [ - 'name' => 'VARIANTS_BY_PRODUCT_ID', + 'name' => 'CATEGORY_VARIANTS_BY_PRODUCT_ID', 'unique' => false, ]); // $table->addIndex([ diff --git a/config/Migrations/20250906074703_CreateProductSkuVariantValues.php b/config/Migrations/20250906074703_CreateProductSkuVariantValues.php index 16d3f86..c95b25d 100644 --- a/config/Migrations/20250906074703_CreateProductSkuVariantValues.php +++ b/config/Migrations/20250906074703_CreateProductSkuVariantValues.php @@ -24,7 +24,7 @@ class CreateProductSkuVariantValues extends BaseMigration 'default' => null, 'null' => false, ]); - $table->addColumn('product_category_variant_id', 'uuid', [ + $table->addColumn('product_variant_id', 'uuid', [ 'default' => null, 'null' => false, ]); diff --git a/config/Migrations/20250922045018_CreateProductVariants.php b/config/Migrations/20250922045018_CreateProductVariants.php new file mode 100644 index 0000000..3da6467 --- /dev/null +++ b/config/Migrations/20250922045018_CreateProductVariants.php @@ -0,0 +1,62 @@ +table('product_variants', ['id' => false, 'primary_key' => ['id']]); + $table->addColumn('id', 'uuid', [ + 'default' => null, + 'null' => false, + ]); + $table->addColumn('name', 'string', [ + 'default' => null, + 'limit' => 255, + 'null' => false, + ]); + $table->addColumn('product_category_variant_id', 'uuid', [ + 'default' => null, + 'null' => true, + ]); + $table->addColumn('product_id', 'uuid', [ + 'default' => null, + 'null' => false, + ]); + $table->addColumn('enabled', 'boolean', [ + 'default' => null, + 'null' => false, + ]); + $table->addIndex([ + 'product_category_variant_id', + ], [ + 'name' => 'VARIANTS_BY_PARENT_PRODUCT_CATEGORY_VARIANT_ID', + 'unique' => false, + ]); + $table->addIndex([ + 'product_id', + ], [ + 'name' => 'VARIANTS_BY_PRODUCT_ID', + 'unique' => false, + ]); + +// $table->addIndex([ +// 'name', +// 'product_category_id', +// ], [ +// 'name' => 'VARIANTS_BY_NAME_AND_PRODUCT_CATEGORY_ID_UNIQUE', +// 'unique' => true, +// ]); + $table->create(); + } +} diff --git a/src/Controller/ProductSkusController.php b/src/Controller/ProductSkusController.php index 279636b..2f17ce0 100644 --- a/src/Controller/ProductSkusController.php +++ b/src/Controller/ProductSkusController.php @@ -53,7 +53,8 @@ class ProductSkusController extends AppController $productSku = $this->ProductSkus->get($id, contain: [ 'Products', 'ProductSkuVariantValues', - 'ProductSkuVariantValues.ProductCategoryVariants', + 'ProductSkuVariantValues.ProductVariants', + 'ProductSkuVariantValues.ProductVariants.ProductCategoryVariants', 'ProductSkuVariantValues.ProductCategoryVariantOptions', ]); $this->set(compact('productSku')); @@ -70,27 +71,50 @@ class ProductSkusController extends AppController $productSkus = []; $table = $this->getTable(); - $productCategoryVariants = $table->Products->ProductCategoryVariants->find() - ->contain(['ProductCategoryVariantOptions']) - ->where(['product_id' => $productId]) - ->toArray(); - $optionMapping = Hash::combine($productCategoryVariants, '{n}.product_category_variant_options.{n}.id', '{n}.product_category_variant_options.{n}.variant_value'); - $variantNameMapping = Hash::combine($productCategoryVariants, '{n}.id', '{n}.name'); - foreach ($productCategoryVariants as $productCategoryVariant) { - $options = Hash::extract($productCategoryVariant->product_category_variant_options ?? [], '{n}.id'); - $toGetCartesianProductsFrom[$productCategoryVariant->id] = $options; + $product = $table->Products->get($productId, contain: [ + 'ProductSkus', + 'ProductSkus.ProductSkuVariantValues', + 'ProductVariants', + 'ProductVariants.ProductCategoryVariants', + 'ProductVariants.ProductCategoryVariants.ProductCategoryVariantOptions', + ]); + $existingProductSkus = Hash::combine($product->product_skus ?? [], '{n}.id', '{n}'); + $existingProductSkusForMapping = Hash::combine($product->product_skus ?? [], '{n}.id', '{n}.product_sku_variant_values'); + $existingSkusForCartesianComparison = []; + foreach ($existingProductSkusForMapping as $existingProductSkuId => $existingProductSku) { + $existingSkusForCartesianComparison[$existingProductSkuId] = Hash::combine($existingProductSku, '{n}.product_category_variant_id', '{n}.product_category_variant_option_id'); } + $productVariants = isset($product->product_variants) ? $product->product_variants : []; +// dd($productVariants); + $productVariantsMapping = Hash::combine($productVariants, '{n}.product_category_variant.id', '{n}.id'); + $productCategoryVariants = Hash::extract($productVariants, '{n}.product_category_variant'); +// dd($productCategoryVariants); + $optionMapping = Hash::combine($productCategoryVariants, '{n}.product_category_variant_options.{n}.id', '{n}.product_category_variant_options.{n}.variant_value'); +// dd($optionMapping); + + $variantNameMapping = Hash::combine($productCategoryVariants, '{n}.id', '{n}.name'); +// dd($variantNameMapping); + + foreach ($productCategoryVariants as $productCategoryVariant) { + $options = Hash::extract($productCategoryVariant['product_category_variant_options'] ?? [], '{n}.id'); + $toGetCartesianProductsFrom[$productCategoryVariant['id']] = $options; + } +// dd($toGetCartesianProductsFrom); + $numSkusToAdd = count(combinations($toGetCartesianProductsFrom)); for ($i = 0; $i < $numSkusToAdd; $i++) { $productSkus[$i] = $this->getTable()->newEmptyEntity(); } $this->set(compact( + 'product', 'productSkus', 'productCategoryVariants', 'toGetCartesianProductsFrom', 'optionMapping', 'variantNameMapping', - 'numSkusToAdd' + 'numSkusToAdd', + 'existingProductSkus', + 'existingSkusForCartesianComparison' )); if ($this->request->is('post')) { @@ -109,9 +133,8 @@ class ProductSkusController extends AppController ], 'associated' => [ 'ProductSkuVariantValues' => [ - 'validate' => false, 'fields' => [ - 'product_category_variant_id', + 'product_variant_id', 'product_category_variant_option_id', ], ], @@ -121,7 +144,7 @@ class ProductSkusController extends AppController $postedSkus = Hash::insert($postedSkus, '{n}.product_id', $productId); foreach ($postedSkus as $postedSkuCnt => $postedSku) { - if (!isset($postedSku['add']) || !$postedSku['add']) { + if (!isset($postedSku['sku']) || !$postedSku['sku']) { unset($productSkus[$postedSkuCnt]); continue; @@ -133,7 +156,7 @@ class ProductSkusController extends AppController return; } - +// dd($finalPostData); $productSkus = $table->patchEntities($productSkus, $finalPostData, $saveOptions); $errors = []; $successes = []; @@ -143,7 +166,7 @@ class ProductSkusController extends AppController if (!$table->save($productSkuToSave, $saveOptions)) { Log::debug(print_r('$productSkuToSave->getErrors()', true)); Log::debug(print_r($productSkuToSave->getErrors(), true)); - + dd($productSkuToSave->getErrors()); continue; } $successes[] = $productSkuToSave; diff --git a/src/Controller/ProductsController.php b/src/Controller/ProductsController.php index 410dc94..fd7cd72 100644 --- a/src/Controller/ProductsController.php +++ b/src/Controller/ProductsController.php @@ -58,8 +58,11 @@ class ProductsController extends AppController 'ProductAttributes', 'ProductAttributes.ProductCategoryAttributes', 'ProductAttributes.ProductCategoryAttributeOptions', - 'ProductCategoryVariants', - 'ProductSkus' + 'ProductVariants', + 'ProductVariants.ProductCategoryVariants', + 'ProductVariants.ProductCategoryVariants.ProductCategoryVariantOptions', + 'ProductSkus', + 'ProductPhotos', ]); $this->set(compact('product')); } diff --git a/src/Model/Entity/ProductSkuVariantValue.php b/src/Model/Entity/ProductSkuVariantValue.php index 85482c9..09b31d4 100644 --- a/src/Model/Entity/ProductSkuVariantValue.php +++ b/src/Model/Entity/ProductSkuVariantValue.php @@ -10,7 +10,7 @@ use Cake\ORM\Entity; * * @property string $id * @property string $product_sku_id - * @property string $product_category_variant_id + * @property string $product_variant_id * @property string $product_category_variant_option_id * * @property ProductSku $product_sku @@ -30,12 +30,12 @@ class ProductSkuVariantValue extends Entity */ protected array $_accessible = [ 'product_sku_id' => true, - 'product_category_variant_id' => true, + 'product_variant_id' => true, 'product_category_variant_option_id' => true, // entities 'product_skus' => true, - 'product_category_variant' => true, + 'product_variant' => true, 'product_category_variant_option' => true, ]; } diff --git a/src/Model/Entity/ProductVariant.php b/src/Model/Entity/ProductVariant.php new file mode 100644 index 0000000..5bcadc3 --- /dev/null +++ b/src/Model/Entity/ProductVariant.php @@ -0,0 +1,39 @@ + + */ + protected array $_accessible = [ + 'name' => true, + 'product_category_variant_id' => true, + 'product_id' => true, + 'enabled' => true, + 'product_category_variant' => true, + 'product' => true, + ]; +} diff --git a/src/Model/Table/ProductCategoryVariantsTable.php b/src/Model/Table/ProductCategoryVariantsTable.php index ddb3fbd..47943a7 100644 --- a/src/Model/Table/ProductCategoryVariantsTable.php +++ b/src/Model/Table/ProductCategoryVariantsTable.php @@ -72,9 +72,9 @@ class ProductCategoryVariantsTable extends Table 'cascadeCallbacks' => true, ]); - $this->hasMany('ProductSkuVariantValues', [ + $this->hasMany('ProductVariants', [ 'foreignKey' => 'product_category_variant_id', - 'className' => 'CakeProducts.ProductSkuVariantValues', + 'className' => 'CakeProducts.ProductVariants', 'dependent' => true, 'cascadeCallbacks' => true, ]); diff --git a/src/Model/Table/ProductSkuVariantValuesTable.php b/src/Model/Table/ProductSkuVariantValuesTable.php index 0cbb39b..95d23d6 100644 --- a/src/Model/Table/ProductSkuVariantValuesTable.php +++ b/src/Model/Table/ProductSkuVariantValuesTable.php @@ -56,9 +56,9 @@ class ProductSkuVariantValuesTable extends Table 'foreignKey' => 'product_sku_id', 'joinType' => 'INNER', ]); - $this->belongsTo('ProductCategoryVariants', [ - 'className' => 'CakeProducts.ProductCategoryVariants', - 'foreignKey' => 'product_category_variant_id', + $this->belongsTo('ProductVariants', [ + 'className' => 'CakeProducts.ProductVariants', + 'foreignKey' => 'product_variant_id', 'joinType' => 'INNER', ]); $this->belongsTo('ProductCategoryVariantOptions', [ @@ -81,8 +81,8 @@ class ProductSkuVariantValuesTable extends Table ->notEmptyString('product_sku_id'); $validator - ->uuid('product_category_variant_id') - ->notEmptyString('product_category_variant_id'); + ->uuid('product_variant_id') + ->notEmptyString('product_variant_id'); $validator ->uuid('product_category_variant_option_id') @@ -103,8 +103,8 @@ class ProductSkuVariantValuesTable extends Table $rules->add($rules->existsIn(['product_sku_id'], 'ProductSkus'), ['errorField' => 'product_sku_id']); // @TODO why not working?? causing tests to fail / associated variant values not saving on product-skus/add -// $rules->add($rules->existsIn(['product_category_variant_id'], 'ProductCategoryVariants'), ['errorField' => 'product_category_variant_id']); -// $rules->add($rules->existsIn(['product_category_variant_option_id'], 'ProductCategoryVariantOptions'), ['errorField' => 'product_category_variant_option_id']); + $rules->add($rules->existsIn(['product_variant_id'], 'ProductVariants'), ['errorField' => 'product_variant_id']); + $rules->add($rules->existsIn(['product_category_variant_option_id'], 'ProductCategoryVariantOptions'), ['errorField' => 'product_category_variant_option_id']); return $rules; } diff --git a/src/Model/Table/ProductSkusTable.php b/src/Model/Table/ProductSkusTable.php index d827f0d..3f0c2cb 100644 --- a/src/Model/Table/ProductSkusTable.php +++ b/src/Model/Table/ProductSkusTable.php @@ -73,6 +73,20 @@ class ProductSkusTable extends Table 'dependent' => true, 'cascadeCallbacks' => true, ]); + + $this->hasMany('ProductPhotos', [ + 'foreignKey' => 'product_sku_id', + 'className' => 'CakeProducts.ProductPhotos', + 'dependent' => true, + 'cascadeCallbacks' => true, + ]); + + $this->hasOne('PrimaryProductPhotos', [ + 'foreignKey' => 'product_sku_id', + 'conditions' => ['PrimaryProductPhotos.primary_photo' => true], + 'className' => 'CakeProducts.ProductPhotos', + 'dependent' => true, + ]); } /** diff --git a/src/Model/Table/ProductVariantsTable.php b/src/Model/Table/ProductVariantsTable.php new file mode 100644 index 0000000..a78d6b9 --- /dev/null +++ b/src/Model/Table/ProductVariantsTable.php @@ -0,0 +1,115 @@ + newEntities(array $data, array $options = []) + * @method ProductVariant get(mixed $primaryKey, array|string $finder = 'all', CacheInterface|string|null $cache = null, Closure|string|null $cacheKey = null, mixed ...$args) + * @method ProductVariant findOrCreate($search, ?callable $callback = null, array $options = []) + * @method ProductVariant patchEntity(EntityInterface $entity, array $data, array $options = []) + * @method array patchEntities(iterable $entities, array $data, array $options = []) + * @method ProductVariant|false save(EntityInterface $entity, array $options = []) + * @method ProductVariant saveOrFail(EntityInterface $entity, array $options = []) + * @method iterable|ResultSetInterface|false saveMany(iterable $entities, array $options = []) + * @method iterable|ResultSetInterface saveManyOrFail(iterable $entities, array $options = []) + * @method iterable|ResultSetInterface|false deleteMany(iterable $entities, array $options = []) + * @method iterable|ResultSetInterface deleteManyOrFail(iterable $entities, array $options = []) + */ +class ProductVariantsTable extends Table +{ + /** + * Initialize method + * + * @param array $config The configuration for the Table. + * @return void + */ + public function initialize(array $config): void + { + parent::initialize($config); + + $this->setTable('product_variants'); + $this->setDisplayField('name'); + $this->setPrimaryKey('id'); + + $this->belongsTo('ProductCategoryVariants', [ + 'className' => 'CakeProducts.ProductCategoryVariants', + 'foreignKey' => 'product_category_variant_id', + ]); + $this->belongsTo('Products', [ + 'className' => 'CakeProducts.Products', + 'foreignKey' => 'product_id', + 'joinType' => 'INNER', + ]); + + $this->hasMany('ProductCategoryVariantOptions', [ + 'className' => 'CakeProducts.Products', + 'foreignKey' => 'product_category_variant_id', + ]); + } + + /** + * Default validation rules. + * + * @param Validator $validator Validator instance. + * @return Validator + */ + public function validationDefault(Validator $validator): Validator + { + $validator + ->scalar('name') + ->maxLength('name', 255) + ->requirePresence('name', 'create') + ->notEmptyString('name'); + + $validator + ->uuid('product_category_variant_id') + ->allowEmptyString('product_category_variant_id'); + + $validator + ->uuid('product_id') + ->notEmptyString('product_id'); + + $validator + ->boolean('enabled') + ->requirePresence('enabled', 'create') + ->notEmptyString('enabled'); + + return $validator; + } + + /** + * Returns a rules checker object that will be used for validating + * application integrity. + * + * @param RulesChecker $rules The rules object to be modified. + * @return RulesChecker + */ + public function buildRules(RulesChecker $rules): RulesChecker + { + $rules->add($rules->existsIn(['product_category_variant_id'], 'ProductCategoryVariants'), ['errorField' => 'product_category_variant_id']); + $rules->add($rules->existsIn(['product_id'], 'Products'), ['errorField' => 'product_id']); + + return $rules; + } +} diff --git a/src/Model/Table/ProductsTable.php b/src/Model/Table/ProductsTable.php index 44077b9..9515482 100644 --- a/src/Model/Table/ProductsTable.php +++ b/src/Model/Table/ProductsTable.php @@ -69,9 +69,9 @@ class ProductsTable extends Table 'cascadeCallbacks' => true, ]); - $this->hasMany('ProductCategoryVariants', [ + $this->hasMany('ProductVariants', [ 'foreignKey' => 'product_id', - 'className' => 'CakeProducts.ProductCategoryVariants', + 'className' => 'CakeProducts.ProductVariants', 'dependent' => true, 'cascadeCallbacks' => true, ]); diff --git a/tests/Fixture/ProductCategoryVariantOptionsFixture.php b/tests/Fixture/ProductCategoryVariantOptionsFixture.php index aaecd09..9bade3a 100644 --- a/tests/Fixture/ProductCategoryVariantOptionsFixture.php +++ b/tests/Fixture/ProductCategoryVariantOptionsFixture.php @@ -36,9 +36,11 @@ class ProductCategoryVariantOptionsFixture extends TestFixture 'modified' => '2025-07-04 12:00:00', 'enabled' => 1, ], + + [ - 'id' => '5a386e9f-6e7a-4ae7-9360-c8e529f78d25', - 'variant_value' => 'Blue', + 'id' => '5a386e9f-6e7a-4ae7-9360-c8e529f78d21', + 'variant_value' => '12AWG', 'variant_label' => null, 'product_category_variant_id' => '5a386e9f-6e7a-4ae7-9360-c8e529f78d94', 'created' => '2025-07-04 12:00:00', @@ -46,8 +48,8 @@ class ProductCategoryVariantOptionsFixture extends TestFixture 'enabled' => 1, ], [ - 'id' => '5a386e9f-6e7a-4ae7-9360-c8e529f78d26', - 'variant_value' => 'Red', + 'id' => '5a386e9f-6e7a-4ae7-9360-c8e529f78d22', + 'variant_value' => '14AWG', 'variant_label' => null, 'product_category_variant_id' => '5a386e9f-6e7a-4ae7-9360-c8e529f78d94', 'created' => '2025-07-04 12:00:00', diff --git a/tests/Fixture/ProductCategoryVariantsFixture.php b/tests/Fixture/ProductCategoryVariantsFixture.php index f7a8d6a..84cc369 100644 --- a/tests/Fixture/ProductCategoryVariantsFixture.php +++ b/tests/Fixture/ProductCategoryVariantsFixture.php @@ -22,14 +22,12 @@ class ProductCategoryVariantsFixture extends TestFixture 'id' => '5a386e9f-6e7a-4ae7-9360-c8e529f78d93', 'name' => 'Color', 'product_category_id' => 'db4b4273-eddc-46d4-93c8-45cf7c6e058e', - 'product_id' => null, 'enabled' => 1, ], [ 'id' => '5a386e9f-6e7a-4ae7-9360-c8e529f78d94', - 'name' => 'Color', + 'name' => 'AWG', 'product_category_id' => 'db4b4273-eddc-46d4-93c8-45cf7c6e058e', - 'product_id' => 'cfc98a9a-29b2-44c8-b587-8156adc05317', 'enabled' => 1, ], ]; diff --git a/tests/Fixture/ProductSkuVariantValuesFixture.php b/tests/Fixture/ProductSkuVariantValuesFixture.php index 5879698..3d1c057 100644 --- a/tests/Fixture/ProductSkuVariantValuesFixture.php +++ b/tests/Fixture/ProductSkuVariantValuesFixture.php @@ -28,7 +28,7 @@ class ProductSkuVariantValuesFixture extends TestFixture [ 'id' => '98b609d8-1d4f-484c-a13a-6adb7102da56', 'product_sku_id' => '3a477e3e-7977-4813-81f6-f85949613979', - 'product_category_variant_id' => '5a386e9f-6e7a-4ae7-9360-c8e529f78d93', + 'product_variant_id' => '2e6e4031-c430-4d07-b8d6-a4e759b72569', 'product_category_variant_option_id' => '5a386e9f-6e7a-4ae7-9360-c8e529f78d23', ], ]; diff --git a/tests/Fixture/ProductVariantsFixture.php b/tests/Fixture/ProductVariantsFixture.php new file mode 100644 index 0000000..fc654a9 --- /dev/null +++ b/tests/Fixture/ProductVariantsFixture.php @@ -0,0 +1,52 @@ +records = [ + [ + 'id' => '2e6e4031-c430-4d07-b8d6-a4e759b72568', + 'name' => 'Color', + 'product_category_variant_id' => '5a386e9f-6e7a-4ae7-9360-c8e529f78d93', + 'product_id' => 'cfc98a9a-29b2-44c8-b587-8156adc05317', + 'enabled' => 1, + ], + [ + 'id' => '2e6e4031-c430-4d07-b8d6-a4e759b72569', + 'name' => 'Color', + 'product_category_variant_id' => '5a386e9f-6e7a-4ae7-9360-c8e529f78d93', + 'product_id' => 'cfc98a9a-29b2-44c8-b587-8156adc05318', + 'enabled' => 1, + ], + [ + 'id' => '2e6e4031-c430-4d07-b8d6-a4e759b72561', + 'name' => 'AWG', + 'product_category_variant_id' => '5a386e9f-6e7a-4ae7-9360-c8e529f78d94', + 'product_id' => 'cfc98a9a-29b2-44c8-b587-8156adc05317', + 'enabled' => 1, + ], + [ + 'id' => '2e6e4031-c430-4d07-b8d6-a4e759b72562', + 'name' => 'AWG', + 'product_category_variant_id' => '5a386e9f-6e7a-4ae7-9360-c8e529f78d94', + 'product_id' => 'cfc98a9a-29b2-44c8-b587-8156adc05318', + 'enabled' => 1, + ] + ]; + parent::init(); + } +} diff --git a/tests/Fixture/ProductsFixture.php b/tests/Fixture/ProductsFixture.php index 6ce5cb6..6138569 100644 --- a/tests/Fixture/ProductsFixture.php +++ b/tests/Fixture/ProductsFixture.php @@ -25,6 +25,13 @@ class ProductsFixture extends TestFixture 'product_type_id' => 1, 'deleted' => null, ], + [ + 'id' => 'cfc98a9a-29b2-44c8-b587-8156adc05318', + 'name' => 'Heat Shrink', + 'product_category_id' => '6d223283-361b-4f9f-a7f1-c97aa0ca4c23', + 'product_type_id' => 1, + 'deleted' => null, + ], ]; parent::init(); } diff --git a/tests/TestCase/Controller/ProductCategoryVariantsControllerTest.php b/tests/TestCase/Controller/ProductCategoryVariantsControllerTest.php index b06b7fe..0a909fc 100644 --- a/tests/TestCase/Controller/ProductCategoryVariantsControllerTest.php +++ b/tests/TestCase/Controller/ProductCategoryVariantsControllerTest.php @@ -37,6 +37,7 @@ class ProductCategoryVariantsControllerTest extends BaseControllerTest */ protected array $fixtures = [ 'plugin.CakeProducts.ProductCategoryVariants', + 'plugin.CakeProducts.ProductVariants', 'plugin.CakeProducts.ProductCategories', 'plugin.CakeProducts.Products', 'plugin.CakeProducts.ProductSkus', @@ -51,6 +52,8 @@ class ProductCategoryVariantsControllerTest extends BaseControllerTest protected function setUp(): void { parent::setUp(); + $this->disableErrorHandlerMiddleware(); + $config = $this->getTableLocator()->exists('ProductCategoryVariants') ? [] : ['className' => ProductCategoryVariantsTable::class]; $this->ProductCategoryVariants = $this->getTableLocator()->get('ProductCategoryVariants', $config); diff --git a/tests/TestCase/Controller/ProductSkusControllerTest.php b/tests/TestCase/Controller/ProductSkusControllerTest.php index 616cfcf..33c3a36 100644 --- a/tests/TestCase/Controller/ProductSkusControllerTest.php +++ b/tests/TestCase/Controller/ProductSkusControllerTest.php @@ -42,6 +42,10 @@ class ProductSkusControllerTest extends BaseControllerTest 'plugin.CakeProducts.ProductSkus', 'plugin.CakeProducts.Products', 'plugin.CakeProducts.ProductAttributes', + 'plugin.CakeProducts.ProductVariants', + 'plugin.CakeProducts.ProductCategoryVariants', + 'plugin.CakeProducts.ProductCategoryVariantOptions', + 'plugin.CakeProducts.ProductSkuVariantValues', ]; /** @@ -173,15 +177,14 @@ class ProductSkusControllerTest extends BaseControllerTest ]; $data = [ 0 => [ - 'add' => '1', 'sku' => 'cfc98a9a-29b2-44c8-b587-8156a', 'barcode' => 'cfc98a9a-29b2-44c8-b587-8156a', 'price' => 1.5, 'cost' => 1.5, 'product_sku_variant_values' => [ 0 => [ - 'product_category_variant_id' => '5a386e9f-6e7a-4ae7-9360-c8e529f78d93', - 'product_category_variant_option_id' => '5a386e9f-6e7a-4ae7-9360-c8e529f78d26', + 'product_variant_id' => '2e6e4031-c430-4d07-b8d6-a4e759b72568', + 'product_category_variant_option_id' => '5a386e9f-6e7a-4ae7-9360-c8e529f78d23', ], ], ], diff --git a/tests/TestCase/Model/Table/ProductVariantsTableTest.php b/tests/TestCase/Model/Table/ProductVariantsTableTest.php new file mode 100644 index 0000000..c25d58f --- /dev/null +++ b/tests/TestCase/Model/Table/ProductVariantsTableTest.php @@ -0,0 +1,108 @@ + + */ + protected array $fixtures = [ + 'plugin.CakeProducts.Products', + 'plugin.CakeProducts.ProductCategoryVariants', + 'plugin.CakeProducts.ProductCategoryVariantOptions', + ]; + + /** + * setUp method + * + * @return void + */ + protected function setUp(): void + { + parent::setUp(); + $config = $this->getTableLocator()->exists('ProductVariants') ? [] : ['className' => ProductVariantsTable::class]; + $this->ProductVariants = $this->getTableLocator()->get('ProductVariants', $config); + } + + /** + * tearDown method + * + * @return void + */ + protected function tearDown(): void + { + unset($this->ProductVariants); + + parent::tearDown(); + } + + /** + * TestInitialize method + * + * @return void + * @uses \App\Model\Table\ProductVariantsTable::initialize() + */ + public function testInitialize(): void + { + // verify all associations loaded + $expectedAssociations = [ + 'Products', + 'ProductCategoryVariants', + 'ProductCategoryVariantOptions', + ]; + $associations = $this->ProductVariants->associations(); + + $this->assertCount(count($expectedAssociations), $associations); + foreach ($expectedAssociations as $expectedAssociation) { + $this->assertTrue($this->ProductVariants->hasAssociation($expectedAssociation)); + } + + // verify all behaviors loaded + $expectedBehaviors = []; + $behaviors = $this->ProductVariants->behaviors(); + + $this->assertCount(count($expectedBehaviors), $behaviors); + foreach ($expectedBehaviors as $expectedBehavior) { + $this->assertTrue($this->ProductVariants->hasBehavior($expectedBehavior)); + } + } + + /** + * Test validationDefault method + * + * @return void + * @uses \App\Model\Table\ProductVariantsTable::validationDefault() + */ + public function testValidationDefault(): void + { + $this->markTestIncomplete('Not implemented yet.'); + } + + /** + * Test buildRules method + * + * @return void + * @uses \App\Model\Table\ProductVariantsTable::buildRules() + */ + public function testBuildRules(): void + { + $this->markTestIncomplete('Not implemented yet.'); + } +} diff --git a/tests/TestCase/Model/Table/ProductsTableTest.php b/tests/TestCase/Model/Table/ProductsTableTest.php index 24589ac..f93f89a 100644 --- a/tests/TestCase/Model/Table/ProductsTableTest.php +++ b/tests/TestCase/Model/Table/ProductsTableTest.php @@ -64,8 +64,10 @@ class ProductsTableTest extends TestCase $expectedAssociations = [ 'ProductCategories', 'ProductAttributes', - 'ProductCategoryVariants', + 'ProductVariants', 'ProductSkus', + 'ProductPhotos', + 'PrimaryProductPhotos', ]; $associations = $this->Products->associations();