Add weekly department results route, enhance date handling in invoicing and statistics logic, and improve Slack notification configuration
This commit is contained in:
@@ -446,22 +446,39 @@ class departments_o extends db
|
||||
* Send department period statistics to Slack
|
||||
* @param string $start_date (YYYY-MM-DD)
|
||||
* @param string $end_date (YYYY-MM-DD)
|
||||
* @return void
|
||||
* @param int[] $product_ids The product ids to include in the statistics (e.g. [25, [23, 24], 22, 27, 21, 26])
|
||||
* @param bool $return_as_array Whether to return the results as an array or not
|
||||
* @return string[]
|
||||
* @throws Exception If the department is not selected
|
||||
*/
|
||||
public function sendPeriodStatisticsToSlack(string $start_date, string $end_date): void
|
||||
public function sendPeriodStatisticsToSlack(string $start_date, string $end_date, array $product_ids = [
|
||||
25,
|
||||
[23, 24], // Used to merge two products into one percentage (Spot Free)
|
||||
22,
|
||||
27,
|
||||
21,
|
||||
26
|
||||
], bool $return_as_array = false): array
|
||||
{
|
||||
self::requireSelected();
|
||||
// Ensure only one message is sent a week using redis cache
|
||||
$cacheKey = "department_{$this->id}_weekly_statistics_sent";
|
||||
// Get time until next monday at 00:00:00
|
||||
$nextMonday = strtotime('next monday');
|
||||
$cacheDuration = $nextMonday - time();
|
||||
$lastSent = redis->get($cacheKey);
|
||||
// If null or more than a week has passed since the last message, send a new message
|
||||
$sendNow = match (true) {
|
||||
$lastSent === null => true,
|
||||
default => (time() - $lastSent) >= $cacheDuration
|
||||
};
|
||||
if (!$sendNow) {
|
||||
return $return_as_array ? ["A weekly statistics message has already been sent for this department."] : ["A weekly statistics message has already been sent for this department."];
|
||||
}
|
||||
$this->cache($cacheKey, $cacheDuration);
|
||||
$this->setCachedExpiration($cacheKey, $cacheDuration);
|
||||
// Configuration
|
||||
$department_id = $this->id;
|
||||
$product_ids = [
|
||||
25,
|
||||
[23, 24], // Used to merge two products into one percentage (Spot Free)
|
||||
22,
|
||||
27,
|
||||
21,
|
||||
26
|
||||
];
|
||||
$date_end = date('Y-m-d 23:59:59', strtotime($end_date)); // End date at 23:59:59
|
||||
$date_start = date('Y-m-d 00:00:00', strtotime($start_date)); // Start date at 00:00:00
|
||||
/**
|
||||
@@ -487,6 +504,10 @@ class departments_o extends db
|
||||
$wash_count = (new orders_o())->countWashesInDateRange($date_start, $date_end, $department_id);
|
||||
$analytics = $this->analyzeAddonSalesData($product_ids, $date_start, $date_end, $department_id, $max_addons, $sold_addons, $percentages);
|
||||
$tmp .= "Washes: $wash_count\n" . implode('', $analytics);
|
||||
// If it should be returned as an array, return it as an array instead of sending it to Slack
|
||||
if ($return_as_array) {
|
||||
return explode("\n", trim($tmp));
|
||||
}
|
||||
|
||||
// Check if there's a custom webhook for the department
|
||||
$slack = new slack();
|
||||
@@ -497,6 +518,8 @@ class departments_o extends db
|
||||
// Set the custom webhook for the department
|
||||
$slack->send_webhook_message($tmp, $this->slack_webhook->value());
|
||||
}
|
||||
|
||||
return explode("\n", trim($tmp));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -686,7 +709,8 @@ class departments_o extends db
|
||||
* @param string $date_end (YYYY-MM-DD)
|
||||
* @param int[] $department_ids
|
||||
* @param int[] $product_ids
|
||||
* @return void
|
||||
* @param bool $return_as_array Whether to return the results as an array or not
|
||||
* @return null|array
|
||||
* @throws Exception
|
||||
*/
|
||||
public function sendSlackInternalStatisticNotification(string $date_start, string $date_end, array $department_ids, array $product_ids = [
|
||||
@@ -696,7 +720,7 @@ class departments_o extends db
|
||||
27,
|
||||
21,
|
||||
26
|
||||
]): void
|
||||
], bool $return_as_array = false): null|array
|
||||
{
|
||||
if (empty($department_ids)) {
|
||||
throw new Exception('No department ids provided for the Slack internal statistic notification.');
|
||||
@@ -810,8 +834,25 @@ class departments_o extends db
|
||||
}
|
||||
$tmp .= "> - Total: " . number_format($total_percentage, 2) . "%\n";
|
||||
}
|
||||
$array_of_results = [
|
||||
"daily_management" => [],
|
||||
"departments" => []
|
||||
];
|
||||
// Add $tmp to the daily management message
|
||||
$array_of_results['daily_management'][] = $tmp;
|
||||
|
||||
// Send the message to the internal Slack webhook
|
||||
$slack = new slack();
|
||||
$slack->send_webhook_message($tmp, (new departments_o())->select(10)->slack_webhook->value());
|
||||
if (!$return_as_array) {
|
||||
$slack->send_webhook_message($tmp, (new departments_o())->select(10)->slack_webhook->value());
|
||||
}
|
||||
// Send a department-specific message for each internal department with the percentage of addons sold
|
||||
foreach ( $department_ids as $department_id ) {
|
||||
$department = (new departments_o())->select($department_id);
|
||||
$tmp_dept = $department->sendPeriodStatisticsToSlack($date_start, $date_end, $product_ids, $return_as_array);
|
||||
$array_of_results['departments'][$department_id] = $tmp_dept;
|
||||
}
|
||||
|
||||
return $array_of_results;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,7 +62,11 @@ class InvoicingPeriodRoute
|
||||
self::requireDateFormat($dateFrom, 'Y-m-d');
|
||||
self::requireDateFormat($dateTo, 'Y-m-d');
|
||||
// Add a day to the dateTo parameter to include the end date in the range
|
||||
$dateTo = date('Y-m-d', strtotime($dateTo . ' +1 day'));
|
||||
$dateFrom = date('Y-m-d 00:00:00', strtotime($dateFrom));
|
||||
$dateTo = date('Y-m-d 23:59:59', strtotime($dateTo));
|
||||
// Add date from and date to to the response meta
|
||||
$response->add_meta('date_from', $dateFrom);
|
||||
$response->add_meta('date_to', $dateTo);
|
||||
// Get the invoicing period for the user
|
||||
$response->success([...self::getInvoicingPeriod($dateFrom, $dateTo)]);
|
||||
} else {
|
||||
|
||||
@@ -429,5 +429,66 @@ class departmentsRoute
|
||||
'department_access_:id' => 'Access the department'
|
||||
]
|
||||
);
|
||||
|
||||
self::get('/departments/weekly-results', function () {
|
||||
// Require the user to be logged in
|
||||
global $response;
|
||||
//self::requirePermission('view_department_weekly_results'); TODO: enable permission check once the feature is fully implemented and tested
|
||||
// Get the user object
|
||||
//$user = (new authentication())->get_user();
|
||||
$user = true;
|
||||
// Check if the request was successful
|
||||
if ($user) {
|
||||
// Get the department results for the week
|
||||
$departments_o = new departments_o();
|
||||
$weeks = 5;
|
||||
$results = [];
|
||||
for ($i = 0; $i < $weeks; $i++) {
|
||||
// Get the week number
|
||||
$week_number = date('W', strtotime("-$i week"));
|
||||
// Skip the next week, only show show weeks where at least monday at 00:00:00 is in the past, to prevent showing incomplete data for the current week
|
||||
// Get the weeks monday
|
||||
$week_start = strtotime("-$i week Monday");
|
||||
if ($week_start < strtotime('now')) {
|
||||
$week_monday = date('Y-m-d 00:00:00', $week_start);
|
||||
// Get the weeks sunday from monday
|
||||
$week_sunday = date('Y-m-d 23:59:59', strtotime("$week_monday +6 days"));
|
||||
$results[$week_number] = [
|
||||
'week_number' => $week_number,
|
||||
'week_monday' => $week_monday,
|
||||
'week_sunday' => $week_sunday,
|
||||
'results' => $departments_o->sendSlackInternalStatisticNotification(
|
||||
$week_monday,
|
||||
$week_sunday,
|
||||
[1, 2, 3, 4, 5, 6, 7],
|
||||
// Default value
|
||||
[
|
||||
25,
|
||||
[23, 24], // Used to merge two products into one percentage (Spot Free)
|
||||
22,
|
||||
27,
|
||||
21,
|
||||
26
|
||||
],
|
||||
true // Return the results instead of sending the notification (This is used to show the results in the frontend, instead of sending them to slack.
|
||||
)
|
||||
];
|
||||
}
|
||||
}
|
||||
// Log the incident
|
||||
//(new logs_o())->add('departments', 'global', 1, $user->id, 'VIEW_DEPARTMENT_WEEKLY_RESULTS', 'Successfully viewed department weekly results');
|
||||
// Return the results
|
||||
$response->success($results);
|
||||
} else {
|
||||
// Log the incident
|
||||
//(new logs_o())->add('departments', 'global', 1, 0, 'VIEW_DEPARTMENT_WEEKLY_RESULTS', 'No user found, or invalid session');
|
||||
// Return an error
|
||||
$response->error('Invalid session', 400);
|
||||
}
|
||||
},
|
||||
[
|
||||
'view_department_weekly_results' => 'View department weekly results'
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1000,11 +1000,13 @@ trait db_object_t
|
||||
* @param int $seconds The number of seconds to set the cached object expiration time
|
||||
* @param null $objectId
|
||||
* @return void
|
||||
* @throws Exception If the object is not selected, and no object id is provided, it throws an exception
|
||||
*/
|
||||
public function setCachedExpiration(string $key, int $seconds, $objectId = null): void
|
||||
{
|
||||
// If the object id is not set, use the object id
|
||||
if (!$objectId) {
|
||||
$this->requireSelected();
|
||||
$objectId = $this->id;
|
||||
}
|
||||
// Set the expiration time for the cached data
|
||||
|
||||
Reference in New Issue
Block a user