diff --git a/composer.json b/composer.json index bcef7e66..703155c0 100644 --- a/composer.json +++ b/composer.json @@ -7,6 +7,7 @@ "creof/doctrine2-spatial": "^1.2", "data-dog/audit-bundle": "^0.1.10", "guzzlehttp/guzzle": "^6.3", + "predis/predis": "^1.1", "sensio/framework-extra-bundle": "^5.1", "symfony/console": "^4.0", "symfony/debug": "^4.0", diff --git a/composer.lock b/composer.lock index a64ad7d6..899340c9 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "3b4c26c90ddb342f0b30fe22f0203470", + "content-hash": "674d8092785a7a621880a5b8649c6392", "packages": [ { "name": "creof/doctrine2-spatial", @@ -1559,6 +1559,56 @@ ], "time": "2017-11-16T23:22:31+00:00" }, + { + "name": "predis/predis", + "version": "v1.1.1", + "source": { + "type": "git", + "url": "https://github.com/nrk/predis.git", + "reference": "f0210e38881631afeafb56ab43405a92cafd9fd1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nrk/predis/zipball/f0210e38881631afeafb56ab43405a92cafd9fd1", + "reference": "f0210e38881631afeafb56ab43405a92cafd9fd1", + "shasum": "" + }, + "require": { + "php": ">=5.3.9" + }, + "require-dev": { + "phpunit/phpunit": "~4.8" + }, + "suggest": { + "ext-curl": "Allows access to Webdis when paired with phpiredis", + "ext-phpiredis": "Allows faster serialization and deserialization of the Redis protocol" + }, + "type": "library", + "autoload": { + "psr-4": { + "Predis\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Daniele Alessandri", + "email": "suppakilla@gmail.com", + "homepage": "http://clorophilla.net" + } + ], + "description": "Flexible and feature-complete Redis client for PHP and HHVM", + "homepage": "http://github.com/nrk/predis", + "keywords": [ + "nosql", + "predis", + "redis" + ], + "time": "2016-06-16T16:22:20+00:00" + }, { "name": "psr/cache", "version": "1.0.1", diff --git a/src/Controller/JobOrderController.php b/src/Controller/JobOrderController.php index e550c379..482d81c2 100644 --- a/src/Controller/JobOrderController.php +++ b/src/Controller/JobOrderController.php @@ -25,6 +25,7 @@ use App\Entity\Battery; use App\Service\InvoiceCreator; use App\Service\MapTools; +use App\Service\HubCounter; use Doctrine\ORM\Query; use Doctrine\DBAL\Connection; @@ -624,6 +625,10 @@ class JobOrderController extends BaseController } else { $hub['distance'] = false; } + + // counters + $hub['rider_count'] = count($hub['hub']->getAvailableRiders()); + $hub['jo_count'] = count($hub['hub']->getForAssignmentJobOrders()); $params['hubs'][] = $hub; } @@ -864,6 +869,9 @@ class JobOrderController extends BaseController ], 422); } + // set rider unavailable + $rider->setAvailable(false); + // validated! save the entity $em->flush(); @@ -976,6 +984,11 @@ class JobOrderController extends BaseController ], 422); } + // set rider available + $rider = $obj->getRider(); + if ($rider != null) + $rider->setAvailable(); + // validated! save the entity $em->flush(); @@ -1353,6 +1366,11 @@ class JobOrderController extends BaseController $obj->setStatus(JOStatus::CANCELLED) ->setCancelReason($cancel_reason); + // set rider available + $rider = $obj->getRider(); + if ($rider != null) + $rider->setAvailable(); + // save $em->flush(); diff --git a/src/Entity/Hub.php b/src/Entity/Hub.php index 53845ccc..840f6d8c 100644 --- a/src/Entity/Hub.php +++ b/src/Entity/Hub.php @@ -3,6 +3,7 @@ namespace App\Entity; use App\Ramcar\Location; +use App\Ramcar\JOStatus; use Doctrine\ORM\Mapping as ORM; use Doctrine\Common\Collections\ArrayCollection; @@ -64,6 +65,14 @@ class Hub return $this->riders->matching($crit); } + public function getActiveRiders() + { + $crit = Criteria::create(); + $crit->where(Criteria::expr()->eq('flag_active', true)); + + return $this->riders->matching($crit); + } + public function getUsers() { return $this->users; @@ -79,6 +88,22 @@ class Hub return $this->job_orders; } + public function getOngoingJobOrders() + { + $crit = Criteria::create(); + $crit->where(Criteria::expr()->notIn('status', [JOStatus::CANCELLED, JOStatus::FULFILLED])); + + return $this->job_orders->matching($crit); + } + + public function getForAssignmentJobOrders() + { + $crit = Criteria::create(); + $crit->where(Criteria::expr()->eq('status', JOStatus::RIDER_ASSIGN)); + + return $this->job_orders->matching($crit); + } + public function addOutlet(Outlet $outlet) { $this->outlets[] = $outlet; diff --git a/src/Entity/Rider.php b/src/Entity/Rider.php index d3b6cc71..a25f8cd0 100644 --- a/src/Entity/Rider.php +++ b/src/Entity/Rider.php @@ -80,18 +80,25 @@ class Rider */ protected $schedules; - // is the rider available or not + // is the rider available or not (no job order assigned to them) /** * @ORM\Column(type="boolean") */ protected $flag_available; + // is the rider active or not (he has logged in and marked himself as active) + /** + * @ORM\Column(type="boolean") + */ + protected $flag_active; + public function __construct() { $this->job_orders = new ArrayCollection(); $this->schedules = new ArrayCollection(); $this->curr_rating = 0; $this->flag_available = false; + $this->flag_active = false; } public function getID() @@ -221,7 +228,13 @@ class Rider public function setAvailable($avail = true) { - $this->flag_available = $avail; + // only set to available if they are active + // non-active riders cannot be available + if ($this->isActive() && $avail) + $this->flag_available = true; + else + $this->flag_available = false; + return $this; } @@ -229,4 +242,15 @@ class Rider { return $this->flag_available; } + + public function setActive($flag = true) + { + $this->flag_active = $flag; + return $this; + } + + public function isActive() + { + return $this->flag_active; + } } diff --git a/src/Service/HubCounter.php b/src/Service/HubCounter.php new file mode 100644 index 00000000..6fa52819 --- /dev/null +++ b/src/Service/HubCounter.php @@ -0,0 +1,114 @@ +em = $em; + + // TODO: make it read redis settings from config + // build a service maybe? + $this->redis = new Predis\Client(); + } + + // get rider key based on id + protected function getRiderKey($hub_id) + { + return self::RIDER_COUNT_KEY . '.' . $hub_id; + } + + // get job order key based on id + protected function getJobOrderKey($hub_id) + { + return self::JOB_ORDER_KEY . '.' . $hub_id; + } + + // get riders available + public function getAvailableRiderCount($hub_id) + { + $key = $this->getRiderKey($hub_id); + $value = $this->redis->get($key); + if ($value != null) + return $value; + + // not in cache + $hub = $em->getRepository(Hub::class)->find($hub_id); + $riders = $hub->getActiveRiders(); + $rider_count = count($riders); + + // store in cache + $this->redis->setnx($key, $rider_count); + return $rider_count; + } + + // get job order queue + public function getUnfinishedJobOrderCount($hub_id) + { + $key = $this->getRiderKey($hub_id); + $value = $this->redis->get($key); + if ($value != null) + return $value; + + // not in cache + $hub = $em->getRepository(Hub::class)->find($hub_id); + $riders = $hub->getActiveRiders(); + $rider_count = count($riders); + + // store in cache + $this->redis->setnx($key, $rider_count); + return $rider_count; + } + + // add rider available + public function addAvailableRider($hub_id, $count = 1) + { + // cache + $this->getAvailableRiderCount($hub_id); + + $key = $this->getRiderKey($hub_id); + $this->redis->incrby($key, $count); + } + + // decrease rider available + public function decAvailableRider($hub_id, $count = 1) + { + // cache + $this->getAvailableRiderCount($hub_id); + + $key = $this->getRiderKey($hub_id); + $this->redis->decrby($key, $count); + } + + // add job order queue + public function addUnfinishedJobOrder($hub_id, $count = 1) + { + // cache + $this->getUnfinishedJobOrderCount($hub_id); + + $key = $this->getJobOrderKey($hub_id); + $this->redis->incrby($key, $count); + } + + // decrease job order queue + public function decUnfinishedJobOrder($hub_id, $count = 1) + { + // cache + $this->getUnfinishedJobOrderCount($hub_id); + + $key = $this->getJobOrderKey($hub_id); + $this->redis->decrby($key, $count); + } +} diff --git a/symfony.lock b/symfony.lock index 08e5085a..c4b35509 100644 --- a/symfony.lock +++ b/symfony.lock @@ -89,6 +89,9 @@ "ocramius/proxy-manager": { "version": "2.2.0" }, + "predis/predis": { + "version": "v1.1.1" + }, "psr/cache": { "version": "1.0.1" }, diff --git a/templates/job-order/form.html.twig b/templates/job-order/form.html.twig index 3f4ef386..9d11ffa9 100644 --- a/templates/job-order/form.html.twig +++ b/templates/job-order/form.html.twig @@ -532,8 +532,8 @@