Merge branch 'master' into 803-fix-invoice-data-disappearing-on-open-edit-form
This commit is contained in:
commit
511aa5ec9b
25 changed files with 1105 additions and 381 deletions
|
|
@ -16,6 +16,7 @@ parameters:
|
|||
android_app_version: "%env(ANDROID_APP_VERSION)%"
|
||||
ios_app_version: "%env(IOS_APP_VERSION)%"
|
||||
insurance_premiums_banner_url: "%env(INSURANCE_PREMIUMS_BANNER_URL)%"
|
||||
enabled_hub_filters: "%env(ENABLED_HUB_FILTERS)%"
|
||||
|
||||
services:
|
||||
# default configuration for services in *this* file
|
||||
|
|
@ -322,3 +323,36 @@ services:
|
|||
App\Service\PriceTierManager:
|
||||
arguments:
|
||||
$em: "@doctrine.orm.entity_manager"
|
||||
|
||||
# hub filters
|
||||
App\Service\HubFilter\BaseHubFilter:
|
||||
arguments:
|
||||
$hub_filter_logger: "@App\\Service\\HubFilterLogger"
|
||||
$em: "@doctrine.orm.entity_manager"
|
||||
$rt: "@App\\Service\\RisingTideGateway"
|
||||
$trans: "@Symfony\\Contracts\\Translation\\TranslatorInterface"
|
||||
|
||||
App\Service\HubFilter\Filters\DateAndTimeHubFilter:
|
||||
public: true
|
||||
|
||||
App\Service\HubFilter\Filters\JoTypeHubFilter:
|
||||
public: true
|
||||
|
||||
App\Service\HubFilter\Filters\MaxResultsHubFilter:
|
||||
public: true
|
||||
|
||||
App\Service\HubFilter\Filters\PaymentMethodHubFilter:
|
||||
public: true
|
||||
|
||||
App\Service\HubFilter\Filters\RiderAvailabilityHubFilter:
|
||||
public: true
|
||||
|
||||
App\Service\HubFilter\Filters\InventoryHubFilter:
|
||||
public: true
|
||||
arguments:
|
||||
$im: "@App\\Service\\InventoryManager"
|
||||
|
||||
App\Service\HubFilter\Filters\RoundRobinHubFilter:
|
||||
public: true
|
||||
arguments:
|
||||
$hub_distributor: "@App\\Service\\HubDistributor"
|
||||
|
|
|
|||
|
|
@ -489,6 +489,8 @@ class JobOrderController extends ApiController
|
|||
JobOrderManager $jo_manager,
|
||||
PriceTierManager $pt_manager
|
||||
) {
|
||||
//error_log("CREATING JOB ORDER WITH PARAMS " . print_r($req->request->all(), true));
|
||||
|
||||
// validate params
|
||||
$validity = $this->validateRequest($req, [
|
||||
'service_type',
|
||||
|
|
@ -576,6 +578,8 @@ class JobOrderController extends ApiController
|
|||
$flag_advance_order = true;
|
||||
// $flag_advance_order = $advance_order ? true : false;
|
||||
|
||||
//error_log("RUNNING QUERY NEXT");
|
||||
|
||||
$jo = new JobOrder();
|
||||
$jo->setSource(TransactionOrigin::MOBILE_APP)
|
||||
->setStatus(JOStatus::PENDING)
|
||||
|
|
@ -644,6 +648,8 @@ class JobOrderController extends ApiController
|
|||
$icrit->addPromo($promo);
|
||||
}
|
||||
|
||||
//error_log("CONTINUING QUERY BUILDING");
|
||||
|
||||
// check customer vehicle
|
||||
$cv = $this->em->getRepository(CustomerVehicle::class)->find($req->request->get('cv_id'));
|
||||
if ($cv == null) {
|
||||
|
|
@ -710,13 +716,30 @@ class JobOrderController extends ApiController
|
|||
$invoice = $ic->generateInvoice($icrit);
|
||||
$jo->setInvoice($invoice);
|
||||
|
||||
//error_log("GENERATED INVOICE");
|
||||
|
||||
// save here first so we have a JO ID which is required for the hub selector
|
||||
$this->em->persist($invoice);
|
||||
$this->em->persist($jo);
|
||||
$this->em->flush();
|
||||
|
||||
// assign hub and rider
|
||||
// check if hub is null
|
||||
if ($hub == null) {
|
||||
//error_log("NO HUB");
|
||||
|
||||
// TODO: need to factor out the setting of HubCriteria fields
|
||||
$hub_criteria = new HubCriteria();
|
||||
$hub_criteria->setPoint($jo->getCoordinates());
|
||||
|
||||
// set job order info
|
||||
$hub_criteria->setJobOrderId($jo->getID())
|
||||
->setJoType($jo->getServiceType())
|
||||
->setJoOrigin($jo->getSource())
|
||||
->setCustomerClass($cust->getCustomerClassification())
|
||||
->setOrderDate($jo->getDateCreate())
|
||||
->setServiceType($jo->getServiceType());
|
||||
|
||||
// get distance limit for mobile from env
|
||||
// get value of hub_filter_enable from env
|
||||
$limit_distance = $_ENV['CUST_DISTANCE_LIMIT'];
|
||||
|
|
@ -754,6 +777,10 @@ class JobOrderController extends ApiController
|
|||
|
||||
$hub_criteria->setCustomerId($customer_id);
|
||||
|
||||
// set filter flags for inventory and available riders
|
||||
$hub_criteria->setInventoryCheck();
|
||||
$hub_criteria->setRidersCheck();
|
||||
|
||||
// find nearest hubs
|
||||
$nearest_hubs = $hub_select->find($hub_criteria);
|
||||
|
||||
|
|
@ -832,6 +859,8 @@ class JobOrderController extends ApiController
|
|||
}
|
||||
}
|
||||
} else {
|
||||
//error_log("HAS HUB: " . $hub->getID());
|
||||
|
||||
$jo->setHub($hub);
|
||||
$jo->setStatus(JOStatus::RIDER_ASSIGN);
|
||||
$jo->setStatusAutoAssign(AutoAssignStatus::HUB_ASSIGNED);
|
||||
|
|
@ -843,8 +872,10 @@ class JobOrderController extends ApiController
|
|||
$hub_dist->incrementJoCountForHub($hub);
|
||||
}
|
||||
|
||||
//error_log("DONE SELECTING HUB");
|
||||
|
||||
// save additional hub related changes
|
||||
$this->em->persist($jo);
|
||||
$this->em->persist($invoice);
|
||||
|
||||
// add event log for JO
|
||||
$event = new JOEvent();
|
||||
|
|
@ -955,6 +986,8 @@ class JobOrderController extends ApiController
|
|||
}
|
||||
}
|
||||
|
||||
//error_log("DONE CREATING JOB ORDER " . $jo->getID());
|
||||
|
||||
// response
|
||||
return new ApiResponse(true, '', [
|
||||
'jo_id' => $jo->getID(),
|
||||
|
|
|
|||
|
|
@ -761,7 +761,7 @@ class JobOrderController extends Controller
|
|||
$lat = $req->request->get('coord_lat', 0);
|
||||
|
||||
$price_tier = 0;
|
||||
if (($lng != 0) && ($lat != 0))
|
||||
if (!empty($lng) && !empty($lat))
|
||||
{
|
||||
$coordinates = new Point($req->request->get('coord_lng'), $req->request->get('coord_lat'));
|
||||
$price_tier = $pt_manager->getPriceTier($coordinates);
|
||||
|
|
|
|||
|
|
@ -236,6 +236,10 @@ class ReportController extends Controller
|
|||
|
||||
$reason = $jor->getReason();
|
||||
|
||||
$dispatched_by = 'system';
|
||||
if ($jor->getUser() != null)
|
||||
$dispatched_by = $jor->getUser()->getFullName();
|
||||
|
||||
$res[] = [
|
||||
$jo->getID(),
|
||||
$jo->getDateSchedule()->format('m/d/Y H:i'),
|
||||
|
|
@ -244,7 +248,7 @@ class ReportController extends Controller
|
|||
JORejectionReason::getName($jor->getReason()),
|
||||
$jor->getContactPerson(),
|
||||
$jor->getRemarks(),
|
||||
$jor->getUser()->getFullName(),
|
||||
!empty($jor->getUser()) ? $jor->getUser()->getFullName() : "",
|
||||
ServiceType::getName($jo->getServiceType()),
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -239,6 +239,10 @@ class JobOrderController extends ApiController
|
|||
// find nearest hubs
|
||||
$nearest_hubs = $hub_select->find($hub_criteria);
|
||||
|
||||
// set filter flags for inventory and available riders
|
||||
$hub_criteria->setInventoryCheck();
|
||||
$hub_criteria->setRidersCheck();
|
||||
|
||||
if (!empty($nearest_hubs))
|
||||
{
|
||||
// go through the hub list, find the nearest hub
|
||||
|
|
|
|||
|
|
@ -114,7 +114,9 @@ class Hub
|
|||
public function getAvailableRiders()
|
||||
{
|
||||
$crit = Criteria::create();
|
||||
$crit->where(Criteria::expr()->eq('flag_available', true));
|
||||
$crit->where(Criteria::expr()->eq('flag_available', true))
|
||||
->where(Criteria::expr()->eq('flag_active', true))
|
||||
->where(Criteria::expr()->eq('current_job_order', null));
|
||||
|
||||
return $this->riders->matching($crit);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,6 +39,12 @@ class SupportedArea
|
|||
*/
|
||||
protected $coverage_area;
|
||||
|
||||
// prevent certain hub filters from being used
|
||||
/**
|
||||
* @ORM\Column(type="json", nullable=true)
|
||||
*/
|
||||
protected $hub_filter_exceptions;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="PriceTier", inversedBy="supported_areas")
|
||||
* @ORM\JoinColumn(name="price_tier_id", referencedColumnName="id", nullable=true)
|
||||
|
|
@ -50,6 +56,7 @@ class SupportedArea
|
|||
$this->date_create = new DateTime();
|
||||
|
||||
$this->price_tier = null;
|
||||
$this->hub_filter_exceptions = [];
|
||||
}
|
||||
|
||||
public function getID()
|
||||
|
|
@ -65,7 +72,7 @@ class SupportedArea
|
|||
|
||||
public function getDateCreate()
|
||||
{
|
||||
return $this->date_Create;
|
||||
return $this->date_create;
|
||||
}
|
||||
|
||||
public function setName($name)
|
||||
|
|
@ -101,5 +108,16 @@ class SupportedArea
|
|||
{
|
||||
return $this->price_tier;
|
||||
}
|
||||
|
||||
public function setHubFilterExceptions($exceptions)
|
||||
{
|
||||
$this->hub_filter_exceptions = $exceptions;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getHubFilterExceptions()
|
||||
{
|
||||
return $this->hub_filter_exceptions;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,8 +23,8 @@ class DeliveryStatus extends NameValue
|
|||
const COLLECTION = [
|
||||
'rider_assign' => 'Assigned Rider',
|
||||
'requeue' => 'Requeue',
|
||||
'accept' => 'Rider Accept',
|
||||
'arrive' => 'Rider Arrive',
|
||||
'rider_accept' => 'Rider Accept',
|
||||
'rider_arrive' => 'Rider Arrive',
|
||||
'rider_edit' => 'Rider Edit',
|
||||
'rider_depart_hub' => 'Rider Depart Hub',
|
||||
'rider_arrive_hub_pre_jo' => 'Rider Arrive Hub Pre JO',
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ class HubCriteria
|
|||
protected $limit_results; // number of results to return
|
||||
protected $limit_distance; // distance limit for search in km
|
||||
protected $flag_inventory_check; // flag if we need to check for inventory
|
||||
protected $flag_riders_check; // flag if we need to check for riders available
|
||||
protected $jo_type; // jo service needed
|
||||
protected $date_time; // date and time to check if hub is open or not
|
||||
protected $items; // array of items: items[sku] = quantity to check for
|
||||
|
|
@ -20,6 +21,10 @@ class HubCriteria
|
|||
protected $flag_round_robin; // flag if we use round robin or not
|
||||
protected $jo_id; // JO id. This is null if called from mobile API
|
||||
protected $customer_id; // customer id
|
||||
protected $customer_class; // customer class
|
||||
protected $order_date; // date JO was created
|
||||
protected $service_type; // service type of JO
|
||||
protected $jo_origin; // origin of JO
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
|
|
@ -29,12 +34,17 @@ class HubCriteria
|
|||
$this->jo_type = '';
|
||||
$this->date_time = new DateTime();
|
||||
$this->flag_inventory_check = false;
|
||||
$this->flag_riders_check = false;
|
||||
$this->items = [];
|
||||
$this->payment_method = '';
|
||||
$flag_emergency = false;
|
||||
$flag_round_robin = false;
|
||||
$jo_id = null;
|
||||
$customer_id = null;
|
||||
$this->flag_emergency = false;
|
||||
$this->flag_round_robin = false;
|
||||
$this->jo_id = null;
|
||||
$this->customer_id = null;
|
||||
$this->customer_class = null;
|
||||
$this->order_date = new DateTime();
|
||||
$this->service_type = null;
|
||||
$this->jo_origin = null;
|
||||
}
|
||||
|
||||
public function setPoint(Point $point)
|
||||
|
|
@ -81,6 +91,17 @@ class HubCriteria
|
|||
return $this->flag_inventory_check;
|
||||
}
|
||||
|
||||
public function setRidersCheck($flag_riders_check = true)
|
||||
{
|
||||
$this->flag_riders_check = $flag_riders_check;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function hasRidersCheck()
|
||||
{
|
||||
return $this->flag_riders_check;
|
||||
}
|
||||
|
||||
public function setJoType($jo_type)
|
||||
{
|
||||
// TODO: validate the jo type
|
||||
|
|
@ -171,5 +192,48 @@ class HubCriteria
|
|||
return $this->customer_id;
|
||||
}
|
||||
|
||||
public function setCustomerClass($customer_class)
|
||||
{
|
||||
$this->customer_class = $customer_class;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getCustomerClass()
|
||||
{
|
||||
return $this->customer_class;
|
||||
}
|
||||
|
||||
public function setOrderDate($order_date)
|
||||
{
|
||||
$this->order_date = $order_date;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getOrderDate()
|
||||
{
|
||||
return $this->order_date;
|
||||
}
|
||||
|
||||
public function setServiceType($service_type)
|
||||
{
|
||||
$this->service_type = $service_type;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getServiceType()
|
||||
{
|
||||
return $this->service_type;
|
||||
}
|
||||
|
||||
public function setJoOrigin($jo_origin)
|
||||
{
|
||||
$this->jo_origin = $jo_origin;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getJoOrigin()
|
||||
{
|
||||
return $this->jo_origin;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,17 +4,24 @@ namespace App\Ramcar;
|
|||
|
||||
class JORejectionReason extends NameValue
|
||||
{
|
||||
const ADMINISTRATIVE = 'administrative';
|
||||
const NO_STOCK_SALES = 'no_stock_sales';
|
||||
const NO_STOCK_SERVICE = 'no_stock_service';
|
||||
const LINE_NO_ANSWER = 'line_no_answer';
|
||||
const LINE_BUSY = 'line_busy';
|
||||
const NO_RIDER_AVAILABLE = 'no_rider_available';
|
||||
const NO_RIDER_IN_TRANSIT = 'no_rider_in_transit';
|
||||
const REFUSAL = 'refusal';
|
||||
const STORE_CLOSED = 'store_closed';
|
||||
const NO_CREDIT_CARD = 'no_credit_card';
|
||||
const DISCOUNT = 'discount';
|
||||
const ADMINISTRATIVE = 'administrative';
|
||||
const NO_STOCK_SALES = 'no_stock_sales';
|
||||
const NO_STOCK_SERVICE = 'no_stock_service';
|
||||
const LINE_NO_ANSWER = 'line_no_answer';
|
||||
const LINE_BUSY = 'line_busy';
|
||||
const NO_RIDER_AVAILABLE = 'no_rider_available';
|
||||
const NO_RIDER_IN_TRANSIT = 'no_rider_in_transit';
|
||||
const REFUSAL = 'refusal';
|
||||
const STORE_CLOSED = 'store_closed';
|
||||
const NO_CREDIT_CARD = 'no_credit_card';
|
||||
const DISCOUNT = 'discount';
|
||||
const STORE_CLOSED_SCHEDULED = 'store_closed_scheduled';
|
||||
const STORE_CLOSED_HALF_DAY = 'store_closed_half_day';
|
||||
const STORE_CLOSED_NO_ADVISE = 'store_closed_no_advise';
|
||||
const PRIORITY_HUB_WTY_CLAIM = 'priority_hub_wty_claim';
|
||||
const PRIORITY_HUB_JUMPSTART = 'priority_hub_jumpstart';
|
||||
const PRIORITY_HUB_RESQ_REQUEST = 'priority_hub_resq_req';
|
||||
const CUSTOMER_REQUEST = 'customer_request';
|
||||
|
||||
const COLLECTION = [
|
||||
'administrative' => 'ADMINISTRATIVE',
|
||||
|
|
@ -28,5 +35,16 @@ class JORejectionReason extends NameValue
|
|||
'store_closed' => 'STORE CLOSED',
|
||||
'no_credit_card' => 'NO CREDIT CARD PAYMENT / NO TERMINAL',
|
||||
'discount' => 'DISCOUNT',
|
||||
'store_closed_scheduled' => 'STORE CLOSED (ON SCHEDULE)',
|
||||
'store_closed_half_day' => 'STORE CLOSED (HALF DAY)',
|
||||
'store_closed_no_advise' => 'STORE CLOSED (NO ADVISE)',
|
||||
'priority_hub_wty_claim' => 'PRIORITY HUB OUTLET FOR WARRANTY CLAIM',
|
||||
'priority_hub_jumpstart' => 'PRIORITY HUB OUTLET FOR JUMPSTART',
|
||||
'priority_hub_resq_req' => 'PRIORITY HUB OUTLET FOR RESQ-Q REQUEST',
|
||||
'customer_request' => 'CUSTOMER REQUEST',
|
||||
];
|
||||
|
||||
const BLACKLIST = [
|
||||
self::ADMINISTRATIVE => true,
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,9 +4,21 @@ namespace App\Ramcar;
|
|||
|
||||
class NameValue
|
||||
{
|
||||
const BLACKLIST = [];
|
||||
|
||||
static public function getCollection()
|
||||
{
|
||||
return static::COLLECTION;
|
||||
$result = [];
|
||||
$blacklist = static::getBlacklist();
|
||||
|
||||
// filter from blacklist
|
||||
foreach(static::COLLECTION as $key => $row) {
|
||||
if (!isset($blacklist[$key])) {
|
||||
$result[$key] = $row;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
static public function validate($value)
|
||||
|
|
@ -24,4 +36,9 @@ class NameValue
|
|||
|
||||
return 'Unknown';
|
||||
}
|
||||
|
||||
static public function getBlacklist()
|
||||
{
|
||||
return static::BLACKLIST ?? [];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -81,6 +81,7 @@ class HubDistributor
|
|||
'distance' => $hub_data['distance'],
|
||||
'duration' => $hub_data['duration'],
|
||||
'jo_count' => $hub_jo_count,
|
||||
'inventory' => $hub_data['inventory'] ?? 0,
|
||||
];
|
||||
}
|
||||
else
|
||||
|
|
@ -91,6 +92,7 @@ class HubDistributor
|
|||
'distance' => $hub_data['distance'],
|
||||
'duration' => $hub_data['duration'],
|
||||
'jo_count' => 0,
|
||||
'inventory' => $hub_data['inventory'] ?? 0,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
144
src/Service/HubFilter/BaseHubFilter.php
Normal file
144
src/Service/HubFilter/BaseHubFilter.php
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
<?php
|
||||
|
||||
namespace App\Service\HubFilter;
|
||||
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
use App\Service\HubFilterLogger;
|
||||
use App\Entity\Hub;
|
||||
use App\Entity\JobOrder;
|
||||
use App\Entity\JORejection;
|
||||
use App\Ramcar\ServiceType;
|
||||
use App\Ramcar\JORejectionReason;
|
||||
use App\Service\RisingTideGateway;
|
||||
|
||||
use DateTime;
|
||||
|
||||
class BaseHubFilter
|
||||
{
|
||||
protected $id;
|
||||
protected $jo_id;
|
||||
protected $customer_id;
|
||||
protected $hub_filter_logger;
|
||||
protected $em;
|
||||
protected $rt;
|
||||
protected $trans;
|
||||
|
||||
public function __construct(HubFilterLogger $hub_filter_logger, EntityManagerInterface $em, RisingTideGateway $rt, TranslatorInterface $trans)
|
||||
{
|
||||
$this->hub_filter_logger = $hub_filter_logger;
|
||||
$this->em = $em;
|
||||
$this->rt = $rt;
|
||||
$this->trans = $trans;
|
||||
|
||||
error_log("-------------------");
|
||||
error_log("HUB FILTER RUNNING: " . $this->getID());
|
||||
error_log("-------------------");
|
||||
}
|
||||
|
||||
public function getID(): string
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function setJOID(int $jo_id)
|
||||
{
|
||||
$this->jo_id = $jo_id;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getJOID(): int
|
||||
{
|
||||
return $this->jo_id;
|
||||
}
|
||||
|
||||
public function setCustomerID(int $customer_id)
|
||||
{
|
||||
$this->customer_id = $customer_id;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getCustomerID(): int
|
||||
{
|
||||
return $this->customer_id;
|
||||
}
|
||||
|
||||
public function log(Hub $hub): void
|
||||
{
|
||||
$this->hub_filter_logger->logFilteredHub($hub, $this->getID(), $this->getJOID(), $this->getCustomerID());
|
||||
|
||||
// log to file
|
||||
$filename = '/../../../var/log/hub_rejection.log';
|
||||
$date = date("Y-m-d H:i:s");
|
||||
|
||||
// build log entry
|
||||
$entry = implode("", [
|
||||
"[JO: " . $this->getJOID() . "]",
|
||||
"[" . $date . "]",
|
||||
"[" . $this->getID() . "]",
|
||||
" " . $hub->getName() . " (ID: " . $hub->getID() . ")",
|
||||
"\r\n",
|
||||
]);
|
||||
|
||||
@file_put_contents(__DIR__ . $filename, $entry, FILE_APPEND);
|
||||
}
|
||||
|
||||
protected function createRejectionEntry($hub, $reason, $remarks = ""): JORejection
|
||||
{
|
||||
$jo = $this->em->getRepository(JobOrder::class)->find($this->getJOID());
|
||||
|
||||
$robj = new JORejection();
|
||||
$robj->setDateCreate(new DateTime())
|
||||
->setHub($hub)
|
||||
->setJobOrder($jo)
|
||||
->setReason($reason)
|
||||
->setRemarks(implode(" ", ["Automatically filtered by hub selector.", $remarks]));
|
||||
|
||||
$this->em->persist($robj);
|
||||
$this->em->flush();
|
||||
|
||||
return $robj;
|
||||
}
|
||||
|
||||
protected function sendSMSMessage($hub, $order_date, $service_type, $rejection, $reason = "", $remarks = ""): void
|
||||
{
|
||||
$jo_id = $this->getJOID();
|
||||
|
||||
// check if we already have a rejection record for this hub and JO. this also means an SMS was already sent
|
||||
$rejection_count = $this->em->createQueryBuilder()
|
||||
->select('count(r)')
|
||||
->from(JORejection::class, 'r')
|
||||
->where('r.job_order = :jo_id')
|
||||
->andWhere('r.hub = :hub_id')
|
||||
->andWhere('r.id != :rejection_id')
|
||||
->setParameter('jo_id', $jo_id)
|
||||
->setParameter('hub_id', $hub->getID())
|
||||
->setParameter('rejection_id', $rejection->getID())
|
||||
->getQuery()
|
||||
->getSingleScalarResult();
|
||||
|
||||
// if we already have a rejection record for this hub and JO, do not send another SMS
|
||||
if ($rejection_count >= 1) {
|
||||
error_log("ALREADY SENT REJECTION SMS TO HUB " . $hub->getID() . " FOR JO " . $jo_id);
|
||||
return;
|
||||
}
|
||||
|
||||
$message = 'Job Order #: ' . $jo_id . "\n" .
|
||||
'Order Date and Time: ' . $order_date->format('d M Y g:i A') . "\n" .
|
||||
'Date and Time Rejected: ' . $rejection->getDateCreate()->format('d M Y g:i A') . "\n" .
|
||||
'Enrollee Name: ' . implode(" - ", [$hub->getName(), $hub->getBranch()]) . "\n" .
|
||||
'Reason of Rejection: ' . $reason . "\n" .
|
||||
'Remarks: ' . $remarks . "\n" .
|
||||
'Type of Service: ' . ServiceType::getName($service_type);
|
||||
|
||||
error_log("SENDING SMS MESSAGE:\r\n" . $message);
|
||||
|
||||
// send SMS message to hub
|
||||
$this->rt->sendSMS(
|
||||
$hub->getNotifNumber(),
|
||||
$this->trans->trans('message.battery_brand_allcaps'),
|
||||
$message
|
||||
);
|
||||
}
|
||||
}
|
||||
58
src/Service/HubFilter/Filters/DateAndTimeHubFilter.php
Normal file
58
src/Service/HubFilter/Filters/DateAndTimeHubFilter.php
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
<?php
|
||||
|
||||
namespace App\Service\HubFilter\Filters;
|
||||
|
||||
use App\Service\HubFilter\BaseHubFilter;
|
||||
use App\Service\HubFilter\HubFilterInterface;
|
||||
|
||||
class DateAndTimeHubFilter extends BaseHubFilter implements HubFilterInterface
|
||||
{
|
||||
protected $id = 'date_and_time';
|
||||
|
||||
public function getRequestedParams() : array
|
||||
{
|
||||
return [
|
||||
'date_time',
|
||||
];
|
||||
}
|
||||
|
||||
public function filter(array $hubs, array $params = []) : array
|
||||
{
|
||||
if ($params['date_time'] == null)
|
||||
return $hubs;
|
||||
|
||||
$results = [];
|
||||
|
||||
foreach ($hubs as $hub_data)
|
||||
{
|
||||
// go through each hub's opening times to check if hub is open
|
||||
// for the specified time
|
||||
// get hub opening and closing times
|
||||
// TODO: maybe in the future, might also have to check if hub
|
||||
// is open/available on date/day
|
||||
$hub = $hub_data['hub'];
|
||||
|
||||
$time_open = $hub->getTimeOpen()->format("H:i:s");
|
||||
$time_close = $hub->getTimeClose()->format("H:i:s");
|
||||
|
||||
$filter_time = $params['date_time']->format("H:i:s");
|
||||
|
||||
if (($filter_time >= $time_open) &&
|
||||
($filter_time <= $time_close))
|
||||
{
|
||||
$results[] = [
|
||||
'hub' => $hub,
|
||||
'db_distance' => $hub_data['db_distance'],
|
||||
'distance' => $hub_data['distance'],
|
||||
'duration' => $hub_data['duration'],
|
||||
'jo_count' => 0,
|
||||
'inventory' => $hub_data['inventory'],
|
||||
];
|
||||
}
|
||||
else
|
||||
$this->log($hub);
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
}
|
||||
164
src/Service/HubFilter/Filters/InventoryHubFilter.php
Normal file
164
src/Service/HubFilter/Filters/InventoryHubFilter.php
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
<?php
|
||||
|
||||
namespace App\Service\HubFilter\Filters;
|
||||
|
||||
use App\Service\HubFilter\BaseHubFilter;
|
||||
use App\Service\HubFilter\HubFilterInterface;
|
||||
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
use App\Ramcar\JORejectionReason;
|
||||
use App\Ramcar\ServiceType;
|
||||
use App\Ramcar\CustomerClassification;
|
||||
use App\Service\InventoryManager;
|
||||
use App\Service\HubFilterLogger;
|
||||
use App\Service\RisingTideGateway;
|
||||
use App\Entity\Battery;
|
||||
use App\Ramcar\TransactionOrigin;
|
||||
|
||||
class InventoryHubFilter extends BaseHubFilter implements HubFilterInterface
|
||||
{
|
||||
protected $id = 'no_inventory';
|
||||
protected $im;
|
||||
|
||||
public function __construct(HubFilterLogger $hub_filter_logger, EntityManagerInterface $em, RisingTideGateway $rt, TranslatorInterface $trans, InventoryManager $im)
|
||||
{
|
||||
parent::__construct($hub_filter_logger, $em, $rt, $trans);
|
||||
$this->im = $im;
|
||||
}
|
||||
|
||||
public function getRequestedParams() : array
|
||||
{
|
||||
return [
|
||||
'flag_inventory_check',
|
||||
'customer_class',
|
||||
'jo_type',
|
||||
'jo_origin',
|
||||
'order_date',
|
||||
'service_type',
|
||||
'items',
|
||||
];
|
||||
}
|
||||
|
||||
public function filter(array $hubs, array $params = []) : array
|
||||
{
|
||||
// check if this is enabled
|
||||
if (!$params['flag_inventory_check']) {
|
||||
error_log("INVENTORY CHECK " . $this->getJOID() . ": DISABLED");
|
||||
return $hubs;
|
||||
}
|
||||
|
||||
// check customer class
|
||||
if ((!empty($params['customer_class']) && $params['customer_class'] == CustomerClassification::VIP) ||
|
||||
$params['jo_origin'] === TransactionOrigin::VIP) {
|
||||
error_log("INVENTORY CHECK " . $this->getJOID() . ": VIP CLASS");
|
||||
return $hubs;
|
||||
}
|
||||
|
||||
// check item list is not empty
|
||||
if (empty($params['items'])) {
|
||||
error_log("INVENTORY CHECK " . $this->getJOID() . ": NO ITEMS");
|
||||
return $hubs;
|
||||
}
|
||||
|
||||
// check this is a battery item related JO
|
||||
if ($params['jo_type'] != ServiceType::BATTERY_REPLACEMENT_NEW &&
|
||||
$params['jo_type'] != ServiceType::BATTERY_REPLACEMENT_WARRANTY
|
||||
) {
|
||||
error_log("INVENTORY CHECK " . $this->getJOID() . ": INVALID SERVICE TYPE: " . $params['jo_type']);
|
||||
return $hubs;
|
||||
}
|
||||
|
||||
// get a list of all hubs with branch codes
|
||||
$branch_codes = [];
|
||||
foreach ($hubs as $hub_data) {
|
||||
$branch_code = $hub_data['hub']->getBranchCode();
|
||||
if (!empty($branch_code)) {
|
||||
$branch_codes[] = $branch_code;
|
||||
}
|
||||
};
|
||||
|
||||
$hubs_to_filter = [];
|
||||
$results = [];
|
||||
$qtys = [];
|
||||
|
||||
// call inventory manager for all hubs for selected SKUs
|
||||
$skus = array_keys($params['items']);
|
||||
|
||||
error_log("CHECKING INVENTORY FOR " . count($skus) . " ITEM(S) ON HUBS " . count($branch_codes) . "...");
|
||||
|
||||
$branches = $this->im->getBranchesInventory($branch_codes, $skus);
|
||||
|
||||
error_log("REQUEST COMPLETE, RESULT COUNT: " . count($branches));
|
||||
|
||||
// check each result to see if sufficient quantity exists to meet request
|
||||
foreach ($branches as $branch) {
|
||||
if (isset($branch['BranchCode'])) {
|
||||
// filter out branch if it does not have sufficient inventory
|
||||
if (!isset($params['items'][$branch['SapCode']]) || $branch['Quantity'] < $params['items'][$branch['SapCode']] &&
|
||||
!isset($hubs_to_filter[$branch['BranchCode']])
|
||||
) {
|
||||
error_log("FILTERING BRANCH WITH NO INVENTORY: " . $branch['BranchCode']);
|
||||
$hubs_to_filter[$branch['BranchCode']] = true;
|
||||
} else {
|
||||
// save inventory count so we don't have to recheck later
|
||||
$qtys[$branch['BranchCode']] = $branch['Quantity'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// get battery models for each requested SKU
|
||||
$batteries = [];
|
||||
foreach ($skus as $sku) {
|
||||
$bobj = $this->em->getRepository(Battery::class)->findOneBy(['sap_code' => $sku]);
|
||||
$batteries[] = implode(" ", [$bobj->getModel()->getName(), $bobj->getSize()->getName()]);
|
||||
}
|
||||
$battery_string = implode(", ", $batteries);
|
||||
|
||||
// remove filtered hubs from list
|
||||
foreach ($hubs as $hub_data) {
|
||||
$hub = $hub_data['hub'];
|
||||
$branch_code = $hub_data['hub']->getBranchCode();
|
||||
|
||||
// check if we are filtering this hub
|
||||
if (isset($hubs_to_filter[$branch_code]) || empty($branch_code) || !isset($qtys[$branch_code])) {
|
||||
// if we have a JO, create rejection record and notify
|
||||
$jo_id = $this->getJOID();
|
||||
|
||||
if (!empty($jo_id)) {
|
||||
// create rejection report entry
|
||||
$robj = $this->createRejectionEntry(
|
||||
$hub,
|
||||
JORejectionReason::NO_STOCK_SALES,
|
||||
"SKU(s): " . $battery_string,
|
||||
);
|
||||
|
||||
// build SMS message
|
||||
$this->sendSMSMessage(
|
||||
$hub,
|
||||
$params['order_date'],
|
||||
$params['service_type'],
|
||||
$robj,
|
||||
JORejectionReason::getName(JORejectionReason::NO_STOCK_SALES),
|
||||
"Requested SKU(s) - " . $battery_string
|
||||
);
|
||||
}
|
||||
|
||||
// log this filter
|
||||
$this->log($hub);
|
||||
|
||||
error_log("FILTERED HUB " . $hub->getID() . " (no_inventory)");
|
||||
} else {
|
||||
// include inventory in hub data
|
||||
$hub_data['inventory'] = $qtys[$branch_code];
|
||||
|
||||
// we only include branches with branch codes and quantities
|
||||
$results[] = $hub_data;
|
||||
}
|
||||
}
|
||||
|
||||
// return filtered hubs
|
||||
return $results;
|
||||
}
|
||||
}
|
||||
52
src/Service/HubFilter/Filters/JoTypeHubFilter.php
Normal file
52
src/Service/HubFilter/Filters/JoTypeHubFilter.php
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
<?php
|
||||
|
||||
namespace App\Service\HubFilter\Filters;
|
||||
|
||||
use App\Service\HubFilter\BaseHubFilter;
|
||||
use App\Service\HubFilter\HubFilterInterface;
|
||||
|
||||
class JoTypeHubFilter extends BaseHubFilter implements HubFilterInterface
|
||||
{
|
||||
protected $id = 'job_order_type';
|
||||
|
||||
public function getRequestedParams() : array
|
||||
{
|
||||
return [
|
||||
'flag_emergency',
|
||||
'jo_type',
|
||||
];
|
||||
}
|
||||
|
||||
public function filter(array $hubs, array $params = []) : array
|
||||
{
|
||||
if ($params['flag_emergency'])
|
||||
return $hubs;
|
||||
|
||||
if (empty($params['jo_type']))
|
||||
return $hubs;
|
||||
|
||||
$results = [];
|
||||
foreach ($hubs as $hub_data)
|
||||
{
|
||||
$hub = $hub_data['hub'];
|
||||
|
||||
// TODO: for now, have this return true
|
||||
$has_jo_type = true;
|
||||
// check if hub offers the jo_type
|
||||
// TODO: add service to hub
|
||||
if ($has_jo_type)
|
||||
$results[] = [
|
||||
'hub' => $hub,
|
||||
'db_distance' => $hub_data['db_distance'],
|
||||
'distance' => $hub_data['distance'],
|
||||
'duration' => $hub_data['duration'],
|
||||
'jo_count' => 0,
|
||||
'inventory' => $hub_data['inventory'],
|
||||
];
|
||||
else
|
||||
$this->log($hub);
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
}
|
||||
35
src/Service/HubFilter/Filters/MaxResultsHubFilter.php
Normal file
35
src/Service/HubFilter/Filters/MaxResultsHubFilter.php
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
namespace App\Service\HubFilter\Filters;
|
||||
|
||||
use App\Service\HubFilter\BaseHubFilter;
|
||||
use App\Service\HubFilter\HubFilterInterface;
|
||||
|
||||
class MaxResultsHubFilter extends BaseHubFilter implements HubFilterInterface
|
||||
{
|
||||
protected $id = 'max_results';
|
||||
|
||||
public function getRequestedParams() : array
|
||||
{
|
||||
return [
|
||||
'limit_results',
|
||||
];
|
||||
}
|
||||
|
||||
public function filter(array $hubs, array $params = []) : array
|
||||
{
|
||||
if (empty($params['limit_results']))
|
||||
return $hubs;
|
||||
|
||||
$results = [];
|
||||
for ($i = 0; $i < count($hubs); $i++)
|
||||
{
|
||||
if ($i < $params['limit_results'])
|
||||
$results[] = $hubs[$i];
|
||||
else
|
||||
$this->log($hubs[$i]['hub']);
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
}
|
||||
63
src/Service/HubFilter/Filters/PaymentMethodHubFilter.php
Normal file
63
src/Service/HubFilter/Filters/PaymentMethodHubFilter.php
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
<?php
|
||||
|
||||
namespace App\Service\HubFilter\Filters;
|
||||
|
||||
use App\Service\HubFilter\BaseHubFilter;
|
||||
use App\Service\HubFilter\HubFilterInterface;
|
||||
|
||||
class PaymentMethodHubFilter extends BaseHubFilter implements HubFilterInterface
|
||||
{
|
||||
protected $id = 'no_payment_method';
|
||||
|
||||
public function getRequestedParams() : array
|
||||
{
|
||||
return [
|
||||
'flag_emergency',
|
||||
'payment_method',
|
||||
];
|
||||
}
|
||||
|
||||
public function filter(array $hubs, array $params = []) : array
|
||||
{
|
||||
if ($params['flag_emergency'])
|
||||
return $hubs;
|
||||
|
||||
if (empty($params['payment_method']))
|
||||
return $hubs;
|
||||
|
||||
$results = [];
|
||||
foreach ($hubs as $hub_data)
|
||||
{
|
||||
$hub = $hub_data['hub'];
|
||||
|
||||
// name of payment method is what is saved
|
||||
$payment_methods = $hub->getPaymentMethods();
|
||||
if ($payment_methods != null)
|
||||
{
|
||||
$flag_found_pmethod = false;
|
||||
foreach ($payment_methods as $pmethod)
|
||||
{
|
||||
if ($pmethod == $params['payment_method'])
|
||||
{
|
||||
$results[] = [
|
||||
'hub' => $hub,
|
||||
'db_distance' => $hub_data['db_distance'],
|
||||
'distance' => $hub_data['distance'],
|
||||
'duration' => $hub_data['duration'],
|
||||
'jo_count' => 0,
|
||||
'inventory' => $hub_data['inventory'],
|
||||
];
|
||||
}
|
||||
$flag_found_pmethod = true;
|
||||
}
|
||||
|
||||
if (!$flag_found_pmethod)
|
||||
$this->log($hub);
|
||||
}
|
||||
else
|
||||
$this->log($hub);
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
}
|
||||
75
src/Service/HubFilter/Filters/RiderAvailabilityHubFilter.php
Normal file
75
src/Service/HubFilter/Filters/RiderAvailabilityHubFilter.php
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
<?php
|
||||
|
||||
namespace App\Service\HubFilter\Filters;
|
||||
|
||||
use App\Service\HubFilter\BaseHubFilter;
|
||||
use App\Service\HubFilter\HubFilterInterface;
|
||||
|
||||
use App\Ramcar\JORejectionReason;
|
||||
use App\Ramcar\CustomerClassification;
|
||||
|
||||
class RiderAvailabilityHubFilter extends BaseHubFilter implements HubFilterInterface
|
||||
{
|
||||
protected $id = 'no_available_rider';
|
||||
|
||||
public function getRequestedParams() : array
|
||||
{
|
||||
return [
|
||||
'flag_riders_check',
|
||||
'customer_class',
|
||||
'order_date',
|
||||
'service_type',
|
||||
];
|
||||
}
|
||||
|
||||
public function filter(array $hubs, array $params = []) : array
|
||||
{
|
||||
// check if this is enabled
|
||||
if (!$params['flag_riders_check']) {
|
||||
return $hubs;
|
||||
}
|
||||
|
||||
// check customer class
|
||||
if (!empty($params['customer_class']) && $params['customer_class'] == CustomerClassification::VIP) {
|
||||
error_log("RIDER CHECK " . $this->getJOID() . ": VIP CLASS");
|
||||
return $hubs;
|
||||
}
|
||||
|
||||
$results = [];
|
||||
|
||||
foreach ($hubs as $hub_data) {
|
||||
$hub = $hub_data['hub'];
|
||||
|
||||
$available_riders = count($hub->getAvailableRiders());
|
||||
// check we have available riders
|
||||
error_log("TOTAL RIDERS: " . $available_riders);
|
||||
if ($available_riders === 0) {
|
||||
// if we have a JO, create rejection record and notify
|
||||
$jo_id = $this->getJOID();
|
||||
|
||||
if (!empty($jo_id)) {
|
||||
// create rejection report entry
|
||||
$robj = $this->createRejectionEntry($hub, JORejectionReason::NO_RIDER_AVAILABLE);
|
||||
|
||||
// build SMS message
|
||||
$this->sendSMSMessage(
|
||||
$hub,
|
||||
$params['order_date'],
|
||||
$params['service_type'],
|
||||
$robj,
|
||||
JORejectionReason::getName(JORejectionReason::NO_RIDER_AVAILABLE),
|
||||
);
|
||||
}
|
||||
|
||||
// log this filter
|
||||
$this->log($hub);
|
||||
|
||||
error_log("FILTERED HUB " . $hub->getID() . " (no_available_rider)");
|
||||
} else {
|
||||
$results[] = $hub_data;
|
||||
}
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
}
|
||||
46
src/Service/HubFilter/Filters/RoundRobinHubFilter.php
Normal file
46
src/Service/HubFilter/Filters/RoundRobinHubFilter.php
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
|
||||
namespace App\Service\HubFilter\Filters;
|
||||
|
||||
use App\Service\HubFilter\BaseHubFilter;
|
||||
use App\Service\HubFilter\HubFilterInterface;
|
||||
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
use App\Service\HubDistributor;
|
||||
use App\Service\HubFilterLogger;
|
||||
use App\Service\RisingTideGateway;
|
||||
|
||||
class RoundRobinHubFilter extends BaseHubFilter implements HubFilterInterface
|
||||
{
|
||||
protected $id = 'round_robin';
|
||||
protected $hub_distributor;
|
||||
|
||||
public function __construct(HubFilterLogger $hub_filter_logger, EntityManagerInterface $em, RisingTideGateway $rt, TranslatorInterface $trans, HubDistributor $hub_distributor)
|
||||
{
|
||||
parent::__construct($hub_filter_logger, $em, $rt, $trans);
|
||||
$this->hub_distributor = $hub_distributor;
|
||||
}
|
||||
|
||||
public function getRequestedParams() : array
|
||||
{
|
||||
return [
|
||||
'flag_round_robin',
|
||||
];
|
||||
}
|
||||
|
||||
public function filter(array $hubs, array $params = []) : array
|
||||
{
|
||||
if (!$params['flag_round_robin'])
|
||||
return $hubs;
|
||||
|
||||
$results = [];
|
||||
|
||||
// call hub distributor service
|
||||
$arranged_hubs = $this->hub_distributor->arrangeHubs($hubs);
|
||||
$results = $arranged_hubs;
|
||||
|
||||
return $results;
|
||||
}
|
||||
}
|
||||
20
src/Service/HubFilter/HubFilterInterface.php
Normal file
20
src/Service/HubFilter/HubFilterInterface.php
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
|
||||
namespace App\Service\HubFilter;
|
||||
|
||||
interface HubFilterInterface
|
||||
{
|
||||
public function getID() : string;
|
||||
|
||||
public function filter(array $hubs, array $params = []) : array;
|
||||
|
||||
public function setJOID(int $jo_id);
|
||||
|
||||
public function getJOID() : int;
|
||||
|
||||
public function setCustomerID(int $customer_id);
|
||||
|
||||
public function getCustomerID() : int;
|
||||
|
||||
public function getRequestedParams() : array;
|
||||
}
|
||||
|
|
@ -5,21 +5,20 @@ namespace App\Service;
|
|||
use Doctrine\ORM\EntityManagerInterface;
|
||||
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
use CrEOF\Spatial\PHP\Types\Geometry\Point;
|
||||
|
||||
use App\Entity\Hub;
|
||||
|
||||
use App\Service\HubDistributor;
|
||||
use App\Service\InventoryManager;
|
||||
use App\Service\HubFilterLogger;
|
||||
use App\Service\RisingTideGateway;
|
||||
|
||||
use App\Ramcar\HubCriteria;
|
||||
use App\Ramcar\ServiceType;
|
||||
|
||||
class HubSelector
|
||||
{
|
||||
protected $container;
|
||||
protected $em;
|
||||
protected $im;
|
||||
protected $hub_distributor;
|
||||
|
|
@ -27,10 +26,11 @@ class HubSelector
|
|||
protected $trans;
|
||||
protected $rt;
|
||||
|
||||
public function __construct(EntityManagerInterface $em, InventoryManager $im,
|
||||
public function __construct(ContainerInterface $container, EntityManagerInterface $em, InventoryManager $im,
|
||||
HubDistributor $hub_distributor, HubFilterLogger $hub_filter_logger,
|
||||
TranslatorInterface $trans, RisingTideGateway $rt)
|
||||
{
|
||||
$this->container = $container;
|
||||
$this->em = $em;
|
||||
$this->im = $im;
|
||||
$this->hub_distributor = $hub_distributor;
|
||||
|
|
@ -39,6 +39,18 @@ class HubSelector
|
|||
$this->rt = $rt;
|
||||
}
|
||||
|
||||
protected function getActiveFilters(): array
|
||||
{
|
||||
$fnames = explode(",", $this->container->getParameter('enabled_hub_filters'));
|
||||
$enabled_filters = [];
|
||||
|
||||
foreach ($fnames as $filter) {
|
||||
$enabled_filters[] = 'App\\Service\\HubFilter\\Filters\\' . $filter;
|
||||
}
|
||||
|
||||
return $enabled_filters;
|
||||
}
|
||||
|
||||
public function find(HubCriteria $criteria)
|
||||
{
|
||||
$point = $criteria->getPoint();
|
||||
|
|
@ -46,15 +58,20 @@ class HubSelector
|
|||
$limit_distance = $criteria->getLimitDistance();
|
||||
$jo_type = $criteria->getJoType();
|
||||
$flag_inventory_check = $criteria->hasInventoryCheck();
|
||||
$flag_riders_check = $criteria->hasRidersCheck();
|
||||
$items = $criteria->getItems();
|
||||
$date_time = $criteria->getDateTime();
|
||||
$payment_method = $criteria->getPaymentMethod();
|
||||
$flag_emergency = $criteria->isEmergency();
|
||||
$flag_round_robin = $criteria->isRoundRobin();
|
||||
$jo_id = $criteria->getJobOrderId();
|
||||
$jo_origin = $criteria->getJoOrigin();
|
||||
$customer_id = $criteria->getCustomerId();
|
||||
$customer_class = $criteria->getCustomerClass();
|
||||
|
||||
$results = [];
|
||||
// needed for JORejection records and SMS notifs
|
||||
$order_date = $criteria->getOrderDate();
|
||||
$service_type = $criteria->getServiceType();
|
||||
|
||||
// error_log('payment methods ' . $payment_method);
|
||||
// error_log('distance limit ' . $limit_distance);
|
||||
|
|
@ -63,278 +80,52 @@ class HubSelector
|
|||
// get all the hubs within distance
|
||||
$filtered_hubs = $this->getClosestHubs($point, $limit_distance, $jo_id, $customer_id);
|
||||
|
||||
// error_log('closest hubs ' . json_encode($filtered_hubs));
|
||||
// build param list
|
||||
$params = [
|
||||
'date_time' => $date_time,
|
||||
'flag_inventory_check' => $flag_inventory_check,
|
||||
'customer_class' => $customer_class,
|
||||
'jo_type' => $jo_type,
|
||||
'jo_origin' => $jo_origin,
|
||||
'order_date' => $order_date,
|
||||
'service_type' => $service_type,
|
||||
'items' => $items,
|
||||
'flag_emergency' => $flag_emergency,
|
||||
'limit_results' => $limit_results,
|
||||
'payment_method' => $payment_method,
|
||||
'flag_riders_check' => $flag_riders_check,
|
||||
'flag_round_robin' => $flag_round_robin,
|
||||
];
|
||||
|
||||
// filter the first hub results for date and opening times
|
||||
$hubs_date_time = $this->filterHubsByDateAndTime($filtered_hubs, $date_time, $jo_id, $customer_id);
|
||||
$filtered_hubs = $hubs_date_time;
|
||||
|
||||
// error_log('date_time hubs ' . json_encode($filtered_hubs));
|
||||
|
||||
if (!$flag_emergency)
|
||||
{
|
||||
// filter jo types
|
||||
$hubs_jo_type = $this->filterHubsByJoType($filtered_hubs, $jo_type, $jo_id, $customer_id);
|
||||
$filtered_hubs = $hubs_jo_type;
|
||||
|
||||
//error_log('jo_type hubs ' . json_encode($filtered_hubs));
|
||||
|
||||
// filter hubs by payment methods
|
||||
$hubs_payment_method = $this->filterHubsByPaymentMethod($filtered_hubs, $payment_method, $jo_id, $customer_id);
|
||||
$filtered_hubs = $hubs_payment_method;
|
||||
|
||||
//error_log('payment hubs ' . json_encode($filtered_hubs));
|
||||
|
||||
// inventory filter
|
||||
$hubs_inventory = $this->filterHubsByInventory($filtered_hubs, $flag_inventory_check,
|
||||
$jo_type, $items, $jo_id, $customer_id);
|
||||
$filtered_hubs = $hubs_inventory;
|
||||
|
||||
//error_log('inventory hubs ' . json_encode($filtered_hubs));
|
||||
|
||||
// round robin filter
|
||||
$hubs_round_robin = $this->filterHubsByRoundRobin($filtered_hubs, $flag_round_robin);
|
||||
$filtered_hubs = $hubs_round_robin;
|
||||
|
||||
// error_log('round robin hubs ' . json_encode($filtered_hubs));
|
||||
|
||||
// max results filter
|
||||
$hubs_max_result = $this->filterHubsByMaxResults($filtered_hubs, $limit_results, $jo_id, $customer_id);
|
||||
$filtered_hubs = $hubs_max_result;
|
||||
}
|
||||
|
||||
$results = $filtered_hubs;
|
||||
|
||||
// error_log(json_encode($results));
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
protected function filterHubsByRoundRobin($hubs, $flag_round_robin)
|
||||
{
|
||||
if (empty($hubs))
|
||||
return $hubs;
|
||||
if (!$flag_round_robin)
|
||||
return $hubs;
|
||||
|
||||
$results = [];
|
||||
// call hub distributor service
|
||||
$arranged_hubs = $this->hub_distributor->arrangeHubs($hubs);
|
||||
$results = $arranged_hubs;
|
||||
|
||||
return $results;
|
||||
|
||||
}
|
||||
|
||||
protected function filterHubsByMaxResults($hubs, $limit_result, $jo_id, $customer_id)
|
||||
{
|
||||
if (empty($hubs))
|
||||
return $hubs;
|
||||
if (empty($limit_result))
|
||||
return $hubs;
|
||||
|
||||
$results = [];
|
||||
for ($i = 0; $i < count($hubs); $i++)
|
||||
{
|
||||
if ($i < $limit_result)
|
||||
$results[] = $hubs[$i];
|
||||
else
|
||||
$this->hub_filter_logger->logFilteredHub($hubs[$i]['hub'], 'max_results', $jo_id, $customer_id);
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
protected function filterHubsByJoType($hubs, $jo_type, $jo_id, $customer_id)
|
||||
{
|
||||
if (empty($hubs))
|
||||
return $hubs;
|
||||
if (empty($jo_type))
|
||||
return $hubs;
|
||||
|
||||
$results = [];
|
||||
foreach ($hubs as $hub_data)
|
||||
{
|
||||
$hub = $hub_data['hub'];
|
||||
|
||||
// TODO: for now, have this return true
|
||||
$has_jo_type = true;
|
||||
// check if hub offers the jo_type
|
||||
// TODO: add service to hub
|
||||
if ($has_jo_type)
|
||||
$results[] = [
|
||||
'hub' => $hub,
|
||||
'db_distance' => $hub_data['db_distance'],
|
||||
'distance' => $hub_data['distance'],
|
||||
'duration' => $hub_data['duration'],
|
||||
'jo_count' => 0,
|
||||
];
|
||||
else
|
||||
$this->hub_filter_logger->logFilteredHub($hub, 'job_order_type', $jo_id, $customer_id);
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
protected function filterHubsByPaymentMethod($hubs, $payment_method, $jo_id, $customer_id)
|
||||
{
|
||||
if (empty($hubs))
|
||||
return $hubs;
|
||||
if (empty($payment_method))
|
||||
return $hubs;
|
||||
|
||||
$results = [];
|
||||
foreach ($hubs as $hub_data)
|
||||
{
|
||||
$hub = $hub_data['hub'];
|
||||
|
||||
// name of payment method is what is saved
|
||||
$payment_methods = $hub->getPaymentMethods();
|
||||
if ($payment_methods != null)
|
||||
{
|
||||
$flag_found_pmethod = false;
|
||||
foreach ($payment_methods as $pmethod)
|
||||
{
|
||||
if ($pmethod == $payment_method)
|
||||
{
|
||||
$results[] = [
|
||||
'hub' => $hub,
|
||||
'db_distance' => $hub_data['db_distance'],
|
||||
'distance' => $hub_data['distance'],
|
||||
'duration' => $hub_data['duration'],
|
||||
'jo_count' => 0,
|
||||
];
|
||||
}
|
||||
$flag_found_pmethod = true;
|
||||
}
|
||||
|
||||
if (!$flag_found_pmethod)
|
||||
$this->hub_filter_logger->logFilteredHub($hub, 'no_payment_method', $jo_id, $customer_id);
|
||||
// loop through all enabled filters
|
||||
foreach ($this->getActiveFilters() as $hub_filter) {
|
||||
// no hubs left to filter
|
||||
if (empty($filtered_hubs)) {
|
||||
break;
|
||||
}
|
||||
else
|
||||
$this->hub_filter_logger->logFilteredHub($hub, 'no_payment_method', $jo_id, $customer_id);
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
$f = $this->container->get($hub_filter);
|
||||
|
||||
protected function filterHubsByDateAndTime($hubs, $date_time, $jo_id, $customer_id)
|
||||
{
|
||||
if (empty($hubs))
|
||||
return $hubs;
|
||||
|
||||
if ($date_time == null)
|
||||
return $hubs;
|
||||
|
||||
$results = [];
|
||||
|
||||
foreach ($hubs as $hub_data)
|
||||
{
|
||||
// go through each hub's opening times to check if hub is open
|
||||
// for the specified time
|
||||
// get hub opening and closing times
|
||||
// TODO: maybe in the future, might also have to check if hub
|
||||
// is open/available on date/day
|
||||
$hub = $hub_data['hub'];
|
||||
|
||||
$time_open = $hub->getTimeOpen()->format("H:i:s");
|
||||
$time_close = $hub->getTimeClose()->format("H:i:s");
|
||||
|
||||
$filter_time = $date_time->format("H:i:s");
|
||||
|
||||
if (($filter_time >= $time_open) &&
|
||||
($filter_time <= $time_close))
|
||||
{
|
||||
$results[] = [
|
||||
'hub' => $hub,
|
||||
'db_distance' => $hub_data['db_distance'],
|
||||
'distance' => $hub_data['distance'],
|
||||
'duration' => $hub_data['duration'],
|
||||
'jo_count' => 0,
|
||||
];
|
||||
// check if supported area is exempted from this filter
|
||||
if ($this->isExemptedByArea($f->getID(), $point)) {
|
||||
continue;
|
||||
}
|
||||
else
|
||||
$this->hub_filter_logger->logFilteredHub($hub, 'date_and_time', $jo_id, $customer_id);
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
protected function filterHubsByInventory($hubs, $flag_inventory_check, $jo_type, $items, $jo_id, $customer_id)
|
||||
{
|
||||
if (empty($hubs))
|
||||
return $hubs;
|
||||
$f->setJOID($jo_id);
|
||||
$f->setCustomerID($customer_id);
|
||||
|
||||
if (!$flag_inventory_check)
|
||||
return $hubs;
|
||||
// get requested params only
|
||||
$req_params = array_intersect_key($params, array_flip($f->getRequestedParams()));
|
||||
|
||||
$results = [];
|
||||
if ($flag_inventory_check)
|
||||
{
|
||||
foreach ($hubs as $hub_data)
|
||||
{
|
||||
$hub = $hub_data['hub'];
|
||||
// filter hub list
|
||||
$filtered_hubs = $f->filter($filtered_hubs, $req_params);
|
||||
|
||||
if ($jo_type == ServiceType::BATTERY_REPLACEMENT_NEW)
|
||||
{
|
||||
// call inventory
|
||||
$has_items = $this->checkInventory($items, $hub);
|
||||
if ($has_items)
|
||||
$results[] = [
|
||||
'hub' => $hub,
|
||||
'db_distance' => $hub_data['db_distance'],
|
||||
'distance' => $hub_data['distance'],
|
||||
'duration' => $hub_data['duration'],
|
||||
'jo_count' => 0,
|
||||
];
|
||||
else
|
||||
{
|
||||
// get the skus for the message
|
||||
$sku_text = '';
|
||||
foreach ($items as $key => $value)
|
||||
{
|
||||
$sku_text .= ' ' . $key;
|
||||
}
|
||||
// send SMS to hub
|
||||
$message = str_replace('item_display', trim($sku_text), $this->trans->trans('no_inventory_message'));
|
||||
// error_log($message);
|
||||
$this->sendSMSMessage($hub, $items);
|
||||
|
||||
$this->hub_filter_logger->logFilteredHub($hub, 'no_inventory', $jo_id, $customer_id);
|
||||
}
|
||||
}
|
||||
if ($jo_type == ServiceType::BATTERY_REPLACEMENT_WARRANTY)
|
||||
{
|
||||
// call inventory
|
||||
$has_items = $this->checkInventory($items, $hub);
|
||||
if ($has_items)
|
||||
$results[] = [
|
||||
'hub' => $hub,
|
||||
'db_distance' => $hub_data['db_distance'],
|
||||
'distance' => $hub_data['distance'],
|
||||
'duration' => $hub_data['duration'],
|
||||
'jo_count' => 0,
|
||||
];
|
||||
else
|
||||
{
|
||||
// get the skus for the message
|
||||
$sku_text = '';
|
||||
foreach ($items as $key => $value)
|
||||
{
|
||||
$sku_text .= ' ' . $key;
|
||||
}
|
||||
// send SMS to hub
|
||||
$message = str_replace('item_display', trim($sku_text), $this->trans->trans('no_inventory_message'));
|
||||
// error_log($message);
|
||||
$this->sendSMSMessage($hub, $items);
|
||||
|
||||
$this->hub_filter_logger->logFilteredHub($hub, 'no_inventory', $jo_id, $customer_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
// error_log($f->getID() . ' hubs ' . json_encode($filtered_hubs));
|
||||
}
|
||||
|
||||
return $results;
|
||||
// error_log('final hub list ' . json_encode($filtered_hubs));
|
||||
|
||||
return $filtered_hubs;
|
||||
}
|
||||
|
||||
protected function getClosestHubs(Point $point, $limit_distance, $jo_id, $customer_id)
|
||||
|
|
@ -375,7 +166,11 @@ class HubSelector
|
|||
'distance' => $dist,
|
||||
'duration' => 0,
|
||||
'jo_count' => 0,
|
||||
'inventory' => 0,
|
||||
];
|
||||
|
||||
// log to file
|
||||
$this->logClosestHubResult($jo_id, $row[0], $dist, $limit_distance);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -386,45 +181,6 @@ class HubSelector
|
|||
return $hubs_data;
|
||||
}
|
||||
|
||||
protected function checkInventory($items, $hub)
|
||||
{
|
||||
// check if hub has all items
|
||||
$skus = [];
|
||||
$branch_codes[] = $hub->getBranchCode();
|
||||
$result = false;
|
||||
|
||||
foreach ($items as $key=> $value)
|
||||
{
|
||||
// add sap code of item/battery into array since
|
||||
// getBranchesInventory takes in an array of hubs/branches
|
||||
// and an array of skus
|
||||
// $items as format: $items[sku] = quantity
|
||||
$skus[] = $key;
|
||||
}
|
||||
|
||||
// call InventoryManager's getBranchesInventory to check if hub has all items
|
||||
$branches_with_items = $this->im->getBranchesInventory($branch_codes, $skus);
|
||||
|
||||
if (!empty($branches_with_items))
|
||||
{
|
||||
// check if branch has enough quantity for item
|
||||
foreach ($branches_with_items as $branch)
|
||||
{
|
||||
// get quantity from call
|
||||
$qty_available = $branch['Quantity'];
|
||||
|
||||
// get the quantity request
|
||||
$sku_requested = $branch['SapCode'];
|
||||
$qty_requested = $items[$sku_requested];
|
||||
if ($qty_available >= $qty_requested)
|
||||
$result = true;
|
||||
}
|
||||
}
|
||||
|
||||
// return true or false
|
||||
return $result;
|
||||
}
|
||||
|
||||
// convert db distance to kilometers
|
||||
protected function distance($lat1, $lon1, $lat2, $lon2)
|
||||
{
|
||||
|
|
@ -440,26 +196,50 @@ class HubSelector
|
|||
return round(($miles * 1.609344), 1);
|
||||
}
|
||||
|
||||
protected function sendSMSMessage($hub, $items)
|
||||
protected function isExemptedByArea(string $filter_id, Point $coordinates): bool
|
||||
{
|
||||
// compose message
|
||||
// get the skus for the message
|
||||
$sku_text = '';
|
||||
foreach ($items as $key => $value)
|
||||
{
|
||||
$sku_text .= ' ' . $key;
|
||||
}
|
||||
$message = str_replace('item_display', trim($sku_text), $this->trans->trans('no_inventory_message'));
|
||||
$long = $coordinates->getLongitude();
|
||||
$lat = $coordinates->getLatitude();
|
||||
|
||||
// get hub notification number
|
||||
$mobile_number = $hub->getNotifNumber();
|
||||
// get supported area given a set of coordinates
|
||||
$query = $this->em->createQuery('SELECT s from App\Entity\SupportedArea s where st_contains(s.coverage_area, point(:long, :lat)) = true');
|
||||
$area = $query->setParameter('long', $long)
|
||||
->setParameter('lat', $lat)
|
||||
->setMaxResults(1)
|
||||
->getOneOrNullResult();
|
||||
|
||||
if (!empty($mobile_number))
|
||||
{
|
||||
// send SMS message
|
||||
// error_log('sending sms to - ' . $mobile_number);
|
||||
$this->rt->sendSMS($mobile_number, $this->trans->trans('message.battery_brand_allcaps'), $message);
|
||||
if ($area !== null) {
|
||||
// get all exceptions
|
||||
$exceptions = $area->getHubFilterExceptions();
|
||||
|
||||
if (isset($exceptions[$filter_id])) {
|
||||
error_log("FILTER " . $filter_id . " DISABLED FOR AREA: " . $area->getName());
|
||||
|
||||
// disable this filter for this area
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// filter is in place
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function logClosestHubResult($jo_id, $hub, $distance, $limit_distance)
|
||||
{
|
||||
// log to file
|
||||
$filename = '/../../var/log/closest_hubs_selected.log';
|
||||
$date = date("Y-m-d H:i:s");
|
||||
|
||||
// build log entry
|
||||
$entry = implode("", [
|
||||
"[JO: " . $jo_id . "]",
|
||||
"[" . $date . "]",
|
||||
"[Distance: " . $distance . " vs " . $limit_distance . "]",
|
||||
" " . $hub->getName() . " (ID: " . $hub->getID() . ")",
|
||||
"\r\n",
|
||||
]);
|
||||
|
||||
@file_put_contents(__DIR__ . $filename, $entry, FILE_APPEND);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface
|
|||
protected $hub_dist;
|
||||
protected $hub_geofence;
|
||||
protected $cust_distance_limit;
|
||||
protected $hub_filter_enable;
|
||||
protected $hub_filter_enabled;
|
||||
protected $jo_manager;
|
||||
protected $pt_manager;
|
||||
|
||||
|
|
@ -2559,10 +2559,20 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface
|
|||
->setDateTime($obj->getDateSchedule())
|
||||
->setLimitResults(50);
|
||||
|
||||
// NOTE: set JO type regardless, for now
|
||||
$hub_criteria->setJoType($obj->getServiceType())
|
||||
->setOrderDate($obj->getDateCreate())
|
||||
->setServiceType($obj->getServiceType());
|
||||
|
||||
// set customer class
|
||||
$cust = $obj->getCustomer();
|
||||
$hub_criteria->setCustomerClass($cust->getCustomerClassification());
|
||||
|
||||
// check if hub filter is enabled. If not, use default values
|
||||
// for the rest of the HubCriteria fields
|
||||
if ($this->hub_filter_enabled == 'true')
|
||||
{
|
||||
// TODO: allow this to be disabled via env or CRM. commenting out for now
|
||||
// error_log('hub filter is enabled');
|
||||
if ($this->hub_geofence->isCovered($long, $lat))
|
||||
{
|
||||
|
|
@ -2570,7 +2580,6 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface
|
|||
// error_log('Area is covered by hub filtering');
|
||||
$hub_criteria->setLimitDistance($this->cust_distance_limit)
|
||||
->setPaymentMethod($obj->getModeOfPayment())
|
||||
->setJoType($obj->getServiceType())
|
||||
->setRoundRobin(true);
|
||||
}
|
||||
}
|
||||
|
|
@ -2581,15 +2590,22 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface
|
|||
{
|
||||
// reset distance limit if emergency
|
||||
//TODO: move to .env the emergency distance limit
|
||||
$hub_criteria->setLimitDistance(500);
|
||||
$hub_criteria->setEmergency(true);
|
||||
$hub_criteria->setLimitDistance(500)
|
||||
->setEmergency(true)
|
||||
->setPaymentMethod(null)
|
||||
->setRoundRobin(false);
|
||||
}
|
||||
|
||||
// set filter flags for inventory and available riders
|
||||
$hub_criteria->setInventoryCheck();
|
||||
$hub_criteria->setRidersCheck();
|
||||
|
||||
// get JO and customer id for logging purposes
|
||||
$jo_id = $obj->getID();
|
||||
$customer_id = $obj->getCustomer()->getID();
|
||||
|
||||
$hub_criteria->setJobOrderId($jo_id)
|
||||
->setJoOrigin($obj->getSource())
|
||||
->setCustomerId($customer_id);
|
||||
|
||||
$hubs = $hub_selector->find($hub_criteria);
|
||||
|
|
@ -2654,7 +2670,7 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface
|
|||
|
||||
// handle inventory data
|
||||
$bcode = $hub['hub']->getBranchCode();
|
||||
$hub['inventory'] = 0;
|
||||
//$hub['inventory'] = 0;
|
||||
if ($bcode != '')
|
||||
{
|
||||
$branch_codes[] = $bcode;
|
||||
|
|
@ -2672,7 +2688,10 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface
|
|||
// get template to display
|
||||
$params['template'] = $this->getTwigTemplate('jo_processing_form');
|
||||
|
||||
// NOTE: as we have included inventory now from the hub selector, we no longer have to redo it here
|
||||
|
||||
// get battery (if any)
|
||||
/*
|
||||
$skus = [];
|
||||
$invoice = $obj->getInvoice();
|
||||
$inv_items = $invoice->getItems();
|
||||
|
|
@ -2702,6 +2721,7 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface
|
|||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// error_log(print_r($mres, true));
|
||||
|
||||
|
|
@ -2897,13 +2917,22 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface
|
|||
->setDateTime($obj->getDateSchedule())
|
||||
->setLimitResults(50);
|
||||
|
||||
// NOTE: set JO type regardless, for now
|
||||
$hub_criteria->setJoType($obj->getServiceType())
|
||||
->setOrderDate($obj->getDateCreate())
|
||||
->setServiceType($obj->getServiceType());
|
||||
|
||||
// set customer class
|
||||
$cust = $obj->getCustomer();
|
||||
$hub_criteria->setCustomerClass($cust->getCustomerClassification());
|
||||
|
||||
// TODO: allow this to be disabled via env or CRM. commenting out for now
|
||||
if ($this->hub_geofence->isCovered($long, $lat))
|
||||
{
|
||||
// if true, set other values for HubCriteria
|
||||
// error_log('Area is covered by hub');
|
||||
$hub_criteria->setLimitDistance($this->cust_distance_limit)
|
||||
->setPaymentMethod($obj->getModeOfPayment())
|
||||
->setJoType($obj->getServiceType())
|
||||
->setRoundRobin(true);
|
||||
}
|
||||
|
||||
|
|
@ -2912,15 +2941,22 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface
|
|||
if ($willing_to_wait == WillingToWaitContent::NOT_WILLING_TO_WAIT)
|
||||
{
|
||||
//TODO: move to .env the emergency distance limit
|
||||
$hub_criteria->setLimitDistance(500);
|
||||
$hub_criteria->setEmergency(true);
|
||||
$hub_criteria->setLimitDistance(500)
|
||||
->setEmergency(true)
|
||||
->setPaymentMethod(null)
|
||||
->setRoundRobin(false);
|
||||
}
|
||||
|
||||
// set filter flags for inventory and available riders
|
||||
$hub_criteria->setInventoryCheck();
|
||||
$hub_criteria->setRidersCheck();
|
||||
|
||||
// get JO and customer id for logging purposes
|
||||
$jo_id = $obj->getID();
|
||||
$customer_id = $obj->getCustomer()->getID();
|
||||
$customer_id = $cust->getID();
|
||||
|
||||
$hub_criteria->setJobOrderId($jo_id)
|
||||
->setJoOrigin($obj->getSource())
|
||||
->setCustomerId($customer_id);
|
||||
|
||||
$hubs = $hub_selector->find($hub_criteria);
|
||||
|
|
@ -2929,6 +2965,8 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface
|
|||
$params['hubs'] = [];
|
||||
|
||||
$branch_codes = [];
|
||||
$inv_data = [];
|
||||
|
||||
// format duration and distance into friendly time
|
||||
foreach ($hubs as $hub) {
|
||||
// duration
|
||||
|
|
@ -2984,7 +3022,7 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface
|
|||
|
||||
// handle inventory data
|
||||
$bcode = $hub['hub']->getBranchCode();
|
||||
$hub['inventory'] = 0;
|
||||
//$hub['inventory'] = 0;
|
||||
if ($bcode != '')
|
||||
{
|
||||
$branch_codes[] = $bcode;
|
||||
|
|
@ -2998,39 +3036,65 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface
|
|||
$params['hubs'][$hub_id] = $hub;
|
||||
}
|
||||
|
||||
// get battery (if any)
|
||||
$skus = [];
|
||||
$invoice = $obj->getInvoice();
|
||||
$inv_items = $invoice->getItems();
|
||||
foreach ($inv_items as $inv_item)
|
||||
{
|
||||
$batt = $inv_item->getBattery();
|
||||
if ($batt == null)
|
||||
continue;
|
||||
// NOTE: as we have included inventory now from the hub selector, we no longer have to redo it here
|
||||
|
||||
$skus[] = $batt->getSapCode();
|
||||
}
|
||||
//error_log("TOTAL HUBS FOUND WITH BRANCH CODE: " . count($inv_data));
|
||||
|
||||
// get inventory
|
||||
$mres = $motiv->getInventory($branch_codes, $skus);
|
||||
foreach ($mres as $mres_item)
|
||||
{
|
||||
// check if we have a valid response from motiv, ignore otherwise
|
||||
if (isset($mres_item['BranchCode']))
|
||||
// get all enabled filters
|
||||
$enabled_filter_str = $_ENV['ENABLED_HUB_FILTERS'];
|
||||
$enabled_filters = explode(",", $enabled_filter_str);
|
||||
|
||||
// if inventory filter is disabled, fetch inventory here
|
||||
if (!in_array('InventoryHubFilter', $enabled_filters) || $this->skipInventoryCheck($obj->getCoordinates())) {
|
||||
error_log("NO INVENTORY CHECKS, GETTING INVENTORY FOR JO " . $obj->getID());
|
||||
|
||||
// get battery (if any)
|
||||
$skus = [];
|
||||
$invoice = $obj->getInvoice();
|
||||
$inv_items = $invoice->getItems();
|
||||
foreach ($inv_items as $inv_item)
|
||||
{
|
||||
$bcode = $mres_item['BranchCode'];
|
||||
$inv_count = $mres_item['Quantity'];
|
||||
if (isset($inv_data[$bcode]))
|
||||
{
|
||||
$hub_id = $inv_data[$bcode]['hub_id'];
|
||||
$batt = $inv_item->getBattery();
|
||||
if ($batt == null)
|
||||
continue;
|
||||
|
||||
$params['hubs'][$hub_id]['inventory'] = $inv_count;
|
||||
$skus[] = $batt->getSapCode();
|
||||
}
|
||||
|
||||
// get inventory
|
||||
$mres = $motiv->getInventory($branch_codes, $skus);
|
||||
$x = 0;
|
||||
|
||||
error_log("TOTAL RESULTS FROM MOTIV: " . count($mres) . " OUT OF " . count($branch_codes) . " BRANCH CODES AND " . count($skus) . " SKUS");
|
||||
|
||||
foreach ($mres as $mres_item)
|
||||
{
|
||||
// check if we have a valid response from motiv, ignore otherwise
|
||||
if (isset($mres_item['BranchCode']))
|
||||
{
|
||||
$bcode = $mres_item['BranchCode'];
|
||||
$inv_count = $mres_item['Quantity'];
|
||||
if (isset($inv_data[$bcode]))
|
||||
{
|
||||
$hub_id = $inv_data[$bcode]['hub_id'];
|
||||
|
||||
$params['hubs'][$hub_id]['inventory'] = $inv_count;
|
||||
|
||||
error_log("SETTING HUB " . $hub_id . " INVENTORY TO " . $inv_count);
|
||||
$x++;
|
||||
} else {
|
||||
error_log("CANNOT FIND BCODE FOR " . $bcode);
|
||||
}
|
||||
} else {
|
||||
error_log("CANNOT FIND BCODE FOR RESULT: " . print_r($mres_item, true));
|
||||
}
|
||||
}
|
||||
|
||||
error_log("SET QUANTITY OF " . $x . " HUBS TO NON ZERO");
|
||||
|
||||
// error_log(print_r($mres, true));
|
||||
}
|
||||
|
||||
// error_log(print_r($mres, true));
|
||||
|
||||
|
||||
$params['obj'] = $obj;
|
||||
// get template to display
|
||||
$params['template'] = $this->getTwigTemplate('jo_open_hub_form');
|
||||
|
|
@ -4306,4 +4370,28 @@ class ResqJobOrderHandler implements JobOrderHandlerInterface
|
|||
$this->rt->sendSMS($phone_number, $this->translator->trans('message.battery_brand_allcaps'), $msg);
|
||||
}
|
||||
|
||||
protected function skipInventoryCheck(Point $coordinates): bool
|
||||
{
|
||||
$long = $coordinates->getLongitude();
|
||||
$lat = $coordinates->getLatitude();
|
||||
|
||||
// get supported area given a set of coordinates
|
||||
$query = $this->em->createQuery('SELECT s from App\Entity\SupportedArea s where st_contains(s.coverage_area, point(:long, :lat)) = true');
|
||||
$area = $query->setParameter('long', $long)
|
||||
->setParameter('lat', $lat)
|
||||
->setMaxResults(1)
|
||||
->getOneOrNullResult();
|
||||
|
||||
if ($area !== null) {
|
||||
// get all exceptions
|
||||
$exceptions = $area->getHubFilterExceptions();
|
||||
|
||||
if (isset($exceptions['no_inventory'])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// filter is in place
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,8 @@ add_cust_vehicle_battery_info: This vehicle is using a Motolite battery
|
|||
jo_title_pdf: Motolite Res-Q Job Order
|
||||
country_code_prefix: '+63'
|
||||
delivery_instructions_label: Delivery Instructions
|
||||
no_inventory_message: No stock for [item_display]
|
||||
no_inventory_message: 'A Job Order was created but there is insufficient stock for the following SKU(s) on this branch: [item_display]'
|
||||
no_riders_message: A Job Order was created but there are no riders available for this branch.
|
||||
|
||||
# images
|
||||
image_logo_login: /assets/images/logo-resq.png
|
||||
|
|
|
|||
2
utils/hub_filter_exceptions/hub_filter_exceptions.sql
Normal file
2
utils/hub_filter_exceptions/hub_filter_exceptions.sql
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
update supported_area set hub_filter_exceptions = '{"no_inventory":true,"no_available_rider":true}' where id = 34;
|
||||
update supported_area set hub_filter_exceptions = '{"no_inventory":true,"no_available_rider":true}' where id = 35;
|
||||
Loading…
Reference in a new issue