Skip to content

Commit ef1e7f3

Browse files
committed
added product related traits, better generate product logic, now using new traits, added physical fields to book model, initial code to implement matrixrate shipping method
1 parent 07fb4b3 commit ef1e7f3

File tree

10 files changed

+296
-77
lines changed

10 files changed

+296
-77
lines changed

app/base/commands/Generate/Product.php

Lines changed: 61 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,48 @@ class Product extends CodeGeneratorCommand
146146
],
147147
];
148148

149+
protected $physical_columns = [
150+
'weight' => [
151+
'col_name' => 'weight',
152+
'php_type' => 'float',
153+
'mysql_type' => 'FLOAT',
154+
'col_parameters' => null,
155+
'col_options' => [],
156+
'nullable' => true,
157+
'default_value' => null,
158+
],
159+
'length' => [
160+
'col_name' => 'length',
161+
'php_type' => 'float',
162+
'mysql_type' => 'FLOAT',
163+
'col_parameters' => null,
164+
'col_options' => [],
165+
'nullable' => true,
166+
'default_value' => null,
167+
],
168+
'width' => [
169+
'col_name' => 'width',
170+
'php_type' => 'float',
171+
'mysql_type' => 'FLOAT',
172+
'col_parameters' => null,
173+
'col_options' => [],
174+
'nullable' => true,
175+
'default_value' => null,
176+
],
177+
'height' => [
178+
'col_name' => 'height',
179+
'php_type' => 'float',
180+
'mysql_type' => 'FLOAT',
181+
'col_parameters' => null,
182+
'col_options' => [],
183+
'nullable' => true,
184+
'default_value' => null,
185+
],
186+
];
187+
188+
protected $interface = 'App\Base\Interfaces\Model\ProductInterface';
189+
protected $traits = ['App\Base\Traits\ProductTrait'];
190+
149191
/**
150192
* {@inheritdoc}
151193
*/
@@ -186,6 +228,13 @@ protected function execute(InputInterface $input, OutputInterface $output) : int
186228
$migration_order = 100 + $last_migration_id;
187229
}
188230

231+
$isPhysical = $this->confirmMessage('Is a physical product?', 'Creating a virtual product');
232+
if ($isPhysical) {
233+
$this->columns = array_merge($this->columns, $this->physical_columns);
234+
$this->interface = 'App\Base\Interfaces\Model\PhysicalProductInterface';
235+
$this->traits[] = 'App\Base\Traits\PhysicalProductTrait';
236+
}
237+
189238
do {
190239
$column_info = $this->askColumnInfo();
191240
if ($column_info) {
@@ -336,36 +385,22 @@ protected function getModelFileContents($className): string
336385
namespace App\\Site\\Models;
337386
338387
use App\\Base\\Abstracts\\Models\\FrontendModel;
339-
use App\Base\Interfaces\Model\ProductInterface;
388+
use ".str_replace('\\','\\\\', $this->interface).";
389+
use ".implode(";\nuse ", $this->traits).";
390+
use App\Base\GraphQl\GraphQLExport;
340391
341392
/**\n" . $comment . " */
342-
class " . $className . " extends FrontendModel implements ProductInterface
393+
#[GraphQLExport]
394+
class " . $className . " extends FrontendModel implements ".$this->getUtils()->getClassBasename($this->interface)."
343395
{
344-
public function isPhysical(): bool
345-
{
346-
return true;
347-
}
348-
349-
public function getId(): int
350-
{
351-
return \$this->getData('id');
352-
}
353-
354-
public function getPrice(): float
355-
{
356-
return \$this->getData('price') ?? 0.0;
357-
}
358-
359-
public function getTaxClassId(): ?int
360-
{
361-
return \$this->getData('tax_class_id');
362-
}
363-
364-
public function getName() : ?string
365-
{
366-
return \$this->getData('title');
367-
}
396+
use ".implode(";\n use ", array_map(fn($t) => $this->getUtils()->getClassBasename($t), $this->traits)).";
368397
398+
/**
399+
* {@inheritdoc}
400+
*
401+
* @return string
402+
*/
403+
#[GraphQLExport]
369404
public function getSku(): string
370405
{
371406
return \$this->getData('sku')?? '".$this->getUtils()->pascalCaseToSnakeCase($className)."_' . \$this->getId();

app/base/controllers/Frontend/Commerce/Checkout/Shipping.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ public function getTemplateName(): string
6262
*/
6363
public function getRouteName(): string
6464
{
65-
return $this->getUtils()->translate('Shippning Address', locale: $this->getCurrentLocale());
65+
return $this->getUtils()->translate('Shipping Address', locale: $this->getCurrentLocale());
6666
}
6767

6868
/**
@@ -341,7 +341,7 @@ public function formSubmitted(FAPI\Form $form, array &$form_state): mixed
341341

342342
$selected_shipping_method = $values['selected_shipping_method'] ?? null;
343343
if ($selected_shipping_method) {
344-
$shippingValues = $values['payment_methods'][$selected_shipping_method];
344+
$shippingValues = $values['shipping_methods'][$selected_shipping_method];
345345

346346
/** @var ShippingMethodInterface $shippingMethod */
347347
$shippingMethod = current(array_filter($this->getShippingMethods(), function($shippingMethod) use ($selected_shipping_method) {
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
/**
4+
* SiteBase
5+
* PHP Version 8.3
6+
*
7+
* @category CMS / Framework
8+
* @package Degami\Sitebase
9+
* @author Mirko De Grandis <degami@github.com>
10+
* @license MIT https://opensource.org/licenses/mit-license.php
11+
* @link https://github.com/degami/sitebase
12+
*/
13+
14+
namespace App\Base\Interfaces\Model;
15+
16+
interface PhysicalProductInterface extends ProductInterface
17+
{
18+
public function getWeight(): float;
19+
public function getLength(): ?float;
20+
public function getWidth(): ?float;
21+
public function getHeight(): ?float;
22+
23+
public function getVolumetricWeight(float $divisor = 5000): float;
24+
}

app/base/models/Cart.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -555,4 +555,21 @@ public function duplicate() : BaseModel
555555

556556
return $copy;
557557
}
558+
559+
public function getBillableWeight(float $divisor = 5000): float
560+
{
561+
$total = 0.0;
562+
563+
foreach ($this->getItems() as $item) {
564+
$product = $item->getProduct();
565+
566+
if ($product instanceof \App\Base\Interfaces\Model\PhysicalProductInterface) {
567+
$real = $product->getWeight() * $item->getQuantity();
568+
$volumetric = $product->getVolumetricWeight($divisor) * $item->getQuantity();
569+
$total += max($real, $volumetric);
570+
}
571+
}
572+
573+
return $total;
574+
}
558575
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
<?php
2+
3+
/**
4+
* SiteBase
5+
* PHP Version 8.3
6+
*
7+
* @category CMS / Framework
8+
* @package Degami\Sitebase
9+
* @author Mirko De Grandis <degami@github.com>
10+
* @license MIT https://opensource.org/licenses/mit-license.php
11+
* @link https://github.com/degami/sitebase
12+
*/
13+
14+
namespace App\Base\Traits;
15+
16+
use App\Base\Interfaces\Model\PhysicalProductInterface;
17+
use RuntimeException;
18+
use App\Base\GraphQl\GraphQLExport;
19+
20+
trait PhysicalProductTrait
21+
{
22+
public function getVolumetricWeight(float $divisor = 5000): float
23+
{
24+
if (!($this instanceof PhysicalProductInterface)) {
25+
throw new RuntimeException("Current object is not an instance of PhysicalProductInterface");
26+
}
27+
28+
$L = $this->getLength() ?: 0;
29+
$W = $this->getWidth() ?: 0;
30+
$H = $this->getHeight() ?: 0;
31+
return ($L * $W * $H) / $divisor;
32+
}
33+
34+
#[GraphQLExport]
35+
public function getWeight(): float
36+
{
37+
if (!($this instanceof PhysicalProductInterface)) {
38+
throw new RuntimeException("Current object is not an instance of PhysicalProductInterface");
39+
}
40+
41+
return $this->getData('weight');
42+
}
43+
44+
#[GraphQLExport]
45+
public function getLength(): ?float
46+
{
47+
if (!($this instanceof PhysicalProductInterface)) {
48+
throw new RuntimeException("Current object is not an instance of PhysicalProductInterface");
49+
}
50+
51+
return $this->getData('length');
52+
}
53+
54+
#[GraphQLExport]
55+
public function getWidth(): ?float
56+
{
57+
if (!($this instanceof PhysicalProductInterface)) {
58+
throw new RuntimeException("Current object is not an instance of PhysicalProductInterface");
59+
}
60+
61+
return $this->getData('width');
62+
}
63+
64+
#[GraphQLExport]
65+
public function getHeight(): ?float
66+
{
67+
if (!($this instanceof PhysicalProductInterface)) {
68+
throw new RuntimeException("Current object is not an instance of PhysicalProductInterface");
69+
}
70+
71+
return $this->getData('height');
72+
}
73+
}

app/base/traits/ProductTrait.php

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<?php
2+
3+
/**
4+
* SiteBase
5+
* PHP Version 8.3
6+
*
7+
* @category CMS / Framework
8+
* @package Degami\Sitebase
9+
* @author Mirko De Grandis <degami@github.com>
10+
* @license MIT https://opensource.org/licenses/mit-license.php
11+
* @link https://github.com/degami/sitebase
12+
*/
13+
14+
namespace App\Base\Traits;
15+
16+
use App\Base\Interfaces\Model\ProductInterface;
17+
use RuntimeException;
18+
use App\Base\GraphQl\GraphQLExport;
19+
20+
trait ProductTrait
21+
{
22+
#[GraphQLExport]
23+
public function getId(): int
24+
{
25+
if (!($this instanceof ProductInterface)) {
26+
throw new RuntimeException("Current object is not an instance of ProductInterface");
27+
}
28+
29+
return $this->getData('id');
30+
}
31+
32+
#[GraphQLExport]
33+
public function getPrice(): float
34+
{
35+
if (!($this instanceof ProductInterface)) {
36+
throw new RuntimeException("Current object is not an instance of ProductInterface");
37+
}
38+
39+
return $this->getData('price') ?? 0.0;
40+
}
41+
42+
#[GraphQLExport]
43+
public function getTaxClassId(): ?int
44+
{
45+
if (!($this instanceof ProductInterface)) {
46+
throw new RuntimeException("Current object is not an instance of ProductInterface");
47+
}
48+
49+
return $this->getData('tax_class_id');
50+
}
51+
52+
#[GraphQLExport]
53+
public function getName() : ?string
54+
{
55+
return $this->getData('title');
56+
}
57+
}

app/site/controllers/Admin/Commerce/Books.php

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,12 +90,15 @@ public function getFormDefinition(FAPI\Form $form, array &$form_state): FAPI\For
9090
case 'new':
9191

9292
$product_title = $product_content = '';
93-
$product_price = $product_weight = 0.0;
93+
$product_price = $product_weight = $product_length =$product_width = $product_height = 0.0;
9494
if ($product->isLoaded()) {
9595
$product_title = $product->title;
9696
$product_content = $product->content;
9797
$product_price = $product->price;
9898
$product_weight = $product->weight;
99+
$product_length = $product->length;
100+
$product_width = $product->width;
101+
$product_height = $product->height;
99102
}
100103

101104
$tax_classes = ['' => '-- Select --'];
@@ -124,6 +127,33 @@ public function getFormDefinition(FAPI\Form $form, array &$form_state): FAPI\For
124127
'step' => '0.01',
125128
'description' => 'in Kilograms',
126129
'validate' => ['required'],
130+
])->addField('length', [
131+
'type' => 'number',
132+
'title' => 'Box Length',
133+
'default_value' => $product_length,
134+
'min' => '0.00',
135+
'max' => '1000000.00',
136+
'step' => '0.01',
137+
'description' => 'in cm',
138+
'validate' => ['required'],
139+
])->addField('width', [
140+
'type' => 'number',
141+
'title' => 'Box Width',
142+
'default_value' => $product_width,
143+
'min' => '0.00',
144+
'max' => '1000000.00',
145+
'step' => '0.01',
146+
'description' => 'in cm',
147+
'validate' => ['required'],
148+
])->addField('height', [
149+
'type' => 'number',
150+
'title' => 'Box Height',
151+
'default_value' => $product_height,
152+
'min' => '0.00',
153+
'max' => '1000000.00',
154+
'step' => '0.01',
155+
'description' => 'in cm',
156+
'validate' => ['required'],
127157
])->addField('price', [
128158
'type' => 'number',
129159
'title' => 'Price',
@@ -201,6 +231,9 @@ public function formSubmitted(FAPI\Form $form, &$form_state): mixed
201231
$product->setContent($values['content']);
202232
$product->setWebsiteId($values['frontend']['website_id']);
203233
$product->setWeight((float)$values['weight']);
234+
$product->setHeight((float)$values['height']);
235+
$product->setLength((float)$values['length']);
236+
$product->setWidth((float)$values['width']);
204237
$product->setPrice((float)$values['price']);
205238
$product->setTaxClassId($values['tax_class_id']);
206239

app/site/migrations/CreateBookTableMigration.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
namespace App\Site\Migrations;
44

55
use App\Base\Abstracts\Migrations\DBMigration;
6-
use Psr\Container\ContainerInterface;
76
use Degami\SqlSchema\Index;
87
use Degami\SqlSchema\Table;
98

@@ -32,7 +31,10 @@ public function addDBTableDefinition(Table $table): Table
3231
->addColumn('meta_description', 'VARCHAR', [1024], [], true, null)
3332
->addColumn('html_title', 'VARCHAR', [1024], [], true, null)
3433
->addColumn('weight', 'FLOAT', null, [], true, null)
35-
->addColumn('created_at', 'TIMESTAMP', null, [], false, 'CURRENT_TIMESTAMP()')
34+
->addColumn('length', 'FLOAT', null, [], true, null)
35+
->addColumn('width', 'FLOAT', null, [], true, null)
36+
->addColumn('height', 'FLOAT', null, [], true, null)
37+
->addColumn('created_at', 'TIMESTAMP', null, [], false, 'CURRENT_TIMESTAMP()')
3638
->addColumn('updated_at', 'TIMESTAMP', null, [], false, 'CURRENT_TIMESTAMP()')
3739
->addIndex(null, 'id', Index::TYPE_PRIMARY)
3840
->addForeignKey('fk_book_website_id', ['website_id'], 'website', ['id'])

0 commit comments

Comments
 (0)