Add caching methods for invoice period flags and cron jobs for warming caches
- Introduced methods for caching, retrieving, and clearing manual and automatic invoice period flags, as well as order item rows, using the Redis interface. - Implemented `warmManualFlagsCache` and `warmAutomaticFlagsForPeriod` methods in `invoice_period_flag_service` to enhance performance by loading flags and order items into cache. - Added new cron jobs `WarmInvoicePeriodManualFlagsCron` and `WarmInvoicePeriodAutomaticFlagsCron` to regularly update cached data for improved access speeds.
This commit is contained in:
@@ -25,6 +25,7 @@ class invoice_period_flag_service
|
|||||||
private array $economicCustomerDiscountCache = [];
|
private array $economicCustomerDiscountCache = [];
|
||||||
private array $userDisplayNameCache = [];
|
private array $userDisplayNameCache = [];
|
||||||
private array $orderItemsPreviewCache = [];
|
private array $orderItemsPreviewCache = [];
|
||||||
|
private ?array $manualFlagsInstanceCache = null;
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
@@ -186,6 +187,7 @@ class invoice_period_flag_service
|
|||||||
*/
|
*/
|
||||||
public function applyFlagsToPeriodTypes(array $types, string $dateFrom, string $dateTo, ?array $onlyCustomerNumbers = null): array
|
public function applyFlagsToPeriodTypes(array $types, string $dateFrom, string $dateTo, ?array $onlyCustomerNumbers = null): array
|
||||||
{
|
{
|
||||||
|
global $response;
|
||||||
$context = $this->buildPeriodContext($types, $dateFrom, $dateTo, $onlyCustomerNumbers);
|
$context = $this->buildPeriodContext($types, $dateFrom, $dateTo, $onlyCustomerNumbers);
|
||||||
$manualFlags = $this->getManualFlagsForPeriod($context, $dateFrom, $dateTo, $onlyCustomerNumbers);
|
$manualFlags = $this->getManualFlagsForPeriod($context, $dateFrom, $dateTo, $onlyCustomerNumbers);
|
||||||
$automaticFlags = $this->getAutomaticFlagsForPeriod($dateFrom, $dateTo, $onlyCustomerNumbers);
|
$automaticFlags = $this->getAutomaticFlagsForPeriod($dateFrom, $dateTo, $onlyCustomerNumbers);
|
||||||
@@ -317,6 +319,30 @@ class invoice_period_flag_service
|
|||||||
return $this->formatStoredFlag($row);
|
return $this->formatStoredFlag($row);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function warmManualFlagsCache(): void
|
||||||
|
{
|
||||||
|
global $db;
|
||||||
|
|
||||||
|
$result = $db->query(
|
||||||
|
"SELECT * FROM invoice_period_flags
|
||||||
|
WHERE source = '" . self::SOURCE_MANUAL . "'
|
||||||
|
AND status = '" . self::STATUS_ACTIVE . "'
|
||||||
|
ORDER BY created_at ASC, id ASC"
|
||||||
|
);
|
||||||
|
|
||||||
|
$flags = [];
|
||||||
|
if ($result) {
|
||||||
|
while ($row = $result->fetch_assoc()) {
|
||||||
|
$flags[] = $this->formatStoredFlag($row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
(new redis())->cache_invoice_period_manual_flags($flags);
|
||||||
|
} catch (Throwable) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private function formatStoredFlag(array $row): array
|
private function formatStoredFlag(array $row): array
|
||||||
{
|
{
|
||||||
$context = [];
|
$context = [];
|
||||||
@@ -353,6 +379,23 @@ class invoice_period_flag_service
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function getCachedManualFlags(): array
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$flags = (new redis())->get_invoice_period_manual_flags();
|
||||||
|
} catch (Throwable) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_array($flags)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return array_values(array_filter($flags, static function ($flag): bool {
|
||||||
|
return is_array($flag);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
private function buildPeriodContext(array $types, string $dateFrom, string $dateTo, ?array $onlyCustomerNumbers): array
|
private function buildPeriodContext(array $types, string $dateFrom, string $dateTo, ?array $onlyCustomerNumbers): array
|
||||||
{
|
{
|
||||||
$customerNumbers = [];
|
$customerNumbers = [];
|
||||||
@@ -398,16 +441,11 @@ class invoice_period_flag_service
|
|||||||
|
|
||||||
private function getManualFlagsForPeriod(array $context, string $dateFrom, string $dateTo, ?array $onlyCustomerNumbers): array
|
private function getManualFlagsForPeriod(array $context, string $dateFrom, string $dateTo, ?array $onlyCustomerNumbers): array
|
||||||
{
|
{
|
||||||
global $db;
|
if ($this->manualFlagsInstanceCache === null) {
|
||||||
|
$this->manualFlagsInstanceCache = $this->getCachedManualFlags();
|
||||||
$result = $db->query(
|
}
|
||||||
"SELECT * FROM invoice_period_flags
|
$cachedFlags = $this->manualFlagsInstanceCache;
|
||||||
WHERE source = '" . self::SOURCE_MANUAL . "'
|
if (empty($cachedFlags)) {
|
||||||
AND status = '" . self::STATUS_ACTIVE . "'
|
|
||||||
ORDER BY created_at ASC, id ASC"
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!$result || $result->num_rows === 0) {
|
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -424,7 +462,7 @@ class invoice_period_flag_service
|
|||||||
}
|
}
|
||||||
|
|
||||||
$flags = [];
|
$flags = [];
|
||||||
while ($row = $result->fetch_assoc()) {
|
foreach ($cachedFlags as $row) {
|
||||||
$targetType = (string)$row['target_type'];
|
$targetType = (string)$row['target_type'];
|
||||||
$targetId = (int)$row['target_id'];
|
$targetId = (int)$row['target_id'];
|
||||||
$customerNumber = null;
|
$customerNumber = null;
|
||||||
@@ -464,7 +502,7 @@ class invoice_period_flag_service
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$flag = $this->formatStoredFlag($row);
|
$flag = $row;
|
||||||
$flag['customer_number'] = $customerNumber;
|
$flag['customer_number'] = $customerNumber;
|
||||||
$flag['message'] = (string)$flag['reason'];
|
$flag['message'] = (string)$flag['reason'];
|
||||||
$flags[] = $flag;
|
$flags[] = $flag;
|
||||||
@@ -475,16 +513,43 @@ class invoice_period_flag_service
|
|||||||
|
|
||||||
private function getAutomaticFlagsForPeriod(string $dateFrom, string $dateTo, ?array $onlyCustomerNumbers): array
|
private function getAutomaticFlagsForPeriod(string $dateFrom, string $dateTo, ?array $onlyCustomerNumbers): array
|
||||||
{
|
{
|
||||||
$rows = $this->getPeriodOrderItemRows($dateFrom, $dateTo, $onlyCustomerNumbers);
|
try {
|
||||||
$attributes = $this->getCustomerAttributes($onlyCustomerNumbers);
|
$flags = (new redis())->get_invoice_period_automatic_flags($dateFrom, $dateTo);
|
||||||
|
} catch (Throwable) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
return array_merge(
|
if (!is_array($flags)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($onlyCustomerNumbers === null) {
|
||||||
|
return $flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
$allowed = array_fill_keys(array_map('intval', $onlyCustomerNumbers), true);
|
||||||
|
return array_values(array_filter($flags, static function (array $flag) use ($allowed): bool {
|
||||||
|
return isset($allowed[(int)($flag['customer_number'] ?? 0)]);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function warmAutomaticFlagsForPeriod(string $dateFrom, string $dateTo): void
|
||||||
|
{
|
||||||
|
$rows = $this->getPeriodOrderItemRows($dateFrom, $dateTo, null);
|
||||||
|
$attributes = $this->getCustomerAttributes(null);
|
||||||
|
|
||||||
|
$flags = array_merge(
|
||||||
$this->detectCustomerRuleViolations($rows, $attributes),
|
$this->detectCustomerRuleViolations($rows, $attributes),
|
||||||
$this->detectPriceMismatches($rows),
|
$this->detectPriceMismatches($rows),
|
||||||
$this->detectAbnormalQuantities($rows, $dateFrom, $dateTo),
|
$this->detectAbnormalQuantities($rows, $dateFrom, $dateTo),
|
||||||
$this->detectVehicleTypeMismatches($rows, $dateFrom),
|
$this->detectVehicleTypeMismatches($rows, $dateFrom),
|
||||||
$this->detectMissingXlVaskLinks($dateFrom, $dateTo, $onlyCustomerNumbers)
|
$this->detectMissingXlVaskLinks($dateFrom, $dateTo, null)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
(new redis())->cache_invoice_period_automatic_flags($dateFrom, $dateTo, $flags);
|
||||||
|
} catch (Throwable) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function filterSuppressedAutomaticFlags(array $flags): array
|
private function filterSuppressedAutomaticFlags(array $flags): array
|
||||||
@@ -523,12 +588,44 @@ class invoice_period_flag_service
|
|||||||
}
|
}
|
||||||
|
|
||||||
private function getPeriodOrderItemRows(string $dateFrom, string $dateTo, ?array $onlyCustomerNumbers): array
|
private function getPeriodOrderItemRows(string $dateFrom, string $dateTo, ?array $onlyCustomerNumbers): array
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$rows = (new redis())->get_invoice_period_order_item_rows($dateFrom, $dateTo);
|
||||||
|
} catch (Throwable) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!is_array($rows)) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->seedOrderItemsPreviewCacheFromRows($rows);
|
||||||
|
|
||||||
|
if ($onlyCustomerNumbers === null) {
|
||||||
|
return $rows;
|
||||||
|
}
|
||||||
|
|
||||||
|
$allowed = array_fill_keys(array_map('intval', $onlyCustomerNumbers), true);
|
||||||
|
return array_values(array_filter($rows, static function (array $row) use ($allowed): bool {
|
||||||
|
return isset($allowed[(int)($row['customer_number'] ?? 0)]);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function warmOrderItemRowsForPeriod(string $dateFrom, string $dateTo): void
|
||||||
|
{
|
||||||
|
$rows = $this->fetchOrderItemRowsFromDb($dateFrom, $dateTo);
|
||||||
|
try {
|
||||||
|
(new redis())->cache_invoice_period_order_item_rows($dateFrom, $dateTo, $rows);
|
||||||
|
} catch (Throwable) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function fetchOrderItemRowsFromDb(string $dateFrom, string $dateTo): array
|
||||||
{
|
{
|
||||||
global $db;
|
global $db;
|
||||||
|
|
||||||
$customerFilter = $this->customerFilterSql('o.customer_id', $onlyCustomerNumbers);
|
$escapedDateFrom = $db->escape_string($dateFrom);
|
||||||
$dateFrom = $db->escape_string($dateFrom);
|
$escapedDateTo = $db->escape_string($dateTo);
|
||||||
$dateTo = $db->escape_string($dateTo);
|
|
||||||
|
|
||||||
$sql = "
|
$sql = "
|
||||||
SELECT
|
SELECT
|
||||||
@@ -593,9 +690,8 @@ class invoice_period_flag_service
|
|||||||
) category_discount
|
) category_discount
|
||||||
ON category_discount.customer_number = o.customer_id
|
ON category_discount.customer_number = o.customer_id
|
||||||
AND category_discount.product_or_category_id = p.category
|
AND category_discount.product_or_category_id = p.category
|
||||||
WHERE o.created_at BETWEEN '{$dateFrom}' AND '{$dateTo}'
|
WHERE o.created_at BETWEEN '{$escapedDateFrom}' AND '{$escapedDateTo}'
|
||||||
AND o.deleted_at IS NULL
|
AND o.deleted_at IS NULL
|
||||||
{$customerFilter}
|
|
||||||
ORDER BY o.customer_id, o.id, oi.id";
|
ORDER BY o.customer_id, o.id, oi.id";
|
||||||
|
|
||||||
$result = $db->query($sql);
|
$result = $db->query($sql);
|
||||||
|
|||||||
@@ -364,6 +364,89 @@ class redis implements redis_i
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function cache_invoice_period_manual_flags(array $flags): self
|
||||||
|
{
|
||||||
|
$this->set_array('invoice_period_manual_flags', $flags);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function get_invoice_period_manual_flags(): array|null
|
||||||
|
{
|
||||||
|
return $this->get_array('invoice_period_manual_flags');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function clear_invoice_period_manual_flags(): self
|
||||||
|
{
|
||||||
|
$this->delete('invoice_period_manual_flags');
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function invoicePeriodCacheKey(string $prefix, string $dateFrom, string $dateTo): string
|
||||||
|
{
|
||||||
|
return $prefix . ':' . $dateFrom . ':' . $dateTo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function cache_invoice_period_automatic_flags(string $dateFrom, string $dateTo, array $flags): self
|
||||||
|
{
|
||||||
|
$this->set_array($this->invoicePeriodCacheKey('invoice_period_automatic_flags', $dateFrom, $dateTo), $flags);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function get_invoice_period_automatic_flags(string $dateFrom, string $dateTo): array|null
|
||||||
|
{
|
||||||
|
return $this->get_array($this->invoicePeriodCacheKey('invoice_period_automatic_flags', $dateFrom, $dateTo));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function clear_invoice_period_automatic_flags(string $dateFrom, string $dateTo): self
|
||||||
|
{
|
||||||
|
$this->delete($this->invoicePeriodCacheKey('invoice_period_automatic_flags', $dateFrom, $dateTo));
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function cache_invoice_period_order_item_rows(string $dateFrom, string $dateTo, array $rows): self
|
||||||
|
{
|
||||||
|
$this->set_array($this->invoicePeriodCacheKey('invoice_period_order_item_rows', $dateFrom, $dateTo), $rows);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function get_invoice_period_order_item_rows(string $dateFrom, string $dateTo): array|null
|
||||||
|
{
|
||||||
|
return $this->get_array($this->invoicePeriodCacheKey('invoice_period_order_item_rows', $dateFrom, $dateTo));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function clear_invoice_period_order_item_rows(string $dateFrom, string $dateTo): self
|
||||||
|
{
|
||||||
|
$this->delete($this->invoicePeriodCacheKey('invoice_period_order_item_rows', $dateFrom, $dateTo));
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritDoc
|
* @inheritDoc
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
use classes\backup_store;
|
use classes\backup_store;
|
||||||
use classes\economic;
|
use classes\economic;
|
||||||
use classes\economic_transfer_queue;
|
use classes\economic_transfer_queue;
|
||||||
|
use classes\invoice_period_flag_service;
|
||||||
use classes\system_search_cache;
|
use classes\system_search_cache;
|
||||||
use classes\system_search_document_index;
|
use classes\system_search_document_index;
|
||||||
use classes\system_search_economic_customer_index;
|
use classes\system_search_economic_customer_index;
|
||||||
@@ -135,8 +136,38 @@ $cron_tasks = [
|
|||||||
'next_run' => 0,
|
'next_run' => 0,
|
||||||
'function' => 'PruneSystemSessionActivityCron',
|
'function' => 'PruneSystemSessionActivityCron',
|
||||||
],
|
],
|
||||||
|
'WarmInvoicePeriodManualFlagsCron' => [
|
||||||
|
'interval' => 300, // 5 minutes
|
||||||
|
'last_run' => 0,
|
||||||
|
'next_run' => 0,
|
||||||
|
'function' => 'WarmInvoicePeriodManualFlagsCron',
|
||||||
|
],
|
||||||
|
'WarmInvoicePeriodAutomaticFlagsCron' => [
|
||||||
|
'interval' => 300, // 5 minutes
|
||||||
|
'last_run' => 0,
|
||||||
|
'next_run' => 0,
|
||||||
|
'function' => 'WarmInvoicePeriodAutomaticFlagsCron',
|
||||||
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
|
function WarmInvoicePeriodManualFlagsCron(): void
|
||||||
|
{
|
||||||
|
(new invoice_period_flag_service())->warmManualFlagsCache();
|
||||||
|
}
|
||||||
|
|
||||||
|
function WarmInvoicePeriodAutomaticFlagsCron(): void
|
||||||
|
{
|
||||||
|
$service = new invoice_period_flag_service();
|
||||||
|
$now = new DateTime();
|
||||||
|
$previousMonth = new DateTime('first day of previous month');
|
||||||
|
foreach ([$now, $previousMonth] as $date) {
|
||||||
|
$dateFrom = $date->format('Y-m-01');
|
||||||
|
$dateTo = $date->format('Y-m-t');
|
||||||
|
$service->warmOrderItemRowsForPeriod($dateFrom, $dateTo);
|
||||||
|
$service->warmAutomaticFlagsForPeriod($dateFrom, $dateTo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function checkUnfulfilledBookings(): void
|
function checkUnfulfilledBookings(): void
|
||||||
{
|
{
|
||||||
// This is deactivated for now, as it is not wanted.
|
// This is deactivated for now, as it is not wanted.
|
||||||
|
|||||||
@@ -290,6 +290,75 @@ interface redis_i
|
|||||||
*/
|
*/
|
||||||
public function clear_auth_session(string $token): self;
|
public function clear_auth_session(string $token): self;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cache invoice period manual flags payload
|
||||||
|
* @param array $flags
|
||||||
|
* @return self
|
||||||
|
*/
|
||||||
|
public function cache_invoice_period_manual_flags(array $flags): self;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get cached invoice period manual flags payload
|
||||||
|
* @return array|null
|
||||||
|
*/
|
||||||
|
public function get_invoice_period_manual_flags(): array|null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear cached invoice period manual flags payload
|
||||||
|
* @return self
|
||||||
|
*/
|
||||||
|
public function clear_invoice_period_manual_flags(): self;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cache invoice period automatic flags payload for a date range
|
||||||
|
* @param string $dateFrom
|
||||||
|
* @param string $dateTo
|
||||||
|
* @param array $flags
|
||||||
|
* @return self
|
||||||
|
*/
|
||||||
|
public function cache_invoice_period_automatic_flags(string $dateFrom, string $dateTo, array $flags): self;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get cached invoice period automatic flags payload for a date range
|
||||||
|
* @param string $dateFrom
|
||||||
|
* @param string $dateTo
|
||||||
|
* @return array|null
|
||||||
|
*/
|
||||||
|
public function get_invoice_period_automatic_flags(string $dateFrom, string $dateTo): array|null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear cached invoice period automatic flags payload for a date range
|
||||||
|
* @param string $dateFrom
|
||||||
|
* @param string $dateTo
|
||||||
|
* @return self
|
||||||
|
*/
|
||||||
|
public function clear_invoice_period_automatic_flags(string $dateFrom, string $dateTo): self;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cache invoice period order item rows for a date range
|
||||||
|
* @param string $dateFrom
|
||||||
|
* @param string $dateTo
|
||||||
|
* @param array $rows
|
||||||
|
* @return self
|
||||||
|
*/
|
||||||
|
public function cache_invoice_period_order_item_rows(string $dateFrom, string $dateTo, array $rows): self;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get cached invoice period order item rows for a date range
|
||||||
|
* @param string $dateFrom
|
||||||
|
* @param string $dateTo
|
||||||
|
* @return array|null
|
||||||
|
*/
|
||||||
|
public function get_invoice_period_order_item_rows(string $dateFrom, string $dateTo): array|null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear cached invoice period order item rows for a date range
|
||||||
|
* @param string $dateFrom
|
||||||
|
* @param string $dateTo
|
||||||
|
* @return self
|
||||||
|
*/
|
||||||
|
public function clear_invoice_period_order_item_rows(string $dateFrom, string $dateTo): self;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cache a permission evaluation
|
* Cache a permission evaluation
|
||||||
* @param string $cache_key
|
* @param string $cache_key
|
||||||
|
|||||||
Reference in New Issue
Block a user