template fixes + bug fixes + style fixes

This commit is contained in:
Dennis Eichhorn 2024-04-02 21:40:48 +00:00
parent a28508a26f
commit a5856ce588
9 changed files with 444 additions and 6 deletions

View File

@ -34,7 +34,7 @@
"type": 3,
"subtype": 1,
"name": "Create",
"uri": "{/base}/warehouse/stocktaking/list?{?}",
"uri": "{/base}/warehouse/stocktaking/create?{?}",
"target": "self",
"icon": null,
"order": 1,

139
Admin/Install/db.json Normal file
View File

@ -0,0 +1,139 @@
{
"stocktaking": {
"name": "stocktaking",
"fields": {
"stocktaking_id": {
"name": "stocktaking_id",
"type": "INT",
"null": false,
"primary": true,
"autoincrement": true
},
"stocktaking_unit": {
"name": "stocktaking_unit",
"type": "INT",
"null": true,
"default": null,
"foreignTable": "organization_unit",
"foreignKey": "organization_unit_id"
},
"stocktaking_created_at": {
"name": "stocktaking_created_at",
"type": "DATETIME",
"null": false
}
}
},
"stocktaking_distribution": {
"name": "stocktaking_distribution",
"fields": {
"stocktaking_distribution_id": {
"name": "stocktaking_distribution_id",
"type": "INT",
"null": false,
"primary": true,
"autoincrement": true
},
"stocktaking_distribution_distribution": {
"name": "stocktaking_distribution_distribution",
"type": "INT",
"null": true,
"default": null,
"foreignTable": "warehousemgmt_stock_distribution",
"foreignKey": "warehousemgmt_stock_distribution_id"
},
"stocktaking_distribution_stocktaking": {
"name": "stocktaking_distribution_stocktaking",
"type": "INT",
"null": true,
"default": null,
"foreignTable": "stocktaking",
"foreignKey": "stocktaking_id"
}
}
},
"stocktaking_stock": {
"name": "stocktaking_stock",
"fields": {
"stocktaking_stock_id": {
"name": "stocktaking_stock_id",
"type": "INT",
"null": false,
"primary": true,
"autoincrement": true
},
"stocktaking_stock_stock": {
"name": "stocktaking_stock_stock",
"type": "INT",
"null": true,
"default": null,
"foreignTable": "warehousemgmt_stock",
"foreignKey": "warehousemgmt_stock_id"
},
"stocktaking_stock_stocktaking": {
"name": "stocktaking_stock_stocktaking",
"type": "INT",
"null": true,
"default": null,
"foreignTable": "stocktaking",
"foreignKey": "stocktaking_id"
}
}
},
"stocktaking_type": {
"name": "stocktaking_type",
"fields": {
"stocktaking_type_id": {
"name": "stocktaking_type_id",
"type": "INT",
"null": false,
"primary": true,
"autoincrement": true
},
"stocktaking_type_type": {
"name": "stocktaking_type_type",
"type": "INT",
"null": true,
"default": null,
"foreignTable": "warehousemgmt_stock_type",
"foreignKey": "warehousemgmt_stock_type_id"
},
"stocktaking_type_stocktaking": {
"name": "stocktaking_type_stocktaking",
"type": "INT",
"null": true,
"default": null,
"foreignTable": "stocktaking",
"foreignKey": "stocktaking_id"
}
}
},
"stocktaking_item": {
"name": "stocktaking_item",
"fields": {
"stocktaking_item_id": {
"name": "stocktaking_item_id",
"type": "INT",
"null": false,
"primary": true,
"autoincrement": true
},
"stocktaking_item_item": {
"name": "stocktaking_item_item",
"type": "INT",
"null": true,
"default": null,
"foreignTable": "itemmgmt_item",
"foreignKey": "itemmgmt_item_id"
},
"stocktaking_item_stocktaking": {
"name": "stocktaking_item_stocktaking",
"type": "INT",
"null": true,
"default": null,
"foreignTable": "stocktaking",
"foreignKey": "stocktaking_id"
}
}
}
}

View File

@ -14,6 +14,18 @@ declare(strict_types=1);
namespace Modules\StockTaking\Controller;
use Modules\StockTaking\Models\StockTaking;
use Modules\StockTaking\Models\StockTakingMapper;
use Modules\WarehouseManagement\Models\NullStock;
use Modules\WarehouseManagement\Models\NullStockType;
use Modules\WarehouseManagement\Models\Stock;
use Modules\WarehouseManagement\Models\StockDistributionMapper;
use Modules\WarehouseManagement\Models\StockMapper;
use Modules\WarehouseManagement\Models\StockType;
use phpOMS\Message\Http\RequestStatusCode;
use phpOMS\Message\RequestAbstract;
use phpOMS\Message\ResponseAbstract;
/**
* Budgeting controller class.
*
@ -24,4 +36,122 @@ namespace Modules\StockTaking\Controller;
*/
final class ApiController extends Controller
{
/**
* Api method to create item payment type
*
* @param RequestAbstract $request Request
* @param ResponseAbstract $response Response
* @param array $data Generic data
*
* @return void
*
* @api
*
* @since 1.0.0
*/
public function apiStockTakingCreate(RequestAbstract $request, ResponseAbstract $response, array $data = []) : void
{
if (!empty($val = $this->validateStockTakingCreate($request))) {
$response->header->status = RequestStatusCode::R_400;
$this->createInvalidCreateResponse($request, $response, $val);
return;
}
$paymentTerm = $this->createStockTakingFromRequest($request);
$this->createModel($request->header->account, $paymentTerm, StockTakingMapper::class, 'stocktaking', $request->getOrigin());
$this->createStandardCreateResponse($request, $response, $paymentTerm);
}
/**
* Validate payment create request
*
* @param RequestAbstract $request Request
*
* @return array<string, bool>
*
* @since 1.0.0
*/
private function validateStockTakingCreate(RequestAbstract $request) : array
{
$val = [];
if (($val['unit'] = !$request->hasData('unit'))) {
return $val;
}
return [];
}
/**
* Method to create payment from request.
*
* @param RequestAbstract $request Request
*
* @return StockTaking
*
* @since 1.0.0
* @todo Implement a function which allows us to add stocks/locations/items to an existing stock taking (admin)
* @todo Implement a function which allows us to add items to a stock taking (user)
*/
private function createStockTakingFromRequest(RequestAbstract $request) : StockTaking
{
// @todo We started to find item->stock associations by using stock distributions
// In the future we MUST change this and create a separate table for item->stock->location->sodium_crypto_aead_chacha20poly1305_ietf_decrypt
// association.
// It is a little bit unfortunate that we cannot use attributes but it is what it is.
// Get distributions based on type and stock filter
$stockTypeList = $request->getDataList('types') ?? [];
$stockList = $request->getDataList('stocks') ?? [];
$stocks = [];
$stockMapper = StockMapper::getAll()
->with('locations')
->with('locations/type')
->where('unit', (int) $request->getData('unit'));
if (!empty($stockTypeList)) {
$stockMapper->where('locations/type', $stockTypeList);
}
if (!empty($stockList)) {
$stockMapper->where('id', $stockList);
}
foreach ($stocks as $idx => $stock) {
if (empty($stock->locations)) {
unset($stocks[$idx]);
}
if (empty($stockTypeList)) {
foreach ($stock->locations as $location) {
$stockTypeList[] = $location->type->id;
}
}
if (empty($stockList)) {
$stockList[] = $stock->id;
}
}
$stocktaking = new StockTaking();
$stocktaking->unit = (int) $request->getData('unit');
$stocktaking->stocks = \array_map(function (int $id) : Stock {
return new NullStock($id);
}, $stockList);
$stocktaking->types = \array_map(function (int $id) : StockType {
return new NullStockType($id);
}, $stockTypeList);
// @todo In the future create create a snapshot of distributions and reference those
// This would also allow us to continue creating bills while doing the stocktaking?
$stocktaking->distributions = StockDistributionMapper::getAll()
->where('stock', $stockList)
->where('stockType', $stockTypeList)
->executeGetArray();
return $stocktaking;
}
}

View File

@ -0,0 +1,47 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package Modules\StockTaking\Models
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace Modules\StockTaking\Models;
/**
* Null model
*
* @package Modules\StockTaking\Models
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
final class NullStockTaking extends StockTaking
{
/**
* Constructor
*
* @param int $id Model id
*
* @since 1.0.0
*/
public function __construct(int $id = 0)
{
$this->id = $id;
parent::__construct();
}
/**
* {@inheritdoc}
*/
public function jsonSerialize() : mixed
{
return ['id' => $this->id];
}
}

45
Models/StockTaking.php Normal file
View File

@ -0,0 +1,45 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package Modules\StockTaking\Models
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace Modules\StockTaking\Models;
/**
* Stock taking
*
* @package Modules\StockTaking\Models
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*/
final class StockTaking
{
public int $id = 0;
public \DateTimeImmutable $createdAt;
public array $stocks = [];
public array $types = [];
public array $items = [];
public array $distributions = [];
public int $unit = 0;
public function __construct()
{
$this->createdAt = new \DateTimeImmutable();
}
}

View File

@ -0,0 +1,75 @@
<?php
/**
* Jingga
*
* PHP Version 8.2
*
* @package Modules\WarehouseManagement\Models
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
namespace Modules\StockTaking\Models;
use Modules\WarehouseManagement\Models\StockDistributionMapper;
use phpOMS\DataStorage\Database\Mapper\DataMapperFactory;
/**
* StockTaking mapper class.
*
* @package Modules\StockTaking\Models
* @license OMS License 2.0
* @link https://jingga.app
* @since 1.0.0
*
* @template T of Stock
* @extends DataMapperFactory<T>
*/
final class StockTakingMapper extends DataMapperFactory
{
/**
* Columns.
*
* @var array<string, array{name:string, type:string, internal:string, autocomplete?:bool, readonly?:bool, writeonly?:bool, annotations?:array}>
* @since 1.0.0
*/
public const COLUMNS = [
'stocktaking_id' => ['name' => 'stocktaking_id', 'type' => 'int', 'internal' => 'id'],
'stocktaking_unit' => ['name' => 'stocktaking_unit', 'type' => 'int', 'internal' => 'unit'],
'stocktaking_created_at' => ['name' => 'stocktaking_created_at', 'type' => 'DateTimeImmutable', 'internal' => 'createdAt'],
];
/**
* Has many relation.
*
* @var array<string, array{mapper:class-string, table:string, self?:?string, external?:?string, column?:string}>
* @since 1.0.0
*/
public const HAS_MANY = [
'distributions' => [
'mapper' => StockDistributionMapper::class,
'table' => 'stocktaking_distribution',
'self' => 'stocktaking_distribution_stocktaking',
'external' => null,
],
];
/**
* Primary table.
*
* @var string
* @since 1.0.0
*/
public const TABLE = 'stocktaking';
/**
* Primary field name.
*
* @var string
* @since 1.0.0
*/
public const PRIMARYFIELD = 'stocktaking_id';
}

View File

@ -14,6 +14,6 @@ declare(strict_types=1);
return ['StockTaking' => [
'Stocktaking' => 'Inventur',
'Date' => 'Datum',
'Status' => 'Status',
'Date' => 'Datum',
'Status' => 'Status',
]];

View File

@ -14,6 +14,6 @@ declare(strict_types=1);
return ['StockTaking' => [
'Stocktaking' => 'Stock Taking',
'Date' => 'Date',
'Status' => 'Status',
'Date' => 'Date',
'Status' => 'Status',
]];

View File

@ -17,7 +17,9 @@
"description": "Stock Taking module.",
"directory": "StockTaking",
"dependencies": {
"Controlling": "*"
"Controlling": "*",
"ItemManagement": "*",
"WarehouseManagement": "*"
},
"providing": {
"Navigation": "*"