mirror of
https://github.com/OpenXE-org/OpenXE.git
synced 2024-12-29 08:00:28 +01:00
251 lines
9.2 KiB
PHP
251 lines
9.2 KiB
PHP
|
<?php
|
||
|
|
||
|
namespace Xentral\Modules\Article\Service;
|
||
|
|
||
|
use Xentral\Components\Database\Database;
|
||
|
use Xentral\Modules\Article\Exception\ArticleNotFoundException;
|
||
|
use Xentral\Modules\Article\Exception\InvalidArgumentException;
|
||
|
use Xentral\Modules\Article\Gateway\ArticleGateway;
|
||
|
|
||
|
final class PurchasePriceService
|
||
|
{
|
||
|
/** @var ArticleGateway $gateway */
|
||
|
private $gateway;
|
||
|
|
||
|
/** @var Database $db */
|
||
|
private $db;
|
||
|
|
||
|
/**
|
||
|
* @param ArticleGateway $gateway
|
||
|
* @param Database $database
|
||
|
*/
|
||
|
public function __construct(ArticleGateway $gateway, Database $database)
|
||
|
{
|
||
|
$this->gateway = $gateway;
|
||
|
$this->db = $database;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param int $articleId
|
||
|
* @param int|float $quantity
|
||
|
*
|
||
|
* @throws InvalidArgumentException|ArticleNotFoundException
|
||
|
*
|
||
|
* @return float
|
||
|
*/
|
||
|
public function calculateCalculatedPurchasePrice($articleId, $quantity)
|
||
|
{
|
||
|
$quantity = (float)$quantity;
|
||
|
$articleId = $this->ensureArticleId($articleId);
|
||
|
if ($quantity <= 0.0) {
|
||
|
throw new InvalidArgumentException(sprintf('Quantity must be greater than 0. Actual: %s', $quantity));
|
||
|
}
|
||
|
|
||
|
$calculatedPurchasePrice = $this->db->fetchValue(
|
||
|
'SELECT a.berechneterek FROM artikel AS a WHERE a.id = :article_id AND a.verwendeberechneterek = 1',
|
||
|
['article_id' => $articleId]
|
||
|
);
|
||
|
|
||
|
$calculatedPurchasePrice = (float)$calculatedPurchasePrice * $quantity;
|
||
|
|
||
|
if ($calculatedPurchasePrice > 0) {
|
||
|
return $calculatedPurchasePrice;
|
||
|
}
|
||
|
|
||
|
if (!$this->gateway->isPartsListArticle($articleId)) {
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
$calculatedPurchasePrice = 0;
|
||
|
$partsListArticles = $this->db->fetchAll(
|
||
|
'SELECT s.artikel, s.menge FROM stueckliste AS s WHERE s.stuecklistevonartikel = :article_id',
|
||
|
['article_id' => $articleId]
|
||
|
);
|
||
|
foreach($partsListArticles as $articles=>$article){
|
||
|
$calculatedPurchasePrice += $this->calculateCalculatedPurchasePrice($article['artikel'], $article['menge']);
|
||
|
}
|
||
|
|
||
|
return $calculatedPurchasePrice;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param int $articleId
|
||
|
*
|
||
|
* @throws InvalidArgumentException
|
||
|
*
|
||
|
* @return int
|
||
|
*/
|
||
|
private function ensureArticleId($articleId)
|
||
|
{
|
||
|
if (empty($articleId) || (int)$articleId < 1) {
|
||
|
throw new InvalidArgumentException('Required argument "articleId" is empty or invalid.');
|
||
|
}
|
||
|
|
||
|
return (int)$articleId;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param int $articleId
|
||
|
* @param int $addressId
|
||
|
* @param float $price
|
||
|
* @param string $currencyCode
|
||
|
* @param float $quantityFrom
|
||
|
* @param string $purchaseNumber
|
||
|
* @param string $purchaseName
|
||
|
*
|
||
|
* @return int
|
||
|
*/
|
||
|
public function setPurchasePrice($articleId,
|
||
|
$addressId,
|
||
|
$price,
|
||
|
$currencyCode = 'EUR',
|
||
|
$quantityFrom = 1.0,
|
||
|
$purchaseNumber = '',
|
||
|
$purchaseName = '')
|
||
|
{
|
||
|
$this->ensureArticleId($articleId);
|
||
|
if(empty($currencyCode)) {
|
||
|
$currencyCode = 'EUR';
|
||
|
}
|
||
|
if($quantityFrom <= 0) {
|
||
|
$quantityFrom = 1.0;
|
||
|
}
|
||
|
$select = $this->db->select();
|
||
|
$select
|
||
|
->cols(['pp.id', 'pp.preis as price','IF(pp.waehrung <> \'\', pp.waehrung, \'EUR\') AS currency_code',
|
||
|
'pp.artikel AS article_id','pp.ab_menge AS quantity_from','pp.bestellnummer AS purchase_number',
|
||
|
'pp.bezeichnunglieferant AS purcase_name'
|
||
|
])
|
||
|
->from('einkaufspreise AS pp')
|
||
|
->where("ab_menge=:quantity_from AND adresse=:address_id AND artikel=:article_id AND waehrung = :currency_code
|
||
|
AND (IFNULL(gueltig_bis='0000-00-00','0000-00-00') OR gueltig_bis >= NOW()) AND geloescht!=1")
|
||
|
->bindValue('quantity_from', (float)$quantityFrom)
|
||
|
->bindValue('address_id', (int)$addressId)
|
||
|
->bindValue('article_id', (int)$articleId)
|
||
|
->bindValue('currency_code', $currencyCode);
|
||
|
|
||
|
$oldPrice = $this->db->fetchRow(
|
||
|
$select->getStatement(),
|
||
|
$select->getBindValues()
|
||
|
);
|
||
|
|
||
|
|
||
|
if(!empty($oldPrice)) {
|
||
|
$isPriceDifferent = round($oldPrice['price'],8) !== round($price,8);
|
||
|
$isNumberOrNameDiffernt = (String)$oldPrice['purchase_number'] !== (String)$purchaseNumber ||
|
||
|
(String)$oldPrice['purcase_name'] !== (String)$purchaseName;
|
||
|
if(!$isPriceDifferent && !$isNumberOrNameDiffernt) {
|
||
|
return $oldPrice['id'];
|
||
|
}
|
||
|
if(!$isPriceDifferent) {
|
||
|
return $oldPrice['id'];
|
||
|
}
|
||
|
$this->db->perform(
|
||
|
'UPDATE einkaufspreise SET gueltig_bis = DATE_SUB(CURDATE(), INTERVAL 1 DAY) WHERE id = :id',
|
||
|
['id'=>$oldPrice['id']]
|
||
|
);
|
||
|
}
|
||
|
|
||
|
$this->db->perform('INSERT INTO einkaufspreise (artikel, adresse, objekt, projekt, preis, waehrung, ab_menge,
|
||
|
bestellnummer, bezeichnunglieferant, nichtberechnet)
|
||
|
VALUES (:article_id, :address_id, :object, :project_id, :price, :currency, :quantity_from,
|
||
|
:purchase_number,:purchase_name, 1)',
|
||
|
[
|
||
|
'article_id' => (int)$articleId,
|
||
|
'address_id' => (int)$addressId,
|
||
|
'object' => '',
|
||
|
'project_id' => 0,
|
||
|
'price' => (float)$price,
|
||
|
'currency' => $currencyCode,
|
||
|
'quantity_from' => (float)$quantityFrom,
|
||
|
'purchase_number' => (String)$purchaseNumber,
|
||
|
'purchase_name' => (String)$purchaseName
|
||
|
|
||
|
]
|
||
|
);
|
||
|
|
||
|
return $this->db->lastInsertId();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param array $purchasePriceArray [article_id, address_id, price, quantity_from, currency_code,purchase_number,purchase_name]
|
||
|
*/
|
||
|
public function setPurchasePriceByArray($purchasePriceArray)
|
||
|
{
|
||
|
if(empty($purchasePriceArray)) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
$articleIds = [];
|
||
|
$addressIds = [];
|
||
|
|
||
|
foreach($purchasePriceArray as $purchasePrice) {
|
||
|
if(!in_array($purchasePrice['article_id'], $articleIds)) {
|
||
|
$articleIds[] = $purchasePrice['article_id'];
|
||
|
}
|
||
|
if(!in_array($purchasePrice['address_id'], $addressIds)) {
|
||
|
$addressIds[] = $purchasePrice['address_id'];
|
||
|
}
|
||
|
}
|
||
|
$select = $this->db->select();
|
||
|
$select
|
||
|
->cols(
|
||
|
[
|
||
|
'pp.id',
|
||
|
'pp.preis as price',
|
||
|
'IF(pp.waehrung <> \'\', pp.waehrung, \'EUR\') AS currency_code',
|
||
|
'pp.artikel AS article_id',
|
||
|
'pp.adresse AS address_id',
|
||
|
'pp.ab_menge AS quantity_from',
|
||
|
'pp.bestellnummer AS purchase_number',
|
||
|
'pp.bezeichnunglieferant AS purcase_name'
|
||
|
]
|
||
|
)
|
||
|
->from('einkaufspreise AS pp')
|
||
|
->where("adresse IN (:address) AND artikel IN (:article)
|
||
|
AND (IFNULL(pp.gueltig_bis,'0000-00-00')='0000-00-00' OR pp.gueltig_bis >= CURDATE()) AND pp.geloescht!=1")
|
||
|
->bindValue('address', $addressIds)
|
||
|
->bindValue('article', $articleIds);
|
||
|
|
||
|
$oldPrices = $this->db->fetchAll(
|
||
|
$select->getStatement(),
|
||
|
$select->getBindValues()
|
||
|
);
|
||
|
|
||
|
$priceTree = [];
|
||
|
foreach($oldPrices as $oldPrice) {
|
||
|
$articleId = (int)$oldPrice['article_id'];
|
||
|
$addressId = (int)$oldPrice['address_id'];
|
||
|
$currencyCode = $oldPrice['currency_code'];
|
||
|
$quantityFrom = round($oldPrice['quantity_from'],8);
|
||
|
$priceTree[$articleId][$addressId][$currencyCode][$quantityFrom] = $oldPrice['price'];
|
||
|
}
|
||
|
unset($oldPrices);
|
||
|
|
||
|
foreach($purchasePriceArray as $purchasePrice) {
|
||
|
$articleId = (int)$purchasePrice['article_id'];
|
||
|
$addressId = (int)$purchasePrice['address_id'];
|
||
|
$currencyCode = $purchasePrice['currency_code'];
|
||
|
$quantityFrom = round($purchasePrice['quantity_from'],8);
|
||
|
$price = round($purchasePrice['price'], 8);
|
||
|
$purchaseNumber = !empty($purchasePrice['purchase_number'])?$purchasePrice['purchase_number']:'';
|
||
|
$purchaseName = !empty($purchasePrice['purchase_name'])?$purchasePrice['purchase_name']:'';
|
||
|
$aricleExists = !empty($priceTree[$articleId]);
|
||
|
$addressExists = $aricleExists && !empty($priceTree[$articleId][$addressId]);
|
||
|
$currencyExists = $addressExists && !empty($priceTree[$articleId][$addressId][$currencyCode]);
|
||
|
$quantityFromExists = $currencyExists && !empty($priceTree[$articleId][$addressId][$currencyCode][$quantityFrom]);
|
||
|
if(!$quantityFromExists || round($oldPrice['price'],8) !== $price) {
|
||
|
$this->setPurchasePrice(
|
||
|
$articleId,
|
||
|
$addressId,
|
||
|
$price,
|
||
|
$currencyCode,
|
||
|
$quantityFrom,
|
||
|
$purchaseNumber,
|
||
|
$purchaseName
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|