code fixes

This commit is contained in:
Dennis Eichhorn 2024-03-15 20:24:39 +00:00
parent 77b345864f
commit a87884f3a9
32 changed files with 340 additions and 312 deletions

View File

@ -57,5 +57,5 @@ return [
'state' => PermissionCategory::ORDER, 'state' => PermissionCategory::ORDER,
], ],
], ],
] ],
]; ];

View File

@ -61,8 +61,8 @@ final class ApiController extends Controller
return; return;
} }
$supplier = $request->getDataString('supplier'); $supplier = $request->getDataString('supplier');
$productGroup = $request->getDataInt('product_group'); $productGroup = $request->getDataInt('product_group');
$showIrrelevant = !($request->getDataBool('hide_irrelevant') ?? true); $showIrrelevant = !($request->getDataBool('hide_irrelevant') ?? true);
try { try {
@ -84,6 +84,17 @@ final class ApiController extends Controller
$this->createStandardBackgroundResponse($request, $response, []); $this->createStandardBackgroundResponse($request, $response, []);
} }
/**
* Returns data from an order suggestion element.
*
* This also re-calculates a lot of values because some depend on the current stock amounts, prices etc.
*
* @param OrderSuggestionElement[] $elements Elements of our order
*
* @return array<int, array{singlePrice:FloatInt, totalPrice:FloatInt, stock:FloatInt, reserved:FloatInt, ordered:FloatInt, minquantity:FloatInt, minstock:FloatInt, quantitystep:FloatInt, avgsales:FloatInt, range_stock:float, range_reserved:float, range_ordered:float}>
*
* @since 1.0.0
*/
public function getOrderSuggestionElementData(array $elements) : array public function getOrderSuggestionElementData(array $elements) : array
{ {
if (empty($elements)) { if (empty($elements)) {
@ -102,16 +113,16 @@ final class ApiController extends Controller
$end = SmartDateTime::endOfMonth(); $end = SmartDateTime::endOfMonth();
$end->smartModify(0, -1); $end->smartModify(0, -1);
$salesHistory = SalesBillMapper::getItemMonthlySalesQuantity($itemIds, $start, $end); $salesHistory = SalesBillMapper::getItemMonthlySalesQuantity($itemIds, $start, $end);
$distributions = \Modules\WarehouseManagement\Models\StockMapper::getStockDistribution($itemIds); $distributions = \Modules\WarehouseManagement\Models\StockMapper::getStockDistribution($itemIds);
$historyStart = (int) $start->format('m'); $historyStart = (int) $start->format('m');
$historyEnd = (int) $end->format('m'); $historyEnd = (int) $end->format('m');
// @todo A lot of the code below is mirrored in the CliController for ALL items. // @todo A lot of the code below is mirrored in the CliController for ALL items.
// Pull out some of the code so we only need to maintain one version // Pull out some of the code so we only need to maintain one version
foreach ($elements as $element) { foreach ($elements as $element) {
$maxHistoryDuration = $element->item->getAttribute('order_suggestion_history_duration')->value->getValue() ?? 12; $maxHistoryDuration = $element->item->getAttribute('order_suggestion_history_duration')->value->valueInt ?? 12;
$salesForecast = []; $salesForecast = [];
@ -161,7 +172,7 @@ final class ApiController extends Controller
// Calculate current range using historic sales + other current stats // Calculate current range using historic sales + other current stats
$totalHistoricSales = \array_sum($salesForecast); $totalHistoricSales = \array_sum($salesForecast);
$avgMonthlySales = (int) \round($totalHistoricSales / $actualHistoricDuration); $avgMonthlySales = (int) \round($totalHistoricSales / $actualHistoricDuration);
$totalStockQuantity = 0; $totalStockQuantity = 0;
foreach ($distributions['dists'][$element->item->id] ?? [] as $dist) { foreach ($distributions['dists'][$element->item->id] ?? [] as $dist) {
@ -169,7 +180,7 @@ final class ApiController extends Controller
} }
$totalReservedQuantity = $distributions['reserved'][$element->item->id] ?? 0; $totalReservedQuantity = $distributions['reserved'][$element->item->id] ?? 0;
$totalOrderedQuantity = $distributions['ordered'][$element->item->id] ?? 0; $totalOrderedQuantity = $distributions['ordered'][$element->item->id] ?? 0;
$currentRangeStock = $avgMonthlySales == 0 ? \PHP_INT_MAX : ($totalStockQuantity + $totalOrderedQuantity) / $avgMonthlySales; $currentRangeStock = $avgMonthlySales == 0 ? \PHP_INT_MAX : ($totalStockQuantity + $totalOrderedQuantity) / $avgMonthlySales;
$currentRangeReserved = $avgMonthlySales == 0 ? \PHP_INT_MAX : ($totalStockQuantity + $totalOrderedQuantity - $totalReservedQuantity) / $avgMonthlySales; $currentRangeReserved = $avgMonthlySales == 0 ? \PHP_INT_MAX : ($totalStockQuantity + $totalOrderedQuantity - $totalReservedQuantity) / $avgMonthlySales;
@ -179,19 +190,19 @@ final class ApiController extends Controller
// -> see SD HTS (depending on other shipments -> not delivered even if available) // -> see SD HTS (depending on other shipments -> not delivered even if available)
// -> maybe it's possible to consider the expected delivery time? // -> maybe it's possible to consider the expected delivery time?
$minimumStockQuantity = $element->item->getAttribute('minimum_stock_quantity')->value->getValue() ?? 0; $minimumStockQuantity = $element->item->getAttribute('minimum_stock_quantity')->value->valueInt ?? 0;
$minimumStockQuantity = (int) \round($minimumStockQuantity * 1000); $minimumStockQuantity = (int) \round($minimumStockQuantity * FloatInt::DIVISOR); // @bug why? shouldn't the value already be 10,000?
$minimumStockRange = $avgMonthlySales === 0 ? 0 : $minimumStockQuantity / $avgMonthlySales; $minimumStockRange = $avgMonthlySales === 0 ? 0 : $minimumStockQuantity / $avgMonthlySales;
$minimumStockQuantity = (int) \round($minimumStockRange * $avgMonthlySales); $minimumStockQuantity = (int) \round($minimumStockRange * $avgMonthlySales);
$minimumOrderQuantity = $element->item->getAttribute('minimum_order_quantity')->value->getValue() ?? 0; $minimumOrderQuantity = $element->item->getAttribute('minimum_order_quantity')->value->valueInt ?? 0;
$minimumOrderQuantity = (int) \round($minimumOrderQuantity * FloatInt::DIVISOR); $minimumOrderQuantity = (int) \round($minimumOrderQuantity * FloatInt::DIVISOR);
$orderQuantityStep = $element->item->getAttribute('order_quantity_steps')->value->getValue() ?? 1; $orderQuantityStep = $element->item->getAttribute('order_quantity_steps')->value->valueInt ?? 1;
$orderQuantityStep = (int) \round($orderQuantityStep * FloatInt::DIVISOR); $orderQuantityStep = (int) \round($orderQuantityStep * FloatInt::DIVISOR);
$orderQuantity = $element->quantity->value; $orderQuantity = $element->quantity->value;
$orderRange = $avgMonthlySales === 0 ? \PHP_INT_MAX : $element->quantity->value / $avgMonthlySales; $orderRange = $avgMonthlySales === 0 ? \PHP_INT_MAX : $element->quantity->value / $avgMonthlySales;
$internalRequest = new HttpRequest(); $internalRequest = new HttpRequest();
$internalRequest->setData('price_quantity', $orderQuantity); $internalRequest->setData('price_quantity', $orderQuantity);
@ -201,18 +212,18 @@ final class ApiController extends Controller
// @question Consider to add gross price // @question Consider to add gross price
$data[$element->item->id] = [ $data[$element->item->id] = [
'singlePrice' => $price['bestActualPrice'], 'singlePrice' => $price['bestActualPrice'],
'totalPrice' => new FloatInt((int) ($price['bestActualPrice']->value * $orderQuantity / FloatInt::DIVISOR)), 'totalPrice' => new FloatInt((int) ($price['bestActualPrice']->value * $orderQuantity / FloatInt::DIVISOR)),
'stock' => new FloatInt($totalStockQuantity), 'stock' => new FloatInt($totalStockQuantity),
'reserved' => new FloatInt($totalReservedQuantity), 'reserved' => new FloatInt($totalReservedQuantity),
'ordered' => new FloatInt($totalOrderedQuantity), 'ordered' => new FloatInt($totalOrderedQuantity),
'minquantity' => new FloatInt($minimumOrderQuantity), 'minquantity' => new FloatInt($minimumOrderQuantity),
'minstock' => new FloatInt($minimumStockQuantity), 'minstock' => new FloatInt($minimumStockQuantity),
'quantitystep' => new FloatInt($orderQuantityStep), 'quantitystep' => new FloatInt($orderQuantityStep),
'avgsales' => new FloatInt($avgMonthlySales), 'avgsales' => new FloatInt($avgMonthlySales),
'range_stock' => $currentRangeStock, // range only considering stock + ordered 'range_stock' => $currentRangeStock, // range only considering stock + ordered
'range_reserved' => $currentRangeReserved, // range considering stock - reserved + ordered 'range_reserved' => $currentRangeReserved, // range considering stock - reserved + ordered
'range_ordered' => $orderRange, // range ADDED with suggested new order quantity 'range_ordered' => $orderRange, // range ADDED with suggested new order quantity
]; ];
} }
@ -274,7 +285,7 @@ final class ApiController extends Controller
return; return;
} }
$elements = $request->getDataJson('element'); $elements = $request->getDataJson('element');
$quantities = $request->getDataJson('quantity'); $quantities = $request->getDataJson('quantity');
// Missmatch -> data corrupted // Missmatch -> data corrupted
@ -286,7 +297,7 @@ final class ApiController extends Controller
} }
foreach ($elements as $idx => $e) { foreach ($elements as $idx => $e) {
$e = (int) $e; $e = (int) $e;
$temp = new FloatInt($quantities[$idx]); $temp = new FloatInt($quantities[$idx]);
foreach ($old->elements as $element) { foreach ($old->elements as $element) {
@ -306,7 +317,7 @@ final class ApiController extends Controller
$internalRequest->setData('price_quantity', $new->quantity->value); $internalRequest->setData('price_quantity', $new->quantity->value);
$internalRequest->setData('price_type', PriceType::PURCHASE); $internalRequest->setData('price_type', PriceType::PURCHASE);
$price = $this->app->moduleManager->get('Billing', 'ApiPrice')->findBestPrice($internalRequest, $element->item); $price = $this->app->moduleManager->get('Billing', 'ApiPrice')->findBestPrice($internalRequest, $element->item);
$new->costs = new FloatInt((int) ($price['bestActualPrice']->value * $new->quantity->value / FloatInt::DIVISOR)); $new->costs = new FloatInt((int) ($price['bestActualPrice']->value * $new->quantity->value / FloatInt::DIVISOR));
$this->updateModel($request->header->account, $element, $new, OrderSuggestionElementMapper::class, 'order_suggestion_element', $request->getOrigin()); $this->updateModel($request->header->account, $element, $new, OrderSuggestionElementMapper::class, 'order_suggestion_element', $request->getOrigin());

View File

@ -84,12 +84,21 @@ final class CliController extends Controller
return $view; return $view;
} }
/**
* Create a suggestion
*
* @param RequestAbstract $request Request
*
* @return OrderSuggestion
*
* @since 1.0.0
*/
public function createSuggestionFromRequest(RequestAbstract $request) : OrderSuggestion public function createSuggestionFromRequest(RequestAbstract $request) : OrderSuggestion
{ {
$showIrrelevant = $request->getDataBool('-irrelevant') ?? false; $showIrrelevant = $request->getDataBool('-irrelevant') ?? false;
$now = new \DateTime('now'); $now = new \DateTime('now');
$suggestion = new OrderSuggestion(); $suggestion = new OrderSuggestion();
$suggestion->createdBy = new NullAccount($request->getDataInt('-user') ?? 1); $suggestion->createdBy = new NullAccount($request->getDataInt('-user') ?? 1);
// @todo define order details per item+stock // @todo define order details per item+stock
@ -99,6 +108,7 @@ final class CliController extends Controller
// @question Consider to save suggestion as model in db // @question Consider to save suggestion as model in db
// This would allow users to work on it for a longer time // This would allow users to work on it for a longer time
// It would also allow for an easier approval process // It would also allow for an easier approval process
/** @var \Modules\ItemManagement\Models\Item[] $items */
$items = ItemMapper::getAll() $items = ItemMapper::getAll()
->with('container') ->with('container')
->with('l11n') ->with('l11n')
@ -140,7 +150,7 @@ final class CliController extends Controller
$end = SmartDateTime::endOfMonth(); $end = SmartDateTime::endOfMonth();
$end->smartModify(0, -1); $end->smartModify(0, -1);
$salesHistory = SalesBillMapper::getItemMonthlySalesQuantity($itemIds, $start, $end); $salesHistory = SalesBillMapper::getItemMonthlySalesQuantity($itemIds, $start, $end);
$distributions = \Modules\WarehouseManagement\Models\StockMapper::getStockDistribution($itemIds); $distributions = \Modules\WarehouseManagement\Models\StockMapper::getStockDistribution($itemIds);
$unitAttribute = UnitAttributeMapper::get() $unitAttribute = UnitAttributeMapper::get()
@ -150,13 +160,13 @@ final class CliController extends Controller
->where('type/name', 'business_year_start') ->where('type/name', 'business_year_start')
->execute(); ->execute();
$businessStart = $unitAttribute->id === 0 ? 1 : $unitAttribute->value->getValue(); $businessStart = $unitAttribute->id === 0 ? 1 : $unitAttribute->value->valueInt;
$historyStart = (int) $start->format('m'); $historyStart = (int) $start->format('m');
$historyEnd = (int) $end->format('m'); $historyEnd = (int) $end->format('m');
foreach ($items as $item) { foreach ($items as $item) {
$maxHistoryDuration = $item->getAttribute('order_suggestion_history_duration')->value->getValue() ?? 12; $maxHistoryDuration = $item->getAttribute('order_suggestion_history_duration')->value->valueInt ?? 12;
$salesForecast = []; $salesForecast = [];
@ -206,7 +216,7 @@ final class CliController extends Controller
// Calculate current range using historic sales + other current stats // Calculate current range using historic sales + other current stats
$totalHistoricSales = \array_sum($salesForecast); $totalHistoricSales = \array_sum($salesForecast);
$avgMonthlySales = (int) \round($totalHistoricSales / $actualHistoricDuration); $avgMonthlySales = (int) \round($totalHistoricSales / $actualHistoricDuration);
$totalStockQuantity = 0; $totalStockQuantity = 0;
foreach ($distributions['dists'][$item->id] ?? [] as $dist) { foreach ($distributions['dists'][$item->id] ?? [] as $dist) {
@ -214,7 +224,7 @@ final class CliController extends Controller
} }
$totalReservedQuantity = $distributions['reserved'][$item->id] ?? 0; $totalReservedQuantity = $distributions['reserved'][$item->id] ?? 0;
$totalOrderedQuantity = $distributions['ordered'][$item->id] ?? 0; $totalOrderedQuantity = $distributions['ordered'][$item->id] ?? 0;
$currentRangeStock = $avgMonthlySales == 0 ? \PHP_INT_MAX : ($totalStockQuantity + $totalOrderedQuantity) / $avgMonthlySales; $currentRangeStock = $avgMonthlySales == 0 ? \PHP_INT_MAX : ($totalStockQuantity + $totalOrderedQuantity) / $avgMonthlySales;
$currentRangeReserved = $avgMonthlySales == 0 ? \PHP_INT_MAX : ($totalStockQuantity + $totalOrderedQuantity - $totalReservedQuantity) / $avgMonthlySales; $currentRangeReserved = $avgMonthlySales == 0 ? \PHP_INT_MAX : ($totalStockQuantity + $totalOrderedQuantity - $totalReservedQuantity) / $avgMonthlySales;
@ -225,30 +235,30 @@ final class CliController extends Controller
// -> maybe it's possible to consider the expected delivery time? // -> maybe it's possible to consider the expected delivery time?
// Get minimum range we want // Get minimum range we want
$wantedStockRange = $item->getAttribute('minimum_stock_range')->value->getValue() ?? 1; $wantedStockRange = $item->getAttribute('minimum_stock_range')->value->valueInt ?? 1;
$minimumStockQuantity = $item->getAttribute('minimum_stock_quantity')->value->getValue() ?? 0; $minimumStockQuantity = $item->getAttribute('minimum_stock_quantity')->value->valueInt ?? 0;
$minimumStockQuantity = (int) \round($minimumStockQuantity * FloatInt::DIVISOR); $minimumStockQuantity = (int) \round($minimumStockQuantity * FloatInt::DIVISOR);
$minimumStockRange = $avgMonthlySales === 0 ? 0 : $minimumStockQuantity / $avgMonthlySales; $minimumStockRange = $avgMonthlySales === 0 ? 0 : $minimumStockQuantity / $avgMonthlySales;
$minimumStockQuantity = (int) \round($minimumStockRange * $avgMonthlySales); $minimumStockQuantity = (int) \round($minimumStockRange * $avgMonthlySales);
$minimumOrderQuantity = $item->getAttribute('minimum_order_quantity')->value->getValue() ?? 0; $minimumOrderQuantity = $item->getAttribute('minimum_order_quantity')->value->valueInt ?? 0;
$minimumOrderQuantity = (int) \round($minimumOrderQuantity * FloatInt::DIVISOR); $minimumOrderQuantity = (int) \round($minimumOrderQuantity * FloatInt::DIVISOR);
$orderQuantityStep = $item->getAttribute('order_quantity_steps')->value->getValue() ?? 1; $orderQuantityStep = $item->getAttribute('order_quantity_steps')->value->valueInt ?? 1;
$orderQuantityStep = (int) \round($orderQuantityStep * FloatInt::DIVISOR); $orderQuantityStep = (int) \round($orderQuantityStep * FloatInt::DIVISOR);
$leadTime = $item->getAttribute('lead_time')->value->getValue() ?? 3; // in days $leadTime = $item->getAttribute('lead_time')->value->valueInt ?? 3; // in days
// @todo Business hours don't have to be 8 hours // @todo Business hours don't have to be 8 hours
// we assume 10 seconds per item if nothing is defined for (invoice handling, stock handling) // we assume 10 seconds per item if nothing is defined for (invoice handling, stock handling)
$adminTime = ($item->getAttribute('admin_time')->value->getValue() ?? 10) / (8 * 60 * 60); // from seconds -> days $adminTime = ($item->getAttribute('admin_time')->value->valueInt ?? 10) / (8 * 60 * 60); // from seconds -> days
// Overhead time in days by estimating at least 1 week worth of order quantity // Overhead time in days by estimating at least 1 week worth of order quantity
$estimatedOverheadTime = $leadTime + $adminTime * \max($minimumOrderQuantity, $avgMonthlySales / 4) / FloatInt::DIVISOR; $estimatedOverheadTime = $leadTime + $adminTime * \max($minimumOrderQuantity, $avgMonthlySales / 4) / FloatInt::DIVISOR;
$orderQuantity = 0; $orderQuantity = 0;
$orderRange = 0; $orderRange = 0;
if ($minimumStockRange - ($currentRangeReserved - $estimatedOverheadTime / 30) > 0) { if ($minimumStockRange - ($currentRangeReserved - $estimatedOverheadTime / 30) > 0) {
// Iteratively approaching overhead time // Iteratively approaching overhead time
@ -296,13 +306,13 @@ final class CliController extends Controller
->where('id', (int) $price['supplier']) ->where('id', (int) $price['supplier'])
->execute(); ->execute();
$element = new OrderSuggestionElement(); $element = new OrderSuggestionElement();
$element->status = OrderSuggestionElementStatus::CALCULATED; $element->status = OrderSuggestionElementStatus::CALCULATED;
$element->modifiedBy = $suggestion->createdBy; $element->modifiedBy = $suggestion->createdBy;
$element->quantity->value = $orderQuantity; $element->quantity->value = $orderQuantity;
$element->item = $item; $element->item = $item;
$element->supplier = $supplier; $element->supplier = $supplier;
$element->costs = new FloatInt((int) ($price['bestActualPrice']->value * $orderQuantity / FloatInt::DIVISOR)); $element->costs = new FloatInt((int) ($price['bestActualPrice']->value * $orderQuantity / FloatInt::DIVISOR));
$suggestion->elements[] = $element; $suggestion->elements[] = $element;
} }

View File

@ -36,14 +36,30 @@ class OrderSuggestion
public \DateTimeImmutable $createdAt; public \DateTimeImmutable $createdAt;
/**
* Order elements
*
* @var OrderSuggestionElement[]
* @since 1.0.0
*/
public array $elements = []; public array $elements = [];
/**
* Constructor.
*/
public function __construct() public function __construct()
{ {
$this->createdBy = new NullAccount(); $this->createdBy = new NullAccount();
$this->createdAt = new \DateTimeImmutable('now'); $this->createdAt = new \DateTimeImmutable('now');
} }
/**
* Calculate total costs of order
*
* @return FloatInt
*
* @since 1.0.0
*/
public function getTotalCosts() : FloatInt public function getTotalCosts() : FloatInt
{ {
$total = new FloatInt(); $total = new FloatInt();

View File

@ -53,13 +53,18 @@ class OrderSuggestionElement
public FloatInt $costs; public FloatInt $costs;
/**
* Constructor.
*
* @since 1.0.0
*/
public function __construct() public function __construct()
{ {
$this->modifiedBy = new NullAccount(); $this->modifiedBy = new NullAccount();
$this->modifiedAt = new \DateTimeImmutable('now'); $this->modifiedAt = new \DateTimeImmutable('now');
$this->item = new NullItem(); $this->item = new NullItem();
$this->supplier = new NullSupplier(); $this->supplier = new NullSupplier();
$this->quantity = new FloatInt(); $this->quantity = new FloatInt();
$this->costs = new FloatInt(); $this->costs = new FloatInt();
} }
} }

View File

@ -21,14 +21,14 @@ use Modules\SupplierManagement\Models\SupplierMapper;
use phpOMS\DataStorage\Database\Mapper\DataMapperFactory; use phpOMS\DataStorage\Database\Mapper\DataMapperFactory;
/** /**
* Client mapper class. * OrderSuggestionElement mapper class.
* *
* @package Modules\Purchase\Models\OrderSuggestion * @package Modules\Purchase\Models\OrderSuggestion
* @license OMS License 2.0 * @license OMS License 2.0
* @link https://jingga.app * @link https://jingga.app
* @since 1.0.0 * @since 1.0.0
* *
* @template T of Client * @template T of OrderSuggestionElement
* @extends DataMapperFactory<T> * @extends DataMapperFactory<T>
*/ */
final class OrderSuggestionElementMapper extends DataMapperFactory final class OrderSuggestionElementMapper extends DataMapperFactory
@ -41,15 +41,15 @@ final class OrderSuggestionElementMapper extends DataMapperFactory
*/ */
public const COLUMNS = [ public const COLUMNS = [
'purchase_order_suggestion_element_id' => ['name' => 'purchase_order_suggestion_element_id', 'type' => 'int', 'internal' => 'id'], 'purchase_order_suggestion_element_id' => ['name' => 'purchase_order_suggestion_element_id', 'type' => 'int', 'internal' => 'id'],
'purchase_order_suggestion_element_status' => ['name' => 'purchase_order_suggestion_element_status', 'type' => 'int', 'internal' => 'status'], 'purchase_order_suggestion_element_status' => ['name' => 'purchase_order_suggestion_element_status', 'type' => 'int', 'internal' => 'status'],
'purchase_order_suggestion_element_updated_by' => ['name' => 'purchase_order_suggestion_element_updated_by', 'type' => 'int', 'internal' => 'modifiedBy'], 'purchase_order_suggestion_element_updated_by' => ['name' => 'purchase_order_suggestion_element_updated_by', 'type' => 'int', 'internal' => 'modifiedBy'],
'purchase_order_suggestion_element_updated_at' => ['name' => 'purchase_order_suggestion_element_updated_at', 'type' => 'DateTimeImmutable', 'internal' => 'modifiedAt'], 'purchase_order_suggestion_element_updated_at' => ['name' => 'purchase_order_suggestion_element_updated_at', 'type' => 'DateTimeImmutable', 'internal' => 'modifiedAt'],
'purchase_order_suggestion_element_suggestion' => ['name' => 'purchase_order_suggestion_element_suggestion', 'type' => 'int', 'internal' => 'suggestion'], 'purchase_order_suggestion_element_suggestion' => ['name' => 'purchase_order_suggestion_element_suggestion', 'type' => 'int', 'internal' => 'suggestion'],
'purchase_order_suggestion_element_item' => ['name' => 'purchase_order_suggestion_element_item', 'type' => 'int', 'internal' => 'item'], 'purchase_order_suggestion_element_item' => ['name' => 'purchase_order_suggestion_element_item', 'type' => 'int', 'internal' => 'item'],
'purchase_order_suggestion_element_bill' => ['name' => 'purchase_order_suggestion_element_bill', 'type' => 'int', 'internal' => 'bill'], 'purchase_order_suggestion_element_bill' => ['name' => 'purchase_order_suggestion_element_bill', 'type' => 'int', 'internal' => 'bill'],
'purchase_order_suggestion_element_supplier' => ['name' => 'purchase_order_suggestion_element_supplier', 'type' => 'int', 'internal' => 'supplier'], 'purchase_order_suggestion_element_supplier' => ['name' => 'purchase_order_suggestion_element_supplier', 'type' => 'int', 'internal' => 'supplier'],
'purchase_order_suggestion_element_quantity' => ['name' => 'purchase_order_suggestion_element_quantity', 'type' => 'Serializable', 'internal' => 'quantity'], 'purchase_order_suggestion_element_quantity' => ['name' => 'purchase_order_suggestion_element_quantity', 'type' => 'Serializable', 'internal' => 'quantity'],
'purchase_order_suggestion_element_costs' => ['name' => 'purchase_order_suggestion_element_costs', 'type' => 'Serializable', 'internal' => 'costs'], 'purchase_order_suggestion_element_costs' => ['name' => 'purchase_order_suggestion_element_costs', 'type' => 'Serializable', 'internal' => 'costs'],
]; ];
/** /**

View File

@ -18,14 +18,14 @@ use Modules\Admin\Models\AccountMapper;
use phpOMS\DataStorage\Database\Mapper\DataMapperFactory; use phpOMS\DataStorage\Database\Mapper\DataMapperFactory;
/** /**
* Client mapper class. * OrderSuggestion mapper class.
* *
* @package Modules\Purchase\Models\OrderSuggestion * @package Modules\Purchase\Models\OrderSuggestion
* @license OMS License 2.0 * @license OMS License 2.0
* @link https://jingga.app * @link https://jingga.app
* @since 1.0.0 * @since 1.0.0
* *
* @template T of Client * @template T of OrderSuggestion
* @extends DataMapperFactory<T> * @extends DataMapperFactory<T>
*/ */
final class OrderSuggestionMapper extends DataMapperFactory final class OrderSuggestionMapper extends DataMapperFactory
@ -38,9 +38,9 @@ final class OrderSuggestionMapper extends DataMapperFactory
*/ */
public const COLUMNS = [ public const COLUMNS = [
'purchase_order_suggestion_id' => ['name' => 'purchase_order_suggestion_id', 'type' => 'int', 'internal' => 'id'], 'purchase_order_suggestion_id' => ['name' => 'purchase_order_suggestion_id', 'type' => 'int', 'internal' => 'id'],
'purchase_order_suggestion_status' => ['name' => 'purchase_order_suggestion_status', 'type' => 'int', 'internal' => 'status'], 'purchase_order_suggestion_status' => ['name' => 'purchase_order_suggestion_status', 'type' => 'int', 'internal' => 'status'],
'purchase_order_suggestion_created_by' => ['name' => 'purchase_order_suggestion_created_by', 'type' => 'int', 'internal' => 'createdBy'], 'purchase_order_suggestion_created_by' => ['name' => 'purchase_order_suggestion_created_by', 'type' => 'int', 'internal' => 'createdBy'],
'purchase_order_suggestion_created_at' => ['name' => 'purchase_order_suggestion_created_at', 'type' => 'DateTimeImmutable', 'internal' => 'createdAt'], 'purchase_order_suggestion_created_at' => ['name' => 'purchase_order_suggestion_created_at', 'type' => 'DateTimeImmutable', 'internal' => 'createdAt'],
]; ];
/** /**

View File

@ -33,5 +33,4 @@ abstract class OrderSuggestionOptimizationType extends Enum
public const COST = 2; // Suggestion focuses on creating better prices if volume discounts exist. public const COST = 2; // Suggestion focuses on creating better prices if volume discounts exist.
public const JUST_IN_TIME = 3; // Suggestion focuses on calculating minimum stock quantities. public const JUST_IN_TIME = 3; // Suggestion focuses on calculating minimum stock quantities.
} }

View File

@ -15,17 +15,15 @@ declare(strict_types=1);
return ['Navigation' => [ return ['Navigation' => [
'Analysis' => 'Analysis', 'Analysis' => 'Analysis',
'Articles' => 'Articles', 'Articles' => 'Articles',
'Create' => 'Create',
'Invoice' => 'Invoice', 'Invoice' => 'Invoice',
'Invoices' => 'Invoices', 'Invoices' => 'Invoices',
'List' => 'List',
'OrderSuggestions' => 'Order Suggestions', 'OrderSuggestions' => 'Order Suggestions',
'PendingOrders' => 'Pending Orders', 'PendingOrders' => 'Pending Orders',
'Profile' => 'Profile', 'Profile' => 'Profile',
'Purchase' => 'Purchase', 'Purchase' => 'Purchase',
'Suppliers' => 'Suppliers', 'Suppliers' => 'Suppliers',
'TaxCodes' => 'Tax Codes', 'TaxCodes' => 'Tax Codes',
'TaxCombinations' => 'Tax Combinations', 'TaxCombinations' => 'Tax Combinations',
'List' => 'List', 'List' => 'List',
'Create' => 'Create', 'Create' => 'Create',
]]; ]];

View File

@ -13,12 +13,12 @@
declare(strict_types=1); declare(strict_types=1);
return ['Purchase' => [ return ['Purchase' => [
'Created' => 'خلقت', 'Created' => 'خلقت',
'Creator' => 'المنشئ', 'Creator' => 'المنشئ',
'Order' => 'طلب', 'Order' => 'طلب',
'Ordered' => 'أمر', 'Ordered' => 'أمر',
'Price' => 'السعر', 'Price' => 'السعر',
'Status' => 'حالة', 'Status' => 'حالة',
'Stock' => 'المخزون', 'Stock' => 'المخزون',
'Supplier' => 'المورد', 'Supplier' => 'المورد',
]]; ]];

View File

@ -13,12 +13,12 @@
declare(strict_types=1); declare(strict_types=1);
return ['Purchase' => [ return ['Purchase' => [
'Created' => 'Vytvořený', 'Created' => 'Vytvořený',
'Creator' => 'Tvůrce', 'Creator' => 'Tvůrce',
'Order' => 'Objednat', 'Order' => 'Objednat',
'Ordered' => 'Objednaný', 'Ordered' => 'Objednaný',
'Price' => 'Cena', 'Price' => 'Cena',
'Status' => 'Postavení', 'Status' => 'Postavení',
'Stock' => 'Skladem', 'Stock' => 'Skladem',
'Supplier' => 'Dodavatel', 'Supplier' => 'Dodavatel',
]]; ]];

View File

@ -13,12 +13,12 @@
declare(strict_types=1); declare(strict_types=1);
return ['Purchase' => [ return ['Purchase' => [
'Created' => 'Oprettet', 'Created' => 'Oprettet',
'Creator' => 'Skaber.', 'Creator' => 'Skaber.',
'Order' => 'Bestille', 'Order' => 'Bestille',
'Ordered' => 'Bestilt.', 'Ordered' => 'Bestilt.',
'Price' => 'Pris', 'Price' => 'Pris',
'Status' => 'Status.', 'Status' => 'Status.',
'Stock' => 'Lager', 'Stock' => 'Lager',
'Supplier' => 'Leverandør', 'Supplier' => 'Leverandør',
]]; ]];

View File

@ -13,48 +13,43 @@
declare(strict_types=1); declare(strict_types=1);
return ['Purchase' => [ return ['Purchase' => [
'Created' => 'Erstellt', 'Created' => 'Erstellt',
'Creator' => 'Ersteller', 'Creator' => 'Ersteller',
'Order' => 'Befehl', 'Order' => 'Befehl',
'Ordered' => 'Bestellt', 'Price' => 'Preis',
'Price' => 'Preis', 'Status' => 'Status',
'Status' => 'Status', 'Item' => 'Artikel',
'Stock' => 'Aktie',
'Order' => 'Bestellen',
'Item' => 'Artikel',
'Supplier' => 'Lieferant', 'Supplier' => 'Lieferant',
'Stock' => 'Lager', 'Stock' => 'Lager',
'Reserved' => 'Reserviert', 'Reserved' => 'Reserviert',
'Ordered' => 'Bestellt', 'Ordered' => 'Bestellt',
'AvgConsumption' => 'Ø Verbrauch', 'AvgConsumption' => 'Ø Verbrauch',
'Range1' => 'Reichw. 1', 'Range1' => 'Reichw. 1',
'Range2' => 'Reichw. 2', 'Range2' => 'Reichw. 2',
'MinStock' => 'Min. Lager', 'MinStock' => 'Min. Lager',
'MinOrder' => 'Min. Bestellmenge', 'MinOrder' => 'Min. Bestellmenge',
'MinRange' => 'Min. Reichw.', 'MinRange' => 'Min. Reichw.',
'Steps' => 'Schritte', 'Steps' => 'Schritte',
'Ordering' => 'Bestellen', 'Ordering' => 'Bestellen',
'NewRange' => 'Neue Reichw.', 'NewRange' => 'Neue Reichw.',
'Price' => 'Preis', 'Total' => 'Gesamt',
'Total' => 'Gesamt', 'Costs' => 'Kosten',
'Costs' => 'Kosten', ':SuggestionStatus-1' => 'Entwurf',
':SuggestionStatus-1' => 'Entwurf', ':SuggestionStatus-2' => 'Gelöscht',
':SuggestionStatus-2' => 'Gelöscht', ':SuggestionStatus-3' => 'Bestellt',
':SuggestionStatus-3' => 'Bestellt', ':OptimizationAlgorithm-0' => 'Artikel specifisch',
':OptimizationAlgorithm-0' => 'Artikel specifisch', ':OptimizationAlgorithm-1' => 'Verfügbarkeit',
':OptimizationAlgorithm-1' => 'Verfügbarkeit', ':OptimizationAlgorithm-2' => 'Kosten',
':OptimizationAlgorithm-2' => 'Kosten', ':OptimizationAlgorithm-3' => 'Just in time',
':OptimizationAlgorithm-3' => 'Just in time', 'Elements' => 'Elemente',
'Elements' => 'Elemente', 'Algorithm' => 'Algorithmus',
'Algorithm' => 'Algorithmus', 'Analyze' => 'Analysiere',
'Analyze' => 'Analysiere', 'Segment' => 'Segment',
'Segment' => 'Segment', 'HideIrrelevant' => 'Nur relevante',
'HideIrrelevant' => 'Nur relevante', 'Section' => 'Sparte',
'Section' => 'Sparte', 'SalesGroup' => 'Umsatzgruppe',
'SalesGroup' => 'Umsatzgruppe', 'ProductGroup' => 'Produktgruppe',
'ProductGroup' => 'Produktgruppe', 'OrderSuggestions' => 'Bestellvorschläge',
'MinRange' => 'Min.-Reichweite', 'OrderSuggestion' => 'Bestellvorschlag',
'OrderSuggestions' => 'Bestellvorschläge',
'OrderSuggestion' => 'Bestellvorschlag',
'Suggestions' => 'Vorschläge', 'Suggestions' => 'Vorschläge',
]]; ]];

View File

@ -13,12 +13,12 @@
declare(strict_types=1); declare(strict_types=1);
return ['Purchase' => [ return ['Purchase' => [
'Created' => 'Δημιουργήθηκε', 'Created' => 'Δημιουργήθηκε',
'Creator' => 'Δημιουργός', 'Creator' => 'Δημιουργός',
'Order' => 'Σειρά', 'Order' => 'Σειρά',
'Ordered' => 'Διέταξε', 'Ordered' => 'Διέταξε',
'Price' => 'Τιμή', 'Price' => 'Τιμή',
'Status' => 'Κατάσταση', 'Status' => 'Κατάσταση',
'Stock' => 'Στοκ', 'Stock' => 'Στοκ',
'Supplier' => 'Προμηθευτής', 'Supplier' => 'Προμηθευτής',
]]; ]];

View File

@ -13,48 +13,42 @@
declare(strict_types=1); declare(strict_types=1);
return ['Purchase' => [ return ['Purchase' => [
'Created' => 'Created', 'Created' => 'Created',
'Creator' => 'Creator', 'Creator' => 'Creator',
'Order' => 'Order', 'Status' => 'Status',
'Ordered' => 'Ordered', 'Order' => 'Order',
'Price' => 'Price', 'Item' => 'Item',
'Status' => 'Status',
'Stock' => 'Stock',
'Supplier' => 'Supplier',
'Order' => 'Order',
'Item' => 'Item',
'Supplier' => 'Supplier', 'Supplier' => 'Supplier',
'Stock' => 'Stock', 'Stock' => 'Stock',
'Reserved' => 'Reserved', 'Reserved' => 'Reserved',
'Ordered' => 'Ordered', 'Ordered' => 'Ordered',
'AvgConsumption' => 'Ø Cons.', 'AvgConsumption' => 'Ø Cons.',
'Range1' => 'Range 1', 'Range1' => 'Range 1',
'Range2' => 'Range 2', 'Range2' => 'Range 2',
'MinStock' => 'Min. Stock', 'MinStock' => 'Min. Stock',
'MinOrder' => 'Min. Order', 'MinOrder' => 'Min. Order',
'MinRange' => 'Min. Range', 'Steps' => 'Steps',
'Steps' => 'Steps',
'Ordering' => 'Ordering', 'Ordering' => 'Ordering',
'NewRange' => 'New Range', 'NewRange' => 'New Range',
'Price' => 'Price', 'Price' => 'Price',
'Total' => 'Total', 'Total' => 'Total',
'Costs' => 'Costs', 'Costs' => 'Costs',
':SuggestionStatus-1' => 'Draft', ':SuggestionStatus-1' => 'Draft',
':SuggestionStatus-2' => 'DELETED', ':SuggestionStatus-2' => 'DELETED',
':SuggestionStatus-3' => 'ORDERED', ':SuggestionStatus-3' => 'ORDERED',
':OptimizationAlgorithm-0' => 'Item specific', ':OptimizationAlgorithm-0' => 'Item specific',
':OptimizationAlgorithm-1' => 'Availability optimization', ':OptimizationAlgorithm-1' => 'Availability optimization',
':OptimizationAlgorithm-2' => 'Cost optimization', ':OptimizationAlgorithm-2' => 'Cost optimization',
':OptimizationAlgorithm-3' => 'Just in time', ':OptimizationAlgorithm-3' => 'Just in time',
'Elements' => 'Elements', 'Elements' => 'Elements',
'Algorithm' => 'Algorithm', 'Algorithm' => 'Algorithm',
'Analyze' => 'Analyze', 'Analyze' => 'Analyze',
'Segment' => 'Segment', 'Segment' => 'Segment',
'HideIrrelevant' => 'Hide irrelevant', 'HideIrrelevant' => 'Hide irrelevant',
'Section' => 'Section', 'Section' => 'Section',
'SalesGroup' => 'Sales Group', 'SalesGroup' => 'Sales Group',
'ProductGroup' => 'Product Group', 'ProductGroup' => 'Product Group',
'MinRange' => 'Min. Range', 'MinRange' => 'Min. Range',
'OrderSuggestions' => 'Order Suggestions', 'OrderSuggestions' => 'Order Suggestions',
'Suggestions' => 'Suggestions', 'Suggestions' => 'Suggestions',
]]; ]];

View File

@ -13,12 +13,12 @@
declare(strict_types=1); declare(strict_types=1);
return ['Purchase' => [ return ['Purchase' => [
'Created' => 'Creado', 'Created' => 'Creado',
'Creator' => 'Creador', 'Creator' => 'Creador',
'Order' => 'Pedido', 'Order' => 'Pedido',
'Ordered' => 'Ordenado', 'Ordered' => 'Ordenado',
'Price' => 'Precio', 'Price' => 'Precio',
'Status' => 'Estado', 'Status' => 'Estado',
'Stock' => 'Valores', 'Stock' => 'Valores',
'Supplier' => 'Proveedor', 'Supplier' => 'Proveedor',
]]; ]];

View File

@ -13,12 +13,12 @@
declare(strict_types=1); declare(strict_types=1);
return ['Purchase' => [ return ['Purchase' => [
'Created' => 'Luotu', 'Created' => 'Luotu',
'Creator' => 'Luoja', 'Creator' => 'Luoja',
'Order' => 'Tilaus', 'Order' => 'Tilaus',
'Ordered' => 'Tilattu', 'Ordered' => 'Tilattu',
'Price' => 'Hinta', 'Price' => 'Hinta',
'Status' => 'Tila', 'Status' => 'Tila',
'Stock' => 'Varasto', 'Stock' => 'Varasto',
'Supplier' => 'Toimittaja', 'Supplier' => 'Toimittaja',
]]; ]];

View File

@ -13,12 +13,12 @@
declare(strict_types=1); declare(strict_types=1);
return ['Purchase' => [ return ['Purchase' => [
'Created' => 'Établi', 'Created' => 'Établi',
'Creator' => 'Créateur', 'Creator' => 'Créateur',
'Order' => 'Commander', 'Order' => 'Commander',
'Ordered' => 'Commandé', 'Ordered' => 'Commandé',
'Price' => 'Prix', 'Price' => 'Prix',
'Status' => 'Statut', 'Status' => 'Statut',
'Stock' => 'Stocker', 'Stock' => 'Stocker',
'Supplier' => 'Fournisseur', 'Supplier' => 'Fournisseur',
]]; ]];

View File

@ -13,12 +13,12 @@
declare(strict_types=1); declare(strict_types=1);
return ['Purchase' => [ return ['Purchase' => [
'Created' => 'Létrehozott', 'Created' => 'Létrehozott',
'Creator' => 'Teremtő', 'Creator' => 'Teremtő',
'Order' => 'Rendelés', 'Order' => 'Rendelés',
'Ordered' => 'Elrendelt', 'Ordered' => 'Elrendelt',
'Price' => 'Ár', 'Price' => 'Ár',
'Status' => 'Állapot', 'Status' => 'Állapot',
'Stock' => 'Készlet', 'Stock' => 'Készlet',
'Supplier' => 'Támogató', 'Supplier' => 'Támogató',
]]; ]];

View File

@ -13,12 +13,12 @@
declare(strict_types=1); declare(strict_types=1);
return ['Purchase' => [ return ['Purchase' => [
'Created' => 'Creato', 'Created' => 'Creato',
'Creator' => 'Creatore', 'Creator' => 'Creatore',
'Order' => 'Ordine', 'Order' => 'Ordine',
'Ordered' => 'Ordinato', 'Ordered' => 'Ordinato',
'Price' => 'Prezzo', 'Price' => 'Prezzo',
'Status' => 'Stato', 'Status' => 'Stato',
'Stock' => 'Azione', 'Stock' => 'Azione',
'Supplier' => 'Fornitore', 'Supplier' => 'Fornitore',
]]; ]];

View File

@ -13,12 +13,12 @@
declare(strict_types=1); declare(strict_types=1);
return ['Purchase' => [ return ['Purchase' => [
'Created' => '作成した', 'Created' => '作成した',
'Creator' => 'クリエーター', 'Creator' => 'クリエーター',
'Order' => '注文', 'Order' => '注文',
'Ordered' => '順序付けられました', 'Ordered' => '順序付けられました',
'Price' => '価格', 'Price' => '価格',
'Status' => '状態', 'Status' => '状態',
'Stock' => 'ストック', 'Stock' => 'ストック',
'Supplier' => 'サプライヤー', 'Supplier' => 'サプライヤー',
]]; ]];

View File

@ -13,12 +13,12 @@
declare(strict_types=1); declare(strict_types=1);
return ['Purchase' => [ return ['Purchase' => [
'Created' => '만들어진', 'Created' => '만들어진',
'Creator' => '창조자', 'Creator' => '창조자',
'Order' => '주문하다', 'Order' => '주문하다',
'Ordered' => '주문했다', 'Ordered' => '주문했다',
'Price' => '가격', 'Price' => '가격',
'Status' => '상태', 'Status' => '상태',
'Stock' => '재고', 'Stock' => '재고',
'Supplier' => '공급자', 'Supplier' => '공급자',
]]; ]];

View File

@ -13,12 +13,12 @@
declare(strict_types=1); declare(strict_types=1);
return ['Purchase' => [ return ['Purchase' => [
'Created' => 'Opprettet', 'Created' => 'Opprettet',
'Creator' => 'Skaperen.', 'Creator' => 'Skaperen.',
'Order' => 'Rekkefølge', 'Order' => 'Rekkefølge',
'Ordered' => 'Bestilt', 'Ordered' => 'Bestilt',
'Price' => 'Pris', 'Price' => 'Pris',
'Status' => 'Status', 'Status' => 'Status',
'Stock' => 'Lager', 'Stock' => 'Lager',
'Supplier' => 'Leverandør', 'Supplier' => 'Leverandør',
]]; ]];

View File

@ -13,12 +13,12 @@
declare(strict_types=1); declare(strict_types=1);
return ['Purchase' => [ return ['Purchase' => [
'Created' => 'Utworzony', 'Created' => 'Utworzony',
'Creator' => 'Twórca', 'Creator' => 'Twórca',
'Order' => 'Zamówienie', 'Order' => 'Zamówienie',
'Ordered' => 'Uporządkowany', 'Ordered' => 'Uporządkowany',
'Price' => 'Cena £', 'Price' => 'Cena £',
'Status' => 'Status', 'Status' => 'Status',
'Stock' => 'Magazyn', 'Stock' => 'Magazyn',
'Supplier' => 'Dostawca', 'Supplier' => 'Dostawca',
]]; ]];

View File

@ -13,12 +13,12 @@
declare(strict_types=1); declare(strict_types=1);
return ['Purchase' => [ return ['Purchase' => [
'Created' => 'Criado', 'Created' => 'Criado',
'Creator' => 'O Criador', 'Creator' => 'O Criador',
'Order' => 'Pedido', 'Order' => 'Pedido',
'Ordered' => 'Encomendado', 'Ordered' => 'Encomendado',
'Price' => 'Preço', 'Price' => 'Preço',
'Status' => 'Status', 'Status' => 'Status',
'Stock' => 'Estoque', 'Stock' => 'Estoque',
'Supplier' => 'Fornecedor', 'Supplier' => 'Fornecedor',
]]; ]];

View File

@ -13,12 +13,12 @@
declare(strict_types=1); declare(strict_types=1);
return ['Purchase' => [ return ['Purchase' => [
'Created' => 'Созданный', 'Created' => 'Созданный',
'Creator' => 'Создатель', 'Creator' => 'Создатель',
'Order' => 'Заказ', 'Order' => 'Заказ',
'Ordered' => 'Заказал', 'Ordered' => 'Заказал',
'Price' => 'Цена', 'Price' => 'Цена',
'Status' => 'Статус', 'Status' => 'Статус',
'Stock' => 'Склад', 'Stock' => 'Склад',
'Supplier' => 'Поставщик', 'Supplier' => 'Поставщик',
]]; ]];

View File

@ -13,12 +13,12 @@
declare(strict_types=1); declare(strict_types=1);
return ['Purchase' => [ return ['Purchase' => [
'Created' => 'Skapad', 'Created' => 'Skapad',
'Creator' => 'Skapare', 'Creator' => 'Skapare',
'Order' => 'Beställa', 'Order' => 'Beställa',
'Ordered' => 'Beställde', 'Ordered' => 'Beställde',
'Price' => 'Pris', 'Price' => 'Pris',
'Status' => 'Status', 'Status' => 'Status',
'Stock' => 'Stock', 'Stock' => 'Stock',
'Supplier' => 'Leverantör', 'Supplier' => 'Leverantör',
]]; ]];

View File

@ -13,12 +13,12 @@
declare(strict_types=1); declare(strict_types=1);
return ['Purchase' => [ return ['Purchase' => [
'Created' => 'สร้าง', 'Created' => 'สร้าง',
'Creator' => 'ผู้สร้าง', 'Creator' => 'ผู้สร้าง',
'Order' => 'คำสั่ง', 'Order' => 'คำสั่ง',
'Ordered' => 'ที่ได้รับคำสั่ง', 'Ordered' => 'ที่ได้รับคำสั่ง',
'Price' => 'ราคา', 'Price' => 'ราคา',
'Status' => 'สถานะ', 'Status' => 'สถานะ',
'Stock' => 'คลังสินค้า', 'Stock' => 'คลังสินค้า',
'Supplier' => 'ผู้ผลิต', 'Supplier' => 'ผู้ผลิต',
]]; ]];

View File

@ -13,12 +13,12 @@
declare(strict_types=1); declare(strict_types=1);
return ['Purchase' => [ return ['Purchase' => [
'Created' => 'Yaratılmış', 'Created' => 'Yaratılmış',
'Creator' => 'Yaratıcı', 'Creator' => 'Yaratıcı',
'Order' => 'Emir', 'Order' => 'Emir',
'Ordered' => 'Emir', 'Ordered' => 'Emir',
'Price' => 'Fiyat', 'Price' => 'Fiyat',
'Status' => 'Durum', 'Status' => 'Durum',
'Stock' => 'Stoklamak', 'Stock' => 'Stoklamak',
'Supplier' => 'Tedarikçi', 'Supplier' => 'Tedarikçi',
]]; ]];

View File

@ -13,12 +13,12 @@
declare(strict_types=1); declare(strict_types=1);
return ['Purchase' => [ return ['Purchase' => [
'Created' => 'Створений', 'Created' => 'Створений',
'Creator' => 'Творець', 'Creator' => 'Творець',
'Order' => 'Порядок', 'Order' => 'Порядок',
'Ordered' => 'Упорядкований', 'Ordered' => 'Упорядкований',
'Price' => 'Ціна', 'Price' => 'Ціна',
'Status' => 'Статус', 'Status' => 'Статус',
'Stock' => 'Запас', 'Stock' => 'Запас',
'Supplier' => 'Постачальник', 'Supplier' => 'Постачальник',
]]; ]];

View File

@ -13,12 +13,12 @@
declare(strict_types=1); declare(strict_types=1);
return ['Purchase' => [ return ['Purchase' => [
'Created' => '创造了', 'Created' => '创造了',
'Creator' => '创造者', 'Creator' => '创造者',
'Order' => '命令', 'Order' => '命令',
'Ordered' => '订购', 'Ordered' => '订购',
'Price' => '价格', 'Price' => '价格',
'Status' => '地位', 'Status' => '地位',
'Stock' => '库存', 'Stock' => '库存',
'Supplier' => '供应商', 'Supplier' => '供应商',
]]; ]];

View File

@ -65,12 +65,12 @@ echo $this->data['nav']->render();
<td><?= $this->getHtml('Costs'); ?> <td><?= $this->getHtml('Costs'); ?>
<tbody> <tbody>
<?php <?php
$now = new SmartDateTime('now'); $now = new SmartDateTime('now');
$total = new FloatInt(); $total = new FloatInt();
$subtotal = new FloatInt(); $subtotal = new FloatInt();
$lastSupplier = 0; $lastSupplier = 0;
$supplier = $this->request->getDataString('supplier'); $supplier = $this->request->getDataString('supplier');
$hasSupplierSwitch = false; $hasSupplierSwitch = false;
$isFirst = true; $isFirst = true;
@ -89,7 +89,7 @@ echo $this->data['nav']->render();
<?php <?php
if (empty($supplier) && $lastSupplier !== $element->supplier->id && !$isFirst) : if (empty($supplier) && $lastSupplier !== $element->supplier->id && !$isFirst) :
$hasSupplierSwitch = true; $hasSupplierSwitch = true;
$lastSupplier = $element->supplier->id; $lastSupplier = $element->supplier->id;
?> ?>
<tr class="hl-7"> <tr class="hl-7">
<td colspan="15"><?= $this->printHtml($element->supplier->account->name1); ?> <?= $this->printHtml($element->supplier->account->name2); ?> <td colspan="15"><?= $this->printHtml($element->supplier->account->name1); ?> <?= $this->printHtml($element->supplier->account->name2); ?>
@ -125,7 +125,7 @@ echo $this->data['nav']->render();
(int) ($months = ($this->data['suggestion_data'][$element->item->id]['range_ordered'] (int) ($months = ($this->data['suggestion_data'][$element->item->id]['range_ordered']
+ $this->data['suggestion_data'][$element->item->id]['range_reserved'])), + $this->data['suggestion_data'][$element->item->id]['range_reserved'])),
(int) (($months - ((int) $months)) * 30)) (int) (($months - ((int) $months)) * 30))
->format('Y-m-d') ->format('Y-m-d');
?> ?>
<td><?= $this->data['suggestion_data'][$element->item->id]['singlePrice']->getAmount(); ?> <td><?= $this->data['suggestion_data'][$element->item->id]['singlePrice']->getAmount(); ?>
<td><?= $element->costs->getAmount(); ?> <td><?= $element->costs->getAmount(); ?>