From f61a4161beadfc17897baab4470f868c3cffdaaf Mon Sep 17 00:00:00 2001 From: Brandon Shipley Date: Sun, 29 Jun 2025 21:52:07 -0700 Subject: [PATCH] wip product category variants --- ...29054627_CreateProductCategoryVariants.php | 65 +++++++++++ .../ProductCategoryVariantsController.php | 107 +++++++++++++++++ src/Model/Entity/ProductCategoryVariant.php | 41 +++++++ .../Table/ProductCategoryVariantsTable.php | 108 ++++++++++++++++++ templates/ProductCategories/select.php | 2 +- templates/ProductCategoryVariants/add.php | 33 ++++++ templates/ProductCategoryVariants/edit.php | 38 ++++++ templates/ProductCategoryVariants/index.php | 52 +++++++++ templates/ProductCategoryVariants/view.php | 48 ++++++++ templates/ProductSkus/add.php | 9 +- templates/ProductSkus/edit.php | 8 +- templates/element/ProductSkus/form.php | 7 ++ 12 files changed, 502 insertions(+), 16 deletions(-) create mode 100644 config/Migrations/20250629054627_CreateProductCategoryVariants.php create mode 100644 src/Controller/ProductCategoryVariantsController.php create mode 100644 src/Model/Entity/ProductCategoryVariant.php create mode 100644 src/Model/Table/ProductCategoryVariantsTable.php create mode 100644 templates/ProductCategoryVariants/add.php create mode 100644 templates/ProductCategoryVariants/edit.php create mode 100644 templates/ProductCategoryVariants/index.php create mode 100644 templates/ProductCategoryVariants/view.php create mode 100644 templates/element/ProductSkus/form.php diff --git a/config/Migrations/20250629054627_CreateProductCategoryVariants.php b/config/Migrations/20250629054627_CreateProductCategoryVariants.php new file mode 100644 index 0000000..b6dcd00 --- /dev/null +++ b/config/Migrations/20250629054627_CreateProductCategoryVariants.php @@ -0,0 +1,65 @@ +table('product_category_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_id', 'uuid', [ + 'default' => null, + 'null' => true, + ]); + $table->addColumn('product_id', 'uuid', [ + 'default' => null, + 'null' => true, + ]); + $table->addColumn('attribute_type_id', 'integer', [ + 'default' => null, + 'limit' => 11, + 'null' => false, + ]); + $table->addColumn('enabled', 'boolean', [ + 'default' => null, + 'null' => false, + ]); + $table->addIndex([ + 'product_category_id', + ], [ + 'name' => 'BY_PRODUCT_CATEGORY_ID', + 'unique' => false, + ]); + $table->addIndex([ + 'product_id', + ], [ + 'name' => 'BY_PRODUCT_ID', + 'unique' => false, + ]); + $table->addIndex([ + 'name', + 'product_category_id', + ], [ + 'name' => 'BY_NAME_AND_PRODUCT_CATEGORY_ID_UNIQUE', + 'unique' => true, + ]); + $table->create(); + } +} diff --git a/src/Controller/ProductCategoryVariantsController.php b/src/Controller/ProductCategoryVariantsController.php new file mode 100644 index 0000000..8e2e9eb --- /dev/null +++ b/src/Controller/ProductCategoryVariantsController.php @@ -0,0 +1,107 @@ +ProductCategoryVariants->find() + ->contain(['ProductCategories', 'Products']); + $productCategoryVariants = $this->paginate($query); + + $this->set(compact('productCategoryVariants')); + } + + /** + * View method + * + * @param string|null $id Product Category Variant id. + * @return \Cake\Http\Response|null|void Renders view + * @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found. + */ + public function view($id = null) + { + $productCategoryVariant = $this->ProductCategoryVariants->get($id, contain: ['ProductCategories', 'Products']); + $this->set(compact('productCategoryVariant')); + } + + /** + * Add method + * + * @return \Cake\Http\Response|null|void Redirects on successful add, renders view otherwise. + */ + public function add() + { + $productCategoryVariant = $this->ProductCategoryVariants->newEmptyEntity(); + if ($this->request->is('post')) { + $productCategoryVariant = $this->ProductCategoryVariants->patchEntity($productCategoryVariant, $this->request->getData()); + if ($this->ProductCategoryVariants->save($productCategoryVariant)) { + $this->Flash->success(__('The product category variant has been saved.')); + + return $this->redirect(['action' => 'index']); + } + $this->Flash->error(__('The product category variant could not be saved. Please, try again.')); + } + $productCategories = $this->ProductCategoryVariants->ProductCategories->find('list', limit: 200)->all(); + $products = $this->ProductCategoryVariants->Products->find('list', limit: 200)->all(); + $this->set(compact('productCategoryVariant', 'productCategories', 'products')); + } + + /** + * Edit method + * + * @param string|null $id Product Category Variant id. + * @return \Cake\Http\Response|null|void Redirects on successful edit, renders view otherwise. + * @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found. + */ + public function edit($id = null) + { + $productCategoryVariant = $this->ProductCategoryVariants->get($id, contain: []); + if ($this->request->is(['patch', 'post', 'put'])) { + $productCategoryVariant = $this->ProductCategoryVariants->patchEntity($productCategoryVariant, $this->request->getData()); + if ($this->ProductCategoryVariants->save($productCategoryVariant)) { + $this->Flash->success(__('The product category variant has been saved.')); + + return $this->redirect(['action' => 'index']); + } + $this->Flash->error(__('The product category variant could not be saved. Please, try again.')); + } + $productCategories = $this->ProductCategoryVariants->ProductCategories->find('list', limit: 200)->all(); + $products = $this->ProductCategoryVariants->Products->find('list', limit: 200)->all(); + $this->set(compact('productCategoryVariant', 'productCategories', 'products')); + } + + /** + * Delete method + * + * @param string|null $id Product Category Variant id. + * @return \Cake\Http\Response|null Redirects to index. + * @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found. + */ + public function delete($id = null) + { + $this->request->allowMethod(['post', 'delete']); + $productCategoryVariant = $this->ProductCategoryVariants->get($id); + if ($this->ProductCategoryVariants->delete($productCategoryVariant)) { + $this->Flash->success(__('The product category variant has been deleted.')); + } else { + $this->Flash->error(__('The product category variant could not be deleted. Please, try again.')); + } + + return $this->redirect(['action' => 'index']); + } +} diff --git a/src/Model/Entity/ProductCategoryVariant.php b/src/Model/Entity/ProductCategoryVariant.php new file mode 100644 index 0000000..38fb6c8 --- /dev/null +++ b/src/Model/Entity/ProductCategoryVariant.php @@ -0,0 +1,41 @@ + + */ + protected array $_accessible = [ + 'name' => true, + 'product_category_id' => true, + 'product_id' => true, + 'attribute_type_id' => true, + 'enabled' => true, + 'product_category' => true, + 'product' => true, + ]; +} diff --git a/src/Model/Table/ProductCategoryVariantsTable.php b/src/Model/Table/ProductCategoryVariantsTable.php new file mode 100644 index 0000000..dd37f0b --- /dev/null +++ b/src/Model/Table/ProductCategoryVariantsTable.php @@ -0,0 +1,108 @@ + newEntities(array $data, array $options = []) + * @method \App\Model\Entity\ProductCategoryVariant get(mixed $primaryKey, array|string $finder = 'all', \Psr\SimpleCache\CacheInterface|string|null $cache = null, \Closure|string|null $cacheKey = null, mixed ...$args) + * @method \App\Model\Entity\ProductCategoryVariant findOrCreate($search, ?callable $callback = null, array $options = []) + * @method \App\Model\Entity\ProductCategoryVariant patchEntity(\Cake\Datasource\EntityInterface $entity, array $data, array $options = []) + * @method array<\App\Model\Entity\ProductCategoryVariant> patchEntities(iterable $entities, array $data, array $options = []) + * @method \App\Model\Entity\ProductCategoryVariant|false save(\Cake\Datasource\EntityInterface $entity, array $options = []) + * @method \App\Model\Entity\ProductCategoryVariant saveOrFail(\Cake\Datasource\EntityInterface $entity, array $options = []) + * @method iterable<\App\Model\Entity\ProductCategoryVariant>|\Cake\Datasource\ResultSetInterface<\App\Model\Entity\ProductCategoryVariant>|false saveMany(iterable $entities, array $options = []) + * @method iterable<\App\Model\Entity\ProductCategoryVariant>|\Cake\Datasource\ResultSetInterface<\App\Model\Entity\ProductCategoryVariant> saveManyOrFail(iterable $entities, array $options = []) + * @method iterable<\App\Model\Entity\ProductCategoryVariant>|\Cake\Datasource\ResultSetInterface<\App\Model\Entity\ProductCategoryVariant>|false deleteMany(iterable $entities, array $options = []) + * @method iterable<\App\Model\Entity\ProductCategoryVariant>|\Cake\Datasource\ResultSetInterface<\App\Model\Entity\ProductCategoryVariant> deleteManyOrFail(iterable $entities, array $options = []) + */ +class ProductCategoryVariantsTable 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_category_variants'); + $this->setDisplayField('name'); + $this->setPrimaryKey('id'); + + $this->belongsTo('ProductCategories', [ + 'foreignKey' => 'product_category_id', + 'bindingKey' => 'internal_id', + 'className' => 'CakeProducts.ProductCategories', + ]); + $this->belongsTo('Products', [ + 'foreignKey' => 'product_id', + 'className' => 'CakeProducts.Products', + ]); + } + + /** + * Default validation rules. + * + * @param \Cake\Validation\Validator $validator Validator instance. + * @return \Cake\Validation\Validator + */ + public function validationDefault(Validator $validator): Validator + { + $validator + ->scalar('name') + ->maxLength('name', 255) + ->requirePresence('name', 'create') + ->notEmptyString('name'); + + $validator + ->uuid('product_category_id') + ->allowEmptyString('product_category_id'); + + $validator + ->uuid('product_id') + ->allowEmptyString('product_id'); + + $validator + ->integer('attribute_type_id') + ->requirePresence('attribute_type_id', 'create') + ->notEmptyString('attribute_type_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 \Cake\ORM\RulesChecker $rules The rules object to be modified. + * @return \Cake\ORM\RulesChecker + */ + public function buildRules(RulesChecker $rules): RulesChecker + { + $rules->add($rules->isUnique(['name', 'product_category_id', 'product_id'], ['allowMultipleNulls' => true]), ['errorField' => 'product_category_id']); + $rules->add($rules->existsIn(['product_category_id'], 'ProductCategories'), ['errorField' => 'product_category_id']); + $rules->add($rules->existsIn(['product_id'], 'Products'), ['errorField' => 'product_id']); + + return $rules; + } +} diff --git a/templates/ProductCategories/select.php b/templates/ProductCategories/select.php index 7caf27c..b5e8ab9 100644 --- a/templates/ProductCategories/select.php +++ b/templates/ProductCategories/select.php @@ -7,7 +7,7 @@ $this->setLayout('ajax'); ?> - + $productCategoryName): ?> \ No newline at end of file diff --git a/templates/ProductCategoryVariants/add.php b/templates/ProductCategoryVariants/add.php new file mode 100644 index 0000000..1f8ff0c --- /dev/null +++ b/templates/ProductCategoryVariants/add.php @@ -0,0 +1,33 @@ + +
+ +
+
+ Form->create($productCategoryVariant) ?> +
+ + Form->control('name'); + echo $this->Form->control('product_category_id', ['options' => $productCategories, 'empty' => true]); + echo $this->Form->control('product_id', ['options' => $products, 'empty' => true]); + echo $this->Form->control('attribute_type_id'); + echo $this->Form->control('enabled'); + ?> +
+ Form->button(__('Submit')) ?> + Form->end() ?> +
+
+
diff --git a/templates/ProductCategoryVariants/edit.php b/templates/ProductCategoryVariants/edit.php new file mode 100644 index 0000000..0a9f27b --- /dev/null +++ b/templates/ProductCategoryVariants/edit.php @@ -0,0 +1,38 @@ + +
+ +
+
+ Form->create($productCategoryVariant) ?> +
+ + Form->control('name'); + echo $this->Form->control('product_category_id', ['options' => $productCategories, 'empty' => true]); + echo $this->Form->control('product_id', ['options' => $products, 'empty' => true]); + echo $this->Form->control('attribute_type_id'); + echo $this->Form->control('enabled'); + ?> +
+ Form->button(__('Submit')) ?> + Form->end() ?> +
+
+
diff --git a/templates/ProductCategoryVariants/index.php b/templates/ProductCategoryVariants/index.php new file mode 100644 index 0000000..9e1600f --- /dev/null +++ b/templates/ProductCategoryVariants/index.php @@ -0,0 +1,52 @@ + $productCategoryVariants + */ +?> +
+ Html->link(__('New Product Category Variant'), ['action' => 'add'], ['class' => 'button float-right']) ?> +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
Paginator->sort('id') ?>Paginator->sort('name') ?>Paginator->sort('product_category_id') ?>Paginator->sort('product_id') ?>Paginator->sort('attribute_type_id') ?>Paginator->sort('enabled') ?>
id) ?>name) ?>hasValue('product_category') ? $this->Html->link($productCategoryVariant->product_category->name, ['controller' => 'ProductCategories', 'action' => 'view', $productCategoryVariant->product_category->id]) : '' ?>hasValue('product') ? $this->Html->link($productCategoryVariant->product->name, ['controller' => 'Products', 'action' => 'view', $productCategoryVariant->product->id]) : '' ?>Number->format($productCategoryVariant->attribute_type_id) ?>enabled) ?> + Html->link(__('View'), ['action' => 'view', $productCategoryVariant->id]) ?> + Html->link(__('Edit'), ['action' => 'edit', $productCategoryVariant->id]) ?> + Form->postLink(__('Delete'), ['action' => 'delete', $productCategoryVariant->id], ['confirm' => __('Are you sure you want to delete # {0}?', $productCategoryVariant->id)]) ?> +
+
+
+
    + Paginator->first('<< ' . __('first')) ?> + Paginator->prev('< ' . __('previous')) ?> + Paginator->numbers() ?> + Paginator->next(__('next') . ' >') ?> + Paginator->last(__('last') . ' >>') ?> +
+

Paginator->counter(__('Page {{page}} of {{pages}}, showing {{current}} record(s) out of {{count}} total')) ?>

+
+
diff --git a/templates/ProductCategoryVariants/view.php b/templates/ProductCategoryVariants/view.php new file mode 100644 index 0000000..533a8ae --- /dev/null +++ b/templates/ProductCategoryVariants/view.php @@ -0,0 +1,48 @@ + +
+ +
+
+

name) ?>

+ + + + + + + + + + + + + + + + + + + + + + + + + +
id) ?>
name) ?>
hasValue('product_category') ? $this->Html->link($productCategoryVariant->product_category->name, ['controller' => 'ProductCategories', 'action' => 'view', $productCategoryVariant->product_category->id]) : '' ?>
hasValue('product') ? $this->Html->link($productCategoryVariant->product->name, ['controller' => 'Products', 'action' => 'view', $productCategoryVariant->product->id]) : '' ?>
Number->format($productCategoryVariant->attribute_type_id) ?>
enabled ? __('Yes') : __('No'); ?>
+
+
+
diff --git a/templates/ProductSkus/add.php b/templates/ProductSkus/add.php index 8d9436f..eef1695 100644 --- a/templates/ProductSkus/add.php +++ b/templates/ProductSkus/add.php @@ -16,14 +16,7 @@ Form->create($productSku) ?>
- Form->control('product_id'); - echo $this->Form->control('sku'); - echo $this->Form->control('barcode'); - echo $this->Form->control('price'); - echo $this->Form->control('cost'); - echo $this->Form->control('deleted', ['empty' => true]); - ?> + element('ProductSkus/form'); ?>
Form->button(__('Submit')) ?> Form->end() ?> diff --git a/templates/ProductSkus/edit.php b/templates/ProductSkus/edit.php index 6bd0cf2..43d27ee 100644 --- a/templates/ProductSkus/edit.php +++ b/templates/ProductSkus/edit.php @@ -21,13 +21,7 @@ Form->create($productSku) ?>
- Form->control('product_id'); - echo $this->Form->control('sku'); - echo $this->Form->control('barcode'); - echo $this->Form->control('price'); - echo $this->Form->control('cost'); - ?> + element('ProductSkus/form'); ?>
Form->button(__('Submit')) ?> Form->end() ?> diff --git a/templates/element/ProductSkus/form.php b/templates/element/ProductSkus/form.php new file mode 100644 index 0000000..13627b6 --- /dev/null +++ b/templates/element/ProductSkus/form.php @@ -0,0 +1,7 @@ +Form->control('product_id'); +echo $this->Form->control('sku'); +echo $this->Form->control('barcode'); +echo $this->Form->control('price'); +echo $this->Form->control('cost'); +?>