Implement counters and fix rider flow #UAT

This commit is contained in:
Kendrick Chan 2018-03-12 18:32:59 +08:00
parent dc3774a835
commit 9ad5f2557b
8 changed files with 242 additions and 7 deletions

View file

@ -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",

52
composer.lock generated
View file

@ -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",

View file

@ -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();

View file

@ -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;

View file

@ -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;
}
}

114
src/Service/HubCounter.php Normal file
View file

@ -0,0 +1,114 @@
<?php
namespace App\Service;
use App\Entity\Hub;
use App\Entity\Rider;
use Doctrine\ORM\EntityManagerInterface;
class HubCounter
{
const RIDER_COUNT_KEY = 'hub.rider';
const JOB_ORDER_KEY = 'hub.jo';
protected $em;
protected $redis;
public function __construct(EntityManagerInterface $em)
{
$this->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);
}
}

View file

@ -89,6 +89,9 @@
"ocramius/proxy-manager": {
"version": "2.2.0"
},
"predis/predis": {
"version": "v1.1.1"
},
"psr/cache": {
"version": "1.0.1"
},

View file

@ -532,8 +532,8 @@
<th>Branch</th>
<th class="text-right">Distance</th>
<th class="text-right">Travel Time</th>
<th class="text-right">Riders Available</th>
<th class="text-right">Job Backlog</th>
<th class="text-right">Available Riders</th>
<th class="text-right">Jobs For Assignment</th>
<th>Contact Numbers</th> </tr>
</thead>
<tbody>
@ -549,8 +549,8 @@
<td>{{ hub.hub.getBranch }}</td>
<td class="text-right">{{ hub.distance ? hub.distance : '-' }}</td>
<td class="text-right">{{ hub.duration ? hub.duration : '-' }}</td>
<td class="text-right">0</td>
<td class="text-right">0</td>
<td class="text-right">{{ hub.rider_count }}</td>
<td class="text-right">{{ hub.jo_count }}</td>
<td>{{ hub.hub.getContactNumbers }}</td>
</tr>
{% endfor %}