Initial xentral_oss_20.3.c9ffacf
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Xentral\Modules\Article\Service;
|
||||
|
||||
|
||||
use Xentral\Modules\Article\Exception\CurrencyExchangeRateNotFoundException;
|
||||
|
||||
class CurrencyConversionService
|
||||
{
|
||||
/**
|
||||
* @deprecated
|
||||
* @var \erpAPI
|
||||
*/
|
||||
private $erp;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $cache;
|
||||
|
||||
/**
|
||||
* CurrencyConversionService constructor.
|
||||
*
|
||||
* @param \erpAPI $erp
|
||||
*/
|
||||
public function __construct(\erpAPI $erp)
|
||||
{
|
||||
$this->erp = $erp;
|
||||
$this->cache = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $currencyCode
|
||||
*
|
||||
* @throws CurrencyExchangeRateNotFoundException
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function tryGetEuroExchangeRateFromCurrencyCode($currencyCode)
|
||||
{
|
||||
if(isset($this->cache[$currencyCode])) {
|
||||
$exchangeRate = $this->cache[$currencyCode];
|
||||
}
|
||||
else {
|
||||
$exchangeRate = $this->erp->GetWaehrungUmrechnungskurs('EUR', $currencyCode, true);
|
||||
$this->cache[$currencyCode] = $exchangeRate;
|
||||
}
|
||||
if ($exchangeRate === false) {
|
||||
throw new CurrencyExchangeRateNotFoundException('Currency exchange rate not found: ' . $currencyCode);
|
||||
}
|
||||
|
||||
return (float)$exchangeRate;
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,226 @@
|
||||
<?php
|
||||
namespace Xentral\Modules\Article\Service;
|
||||
|
||||
use Xentral\Components\Database\Database;
|
||||
use Xentral\Modules\Article\Service\CurrencyConversionService;
|
||||
use Xentral\Modules\Article\Exception\CurrencyExchangeRateNotFoundException;
|
||||
|
||||
final class SellingPriceService
|
||||
{
|
||||
/** @var Database $db */
|
||||
private $db;
|
||||
|
||||
/** @var CurrencyConversionService */
|
||||
private $currencyConversion;
|
||||
|
||||
/**
|
||||
* @param Database $database
|
||||
* @param CurrencyConversionService $currencyConversion
|
||||
*/
|
||||
public function __construct(Database $database, CurrencyConversionService $currencyConversion)
|
||||
{
|
||||
$this->db = $database;
|
||||
$this->currencyConversion = $currencyConversion;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $articleId
|
||||
* @param float $price
|
||||
* @param string $currencyCode
|
||||
* @param float $quantityFrom
|
||||
*/
|
||||
public function setStandardPrice($articleId, $price, $currencyCode, $quantityFrom = 0.0)
|
||||
{
|
||||
if(empty($currencyCode)) {
|
||||
$currencyCode = 'EUR';
|
||||
}
|
||||
$oldPrices = $this->db->fetchAll(
|
||||
"SELECT id, preis AS price, waehrung AS currency_code
|
||||
FROM verkaufspreise WHERE artikel = :article_id AND art <> 'Gruppe'
|
||||
AND (IFNULL(gueltig_bis,'0000-00-00') = '0000-00-00' OR gueltig_bis >= CURDATE())
|
||||
AND adresse = 0 AND IF(waehrung <> '', waehrung, 'EUR') = :currency_code AND ab_menge = :quantity_from
|
||||
",
|
||||
|
||||
[
|
||||
'article_id' => (int)$articleId,
|
||||
'currency_code' => $currencyCode,
|
||||
'quantity_from' => (float)$quantityFrom
|
||||
]
|
||||
);
|
||||
|
||||
if(!empty($oldPrices)) {
|
||||
foreach($oldPrices as $oldPrice) {
|
||||
if(round($oldPrice['price'],8) === round($price, 8)) {
|
||||
return;
|
||||
}
|
||||
$this->expire($oldPrice['id']);
|
||||
}
|
||||
}
|
||||
try {
|
||||
$conversionRate = $this->currencyConversion->tryGetEuroExchangeRateFromCurrencyCode($currencyCode);
|
||||
}
|
||||
catch (CurrencyExchangeRateNotFoundException $e) {
|
||||
$conversionRate = 0;
|
||||
}
|
||||
$this->db->perform("INSERT INTO verkaufspreise
|
||||
(artikel, objekt, projekt, adresse, preis, waehrung, ab_menge, vpe, vpe_menge, angelegt_am,
|
||||
firma, geloescht, art, gruppe, apichange, nichtberechnet, kurs, kursdatum)
|
||||
VALUES (:article_id, '', 0, 0, :price, :currency_code, :quantity_from, '',0, NOW(),
|
||||
1, 0,'Kunde', 0, 0,1, :conversion_rate, NOW())",
|
||||
[
|
||||
'article_id' => (int)$articleId,
|
||||
'price' => (float)$price,
|
||||
'currency_code' => (String)$currencyCode,
|
||||
'quantity_from' => (float)$quantityFrom,
|
||||
'conversion_rate' => $conversionRate,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $priceArr
|
||||
*/
|
||||
public function setStandardPriceByArray($priceArr)
|
||||
{
|
||||
if(empty($priceArr)) {
|
||||
return;
|
||||
}
|
||||
$articleIds = [];
|
||||
foreach($priceArr as $priceRow) {
|
||||
if(!in_array($priceRow['article_id'], $articleIds, false)) {
|
||||
$articleIds[] = $priceRow['article_id'];
|
||||
}
|
||||
}
|
||||
$select = $this->db->select();
|
||||
$select
|
||||
->cols([
|
||||
'p.id',
|
||||
'p.preis as price',
|
||||
'IF(p.waehrung <> \'\', p.waehrung, \'EUR\') AS currency_code',
|
||||
'p.artikel AS article_id',
|
||||
'p.ab_menge AS quantity_from'
|
||||
]
|
||||
)
|
||||
->from('verkaufspreise AS p')
|
||||
->where("art <> 'Gruppe'AND (IFNULL(gueltig_bis,'0000-00-00') = '0000-00-00' OR gueltig_bis >= CURDATE())
|
||||
AND adresse = 0 AND artikel IN (:articles)")
|
||||
->bindValue('articles', $articleIds);
|
||||
|
||||
$oldPrices = $this->db->fetchAll(
|
||||
$select->getStatement(),
|
||||
$select->getBindValues()
|
||||
);
|
||||
|
||||
$priceTree = [];
|
||||
foreach($oldPrices as $oldPrice) {
|
||||
$priceTree[(int)$oldPrice['article_id']][$oldPrice['currency_code']][round($oldPrice['quantity_from'],8)] =
|
||||
round($oldPrice['price'],8);
|
||||
}
|
||||
unset($oldPrices);
|
||||
|
||||
foreach($priceArr as $prices) {
|
||||
if($prices['currency_code'] === '') {
|
||||
$prices['currency_code'] = 'EUR';
|
||||
}
|
||||
$prices['quantity_from'] = round($prices['quantity_from'], 8);
|
||||
$prices['price'] = round($prices['price'], 8);
|
||||
$prices['article_id'] = (int)$prices['article_id'];
|
||||
$emptyArticle = empty($priceTree[$prices['article_id']]);
|
||||
$emptyCurrency = $emptyArticle|| empty($priceTree[$prices['article_id']][$prices['currency_code']]);
|
||||
if($emptyCurrency
|
||||
|| empty($priceTree[$prices['article_id']][$prices['currency_code']][$prices['quantity_from']])
|
||||
|| $priceTree[$prices['article_id']][$prices['currency_code']][$prices['quantity_from']]
|
||||
!== $prices['price']
|
||||
) {
|
||||
$this->setStandardPrice(
|
||||
$prices['article_id'],
|
||||
$prices['price'],
|
||||
$prices['currency_code'],
|
||||
$prices['quantity_from']
|
||||
);
|
||||
$priceTree[$prices['article_id']][$prices['currency_code']][$prices['quantity_from']] = $prices['price'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $articleId
|
||||
* @param int $addressId
|
||||
* @param float $price
|
||||
* @param string $currencyCode
|
||||
* @param float $quantityFrom
|
||||
*/
|
||||
public function saveCustomerPrice($articleId, $addressId, $price, $currencyCode, $quantityFrom = 0.0)
|
||||
{
|
||||
$this->db->perform("INSERT INTO verkaufspreise
|
||||
(artikel, objekt, projekt, adresse, preis, waehrung, ab_menge, vpe, vpe_menge, angelegt_am,
|
||||
firma, geloescht, art, gruppe, apichange, nichtberechnet)
|
||||
VALUES (:article_id, '', 0, :address_id, :price, :currency_code, :quantity_from, '',0, NOW(),
|
||||
1, 0,'Kunde', 0, 0,1)",
|
||||
[
|
||||
'article_id' => (int)$articleId,
|
||||
'address_id' => (int)$addressId,
|
||||
'price' => (float)$price,
|
||||
'currency_code' => $currencyCode,
|
||||
'quantity_from' => (float)$quantityFrom
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $articleId
|
||||
* @param int $groupId
|
||||
* @param float $price
|
||||
* @param string $currencyCode
|
||||
* @param float $quantityFrom
|
||||
*/
|
||||
public function saveGroupPrice($articleId, $groupId, $price, $currencyCode, $quantityFrom = 0.0)
|
||||
{
|
||||
$this->db->perform("INSERT INTO verkaufspreise
|
||||
(artikel, objekt, projekt, adresse, preis, waehrung, ab_menge, vpe, vpe_menge, angelegt_am,
|
||||
firma, geloescht, art, gruppe, apichange, nichtberechnet)
|
||||
VALUES (:article_id, '', 0, 0, :price, :currency_code, :quantity_from, '',0, NOW(),
|
||||
1, 0, 'Gruppe', :group_id, 0,1)",
|
||||
[
|
||||
'article_id' => (int)$articleId,
|
||||
'group_id' => (int)$groupId,
|
||||
'price' => (float)$price,
|
||||
'currency_code' => $currencyCode,
|
||||
'quantity_from' => (float)$quantityFrom
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $sellingPriceId
|
||||
*/
|
||||
public function delete($sellingPriceId)
|
||||
{
|
||||
$this->db->perform(
|
||||
'DELETE FROM verkaufspreise WHERE id = :sellingprice_id',
|
||||
['sellingprice_id' => $sellingPriceId]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $aricleId
|
||||
*/
|
||||
public function deleteAllByAricleId($aricleId)
|
||||
{
|
||||
$this->db->perform(
|
||||
'DELETE FROM verkaufspreise WHERE artikel = :article_id',
|
||||
['article_id' => (int)$aricleId]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $sellingPriceId
|
||||
*/
|
||||
public function expire($sellingPriceId)
|
||||
{
|
||||
$this->db->perform(
|
||||
'UPDATE verkaufspreise SET gueltig_bis = DATE_SUB(CURDATE(), INTERVAL 1 DAY) WHERE id = :sellingprice_id',
|
||||
['sellingprice_id' => $sellingPriceId]
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user