From b3f059ad04fc0f54282aea98c5c2af8d7e46867a Mon Sep 17 00:00:00 2001 From: Igor Scheller Date: Fri, 21 Dec 2018 20:09:15 +0100 Subject: [PATCH] metrics: Added vouchers and tshirts --- src/Controllers/Metrics/Controller.php | 18 +++++- src/Controllers/Metrics/Stats.php | 35 ++++++++++- .../Controllers/Metrics/ControllerTest.php | 13 ++++ tests/Unit/Controllers/Metrics/StatsTest.php | 63 +++++++++++++++++-- 4 files changed, 121 insertions(+), 8 deletions(-) diff --git a/src/Controllers/Metrics/Controller.php b/src/Controllers/Metrics/Controller.php index 0fd26396..86c21562 100644 --- a/src/Controllers/Metrics/Controller.php +++ b/src/Controllers/Metrics/Controller.php @@ -55,6 +55,17 @@ class Controller extends BaseController $now = microtime(true); $this->checkAuth(); + $tshirtSizes = []; + $userSizes = $this->stats->tshirtSizes(); + + foreach ($this->config->get('tshirt_sizes') as $name => $description) { + $size = $userSizes->where('shirt_size', '=', $name)->sum('count'); + $tshirtSizes[] = [ + 'labels' => ['size' => $name], + $size, + ]; + } + $data = [ $this->config->get('app_name') . ' stats', 'users' => [ @@ -84,6 +95,9 @@ class Controller extends BaseController ['labels' => ['state' => 'freeloaded'], 'value' => $this->stats->workSeconds(null, true)], ], 'worklog_seconds' => ['type' => 'gauge', $this->stats->worklogSeconds()], + 'vouchers' => ['type' => 'counter', $this->stats->vouchers()], + 'tshirts_issued' => ['type' => 'counter', 'help' => 'Issued T-Shirts', $this->stats->tshirts()], + 'tshirt_sizes' => ['type' => 'gauge', 'help' => 'The sizes users have configured'] + $tshirtSizes, 'shifts' => ['type' => 'gauge', $this->stats->shifts()], 'announcements' => [ 'type' => 'gauge', @@ -92,8 +106,8 @@ class Controller extends BaseController ], 'questions' => [ 'type' => 'gauge', - ['labels' => ['answered' => true], 'value' => $this->stats->questions(true)], - ['labels' => ['answered' => false], 'value' => $this->stats->questions(false)], + ['labels' => ['state' => 'answered'], 'value' => $this->stats->questions(true)], + ['labels' => ['state' => 'pending'], 'value' => $this->stats->questions(false)], ], 'messages' => ['type' => 'gauge', $this->stats->messages()], 'password_resets' => ['type' => 'gauge', $this->stats->passwordResets()], diff --git a/src/Controllers/Metrics/Stats.php b/src/Controllers/Metrics/Stats.php index 838411d1..11643e46 100644 --- a/src/Controllers/Metrics/Stats.php +++ b/src/Controllers/Metrics/Stats.php @@ -96,6 +96,40 @@ class Stats return $query->count(); } + /** + * @return int + */ + public function vouchers(): int + { + return $this + ->getQuery('users_state') + ->sum('got_voucher'); + } + + /** + * @return int + */ + public function tshirts(): int + { + return $this + ->getQuery('users_state') + ->where('got_shirt', '=', true) + ->count(); + } + + /** + * @return \Illuminate\Support\Collection + */ + public function tshirtSizes() + { + return $this + ->getQuery('users_personal_data') + ->select(['shirt_size', $this->raw('COUNT(shirt_size) AS count')]) + ->whereNotNull('shirt_size') + ->groupBy('shirt_size') + ->get(); + } + /** * @param string $vehicle * @return int @@ -267,7 +301,6 @@ class Stats /** * @param mixed $value * @return QueryExpression - * @codeCoverageIgnore */ protected function raw($value) { diff --git a/tests/Unit/Controllers/Metrics/ControllerTest.php b/tests/Unit/Controllers/Metrics/ControllerTest.php index 37310ddf..56415e23 100644 --- a/tests/Unit/Controllers/Metrics/ControllerTest.php +++ b/tests/Unit/Controllers/Metrics/ControllerTest.php @@ -10,6 +10,7 @@ use Engelsystem\Http\Exceptions\HttpForbidden; use Engelsystem\Http\Request; use Engelsystem\Http\Response; use Engelsystem\Test\Unit\TestCase; +use Illuminate\Support\Collection; use PHPUnit\Framework\MockObject\MockObject; use Psr\Log\LogLevel; use Symfony\Component\HttpFoundation\ServerBag; @@ -41,6 +42,9 @@ class ControllerTest extends TestCase $this->assertArrayHasKey('users_working', $data); $this->assertArrayHasKey('work_seconds', $data); $this->assertArrayHasKey('worklog_seconds', $data); + $this->assertArrayHasKey('vouchers', $data); + $this->assertArrayHasKey('tshirts_issued', $data); + $this->assertArrayHasKey('tshirt_sizes', $data); $this->assertArrayHasKey('shifts', $data); $this->assertArrayHasKey('announcements', $data); $this->assertArrayHasKey('questions', $data); @@ -102,12 +106,21 @@ class ControllerTest extends TestCase ->willReturnOnConsecutiveCalls(0, 1, 0, 5, 999, 4, 55, 3); $this->setExpects($stats, 'newUsers', null, 9); $this->setExpects($stats, 'worklogSeconds', null, 39 * 60 * 60); + $this->setExpects($stats, 'vouchers', null, 17); + $this->setExpects($stats, 'tshirts', null, 3); + $this->setExpects($stats, 'tshirtSizes', null, new Collection([ + (object)['shirt_size' => 'L', 'count' => 2], + ])); $this->setExpects($stats, 'shifts', null, 142); $this->setExpects($stats, 'messages', null, 3); $this->setExpects($stats, 'passwordResets', null, 1); $this->setExpects($stats, 'sessions', null, 1234); $config->set('registration_enabled', 1); + $config->set('tshirt_sizes', [ + 'L' => 'Large', + 'XL' => 'X Large', + ]); $controller = new Controller($response, $engine, $config, $request, $stats); $controller->metrics(); diff --git a/tests/Unit/Controllers/Metrics/StatsTest.php b/tests/Unit/Controllers/Metrics/StatsTest.php index 2ebe52ae..8dc7459e 100644 --- a/tests/Unit/Controllers/Metrics/StatsTest.php +++ b/tests/Unit/Controllers/Metrics/StatsTest.php @@ -6,10 +6,12 @@ use Carbon\Carbon; use Engelsystem\Controllers\Metrics\Stats; use Engelsystem\Models\LogEntry; use Engelsystem\Models\User\PasswordReset; +use Engelsystem\Models\User\PersonalData; use Engelsystem\Models\User\State; use Engelsystem\Models\User\User; use Engelsystem\Test\Unit\HasDatabase; use Engelsystem\Test\Unit\TestCase; +use Illuminate\Support\Collection; use Illuminate\Support\Str; use Psr\Log\LogLevel; @@ -31,6 +33,48 @@ class StatsTest extends TestCase $this->assertEquals(2, $stats->newUsers()); } + /** + * @covers \Engelsystem\Controllers\Metrics\Stats::vouchers + */ + public function testVouchers() + { + $this->initDatabase(); + $this->addUsers(); + + $stats = new Stats($this->database); + $this->assertEquals(14, $stats->vouchers()); + } + + /** + * @covers \Engelsystem\Controllers\Metrics\Stats::tshirts + */ + public function testTshirts() + { + $this->initDatabase(); + $this->addUsers(); + + $stats = new Stats($this->database); + $this->assertEquals(2, $stats->tshirts()); + } + + /** + * @covers \Engelsystem\Controllers\Metrics\Stats::tshirtSizes + * @covers \Engelsystem\Controllers\Metrics\Stats::raw + */ + public function testTshirtSizes() + { + $this->initDatabase(); + $this->addUsers(); + + $stats = new Stats($this->database); + $sizes = $stats->tshirtSizes(); + $this->assertCount(2, $sizes); + $this->assertEquals(new Collection([ + (object)['shirt_size' => 'L', 'count' => 2], + (object)['shirt_size' => 'XXL', 'count' => 1], + ]), $sizes); + } + /** * @covers \Engelsystem\Controllers\Metrics\Stats::arrivedUsers */ @@ -40,7 +84,7 @@ class StatsTest extends TestCase $this->addUsers(); $stats = new Stats($this->database); - $this->assertEquals(3, $stats->arrivedUsers()); + $this->assertEquals(6, $stats->arrivedUsers()); } /** @@ -105,16 +149,20 @@ class StatsTest extends TestCase protected function addUsers() { $this->addUser(); - $this->addUser(); + $this->addUser([], ['shirt_size' => 'L']); $this->addUser(['arrived' => 1]); - $this->addUser(['arrived' => 1, 'active' => 1]); - $this->addUser(['arrived' => 1, 'active' => 1]); + $this->addUser(['arrived' => 1, 'got_voucher' => 2], ['shirt_size' => 'XXL']); + $this->addUser(['arrived' => 1, 'got_voucher' => 9]); + $this->addUser(['arrived' => 1, 'got_voucher' => 3]); + $this->addUser(['arrived' => 1, 'active' => 1, 'got_shirt' => true]); + $this->addUser(['arrived' => 1, 'active' => 1, 'got_shirt' => true], ['shirt_size' => 'L']); } /** * @param array $state + * @param array $personalData */ - protected function addUser(array $state = []) + protected function addUser(array $state = [], $personalData = []) { $name = 'user_' . Str::random(5); @@ -130,5 +178,10 @@ class StatsTest extends TestCase $state->user() ->associate($user) ->save(); + + $personalData = new PersonalData($personalData); + $personalData->user() + ->associate($user) + ->save(); } }