Initial xentral_oss_20.3.c9ffacf
This commit is contained in:
@@ -0,0 +1,250 @@
|
||||
<?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
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user