Skip to content

Commit 9fc5427

Browse files
stock management
1 parent 4672cd4 commit 9fc5427

File tree

22 files changed

+722
-22
lines changed

22 files changed

+722
-22
lines changed

app/base/abstracts/Controllers/AdminManageModelsPage.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -503,7 +503,8 @@ public function addVersionsButton(?BaseModel $object = null)
503503

504504
$this->addActionLink(
505505
static::VERSIONS_BTN,
506-
static::VERSIONS_BTN, '☰ ' . $this->getUtils()->translate('Versions', locale: $this->getCurrentLocale()),
506+
static::VERSIONS_BTN,
507+
$this->getHtmlRenderer()->getIcon('git-branch') . ' ' . $this->getUtils()->translate('Versions', locale: $this->getCurrentLocale()),
507508
$this->getUrl('crud.app.base.controllers.admin.json.versions', ['class' => base64_encode(get_class($object)), 'key' => base64_encode($primaryKey) ]),
508509
'btn btn-sm btn-light inToolSidePanel',
509510
['data-panelWidth' => '80%']

app/base/abstracts/Controllers/AdminManageProductsPage.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -120,14 +120,14 @@ protected function collectActionButtons() : self
120120

121121
if (($this->template_data['action'] ?? 'list') == 'edit') {
122122
$product = $this->getObject();
123-
if (false && $product instanceof ProductInterface) {
123+
if ($product instanceof ProductInterface) {
124124
// Add Manage Stock button for physical products
125125
if ($product->isPhysical()) {
126126
$this->addActionLink(
127127
'stock-btn',
128128
'stock-btn',
129-
$this->getUtils()->translate('Manage Stock', locale: $this->getCurrentLocale()),
130-
'#',
129+
$this->getHtmlRenderer()->getIcon('layers') . ' ' .$this->getUtils()->translate('Manage Stock', locale: $this->getCurrentLocale()),
130+
$this->getUrl('crud.app.base.controllers.admin.json.productstocks', ['product_details' => base64_encode(json_encode(['product_class' => $this->getObjectClass(),'product_id' => $product->getId()]))]) . '?product_id=' . $this->getRequest()->query->get('product_id') . '&action=',
131131
'btn btn-sm btn-light inToolSidePanel',
132132
['data-panelWidth' => '80%']
133133
);
Lines changed: 304 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,304 @@
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\Controllers\Admin\Commerce;
15+
16+
use App\App;
17+
use Degami\Basics\Exceptions\BasicException;
18+
use DI\DependencyException;
19+
use DI\NotFoundException;
20+
use Exception;
21+
use App\Base\Abstracts\Controllers\AdminManageFrontendModelsPage;
22+
use Degami\PHPFormsApi as FAPI;
23+
use App\Base\Models\ProductStock;
24+
use Phpfastcache\Exceptions\PhpfastcacheSimpleCacheException;
25+
use Symfony\Component\HttpFoundation\Response;
26+
use App\Base\Abstracts\Controllers\BasePage;
27+
use HaydenPierce\ClassFinder\ClassFinder;
28+
29+
/**
30+
* "Product Stocks" Admin Page
31+
*/
32+
class ProductStocks extends AdminManageFrontendModelsPage
33+
{
34+
/**
35+
* @var string page title
36+
*/
37+
protected ?string $page_title = 'Product Stocks';
38+
39+
/**
40+
* {@inheritdoc}
41+
*
42+
* @return string
43+
*/
44+
public function getTemplateName(): string
45+
{
46+
return 'base_admin_page';
47+
}
48+
49+
/**
50+
* {@inheritdoc}
51+
*
52+
* @return string
53+
*/
54+
public static function getAccessPermission(): string
55+
{
56+
return 'administer_orders';
57+
}
58+
59+
/**
60+
* {@inheritdoc}
61+
*
62+
* @return string
63+
*/
64+
public static function getObjectClass(): string
65+
{
66+
return ProductStock::class;
67+
}
68+
69+
/**
70+
* {@inheritdoc}
71+
*
72+
* @return string
73+
*/
74+
protected function getObjectIdQueryParam(): string
75+
{
76+
return 'stock_id';
77+
}
78+
79+
/**
80+
* {@inheritdoc}
81+
*
82+
* @return array|null
83+
*/
84+
public static function getAdminPageLink() : array|null
85+
{
86+
return [
87+
'permission_name' => static::getAccessPermission(),
88+
'route_name' => static::getPageRouteName(),
89+
'icon' => 'layers',
90+
'text' => 'Product Stocks',
91+
'section' => 'commerce',
92+
'order' => 30,
93+
];
94+
}
95+
96+
/**
97+
* {@inheritdoc}
98+
*
99+
* @param FAPI\Form $form
100+
* @param array &$form_state
101+
* @return FAPI\Form
102+
* @throws BasicException
103+
* @throws DependencyException
104+
* @throws NotFoundException
105+
* @throws PhpfastcacheSimpleCacheException
106+
*/
107+
public function getFormDefinition(FAPI\Form $form, array &$form_state): FAPI\Form
108+
{
109+
$type = $this->getRequest()->query->get('action') ?? 'list';
110+
111+
/**
112+
* @var ProductStock $productStock
113+
*/
114+
$productStock = $this->getObject();
115+
116+
$form->addField('action', [
117+
'type' => 'value',
118+
'value' => $type,
119+
]);
120+
121+
$websites = $this->getUtils()->getWebsitesSelectOptions();
122+
123+
$physicalProductClasses = array_filter(array_merge(
124+
ClassFinder::getClassesInNamespace(App::MODELS_NAMESPACE, ClassFinder::RECURSIVE_MODE),
125+
ClassFinder::getClassesInNamespace(App::BASE_MODELS_NAMESPACE, ClassFinder::RECURSIVE_MODE)
126+
), function ($className) {
127+
return is_subclass_of($className, \App\Base\Interfaces\Model\PhysicalProductInterface::class);
128+
});
129+
130+
switch ($type) {
131+
case 'edit':
132+
case 'new':
133+
134+
$form->addField('website_id', [
135+
'type' => 'select',
136+
'title' => 'Website',
137+
'options' => $websites,
138+
'required' => true,
139+
'default_value' => $productStock->getWebsiteId(),
140+
]);
141+
142+
$classesOptions = [];
143+
foreach ($physicalProductClasses as $class) {
144+
$classesOptions[$class] = $this->getUtils()->getClassBasename($class);
145+
}
146+
147+
$form->addField('product_class', [
148+
'type' => 'select',
149+
'title' => 'Product Class',
150+
'options' => $classesOptions,
151+
'required' => true,
152+
'default_value' => $productStock->getProductClass(),
153+
]);
154+
155+
$form->addField('product_id', [
156+
'type' => 'textfield',
157+
'title' => 'Product ID',
158+
'required' => true,
159+
'default_value' => $productStock->getProductId(),
160+
]);
161+
162+
$form->addField('quantity', [
163+
'type' => 'number',
164+
'title' => 'Quantity',
165+
'required' => true,
166+
'default_value' => $productStock->getQuantity(),
167+
]);
168+
169+
$this->addSubmitButton($form);
170+
171+
break;
172+
173+
case 'delete':
174+
$this->fillConfirmationForm('Do you confirm the deletion of the selected element?', $form);
175+
break;
176+
}
177+
178+
return $form;
179+
}
180+
181+
/**
182+
* {@inheritdoc}
183+
*
184+
* @param FAPI\Form $form
185+
* @param array &$form_state
186+
* @return bool|string
187+
*/
188+
public function formValidate(FAPI\Form $form, &$form_state): bool|string
189+
{
190+
//$values = $form->values();
191+
// @todo : check if page language is in page website languages?
192+
return true;
193+
}
194+
195+
/**
196+
* {@inheritdoc}
197+
*
198+
* @param FAPI\Form $form
199+
* @param array &$form_state
200+
* @return mixed
201+
* @throws BasicException
202+
* @throws DependencyException
203+
* @throws NotFoundException
204+
*/
205+
public function formSubmitted(FAPI\Form $form, &$form_state): mixed
206+
{
207+
/**
208+
* @var ProductStock $productStock
209+
*/
210+
$productStock = $this->getObject();
211+
212+
$values = $form->values();
213+
214+
switch ($values['action']) {
215+
case 'new':
216+
217+
// intentional fall trough
218+
// no break
219+
case 'edit':
220+
221+
$this->setAdminActionLogData($productStock->getChangedData());
222+
223+
$productStock
224+
->setUserId($this->getCurrentUser()?->getId())
225+
->setProductClass($values['product_class'])
226+
->setProductId($values['product_id'])
227+
->setQuantity($values['quantity'])
228+
->setWebsiteId($values['website_id']);
229+
230+
$productStock->persist();
231+
232+
$this->addSuccessFlashMessage($this->getUtils()->translate("Product stock Saved."));
233+
break;
234+
case 'delete':
235+
$productStock->delete();
236+
237+
$this->setAdminActionLogData('Deleted product stock ' . $productStock->getId());
238+
239+
$this->addInfoFlashMessage($this->getUtils()->translate("Product stock Deleted."));
240+
241+
break;
242+
}
243+
return $this->refreshPage();
244+
}
245+
246+
/**
247+
* {@inheritdoc}
248+
*
249+
* @return array
250+
*/
251+
protected function getTableHeader(): ?array
252+
{
253+
return [
254+
'ID' => 'id',
255+
'Website' => ['order' => 'website_id', 'foreign' => 'website_id', 'table' => $this->getModelTableName(), 'view' => 'site_name'],
256+
'Product Class' => ['order' => 'product_class', 'search' => 'product_class'],
257+
'Product Id' => ['order' => 'product_id'],
258+
'Quantity' => ['order' => 'quantity', 'search' => 'quantity'],
259+
'actions' => null,
260+
];
261+
}
262+
263+
/**
264+
* {@inheritdoc}
265+
*
266+
* @param array $data
267+
* @param array $options
268+
* @return array
269+
* @throws BasicException
270+
* @throws Exception
271+
*/
272+
protected function getTableElements(array $data, array $options = []): array
273+
{
274+
return array_map(
275+
function ($productStock) {
276+
return [
277+
'ID' => $productStock->id,
278+
'Website' => $productStock->getWebsiteId() == null ? 'All websites' : $productStock->getWebsite()->domain,
279+
'Product Class' => $productStock->getProductClass(),
280+
'Product Id' => $productStock->getProductId(),
281+
'Quantity' => $productStock->getQuantity(),
282+
'actions' => [
283+
static::EDIT_BTN => $this->getEditButton($productStock->id),
284+
static::DELETE_BTN => $this->getDeleteButton($productStock->id),
285+
],
286+
];
287+
},
288+
$data
289+
);
290+
}
291+
292+
protected function beforeRender(): BasePage|Response
293+
{
294+
if (App::getInstance()->getEnvironment()->getVariable('ENABLE_COMMERCE', false) == false) {
295+
$this->addWarningFlashMessage($this->getUtils()->translate("Commerce functionallity is currently disabled"), true);
296+
}
297+
return parent::beforeRender();
298+
}
299+
300+
public static function exposeDataToDashboard() : mixed
301+
{
302+
return null;
303+
}
304+
}

0 commit comments

Comments
 (0)