Newer
Older
<?php
/**
* This file contains QUI\ERP\Process
*/
namespace QUI\ERP;
use QUI;
use function array_filter;
use function array_map;
use function array_merge;
use function class_exists;
use function is_callable;
/**
* Class Process

Henning Leutz
committed
* - represents a complete erp process
*
* @package QUI\ERP
*/
class Process
{
/**
* this date determines when the global process ids start to work.
* also the relationships.
*/
const PROCESS_ACTIVE_DATE = '2024-07-01 00:00:00';
/**
* @var string
*/
/**
* @var null|array
*/

Henning Leutz
committed
/**
* @var null|QUI\ERP\Comments
*/

Henning Leutz
committed
/**
* Process constructor.
*
* @param string $processId - the global process id
*/
{
$this->processId = $processId;
}
/**

Henning Leutz
committed
* Return the db table name
*

Henning Leutz
committed
* @return string
*/
{

Henning Leutz
committed
return QUI::getDBTableName('process');
}
public function getUUID(): string
{
return $this->processId;
}
/**
* Return all entities which are connected to this process
*
*/
public function getEntities(): array
{
$entities = array_merge(
$this->getInvoices(),
$this->getOrders(),
$this->getOffers(),
$this->getBookings(),
$this->getPurchasing(),
$this->getSalesOrders()
);
return array_filter($entities);
}
/**
* This method is designed to organize and group ERP transaction entities that implement the ErpTransactionsInterface.
* It filters entities such as invoices, invoice drafts, orders,
* and other related items to identify and group together entities that are interconnected.
*
* For instance, if an order generates an invoice, this method will group them together.
* The primary function is to categorize these ERP entities based on their relationships and associations,
* facilitating easier management and retrieval of related transactional data within the ERP system.
*
* @param callable|null $filterEntityTypes - own filter function
public function getGroupedRelatedTransactionEntities(?callable $filterEntityTypes = null): array
{
$entities = $this->getEntities();
$entities = array_filter($entities, function ($obj) {
return $obj instanceof ErpTransactionsInterface;
});
if (is_callable($filterEntityTypes)) {
$entities = array_filter($entities, $filterEntityTypes);
}
$groups = [];
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
// invoices into the groups
if (
class_exists('QUI\ERP\Accounting\Invoice\Invoice')
&& class_exists('QUI\ERP\Accounting\Invoice\InvoiceTemporary')
) {
foreach ($entities as $Entity) {
if (
!($Entity instanceof QUI\ERP\Accounting\Invoice\Invoice
|| $Entity instanceof QUI\ERP\Accounting\Invoice\InvoiceTemporary)
) {
continue;
}
$uuid = $Entity->getUUID();
$groups[$uuid][] = $Entity;
if (class_exists('QUI\ERP\Order\Handler') && $Entity->getAttribute('order_id')) {
try {
$groups[$uuid][] = QUI\ERP\Order\Handler::getInstance()->get(
$Entity->getAttribute('order_id')
);
} catch (QUI\Exception) {
}
}
if (class_exists('QUI\ERP\SalesOrders\SalesOrder')) {
$salesOrder = $Entity->getPaymentData('salesOrder');
if ($salesOrder) {
try {
$groups[$uuid][] = QUI\ERP\SalesOrders\Handler::getSalesOrder($salesOrder['hash']);
} catch (QUI\Exception) {
}
}
}
}
}
// not group
$notGroup = [];
$isInGroups = function (ErpEntityInterface $Entity) use ($groups) {
foreach ($groups as $group) {
foreach ($group as $EntityInstance) {
if ($Entity->getUUID() === $EntityInstance->getUUID()) {
return true;
}
}
}
return false;
};
foreach ($entities as $Entity) {
if (!$isInGroups($Entity)) {
$notGroup[] = $Entity;
}
}
// resulting
$entitiesArray = array_map(function ($Entity) {
return $Entity->toArray();
}, $entities);
$notGroup = array_map(function ($Entity) {
return $Entity->toArray();
}, $notGroup);
$grouped = [];
foreach ($groups as $key => $entries) {
foreach ($entries as $entity) {
$grouped[$key][] = $entity->toArray();
}
}
return [
'entities' => $entitiesArray,
'grouped' => $grouped,
'notGroup' => $notGroup
];
}

Henning Leutz
committed
//region messages

Henning Leutz
committed
/**
* Add a comment to the history for the complete process
*
* @param string $message
* @param bool|int $time - optional, unix timestamp

Henning Leutz
committed
*/
public function addHistory(string $message, bool|int $time = false): void

Henning Leutz
committed
{
$this->getHistory()->addComment($message, $time);
try {
QUI::getDataBase()->update(
$this->table(),
['history' => $this->getHistory()->toJSON()],
['id' => $this->processId]
);
} catch (\QUI\Exception $Exception) {
QUI\System\Log::addError($Exception->getMessage());
}
}
/**

Henning Leutz
committed
* Return the history of the process
* This history only contains the process history
*
* If you want the complete history of all process objects, use getCompleteHistory()
*
* @return QUI\ERP\Comments
*/
{

Henning Leutz
committed
if ($this->History === null) {
$history = '';
'where' => [
'id' => $this->processId
],
'limit' => 1
if (isset($result[0]['history'])) {
$history = $result[0]['history'];
QUI::getDataBase()->insert($this->table(), [
'id' => $this->processId
]);
}
} catch (\QUI\Exception $Exception) {
QUI\System\Log::addError($Exception->getMessage());

Henning Leutz
committed
}
$this->History = QUI\ERP\Comments::unserialize($history);
}

Henning Leutz
committed
return $this->History;
}

Henning Leutz
committed
/**
* Return a complete history of all process objects

Henning Leutz
committed
*
* @return Comments
*/

Henning Leutz
committed
{
$History = $this->getHistory();
$this->parseInvoices($History);
$this->parseOffers($History);
$this->parseSalesOrders($History);
$this->parseTransactions($History);

Henning Leutz
committed
if ($History->isEmpty()) {
$History->addComment(
QUI::getLocale()->get('quiqqer/erp', 'process.history.empty.info'),
strtotime(self::PROCESS_ACTIVE_DATE),
'quiqqer/erp',
'fa fa-info'
);
}
try {
QUI::getEvents()->fireEvent('quiqqerErpGetCompleteHistory', [$this, $this->processId]);
} catch (\Exception $exception) {
QUI\System\Log::addError($exception->getMessage());
}
try {
QUI::getEvents()->fireEvent('quiqqerErpProcessHistory', [$this, $this->processId]);
} catch (\Exception $exception) {
QUI\System\Log::addError($exception->getMessage());
}

Henning Leutz
committed
return $History;
}
//endregion
//region invoice
protected function parseInvoices(Comments $History): void
{
$invoices = $this->getInvoices();
foreach ($invoices as $Invoice) {
$History->addComment(
QUI::getLocale()->get('quiqqer/erp', 'process.history.invoice.created', [
]),
strtotime($Invoice->getAttribute('date')),
'quiqqer/invoice',
'fa fa-file-text-o',
false,
);
$history = $Invoice->getHistory()->toArray();
foreach ($history as $entry) {
if (empty($entry['source'])) {
$entry['source'] = 'quiqqer/invoice';
}
if (empty($entry['sourceIcon'])) {
$entry['sourceIcon'] = 'fa fa-file-text-o';
}
$History->addComment(
$entry['message'],
$entry['time'],
$entry['source'],
$entry['sourceIcon'],
/**
* Return if the process has invoices or not
*
* @return bool
*/
{
$invoices = $this->getInvoices();
foreach ($invoices as $Invoice) {
if ($Invoice instanceof QUI\ERP\Accounting\Invoice\Invoice) {
return true;
}
}
return false;
}
/**
* Return if the process has temporary invoices or not
*
* @return bool
*/
{
$invoices = $this->getInvoices();
foreach ($invoices as $Invoice) {
if ($Invoice instanceof QUI\ERP\Accounting\Invoice\InvoiceTemporary) {
return true;
}
}
return false;
}
/**

Henning Leutz
committed
* @return Accounting\Invoice\Invoice[]|Accounting\Invoice\InvoiceTemporary[]
*/
{
if (!QUI::getPackageManager()->isInstalled('quiqqer/invoice')) {
return [];
}
$invoices = QUI\ERP\Accounting\Invoice\Handler::getInstance()->getInvoicesByGlobalProcessId(
$this->processId
);
$processDate = strtotime(self::PROCESS_ACTIVE_DATE);
return array_filter($invoices, function ($Invoice) use ($processDate) {
$createDate = $Invoice->getAttribute('c_date');
$createDate = strtotime($createDate);
if ($createDate > $processDate) {
return true;
}
return false;
});
}
//endregion
//region order
protected function parseOrders(Comments $History): void
{
// orders
$orders = $this->getOrders();
foreach ($orders as $Order) {
$history = $Order->getHistory()->toArray();
$hasCreateMessage = false;
$createMessage = QUI::getLocale()->get('quiqqer/erp', 'process.history.order.created', [
]);
foreach ($history as $entry) {
if ($entry['message'] === $createMessage) {
$hasCreateMessage = true;
break;
}
}
if ($hasCreateMessage === false) {
$History->addComment(
$createMessage,
strtotime($Order->getCreateDate()),
'quiqqer/order',
'fa fa-shopping-basket'
);
}
foreach ($history as $entry) {
if (empty($entry['source'])) {
$entry['source'] = 'quiqqer/order';
}
if (empty($entry['sourceIcon'])) {
$entry['sourceIcon'] = 'fa fa-shopping-basket';
}
$History->addComment(
$entry['message'],
$entry['time'],
$entry['source'],
$entry['sourceIcon'],
/**
* @return bool
*/
{
return !($this->getOrder() === null);
}
/**

Henning Leutz
committed
* Return the first order of the process
*
*/
public function getOrder(): Order\OrderInProcess|Order\Order|null
{
if (!QUI::getPackageManager()->isInstalled('quiqqer/order')) {
return null;
}
$OrderHandler = QUI\ERP\Order\Handler::getInstance();
try {
return $OrderHandler->getOrderByGlobalProcessId($this->processId);
} catch (QUI\Exception $Exception) {
QUI\System\Log::writeDebugException($Exception);
}
try {
return $OrderHandler->getOrderByHash($this->processId);
} catch (QUI\Exception $Exception) {
QUI\System\Log::writeDebugException($Exception);
}
return null;
}

Henning Leutz
committed
/**
* Return all orders from the process
*

Henning Leutz
committed
*/
public function getOrders(): array

Henning Leutz
committed
{
if (!QUI::getPackageManager()->isInstalled('quiqqer/order')) {
return [];
}
$orders = QUI\ERP\Order\Handler::getInstance()->getOrdersByGlobalProcessId($this->processId);
$processDate = strtotime(self::PROCESS_ACTIVE_DATE);
return array_filter($orders, function ($Order) use ($processDate) {
$createDate = $Order->getAttribute('c_date');
$createDate = strtotime($createDate);
if ($createDate > $processDate) {
return true;
}
return false;
});

Henning Leutz
committed
return [];
}
}
//endregion
//region offers
protected function parseOffers(Comments $History): void
{
if (!QUI::getPackageManager()->isInstalled('quiqqer/offers')) {
return;
}
// orders
$offers = $this->getOffers();
foreach ($offers as $Offer) {
$History->addComment(
QUI::getLocale()->get('quiqqer/erp', 'process.history.offer.created', [
'hash' => $Offer->getHash()
]),
strtotime($Offer->getAttribute('date')),
'quiqqer/offer',
false,
$Offer->getHash()
);
$history = $Offer->getHistory()->toArray();
foreach ($history as $entry) {
if (empty($entry['source'])) {
$entry['source'] = 'quiqqer/offer';
}
if (empty($entry['sourceIcon'])) {
$entry['sourceIcon'] = 'fa fa-regular fa-handshake';
}
$History->addComment(
$entry['message'],
$entry['time'],
$entry['source'],
$entry['sourceIcon'],
$entry['id'],
$Offer->getHash()
);
}
}
}
/**
* @return QUI\ERP\Accounting\Offers\Offer[]
*/
public function getOffers(): array
{
if (!QUI::getPackageManager()->isInstalled('quiqqer/offers')) {
return [];
}
try {
$offers = QUI::getDatabase()->fetch([
'select' => 'id,hash,global_process_id,date',
'from' => QUI\ERP\Accounting\Offers\Handler::getInstance()->offersTable(),
'where_or' => [
'global_process_id' => $this->processId,
'hash' => $this->processId
]
]);
} catch (\Exception) {
$Offers = QUI\ERP\Accounting\Offers\Handler::getInstance();
foreach ($offers as $offer) {
try {
$result[] = $Offers->getOffer($offer['id']);
} catch (\Exception) {
}
}
// temporary
try {
$temporaryOffers = QUI::getDatabase()->fetch([
'select' => 'id,hash,global_process_id,date',
'from' => QUI\ERP\Accounting\Offers\Handler::getInstance()->temporaryOffersTable(),
'where_or' => [
'global_process_id' => $this->processId,
'hash' => $this->processId
]
]);
} catch (\Exception) {
$temporaryOffers = [];
}
foreach ($temporaryOffers as $temporaryOffer) {
try {
$result[] = $Offers->getTemporaryOffer($temporaryOffer['id']);
} catch (\Exception) {
}
}
$processDate = strtotime(self::PROCESS_ACTIVE_DATE);
return array_filter($result, function ($Offer) use ($processDate) {
$createDate = $Offer->getAttribute('c_date');
$createDate = strtotime($createDate);
if ($createDate > $processDate) {
return true;
}
return false;
});
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
//region booking
protected function parseBookings(Comments $History): void
{
// orders
$bookings = $this->getBookings();
foreach ($bookings as $Booking) {
$History->addComment(
QUI::getLocale()->get('quiqqer/erp', 'process.history.booking.created', [
'hash' => $Booking->getUuid()
]),
$Booking->getCreateDate()->getTimestamp(),
'quiqqer/booking',
'fa fa-ticket',
false,
$Booking->getUuid()
);
$history = $Booking->getHistory()->toArray();
foreach ($history as $entry) {
if (empty($entry['source'])) {
$entry['source'] = 'quiqqer/booking';
}
if (empty($entry['sourceIcon'])) {
$entry['sourceIcon'] = 'fa fa-ticket';
}
$History->addComment(
$entry['message'],
$entry['time'],
$entry['source'],
$entry['sourceIcon'],
$entry['id'],
$Booking->getUuid()
);
}
}
}
/**
* @return array
*/
public function getBookings(): array
{
if (!QUI::getPackageManager()->isInstalled('quiqqer/booking')) {
return [];
}
if (!class_exists('QUI\ERP\Booking\Repository\BookingRepository')) {
return [];
}
if (!class_exists('QUI\ERP\Booking\Table')) {
return [];
}
try {
$bookings = QUI::getDatabase()->fetch([
'select' => 'uuid,globalProcessId,createDate',
'from' => QUI\ERP\Booking\Table::BOOKINGS->tableName(),
'where_or' => [
'globalProcessId' => $this->processId,
'uuid' => $this->processId
]
]);
} catch (\Exception) {
return [];
}
$result = [];
$BookingRepository = new QUI\ERP\Booking\Repository\BookingRepository();
foreach ($bookings as $booking) {
try {
$result[] = $BookingRepository->getByUuid($booking['uuid']);
} catch (\Exception) {
}
}
$processDate = strtotime(self::PROCESS_ACTIVE_DATE);
return array_filter($result, function ($Booking) use ($processDate) {
// @todo c_date??
$createDate = $Booking->getAttribute('c_date');
$createDate = strtotime($createDate);
if ($createDate > $processDate) {
return true;
}
return false;
});
//region purchase / Einkauf
protected function parsePurchasing(Comments $History): void
{
// orders
$purchasing = $this->getPurchasing();
foreach ($purchasing as $Purchasing) {
$History->addComment(
QUI::getLocale()->get('quiqqer/erp', 'process.history.purchasing.created', [
'hash' => $Purchasing->getHash()
]),
strtotime($Purchasing->getAttribute('c_date')),
'quiqqer/purchasing',
'fa fa-cart-arrow-down',
false,
$Purchasing->getHash()
);
$history = $Purchasing->getHistory()->toArray();
foreach ($history as $entry) {
if (empty($entry['source'])) {
$entry['source'] = 'quiqqer/purchasing';
}
if (empty($entry['sourceIcon'])) {
$entry['sourceIcon'] = 'fa fa-cart-arrow-down';
}
$History->addComment(
$entry['message'],
$entry['time'],
$entry['source'],
$entry['sourceIcon'],
$entry['id'],
$Purchasing->getHash()
*/
public function getPurchasing(): array
{
if (!QUI::getPackageManager()->isInstalled('quiqqer/purchasing')) {
return [];
}
if (!class_exists('QUI\ERP\Purchasing\Processes\PurchasingProcess')) {
return [];
}
if (!class_exists('QUI\ERP\Purchasing\Processes\Handler')) {
return [];
}
try {
$purchasing = QUI::getDatabase()->fetch([
'select' => 'id,hash,global_process_id,date',
'from' => QUI\ERP\Purchasing\Processes\Handler::getTablePurchasingProcesses(),
'where_or' => [
'global_process_id' => $this->processId,
'hash' => $this->processId
]
]);
} catch (\Exception) {
return [];
}
$result = [];
foreach ($purchasing as $process) {
try {
$result[] = QUI\ERP\Purchasing\Processes\Handler::getPurchasingProcess($process['id']);
$processDate = strtotime(self::PROCESS_ACTIVE_DATE);
return array_filter($result, function ($Purchase) use ($processDate) {
$createDate = $Purchase->getAttribute('c_date');
$createDate = strtotime($createDate);
if ($createDate > $processDate) {
return true;
}
return false;
});
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
//region sales orders / Aufträge
protected function parseSalesOrders(Comments $History): void
{
// orders
$salesOrders = $this->getSalesOrders();
foreach ($salesOrders as $SalesOrder) {
$History->addComment(
QUI::getLocale()->get('quiqqer/erp', 'process.history.salesorders.created', [
'hash' => $SalesOrder->getHash()
]),
strtotime($SalesOrder->getAttribute('c_date')),
'quiqqer/salesorders',
'fa fa-suitcase',
false,
$SalesOrder->getHash()
);
$history = $SalesOrder->getHistory()->toArray();
foreach ($history as $entry) {
if (empty($entry['source'])) {
$entry['source'] = 'quiqqer/salesorders';
}
if (empty($entry['sourceIcon'])) {
$entry['sourceIcon'] = 'fa fa-suitcase';
}
$History->addComment(
$entry['message'],
$entry['time'],
$entry['source'],
$entry['sourceIcon'],
$entry['id'],
$SalesOrder->getHash()
);
}
}
}
/**
*/
public function getSalesOrders(): array
{
if (!QUI::getPackageManager()->isInstalled('quiqqer/salesorders')) {
return [];
}
try {
$salesOrders = QUI::getDatabase()->fetch([
'select' => 'id,hash,global_process_id,date',
'from' => QUI\ERP\SalesOrders\Handler::getTableSalesOrders(),
'where_or' => [
'global_process_id' => $this->processId,
'hash' => $this->processId
]
]);
} catch (\Exception) {
return [];
}
$result = [];
foreach ($salesOrders as $salesOrder) {
try {
$result[] = QUI\ERP\SalesOrders\Handler::getSalesOrder($salesOrder['id']);
} catch (\Exception) {
}
}
$processDate = strtotime(self::PROCESS_ACTIVE_DATE);
return array_filter($result, function ($SalesOrder) use ($processDate) {
$createDate = $SalesOrder->getAttribute('c_date');
$createDate = strtotime($createDate);
if ($createDate > $processDate) {
return true;
}
return false;
});
//region transactions
protected function parseTransactions(Comments $History): void
{
// orders
$transactions = $this->getTransactions();
foreach ($transactions as $Transaction) {
$History->addComment(
QUI::getLocale()->get('quiqqer/erp', 'process.history.transaction.created', [
'hash' => $Transaction->getHash(),
'amount' => $Transaction->getAmountFormatted()
]),
strtotime($Transaction->getDate()),
'quiqqer/payment-transaction',
'fa fa-money',
false,
$Transaction->getHash()
);
}
}
/**
* @return bool
*/
{
$transactions = $this->getTransactions();
}
/**
* Return all related transactions
*
* @return QUI\ERP\Accounting\Payments\Transactions\Transaction[];
*/
{
if (!QUI::getPackageManager()->isInstalled('quiqqer/payment-transactions')) {
return [];
}
if ($this->transactions !== null) {
return $this->transactions;
}
$Transactions = QUI\ERP\Accounting\Payments\Transactions\Handler::getInstance();
$transactions = $Transactions->getTransactionsByProcessId($this->processId);
$processDate = strtotime(self::PROCESS_ACTIVE_DATE);
$this->transactions = array_filter($transactions, function ($Transaction) use ($processDate) {
$createDate = $Transaction->getDate();
$createDate = strtotime($createDate);
if ($createDate > $processDate) {
return true;
}
return false;
});
return $this->transactions;
}
//endregion
}