Optimize order and transaction processing logic with caching, and implement opt-in Slack summaries to reduce request latency.
This commit is contained in:
@@ -1332,31 +1332,42 @@ class orders_o extends db
|
||||
{
|
||||
// Get the original net amount for the order items, ignoring any temporary net amount set
|
||||
self::requireSelected();
|
||||
$order_items = $this->getOrderItems((int)$this->id);
|
||||
//echo 'Calculating net amount for order ID ' . $this->id . ' with ' . count($order_items) . " items\n";
|
||||
return array_sum(array_map(/**
|
||||
* @throws Exception
|
||||
*/ function ($item) {
|
||||
if ( (int)$item['price'] > 0 && (int)$item['quantity'] > 0) {
|
||||
return (int)$item['price'] * (int)$item['quantity'];
|
||||
$order_items = (new order_items_o())->getFieldsWhere(
|
||||
['order_id' => (int)$this->id],
|
||||
['price', 'quantity', 'product_id']
|
||||
);
|
||||
if (empty($order_items)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$total = 0;
|
||||
$department_id = (int)$this->department_id->value();
|
||||
$tmp_user = null;
|
||||
$department_price_cache = [];
|
||||
|
||||
foreach ( $order_items as $item ) {
|
||||
$price = (int)$item['price'];
|
||||
$quantity = (int)$item['quantity'];
|
||||
|
||||
if ($price > 0 && $quantity > 0) {
|
||||
$total += $price * $quantity;
|
||||
continue;
|
||||
}
|
||||
// Otherwise we need to get the product price
|
||||
$product = (new products_o())->select((int)$item['product_id']);
|
||||
// Apply the customer discount if applicable
|
||||
$department_price_original = (int)$product->getDepartmentPrice((int)$this->department_id->value());
|
||||
// Get the customers user object
|
||||
$tmp_user = (new users_o())->getUserByCustomerNumber((int)$this->customer_id->value());
|
||||
// Get the discount percentage for the customer
|
||||
$discount = $tmp_user->getCustomPrice((int)$product->id, false);
|
||||
// Calculate the final price after discount
|
||||
$post_discount = (int)round($department_price_original * (1 - ($discount / 100))) * (int)$item['quantity'];
|
||||
//echo 'Adding ' . $post_discount . ' for product ' . $product->name . ' (Original price: ' . $department_price_original . ', Discount: ' . $discount . '%, Quantity: ' . (int)$item['quantity'] . ")\n";
|
||||
$actual_price = (int)$item['price'];
|
||||
if ($actual_price !== $post_discount) {
|
||||
//echo "Warning: The actual price ($actual_price) does not match the calculated price ($post_discount) for product " . $product->name . "\n";
|
||||
|
||||
$product_id = (int)$item['product_id'];
|
||||
if (!isset($department_price_cache[$product_id])) {
|
||||
$product = (new products_o())->select($product_id);
|
||||
$department_price_cache[$product_id] = (int)$product->getDepartmentPrice($department_id);
|
||||
}
|
||||
return $post_discount;
|
||||
}, $order_items));
|
||||
if ($tmp_user === null) {
|
||||
$tmp_user = (new users_o())->getUserByCustomerNumber((int)$this->customer_id->value());
|
||||
}
|
||||
$discount = $tmp_user->getCustomPrice($product_id, false);
|
||||
$post_discount = (int)round($department_price_cache[$product_id] * (1 - ($discount / 100))) * $quantity;
|
||||
$total += $post_discount;
|
||||
}
|
||||
|
||||
return $total;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1624,4 +1635,4 @@ class orders_o extends db
|
||||
}
|
||||
return $orders;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,6 +54,25 @@ class InvoicingPeriodRoute
|
||||
return self::$departmentExcludedFromInvoicingCache[$departmentId];
|
||||
}
|
||||
|
||||
/**
|
||||
* Slack summaries are expensive on request latency, so they are opt-in.
|
||||
* Enable with query param `sendSlackSummary=1` or env `INVOICING_PERIOD_SEND_SLACK_SUMMARY=true`.
|
||||
*/
|
||||
private static function shouldSendSlackSummary(): bool
|
||||
{
|
||||
$requestOverride = $_GET['sendSlackSummary'] ?? null;
|
||||
if ($requestOverride !== null) {
|
||||
return in_array(strtolower((string)$requestOverride), ['1', 'true', 'yes'], true);
|
||||
}
|
||||
|
||||
$envFlag = getenv('INVOICING_PERIOD_SEND_SLACK_SUMMARY');
|
||||
if ($envFlag === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return in_array(strtolower((string)$envFlag), ['1', 'true', 'yes'], true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $collective_results
|
||||
@@ -538,17 +557,19 @@ class InvoicingPeriodRoute
|
||||
$collective_results['subscription_price_department_distribution_parsed'] = $parsed_distribution;
|
||||
// Include the collective results in the response
|
||||
$response->add_include('collective_subscription_results', $collective_results);
|
||||
// Send summary to slack
|
||||
$slack_message = "Subscription Price Distribution Summary:\n";
|
||||
$slack_message .= "Total Subscription Price: " . $collective_results['total_subscription_price'] . "\n";
|
||||
$slack_message .= "Department Distribution:\n";
|
||||
$tmp_total = 0;
|
||||
foreach ( $collective_results['subscription_price_department_distribution_parsed'] as $department_name => $price ) {
|
||||
$slack_message .= "- " . $department_name . ": " . $price . "\n";
|
||||
$tmp_total += $price;
|
||||
if (self::shouldSendSlackSummary()) {
|
||||
// Send summary to slack
|
||||
$slack_message = "Subscription Price Distribution Summary:\n";
|
||||
$slack_message .= "Total Subscription Price: " . $collective_results['total_subscription_price'] . "\n";
|
||||
$slack_message .= "Department Distribution:\n";
|
||||
$tmp_total = 0;
|
||||
foreach ( $collective_results['subscription_price_department_distribution_parsed'] as $department_name => $price ) {
|
||||
$slack_message .= "- " . $department_name . ": " . $price . "\n";
|
||||
$tmp_total += $price;
|
||||
}
|
||||
$slack_message .= "Total Distribution: " . $tmp_total . "\n";
|
||||
(new slack())->send_message($slack_message, 'Subscription Price Distribution Summary');
|
||||
}
|
||||
$slack_message .= "Total Distribution: " . $tmp_total . "\n";
|
||||
(new slack())->send_message($slack_message, 'Subscription Price Distribution Summary');
|
||||
return $customersWithSubscriptions;
|
||||
}
|
||||
|
||||
@@ -740,11 +761,13 @@ class InvoicingPeriodRoute
|
||||
private static function getOriginalPrice(array $fixed_pricing): array
|
||||
{
|
||||
global $response;
|
||||
$orders = new orders_o();
|
||||
$order_items = new order_items_o();
|
||||
foreach ( $fixed_pricing as &$customer ) {
|
||||
if (isset($customer['meta']['fixed_pricing'])) {
|
||||
$original_price = 0;
|
||||
$department_totals = []; // Array to hold totals per department
|
||||
|
||||
$eligible_transaction_department_ids = [];
|
||||
foreach ( $customer['transactions'] as $transaction ) {
|
||||
$department_id = (int)($transaction['department_id'] ?? 0);
|
||||
$excluded = (bool)($transaction['excluded'] ?? false);
|
||||
@@ -753,16 +776,60 @@ class InvoicingPeriodRoute
|
||||
if ($excluded || $department_id === 10) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$transaction_original_price = $orders->select((int)$transaction['id'])->getNetAmountForOrderItemsOriginal();
|
||||
$original_price += $transaction_original_price;
|
||||
// Initialize the department total if it doesn't exist
|
||||
if (!isset($department_totals[$department_id])) {
|
||||
$department_totals[$department_id] = 0;
|
||||
}
|
||||
// Add the transaction amount to the department total
|
||||
$department_totals[$department_id] += $transaction_original_price;
|
||||
$eligible_transaction_department_ids[(int)$transaction['id']] = $department_id;
|
||||
}
|
||||
|
||||
if (!empty($eligible_transaction_department_ids)) {
|
||||
$transaction_original_prices = [];
|
||||
$product_cache = [];
|
||||
$department_price_cache = [];
|
||||
$discount_cache = [];
|
||||
$user = (new users_o())->getUserByCustomerNumber((int)$customer['customer_number']);
|
||||
$rows = $order_items->getFieldsWhere(
|
||||
['order_id' => array_keys($eligible_transaction_department_ids)],
|
||||
['order_id', 'product_id', 'price', 'quantity']
|
||||
);
|
||||
|
||||
foreach ( $rows as $row ) {
|
||||
$order_id = (int)$row['order_id'];
|
||||
$department_id = (int)($eligible_transaction_department_ids[$order_id] ?? 0);
|
||||
if ($department_id <= 0) {
|
||||
continue;
|
||||
}
|
||||
$product_id = (int)$row['product_id'];
|
||||
$price = (int)$row['price'];
|
||||
$quantity = (int)$row['quantity'];
|
||||
|
||||
if ($price > 0 && $quantity > 0) {
|
||||
$transaction_original_prices[$order_id] = (int)(($transaction_original_prices[$order_id] ?? 0) + ($price * $quantity));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isset($product_cache[$product_id])) {
|
||||
$product_cache[$product_id] = (new products_o())->select($product_id);
|
||||
}
|
||||
if (!isset($department_price_cache[$department_id][$product_id])) {
|
||||
$department_price_cache[$department_id][$product_id] = (int)$product_cache[$product_id]->getDepartmentPrice($department_id);
|
||||
}
|
||||
if (!array_key_exists($product_id, $discount_cache)) {
|
||||
$discount_cache[$product_id] = $user->getCustomPrice($product_id, false);
|
||||
}
|
||||
$post_discount = (int)round($department_price_cache[$department_id][$product_id] * (1 - ($discount_cache[$product_id] / 100))) * $quantity;
|
||||
$transaction_original_prices[$order_id] = (int)(($transaction_original_prices[$order_id] ?? 0) + $post_discount);
|
||||
}
|
||||
|
||||
foreach ( $eligible_transaction_department_ids as $transaction_id => $department_id ) {
|
||||
$transaction_original_price = (int)($transaction_original_prices[$transaction_id] ?? 0);
|
||||
$original_price += $transaction_original_price;
|
||||
// Initialize the department total if it doesn't exist
|
||||
if (!isset($department_totals[$department_id])) {
|
||||
$department_totals[$department_id] = 0;
|
||||
}
|
||||
// Add the transaction amount to the department total
|
||||
$department_totals[$department_id] += $transaction_original_price;
|
||||
}
|
||||
}
|
||||
|
||||
$customer['meta']['fixed_pricing']['original_price'] = $original_price;
|
||||
$customer['meta']['fixed_pricing']['department_totals'] = $department_totals;
|
||||
// Take the relative price of the department totals in relation to the fixed price
|
||||
@@ -810,25 +877,27 @@ class InvoicingPeriodRoute
|
||||
$collective_results = self::parseTheDepartmentIdsToDepartmentNames($collective_results);
|
||||
// Include the collective results in the response
|
||||
$response->add_include('collective_fixed_pricing_results', $collective_results);
|
||||
// Send slack message with the collective results
|
||||
$slack_message = "Fixed Pricing Invoicing Period Summary:\n";
|
||||
$slack_message .= "Total Fixed Price: " . number_format($collective_results['total_fixed_price'], 2) . " DKK\n";
|
||||
$slack_message .= "Total Original Price: " . number_format($collective_results['total_original_price'], 2) . " DKK\n";
|
||||
$slack_message .= "Department Totals:\n";
|
||||
$tmp_sum = 0;
|
||||
foreach ( $collective_results['total_department_totals_parsed'] as $department_name => $amount ) {
|
||||
$slack_message .= "- " . $department_name . ": " . number_format($amount, 2) . " DKK\n";
|
||||
$tmp_sum += $amount;
|
||||
if (self::shouldSendSlackSummary()) {
|
||||
// Send slack message with the collective results
|
||||
$slack_message = "Fixed Pricing Invoicing Period Summary:\n";
|
||||
$slack_message .= "Total Fixed Price: " . number_format($collective_results['total_fixed_price'], 2) . " DKK\n";
|
||||
$slack_message .= "Total Original Price: " . number_format($collective_results['total_original_price'], 2) . " DKK\n";
|
||||
$slack_message .= "Department Totals:\n";
|
||||
$tmp_sum = 0;
|
||||
foreach ( $collective_results['total_department_totals_parsed'] as $department_name => $amount ) {
|
||||
$slack_message .= "- " . $department_name . ": " . number_format($amount, 2) . " DKK\n";
|
||||
$tmp_sum += $amount;
|
||||
}
|
||||
$slack_message .= "Total Department Totals: " . number_format($tmp_sum, 2) . " DKK\n";
|
||||
$slack_message .= "Relative Department Totals:\n";
|
||||
$tmp_sum = 0;
|
||||
foreach ( $collective_results['total_department_totals_relative_parsed'] as $department_name => $amount ) {
|
||||
$slack_message .= "- " . $department_name . ": " . number_format($amount, 2) . " DKK\n";
|
||||
$tmp_sum += $amount;
|
||||
}
|
||||
$slack_message .= "Total Relative Department Totals: " . number_format($tmp_sum, 2) . " DKK\n";
|
||||
(new slack())->send_message($slack_message, 'Fixed Pricing Invoicing Period Summary');
|
||||
}
|
||||
$slack_message .= "Total Department Totals: " . number_format($tmp_sum, 2) . " DKK\n";
|
||||
$slack_message .= "Relative Department Totals:\n";
|
||||
$tmp_sum = 0;
|
||||
foreach ( $collective_results['total_department_totals_relative_parsed'] as $department_name => $amount ) {
|
||||
$slack_message .= "- " . $department_name . ": " . number_format($amount, 2) . " DKK\n";
|
||||
$tmp_sum += $amount;
|
||||
}
|
||||
$slack_message .= "Total Relative Department Totals: " . number_format($tmp_sum, 2) . " DKK\n";
|
||||
(new slack())->send_message($slack_message, 'Fixed Pricing Invoicing Period Summary');
|
||||
return $fixed_pricing;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user