From 7e7d99d9c957d8a78d38c5fcbcdc9b275ca51474 Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Fri, 22 Feb 2019 05:29:10 -0500 Subject: [PATCH 01/36] Add initial changes to script that generates warranties for existing job orders --- .../GenerateWarrantyFromJobOrderCommand.php | 86 +++++++++++++++++++ symfony.lock | 15 ++++ 2 files changed, 101 insertions(+) create mode 100644 src/Command/GenerateWarrantyFromJobOrderCommand.php diff --git a/src/Command/GenerateWarrantyFromJobOrderCommand.php b/src/Command/GenerateWarrantyFromJobOrderCommand.php new file mode 100644 index 00000000..26e4c759 --- /dev/null +++ b/src/Command/GenerateWarrantyFromJobOrderCommand.php @@ -0,0 +1,86 @@ +em = $em; + + parent::__construct(); + } + + protected function configure() + { + $this->setName('warranty:generate') + ->setDescription('Generates warranty from job order and inserts into database') + ->setHelp('Generate warranty from job order'); + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $em = $this->em; + + $qb = $this->em->getRepository(JobOrder::class)->createQueryBuilder('j'); + + // get all job orders with service_type='battery_warranty' + $qb->select('j') + ->where('j.service_type = :service_type') + ->setParameter('service_type', ServiceType::BATTERY_REPLACEMENT_WARRANTY); + + $query = $qb->getQuery(); + $result = $query->getResult(); + + foreach ($result as $jo) + { + $invoice_items = []; + // For now, one invoice == one battery + $invoice_items = $jo->getInvoice()->getItems(); + $invoice_item = $invoice_items[0]; + if ($invoice_item != null) + { + if($invoice_item->getBattery() != null) + { + // manually retrieve the SAPBattery using the SAPCode + $battery_sap_code = $invoice_item->getBattery()->getSAPCode(); + $sap_battery = $this->em->getRepository(SAPBattery::class)->find($battery_sap_code); + + if ($jo->getInvoice()->getDatePaid() != null) + { + // TODO: compute for date_expire = datePurchase + warranty period + // get warranty period from battery. Check if personal or commercial + // warranty period in battery is in months + $warranty = new Warranty(); + $warranty->setWarrantyClass($jo->getWarrantyClass()) + ->setFirstName($jo->getCustomer()->getFirstName()) + ->setLastName($jo->getCustomer()->getLastName()) + ->setMobileNumber($jo->getCustomer()->getPhoneMobile()) + ->setPlateNumber($jo->getCustomerVehicle()->getPlateNumber()) + ->setDatePurchase($jo->getInvoice()->getDatePaid()) + ->setBatteryModel($invoice_item->getBattery()->getModel()) + ->setBatterySize($invoice_item->getBattery()->getSize()) + ->setSAPBattery($sap_battery); + $em->persist($warranty); + } + $em->flush(); + } + } + } + } +} diff --git a/symfony.lock b/symfony.lock index 80750229..45250b81 100644 --- a/symfony.lock +++ b/symfony.lock @@ -1,4 +1,16 @@ { + "creof/doctrine2-spatial": { + "version": "1.2.0" + }, + "creof/geo-parser": { + "version": "2.1.0" + }, + "creof/wkb-parser": { + "version": "v2.3.0" + }, + "creof/wkt-parser": { + "version": "2.2.0" + }, "data-dog/audit-bundle": { "version": "v0.1.10" }, @@ -263,6 +275,9 @@ "symfony/stopwatch": { "version": "v4.0.2" }, + "symfony/thanks": { + "version": "v1.1.0" + }, "symfony/twig-bridge": { "version": "v4.0.2" }, From 084d058341f43e21831e30f7f2692b76e8307fae Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Tue, 26 Feb 2019 20:04:51 -0500 Subject: [PATCH 02/36] Create Symfony command to generate warranties from existing job orders #187 --- .../GenerateWarrantyFromJobOrderCommand.php | 34 ++++++++++++++++--- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/src/Command/GenerateWarrantyFromJobOrderCommand.php b/src/Command/GenerateWarrantyFromJobOrderCommand.php index 26e4c759..ef41209e 100644 --- a/src/Command/GenerateWarrantyFromJobOrderCommand.php +++ b/src/Command/GenerateWarrantyFromJobOrderCommand.php @@ -2,6 +2,9 @@ namespace App\Command; +use DateTime; +use DateInterval; + use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; @@ -33,6 +36,13 @@ class GenerateWarrantyFromJobOrderCommand extends Command ->setHelp('Generate warranty from job order'); } + protected function computeDateExpire($date_create, $warranty_period) + { + $expire_date = clone $date_create; + $expire_date->add(new DateInterval('P'.$warranty_period.'M')); + return $expire_date; + } + protected function execute(InputInterface $input, OutputInterface $output) { $em = $this->em; @@ -61,18 +71,32 @@ class GenerateWarrantyFromJobOrderCommand extends Command $battery_sap_code = $invoice_item->getBattery()->getSAPCode(); $sap_battery = $this->em->getRepository(SAPBattery::class)->find($battery_sap_code); - if ($jo->getInvoice()->getDatePaid() != null) + // get warranty period for battery + $warranty_period = 0; + if ($invoice_item->getBattery()->getWarrantyPrivate() != null) { - // TODO: compute for date_expire = datePurchase + warranty period - // get warranty period from battery. Check if personal or commercial - // warranty period in battery is in months + $warranty_period = $invoice_item->getBattery()->getWarrantyPrivate(); + } + else + { + $warranty_period = $invoice_item->getBattery()->getWarrantyCommercial(); + } + + if ($jo->getInvoice()->getDateCreate() != null) + { + // check if plate number is "clean". If not, do not insert into warranty + if (!(Warranty::cleanPlateNumber($jo->getCustomerVehicle()->getPlateNumber()))) + { + continue; + } $warranty = new Warranty(); $warranty->setWarrantyClass($jo->getWarrantyClass()) ->setFirstName($jo->getCustomer()->getFirstName()) ->setLastName($jo->getCustomer()->getLastName()) ->setMobileNumber($jo->getCustomer()->getPhoneMobile()) ->setPlateNumber($jo->getCustomerVehicle()->getPlateNumber()) - ->setDatePurchase($jo->getInvoice()->getDatePaid()) + ->setDatePurchase($jo->getInvoice()->getDateCreate()) + ->setDateExpire($this->computeDateExpire($jo->getInvoice()->getDateCreate(), $warranty_period)) ->setBatteryModel($invoice_item->getBattery()->getModel()) ->setBatterySize($invoice_item->getBattery()->getSize()) ->setSAPBattery($sap_battery); From d7a2e7f899f5387d10484d2d1f5dc62093549425 Mon Sep 17 00:00:00 2001 From: Kendrick Chan Date: Thu, 28 Mar 2019 11:22:28 +0800 Subject: [PATCH 03/36] Replace apns sender with new one #196 --- src/Command/TestRegAPNSCommand.php | 40 +++++++++++++ src/Service/APNSClient.php | 6 ++ utils/apns_sender/apns_sender.py | 2 +- utils/apns_sender/new_sender.py | 90 ++++++++++++++++++++++++++++++ utils/test_apns/test_apns.py | 13 +++++ 5 files changed, 150 insertions(+), 1 deletion(-) create mode 100644 src/Command/TestRegAPNSCommand.php create mode 100644 utils/apns_sender/new_sender.py create mode 100644 utils/test_apns/test_apns.py diff --git a/src/Command/TestRegAPNSCommand.php b/src/Command/TestRegAPNSCommand.php new file mode 100644 index 00000000..d9615141 --- /dev/null +++ b/src/Command/TestRegAPNSCommand.php @@ -0,0 +1,40 @@ +apns = $apns; + + parent::__construct(); + } + + protected function configure() + { + $this->setName('apns:test_reg') + ->setDescription('Test new format for Apple Push Notification.') + ->setHelp('Test new format for Apple Push Notification.') + ->addArgument('push_id', InputArgument::REQUIRED, 'push_id'); + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $push_id = $input->getArgument('push_id'); + $this->apns->sendReg($push_id, 'Test Delay', 'Body'); + } +} diff --git a/src/Service/APNSClient.php b/src/Service/APNSClient.php index 2fc02fe9..3c48102d 100644 --- a/src/Service/APNSClient.php +++ b/src/Service/APNSClient.php @@ -9,6 +9,7 @@ use Redis; class APNSClient { + // TODO: make this a config entry const REDIS_KEY = 'apns_push'; // protected $mclient; @@ -53,4 +54,9 @@ class APNSClient $this->push($push_id, $message); } } + + public function sendReg($push_id, $message) + { + $this->push($push_id, $message); + } } diff --git a/utils/apns_sender/apns_sender.py b/utils/apns_sender/apns_sender.py index ce3a4823..b9034ab1 100644 --- a/utils/apns_sender/apns_sender.py +++ b/utils/apns_sender/apns_sender.py @@ -59,7 +59,7 @@ class APNSClient(): def setupConnection(self): # socket sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - wsock = ssl.wrap_socket(sock, ssl_version=ssl.PROTOCOL_TLSv1, certfile=self.cert_file) + wsock = ssl.wrap_socket(sock, ssl_version=ssl.PROTOCOL_TLSv1_2, certfile=self.cert_file) wsock.connect((self.host, self.port)) self.is_connected = True diff --git a/utils/apns_sender/new_sender.py b/utils/apns_sender/new_sender.py new file mode 100644 index 00000000..557cd605 --- /dev/null +++ b/utils/apns_sender/new_sender.py @@ -0,0 +1,90 @@ +from daemonize import Daemonize +from apns import APNs, Frame, Payload +import redis +import time +import signal +import sys +import os +import logging +import socket + +import ssl +import struct +import binascii + + + +def sigint_handler(signal, frame): + sys.exit(0) + os._exit(0) + +def redisLoop(apns, logger): + r = redis.StrictRedis(host='localhost', port=6379, db=0) + while 1: + #logger.info("Checking queue for messages to send...") + time.sleep(0) + data = r.brpop("apns_push", 10) + if data: + info = data[1].split('|') + logger.info("Token: " + info[0] + " message: " + info[1]) + try: + apns.sendNotification(info[0], info[1], "notification") + except TypeError: + logger.info("Invalid token: " + info[0]) + + +def sigint_handler(signal, frame): + sys.exit(0) + +def get_logger(): + logger = logging.getLogger("apns_logger") + logger.setLevel(logging.INFO) + + fh = logging.FileHandler("/tmp/apns_sender.log") + fmt = '%(asctime)s - %(threadName)s - %(levelname)s - %(message)s' + formatter = logging.Formatter(fmt) + fh.setFormatter(formatter) + + logger.addHandler(fh) + return logger + +class APNSClient(): + def __init__(self, title, cert_file, logger): + self.title = title + self.cert_file = cert_file + self.logger = logger + # connect + self.apns = APNs(cert_file=self.cert_file) + + def sendNotification(self, token, body, notif_type): + # apns packet + alert = {"title" : self.title, + "body" : body, + "type" : notif_type} + + payload = Payload(alert=alert, sound="default", badge=1, content_available=True) + self.apns.gateway_server.send_notification(token, payload) + + +def main(): + logger = get_logger() + logger.info("Starting apns_sender") + + #apns = APNs(use_sandbox=False, cert_file=cert_file) + #apns = setup_apns() + + # TODO: load from config file + cert_file = "/root/ios_push_test/ios_prod.pem" + apns = APNSClient("Motolite Res-q", cert_file, logger) + + logger.info("Starting redis loop") + redisLoop(apns, logger) + + signal.signal(signal.SIGINT, sigint_handler) + + + +pid = "/tmp/apns_sender.pid" +#daemon = Daemonize(app="apns_sender", pid=pid, action=main) +#daemon.start() +main() diff --git a/utils/test_apns/test_apns.py b/utils/test_apns/test_apns.py new file mode 100644 index 00000000..8ee22b17 --- /dev/null +++ b/utils/test_apns/test_apns.py @@ -0,0 +1,13 @@ +from apns import APNs, Frame, Payload + + +#apns = APNs(use_sandbox=True, cert_file='/root/ios_push_test/motoliteUserDev.pem') +apns = APNs(cert_file='/root/ios_push_test/motoliteUserProd.pem') + +alert = {"title" : "Motolite Res-q Notification", + "body" : "Test Notification", + "type" : "register"} + +token_hex = "0D89F702B8E5A235E5100C47912DCBC346CE503DBB860572402031595D6F4C6C" +payload = Payload(alert=alert, sound="default", badge=1, content_available=True) +apns.gateway_server.send_notification(token_hex, payload) From beeaed5c001af87a16d88607d1153a9e0d252b42 Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Fri, 12 Apr 2019 01:44:00 +0000 Subject: [PATCH 04/36] Fix query that checks if a warranty already exists. #187 --- .../GenerateWarrantyFromJobOrderCommand.php | 49 ++++++++++++------- 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/src/Command/GenerateWarrantyFromJobOrderCommand.php b/src/Command/GenerateWarrantyFromJobOrderCommand.php index ef41209e..1412c706 100644 --- a/src/Command/GenerateWarrantyFromJobOrderCommand.php +++ b/src/Command/GenerateWarrantyFromJobOrderCommand.php @@ -49,10 +49,10 @@ class GenerateWarrantyFromJobOrderCommand extends Command $qb = $this->em->getRepository(JobOrder::class)->createQueryBuilder('j'); - // get all job orders with service_type='battery_warranty' + // get all job orders with service_type='battery_replacement_new' $qb->select('j') ->where('j.service_type = :service_type') - ->setParameter('service_type', ServiceType::BATTERY_REPLACEMENT_WARRANTY); + ->setParameter('service_type', ServiceType::BATTERY_REPLACEMENT_NEW); $query = $qb->getQuery(); $result = $query->getResult(); @@ -77,10 +77,14 @@ class GenerateWarrantyFromJobOrderCommand extends Command { $warranty_period = $invoice_item->getBattery()->getWarrantyPrivate(); } - else + if ($invoice_item->getBattery()->getWarrantyCommercial() != null) { $warranty_period = $invoice_item->getBattery()->getWarrantyCommercial(); } + if ($invoice_item->getBattery()->getWarrantyTnv() != null) + { + $warranty_period = $invoice_item->getBattery()->getWarrantyTnv(); + } if ($jo->getInvoice()->getDateCreate() != null) { @@ -89,20 +93,31 @@ class GenerateWarrantyFromJobOrderCommand extends Command { continue; } - $warranty = new Warranty(); - $warranty->setWarrantyClass($jo->getWarrantyClass()) - ->setFirstName($jo->getCustomer()->getFirstName()) - ->setLastName($jo->getCustomer()->getLastName()) - ->setMobileNumber($jo->getCustomer()->getPhoneMobile()) - ->setPlateNumber($jo->getCustomerVehicle()->getPlateNumber()) - ->setDatePurchase($jo->getInvoice()->getDateCreate()) - ->setDateExpire($this->computeDateExpire($jo->getInvoice()->getDateCreate(), $warranty_period)) - ->setBatteryModel($invoice_item->getBattery()->getModel()) - ->setBatterySize($invoice_item->getBattery()->getSize()) - ->setSAPBattery($sap_battery); - $em->persist($warranty); - } - $em->flush(); + // check if warranty already exists + $cleaned_plate_number = Warranty::cleanPlateNumber($jo->getCustomerVehicle()->getPlateNumber()); + $expiry_date = $this->computeDateExpire($jo->getInvoice()->getDateCreate(), $warranty_period); + $found_warranty = $this->em->createQuery("SELECT count(w) FROM App\Entity\Warranty w + WHERE w.plate_number = :plate_number AND w.date_expire = :date_expire") + ->setParameter('plate_number', $cleaned_plate_number) + ->setParameter('date_expire', $expiry_date->format('Y-m-d')) + ->getSingleScalarResult(); + if ($found_warranty == 0) + { + $warranty = new Warranty(); + $warranty->setWarrantyClass($jo->getWarrantyClass()) + ->setFirstName($jo->getCustomer()->getFirstName()) + ->setLastName($jo->getCustomer()->getLastName()) + ->setMobileNumber($jo->getCustomer()->getPhoneMobile()) + ->setPlateNumber($cleaned_plate_number) + ->setDatePurchase($jo->getInvoice()->getDateCreate()) + ->setDateExpire($expiry_date) + ->setBatteryModel($invoice_item->getBattery()->getModel()) + ->setBatterySize($invoice_item->getBattery()->getSize()) + ->setSAPBattery($sap_battery); + $em->persist($warranty); + } + $em->flush(); + } } } } From fd6e617f95eb5c453b64968449d57a24326bdd9c Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Fri, 12 Apr 2019 07:39:21 +0000 Subject: [PATCH 05/36] Add a service that sets the job order as fulfilled and sets the current battery of the customer vehicle to the battery that was purchased. Create a command that tests the service. #204 --- src/Command/TestJobOrderFulfillCommand.php | 40 ++++++++++++++++ src/Service/JobOrderFulfill.php | 53 ++++++++++++++++++++++ 2 files changed, 93 insertions(+) create mode 100644 src/Command/TestJobOrderFulfillCommand.php create mode 100644 src/Service/JobOrderFulfill.php diff --git a/src/Command/TestJobOrderFulfillCommand.php b/src/Command/TestJobOrderFulfillCommand.php new file mode 100644 index 00000000..258fac01 --- /dev/null +++ b/src/Command/TestJobOrderFulfillCommand.php @@ -0,0 +1,40 @@ +setName('test:fulfilljoborder') + ->setDescription('Test fulfill job order service.') + ->setHelp('Test the fulfill job order service.') + ->addArgument('job_order_id', InputArgument::REQUIRED, 'Job Order ID'); + } + + public function __construct(JobOrderFulfill $fulfill_jo) + { + $this->fulfill_jo = $fulfill_jo; + + parent::__construct(); + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $jo_id = $input->getArgument('job_order_id'); + + $result = $this->fulfill_jo->fulfillJobOrder($jo_id); + + if ($result) + echo "Job Order successfully updated" . "\n"; + else + echo "Job Order not updated" . "\n"; + } +} diff --git a/src/Service/JobOrderFulfill.php b/src/Service/JobOrderFulfill.php new file mode 100644 index 00000000..b73044a8 --- /dev/null +++ b/src/Service/JobOrderFulfill.php @@ -0,0 +1,53 @@ +em = $em; + } + + public function fulfillJobOrder($jo_id) + { + $results = $this->em->getRepository(JobOrder::class)->findby(array('id' => $jo_id, 'service_type' => ServiceType::BATTERY_REPLACEMENT_NEW)); + if (isset($results[0])) + { + $jo = $results[0]; + $jo->fulfill(); + + $cust_vehicle = $jo->getCustomerVehicle(); + $invoice = $jo->getInvoice(); + $this->updateCustomerVehicleBattery($cust_vehicle, $invoice); + + return true; + + } + + return false; + } + + protected function updateCustomerVehicleBattery($cust_vehicle, $invoice) + { + if (($cust_vehicle != null) && ($invoice != null)) + { + $items = $invoice->getItems(); + foreach ($items as $item) + { + $new_battery = $item->getBattery(); + $cust_vehicle->setCurrentBattery($new_battery); + } + + $this->em->flush(); + } + } +} From 24715196e5be3db3cb0de17efd894237a5590460 Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Mon, 15 Apr 2019 08:58:30 +0000 Subject: [PATCH 06/36] Create command to update the battery of the customer vehicle to the battery last purchased. #204 --- .../UpdateCustomerVehicleBatteryCommand.php | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 src/Command/UpdateCustomerVehicleBatteryCommand.php diff --git a/src/Command/UpdateCustomerVehicleBatteryCommand.php b/src/Command/UpdateCustomerVehicleBatteryCommand.php new file mode 100644 index 00000000..f7e09e30 --- /dev/null +++ b/src/Command/UpdateCustomerVehicleBatteryCommand.php @@ -0,0 +1,67 @@ +em = $om; + $this->custvehicle_hash = []; + + parent::__construct(); + } + + protected function configure() + { + $this->setName('joborder:updatebattery') + ->setDescription('Update customer vehicle battery information.') + ->setHelp('Updates the customer vehicle battery based on the latest battery purchased. '); + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + // get all job orders with fulfilled status + $jos = $this->em->getRepository(JobOrder::class)->findBy(['status' => JOStatus::FULFILLED], ['date_create' => 'DESC']); + foreach ($jos as $jo) + { + if ($jo->getCustomerVehicle() != null) + { + $custvehicle_id = $jo->getCustomerVehicle()->getID(); + // check if custvehicle is in hash. This would mean that the battery has already been set + if(!isset($this->custvehicle_hash[$custvehicle_id])) + { + // get battery purchased from job order + $items = $jo->getInvoice()->getItems(); + foreach($items as $item) + { + if ($item->getBattery() != null) + { + // set battery of vehicle to the latest battery purchased + $new_battery = $item->getBattery(); + $jo->getCustomerVehicle()->setCurrentBattery($new_battery); + + // add customer vehicle to hash + $this->custvehicle_hash[$custvehicle_id] = true; + } + } + $this->em->flush(); + } + } + } + } +} From 4e711ca2c329c725e3499e8e1945d7ecc883acb6 Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Mon, 22 Apr 2019 06:04:22 +0000 Subject: [PATCH 07/36] Rename the service to JobOrderManager. #204 --- ...lfillCommand.php => TestJobOrderManagerCommand.php} | 10 +++++----- .../{JobOrderFulfill.php => JobOrderManager.php} | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) rename src/Command/{TestJobOrderFulfillCommand.php => TestJobOrderManagerCommand.php} (78%) rename src/Service/{JobOrderFulfill.php => JobOrderManager.php} (98%) diff --git a/src/Command/TestJobOrderFulfillCommand.php b/src/Command/TestJobOrderManagerCommand.php similarity index 78% rename from src/Command/TestJobOrderFulfillCommand.php rename to src/Command/TestJobOrderManagerCommand.php index 258fac01..4beeea46 100644 --- a/src/Command/TestJobOrderFulfillCommand.php +++ b/src/Command/TestJobOrderManagerCommand.php @@ -7,9 +7,9 @@ use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use App\Service\JobOrderFulfill; +use App\Service\JobOrderManager; -class TestJobOrderFulfillCommand extends Command +class TestJobOrderManagerCommand extends Command { protected function configure() { @@ -19,9 +19,9 @@ class TestJobOrderFulfillCommand extends Command ->addArgument('job_order_id', InputArgument::REQUIRED, 'Job Order ID'); } - public function __construct(JobOrderFulfill $fulfill_jo) + public function __construct(JobOrderManager $jo_manager) { - $this->fulfill_jo = $fulfill_jo; + $this->jo_manager = $jo_manager; parent::__construct(); } @@ -30,7 +30,7 @@ class TestJobOrderFulfillCommand extends Command { $jo_id = $input->getArgument('job_order_id'); - $result = $this->fulfill_jo->fulfillJobOrder($jo_id); + $result = $this->jo_manager->fulfillJobOrder($jo_id); if ($result) echo "Job Order successfully updated" . "\n"; diff --git a/src/Service/JobOrderFulfill.php b/src/Service/JobOrderManager.php similarity index 98% rename from src/Service/JobOrderFulfill.php rename to src/Service/JobOrderManager.php index b73044a8..94d923a3 100644 --- a/src/Service/JobOrderFulfill.php +++ b/src/Service/JobOrderManager.php @@ -8,7 +8,7 @@ use App\Ramcar\ServiceType; use Doctrine\ORM\EntityManagerInterface; -class JobOrderFulfill +class JobOrderManager { protected $em; From deff9b7f741ed5ba4e68d9a0861f6eabac3e9f69 Mon Sep 17 00:00:00 2001 From: Kendrick Chan Date: Mon, 22 Apr 2019 14:19:13 +0800 Subject: [PATCH 08/36] Remove mysql connector and misc code #180 --- .../rider_location_cache.py | 36 +++---------------- 1 file changed, 5 insertions(+), 31 deletions(-) diff --git a/utils/rider_location_cache/rider_location_cache.py b/utils/rider_location_cache/rider_location_cache.py index 441938e4..0b4e85b6 100644 --- a/utils/rider_location_cache/rider_location_cache.py +++ b/utils/rider_location_cache/rider_location_cache.py @@ -9,28 +9,14 @@ import os import mysql.connector import json -def mysql_connect(user, password, host, database): - conn = mysql.connector.connect(user=user, - password=password, - host=host, - database=database) - return conn - -def init_subscriptions(client, conn): - # given mysql connection, get all rider sessions - query = ("select id from rider_session") - cursor = conn.cursor() - cursor.execute(query) - for (id) in cursor: - print "subscribing to rider session %s" % id - client.subscribe('motorider_%s' % id) - cursor.close() +def init_subscriptions(client): + print "subscribing to wildcard" + client.subscribe('#') def on_connect(client, userdata, flags, rc): - conn = mysql_connect('resq', 'Motolite456', '127.0.0.1', 'resq') - init_subscriptions(client, conn) + init_subscriptions(client) print("Connected with result code "+str(rc)) - client.subscribe("$SYS/#") + # client.subscribe("$SYS/#") def on_publish(client, userdata, mid): pass @@ -62,18 +48,6 @@ def on_message(client, userdata, message): redis_conn.setex(key, 1600, message.payload) - -def getRedis(i): - r = redis.StrictRedis(host='localhost', port=6379, db=0) - while 1: - time.sleep(0) - data = r.brpop("events", 10) - if data: - info = data[1].split('|') - print "Channel: " + info[0] + " message: " + info[1] - client.publish(info[0], info[1]) - - def sigint_handler(signal, frame): print 'Interrupted' sys.exit(0) From d1b41ca36ce62b91221776879ec3f73e9efe40ab Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Tue, 23 Apr 2019 05:59:06 +0000 Subject: [PATCH 09/36] Save rider's coordinates into redis hash. #180 --- .../rider_location_cache.py | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/utils/rider_location_cache/rider_location_cache.py b/utils/rider_location_cache/rider_location_cache.py index 0b4e85b6..d1a3de15 100644 --- a/utils/rider_location_cache/rider_location_cache.py +++ b/utils/rider_location_cache/rider_location_cache.py @@ -6,7 +6,6 @@ import time import signal import sys import os -import mysql.connector import json def init_subscriptions(client): @@ -30,6 +29,7 @@ def on_message(client, userdata, message): # check if json decodable res = json.loads(message.payload) + print res # get rider session id sess_id = message.topic[10:] @@ -42,12 +42,20 @@ def on_message(client, userdata, message): if res['event'] != 'driver_location': return + # save the longitude and latitude + # get the rider id from sess_id + rider_key = "rider.location.%s" % sess_id + rider_long = str(res['longitude']) + rider_lat = str(res['latitude']) + + # set the location + redis_conn.hmset(rider_key, {'longitude': rider_long, 'latitude': rider_lat}) + # update our redis key key = 'location_%s' % sess_id print "setting %s" % key redis_conn.setex(key, 1600, message.payload) - def sigint_handler(signal, frame): print 'Interrupted' sys.exit(0) @@ -65,10 +73,11 @@ redis_conn = redis.StrictRedis(host='localhost', port=6379, db=0) #client.tls_set( # "/etc/letsencrypt/live/resqaws.jankstudio.com/fullchain.pem", cert_reqs=ssl.CERT_NONE, # tls_version=ssl.PROTOCOL_TLSv1) -client.tls_set( - "/root/aws_ssl_keys/fullchain.pem", cert_reqs=ssl.CERT_NONE, - tls_version=ssl.PROTOCOL_TLSv1) -client.connect("resqaws.jankstudio.com", 8883, 60) +#client.tls_set( +# "/root/aws_ssl_keys/fullchain.pem", cert_reqs=ssl.CERT_NONE, +# tls_version=ssl.PROTOCOL_TLSv1) +#client.connect("resqaws.jankstudio.com", 8883, 60) +client.connect("localhost", 1883, 60) #t = Thread(target=getRedis, args=(1,)) @@ -77,4 +86,3 @@ client.connect("resqaws.jankstudio.com", 8883, 60) #signal.signal(signal.SIGINT, sigint_handler) client.loop_forever() - From 76b1f07febd72166f73b47188acfd1b3e9102298 Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Tue, 23 Apr 2019 11:02:12 +0000 Subject: [PATCH 10/36] Create rider tracker service. Create a test command to test rider tracker service. #180 --- src/Command/TestRiderTrackerCommand.php | 46 ++++++++++++++++++++ src/Service/RiderTracker.php | 58 +++++++++++++++++++++++++ 2 files changed, 104 insertions(+) create mode 100644 src/Command/TestRiderTrackerCommand.php create mode 100644 src/Service/RiderTracker.php diff --git a/src/Command/TestRiderTrackerCommand.php b/src/Command/TestRiderTrackerCommand.php new file mode 100644 index 00000000..7b26a9ed --- /dev/null +++ b/src/Command/TestRiderTrackerCommand.php @@ -0,0 +1,46 @@ +setName('test:ridertracker') + ->setDescription('Test the rider tracker service') + ->setHelp('Test the rider tracker service.') + ->addArgument('rider_id', InputArgument::REQUIRED, 'Rider ID'); + } + + public function __construct(RiderTracker $rtracker) + { + $this->rtracker = $rtracker; + + parent::__construct(); + } + + public function execute(InputInterface $input, OutputInterface $output) + { + $rider_id = $input->getArgument('rider_id'); + + $coordinates = $this->rtracker->getRiderLocation($rider_id); + + if ($coordinates != null) + { + echo "Rider Location: " . $coordinates->getLongitude() . "," . $coordinates->getLatitude() . "\n"; + } + else + { + echo "Invalid rider id." . "\n"; + } + } +} diff --git a/src/Service/RiderTracker.php b/src/Service/RiderTracker.php new file mode 100644 index 00000000..59bf1f17 --- /dev/null +++ b/src/Service/RiderTracker.php @@ -0,0 +1,58 @@ +em = $em; + + // TODO: make it read redis settings from config + // build a service maybe? + $this->redis = new PredisClient(); + } + + protected function getRiderKey($rider_id) + { + return self::RIDER_PREFIX_KEY . '.' . $rider_id; + } + + public function getRiderLocation($rider_id) + { + // check if rider id exists or is valid + $rider = $this->em->getRepository(Rider::class)->find($rider_id); + if ($rider != null) + { + $coordinates = $rider->getHub()->getCoordinates(); + + $key = $this->getRiderKey($rider_id); + + // check redis cache for rider information + if (($this->redis->hexists($key, 'longitude')) && + ($this->redis->hexists($key, 'latitude'))) + { + $long = $this->redis->hget($key, 'longitude'); + $lat = $this->redis->hget($key, 'latitude'); + + $coordinates = new Point($long, $lat); + } + + return $coordinates; + + } + } +} From 82eec39cfd5cdadfb7b5dbed2afaee1d0552a49b Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Thu, 25 Apr 2019 09:57:30 +0000 Subject: [PATCH 11/36] Create daemon for graceful shutdown for rider location script. #180 --- utils/rider_location_cache/daemon.py | 129 ++++++++++++++++++ utils/rider_location_cache/daemon.pyc | Bin 0 -> 4096 bytes .../rider_location_cache.py | 55 ++++---- .../rider_location_daemon.py | 31 +++++ 4 files changed, 189 insertions(+), 26 deletions(-) create mode 100644 utils/rider_location_cache/daemon.py create mode 100644 utils/rider_location_cache/daemon.pyc create mode 100644 utils/rider_location_cache/rider_location_daemon.py diff --git a/utils/rider_location_cache/daemon.py b/utils/rider_location_cache/daemon.py new file mode 100644 index 00000000..f371720d --- /dev/null +++ b/utils/rider_location_cache/daemon.py @@ -0,0 +1,129 @@ +#!/usr/bin/env python + +import sys, os, time, atexit +from signal import SIGTERM + +class Daemon: + """ + A generic daemon class. + + Usage: subclass the Daemon class and override the run() method + """ + def __init__(self, pidfile, stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'): + self.stdin = stdin + self.stdout = stdout + self.stderr = stderr + self.pidfile = pidfile + + def daemonize(self): + """ + do the UNIX double-fork magic, see Stevens' "Advanced + Programming in the UNIX Environment" for details (ISBN 0201563177) + http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC16 + """ + try: + pid = os.fork() + if pid > 0: + # exit first parent + sys.exit(0) + except OSError, e: + sys.stderr.write("fork #1 failed: %d (%s)\n" % (e.errno, e.strerror)) + sys.exit(1) + + # decouple from parent environment + os.chdir("/") + os.setsid() + os.umask(0) + + # do second fork + try: + pid = os.fork() + if pid > 0: + # exit from second parent + sys.exit(0) + except OSError, e: + sys.stderr.write("fork #2 failed: %d (%s)\n" % (e.errno, e.strerror)) + sys.exit(1) + + # redirect standard file descriptors + sys.stdout.flush() + sys.stderr.flush() + si = file(self.stdin, 'r') + so = file(self.stdout, 'a+') + se = file(self.stderr, 'a+', 0) + os.dup2(si.fileno(), sys.stdin.fileno()) + os.dup2(so.fileno(), sys.stdout.fileno()) + os.dup2(se.fileno(), sys.stderr.fileno()) + + # write pidfile + atexit.register(self.delpid) + pid = str(os.getpid()) + file(self.pidfile,'w+').write("%s\n" % pid) + + def delpid(self): + os.remove(self.pidfile) + + def start(self): + """ + Start the daemon + """ + # Check for a pidfile to see if the daemon already runs + try: + pf = file(self.pidfile,'r') + pid = int(pf.read().strip()) + pf.close() + except IOError: + pid = None + + if pid: + message = "pidfile %s already exist. Daemon already running?\n" + sys.stderr.write(message % self.pidfile) + sys.exit(1) + + # Start the daemon + self.daemonize() + self.run() + + def stop(self): + """ + Stop the daemon + """ + # Get the pid from the pidfile + try: + pf = file(self.pidfile,'r') + pid = int(pf.read().strip()) + pf.close() + except IOError: + pid = None + + if not pid: + message = "pidfile %s does not exist. Daemon not running?\n" + sys.stderr.write(message % self.pidfile) + return # not an error in a restart + + # Try killing the daemon process + try: + while 1: + os.kill(pid, SIGTERM) + time.sleep(0.1) + except OSError, err: + err = str(err) + if err.find("No such process") > 0: + if os.path.exists(self.pidfile): + os.remove(self.pidfile) + else: + print str(err) + sys.exit(1) + + def restart(self): + """ + Restart the daemon + """ + self.stop() + self.start() + + def run(self): + """ + You should override this method when you subclass Daemon. It will be called after the process has been + daemonized by start() or restart(). + """ diff --git a/utils/rider_location_cache/daemon.pyc b/utils/rider_location_cache/daemon.pyc new file mode 100644 index 0000000000000000000000000000000000000000..51504185fb3183608e794c1827f259f9ab078099 GIT binary patch literal 4096 zcmb_fQEwZ^5#HsIl#Z5cS+?Y)DUwAT#Z+yRwu;z+QPhbY!_`BX^w`9)kl=8>Tarf| z@2K0QWCj-ckmSASTMOieBo6`ln~J=q{brV=Tr~}f+9Yo|JG(nOyZg;Id)_}*8-Kp? z_s?Q6`*`?&5080-BEe6JOo+XOEXAIj>nmcfGM7EE=doN7SyhZ`Vy`A-0#!{URq>S& zUkdSfuTJ*5%{pwS|HP-$lo0I_itg^iKRyV4Z>jBrNRNtq;Zqf=dw9$zC^Wob4`^-( z?pG0CIS)LVYp*(+6i&ba(qQH~3riwdVqsY%%PjaJ=r(<_|2c|=|Gw($T$gFA681yI zS!7JB;Wzw`P1M(Sl$ktXow5V1oU^WzitojR|EEzF2Nps#lNX5j? zML5G7JWi8dn&~F>wKU4;tQSx%p!owj`GEA~ge%Mrr1oJ{wvUdE+NCxJ?TJk@)28K> zVOGSEO^ZB?qj;d(Zns+Fsa?jfFii8*hT#fiLkb~%{>F6Vbjma}ulfgQrq_fOVkikG z$5wZ;~SB0&JA(o6LDP%6hqx?Nl#R~QtqRfRnt_Vq8YGQ~(#wI~t;&NH^Dq@pH z%}jXCgcP6BTt0z>TTyAy#FEr!=2QJwm%jg5m!v%9Qtf|q34X7L;i_}QEofFbOUFJu zM-cw9B91*_oo0owOq%Lk1H1#^*eXvP*LX+Q2uH*7WR-T|+)TzOUM-rd&o#pV?)qFa z_H{9OE_3s`7+zqapvVE3N(zM6tcpJe)auPFD`DC(#2HD$C`U8@guZmy^|-%k#sJl2WAz>mtJUq+)*n)g+j zpBQ`t{A*x3^(rVD0!$n{eLJWrj&? zRJIbLp;lb9Cj0G4o<42&qJwa!HL#=Xa`(ago3}79h4;d|f`Yxhd{gx>iB9gQtwc4q z%yuJXj-#UeT)&6Zftwl2 zW6I!KG8ymiP$Cx?r^t>hJ3~=l>V9ghcGeS}frXsc)~Wj1Ld7)1X(6ET+=F`3j%Z%B zN!?%J{`8BJ6j8CGtn>@Lj*58~g{XUSMXppX%5zf5^WLg#$W`yOZdI=1yCL78ueSy{ zCRgcMaQQ`49Hmk4RyalyO(6ofwV*Iwt=khHoWi}gV$i{E*?gca844% zFR1q$RHpBepX4NyE+Um;m$MCc7tuTfO}dzN${JPWqx=$RxXv{E2LaXtn}UmTuq!CI z{F=C!sA`#*7X0ec8Rl?|3^kZ`#>j5^6}C%`INpQ7E~hKA2{#dIT?D1&0CxumRltdx z^3*K9sV$?Ttkh95RY0M!t$Bu?Ymt(3aK&90n4RWX3=U`p-hRd&5-Ee5%rN>9F6r3C zN>&)nakl#*#~F9*6uAy4)p67X=SW(m;xY<0Nf!aydIxYq$+#E1POWtN8EHdTix)oe znX}lYd$7uMBWfP-`HDO%f#phF*5xI+<~1A`2nY)>ybk2OG%z3mEx=%=KMw}LpgX-H zo+@F_P!a@wEFeHB>MZ9ym!}W@gxr4w(5*4(UPYppa15W|Zzh@+|8lr+)CiAEl5%7b5=*n0Ro!tEyKSGsio)Z}E7D9vo3U^Euvp8{hW z&Ch``DYQ`_##3k{%>s#?{@?yepKtFPf=;Kv6*C^FaaqIw2B#R#BF#%^J;7?QMb)>d zxIzWNC)lRqS5%zBBa;n5a6iqm0RQe9Xj9xy2?Hk6dK_>x{BqvdOY?*QK91~wnTlh| z1aF}SBb)=2K^k*yd($sBISaJ_y7EO16Q*_heF2ODI3tA|c%wG;!GY{a7 zO_LsyAGB;yodqiSzgPpcocQ|})Zp*qVxr8Tm}LL<29lcD%ZEA|=v+;y)BNqly}7j1 zu2n~XgnFV?9A&t>sHlgO&DfqnPz@r3cAaCQMbb>vlc{2V@rr}{)y(HmE5323>L&&?VMwYprd``3NX-|*k?m)soe3x_5-9NeJdRTLauChg~u3r@E6 Wa@^t@-*4Q`{FcI!v2{bPRsIF*e>fNb literal 0 HcmV?d00001 diff --git a/utils/rider_location_cache/rider_location_cache.py b/utils/rider_location_cache/rider_location_cache.py index d1a3de15..e96cba0e 100644 --- a/utils/rider_location_cache/rider_location_cache.py +++ b/utils/rider_location_cache/rider_location_cache.py @@ -1,6 +1,7 @@ import paho.mqtt.client as mqtt import ssl from threading import Thread +from daemon import Daemon import redis import time import signal @@ -8,6 +9,34 @@ import sys import os import json +class RiderLocationCache(object): + + def run(self): + global client, redis_conn + client = mqtt.Client() + client.on_connect = on_connect + # client.on_publish = on_publish + client.on_message = on_message + + redis_conn = redis.StrictRedis(host='localhost', port=6379, db=0) + + #client.tls_set( + # "/etc/letsencrypt/live/resqaws.jankstudio.com/fullchain.pem", cert_reqs=ssl.CERT_NONE, + # tls_version=ssl.PROTOCOL_TLSv1) + #client.tls_set( + # "/root/aws_ssl_keys/fullchain.pem", cert_reqs=ssl.CERT_NONE, + # tls_version=ssl.PROTOCOL_TLSv1) + #client.connect("resqaws.jankstudio.com", 8883, 60) + client.connect("localhost", 1883, 60) + + #t = Thread(target=getRedis, args=(1,)) + + #t.start() + + #signal.signal(signal.SIGINT, sigint_handler) + client.loop_forever() + + def init_subscriptions(client): print "subscribing to wildcard" client.subscribe('#') @@ -60,29 +89,3 @@ def sigint_handler(signal, frame): print 'Interrupted' sys.exit(0) - - -client = mqtt.Client() -client.on_connect = on_connect -# client.on_publish = on_publish -client.on_message = on_message - -redis_conn = redis.StrictRedis(host='localhost', port=6379, db=0) - - -#client.tls_set( -# "/etc/letsencrypt/live/resqaws.jankstudio.com/fullchain.pem", cert_reqs=ssl.CERT_NONE, -# tls_version=ssl.PROTOCOL_TLSv1) -#client.tls_set( -# "/root/aws_ssl_keys/fullchain.pem", cert_reqs=ssl.CERT_NONE, -# tls_version=ssl.PROTOCOL_TLSv1) -#client.connect("resqaws.jankstudio.com", 8883, 60) -client.connect("localhost", 1883, 60) - - -#t = Thread(target=getRedis, args=(1,)) - -#t.start() - -#signal.signal(signal.SIGINT, sigint_handler) -client.loop_forever() diff --git a/utils/rider_location_cache/rider_location_daemon.py b/utils/rider_location_cache/rider_location_daemon.py new file mode 100644 index 00000000..6889628f --- /dev/null +++ b/utils/rider_location_cache/rider_location_daemon.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python + +import sys +import time +from daemon import Daemon +import rider_location_cache + +class RiderLocationDaemon(Daemon): + def run(self): + print "mogol in daemon" + rider_location = rider_location_cache.RiderLocationCache() + rider_location.run() + +if __name__ == "__main__": + daemon = RiderLocationDaemon('/tmp/rider_location_daemon.pid') + if len(sys.argv) == 2: + if 'start' == sys.argv[1]: + daemon.start() + elif 'stop' == sys.argv[1]: + daemon.stop() + elif 'restart' == sys.argv[1]: + daemon.restart() + elif 'foreground' == sys.argv[1]: + daemon.run() + else: + print "Unknown command" + sys.exit(2) + sys.exit(0) + else: + print "usage: %s start|stop|restart" % sys.argv[0] + sys.exit(2) From d15099b456690129051a81deaa5919d450734526 Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Fri, 26 Apr 2019 02:12:00 +0000 Subject: [PATCH 12/36] Remove debug message. #180 --- utils/rider_location_cache/rider_location_daemon.py | 1 - 1 file changed, 1 deletion(-) diff --git a/utils/rider_location_cache/rider_location_daemon.py b/utils/rider_location_cache/rider_location_daemon.py index 6889628f..f56de6a5 100644 --- a/utils/rider_location_cache/rider_location_daemon.py +++ b/utils/rider_location_cache/rider_location_daemon.py @@ -7,7 +7,6 @@ import rider_location_cache class RiderLocationDaemon(Daemon): def run(self): - print "mogol in daemon" rider_location = rider_location_cache.RiderLocationCache() rider_location.run() From 950308964248d7aa54ae4bcd717866f19a640f6e Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Fri, 26 Apr 2019 03:10:16 +0000 Subject: [PATCH 13/36] Remove the declaration of global variables from the run method. #180 --- utils/rider_location_cache/rider_location_cache.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/utils/rider_location_cache/rider_location_cache.py b/utils/rider_location_cache/rider_location_cache.py index e96cba0e..cbd1bd4b 100644 --- a/utils/rider_location_cache/rider_location_cache.py +++ b/utils/rider_location_cache/rider_location_cache.py @@ -12,14 +12,10 @@ import json class RiderLocationCache(object): def run(self): - global client, redis_conn - client = mqtt.Client() client.on_connect = on_connect # client.on_publish = on_publish client.on_message = on_message - redis_conn = redis.StrictRedis(host='localhost', port=6379, db=0) - #client.tls_set( # "/etc/letsencrypt/live/resqaws.jankstudio.com/fullchain.pem", cert_reqs=ssl.CERT_NONE, # tls_version=ssl.PROTOCOL_TLSv1) @@ -36,6 +32,8 @@ class RiderLocationCache(object): #signal.signal(signal.SIGINT, sigint_handler) client.loop_forever() +client = mqtt.Client() +redis_conn = redis.StrictRedis(host='localhost', port=6379, db=0) def init_subscriptions(client): print "subscribing to wildcard" From e61d77ad8bccc36aedac36e3042a258ad553e07f Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Mon, 29 Apr 2019 02:16:03 +0000 Subject: [PATCH 14/36] Remove checking for rider validity. Add call to RiderTracker service from the APIController. #180 --- src/Controller/APIController.php | 6 ++++-- src/Service/RiderTracker.php | 35 ++++++++++++++++---------------- 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/src/Controller/APIController.php b/src/Controller/APIController.php index 4925cf9b..d85978a8 100644 --- a/src/Controller/APIController.php +++ b/src/Controller/APIController.php @@ -26,6 +26,7 @@ use App\Service\InvoiceCreator; use App\Service\RisingTideGateway; use App\Service\MQTTClient; use App\Service\GeofenceTracker; +use App\Service\RiderTracker; use App\Entity\MobileSession; use App\Entity\Customer; @@ -1116,7 +1117,7 @@ class APIController extends Controller return $res->getReturnResponse(); } - public function getRiderStatus(Request $req) + public function getRiderStatus(Request $req, RiderTracker $rt) { $required_params = []; $em = $this->getDoctrine()->getManager(); @@ -1243,8 +1244,9 @@ class APIController extends Controller case JOStatus::ASSIGNED: case JOStatus::IN_TRANSIT: case JOStatus::IN_PROGRESS: - $coord = $jo->getHub()->getCoordinates(); $rider = $jo->getRider(); + // get rider coordinates from redis + $coord = $rt->getRiderLocation($rider->getID()); // default image url $url_prefix = $req->getSchemeAndHttpHost(); diff --git a/src/Service/RiderTracker.php b/src/Service/RiderTracker.php index 59bf1f17..c34d215d 100644 --- a/src/Service/RiderTracker.php +++ b/src/Service/RiderTracker.php @@ -33,26 +33,25 @@ class RiderTracker public function getRiderLocation($rider_id) { - // check if rider id exists or is valid - $rider = $this->em->getRepository(Rider::class)->find($rider_id); - if ($rider != null) + $coordinates = new Point(0,0); + $key = $this->getRiderKey($rider_id); + + // check redis cache for rider information + if (($this->redis->hexists($key, 'longitude')) && + ($this->redis->hexists($key, 'latitude'))) { - $coordinates = $rider->getHub()->getCoordinates(); - - $key = $this->getRiderKey($rider_id); - - // check redis cache for rider information - if (($this->redis->hexists($key, 'longitude')) && - ($this->redis->hexists($key, 'latitude'))) - { - $long = $this->redis->hget($key, 'longitude'); - $lat = $this->redis->hget($key, 'latitude'); - - $coordinates = new Point($long, $lat); - } - - return $coordinates; + $long = $this->redis->hget($key, 'longitude'); + $lat = $this->redis->hget($key, 'latitude'); + $coordinates = new Point($long, $lat); } + else + { + $rider = $this->em->getRepository(Rider::class)->find($rider_id); + $coordinates = $rider->getHub()->getCoordinates(); + } + + return $coordinates; + } } From 2c8dad91649b4015cfe92cb30389946bef8ab714 Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Mon, 29 Apr 2019 09:04:37 +0000 Subject: [PATCH 15/36] Remove debug messages and sigint_handler. Create user_data_set to set the redis client. #180 --- .../rider_location_cache.py | 78 +++++++++---------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/utils/rider_location_cache/rider_location_cache.py b/utils/rider_location_cache/rider_location_cache.py index cbd1bd4b..504884e3 100644 --- a/utils/rider_location_cache/rider_location_cache.py +++ b/utils/rider_location_cache/rider_location_cache.py @@ -12,6 +12,8 @@ import json class RiderLocationCache(object): def run(self): + client = mqtt.Client() + client.on_connect = on_connect # client.on_publish = on_publish client.on_message = on_message @@ -32,58 +34,56 @@ class RiderLocationCache(object): #signal.signal(signal.SIGINT, sigint_handler) client.loop_forever() -client = mqtt.Client() -redis_conn = redis.StrictRedis(host='localhost', port=6379, db=0) - def init_subscriptions(client): - print "subscribing to wildcard" - client.subscribe('#') + #print "subscribing to wildcard" + client.subscribe('#') def on_connect(client, userdata, flags, rc): - init_subscriptions(client) - print("Connected with result code "+str(rc)) - # client.subscribe("$SYS/#") + init_subscriptions(client) + #print("Connected with result code "+str(rc)) + # client.subscribe("$SYS/#") + +def user_data_set(userdata): + conn = redis.StrictRedis(host='localhost', port=6379, db=0) + return conn def on_publish(client, userdata, mid): - pass + pass def on_message(client, userdata, message): - print("message topic=",message.topic[0:10]) + redis_conn = user_data_set(userdata) + #print("message topic=", message.topic[0:10]) - if message.topic[0:10] != 'motorider_': - return - #print repr(message) + if message.topic[0:10] != 'motorider_': + return + #print repr(message) - # check if json decodable - res = json.loads(message.payload) - print res + # check if json decodable + res = json.loads(message.payload) + #print res - # get rider session id - sess_id = message.topic[10:] + # get rider session id + sess_id = message.topic[10:] - # check if it has event - if 'event' not in res: - return + # check if it has event + if 'event' not in res: + return - # check if event is driver_location - if res['event'] != 'driver_location': - return + # check if event is driver_location + if res['event'] != 'driver_location': + return - # save the longitude and latitude - # get the rider id from sess_id - rider_key = "rider.location.%s" % sess_id - rider_long = str(res['longitude']) - rider_lat = str(res['latitude']) + # save the longitude and latitude + # get the rider id from sess_id + rider_key = "rider.location.%s" % sess_id + rider_long = str(res['longitude']) + rider_lat = str(res['latitude']) - # set the location - redis_conn.hmset(rider_key, {'longitude': rider_long, 'latitude': rider_lat}) + # set the location + redis_conn.hmset(rider_key, {'longitude': rider_long, 'latitude': rider_lat}) - # update our redis key - key = 'location_%s' % sess_id - print "setting %s" % key - redis_conn.setex(key, 1600, message.payload) - -def sigint_handler(signal, frame): - print 'Interrupted' - sys.exit(0) + # update our redis key + key = 'location_%s' % sess_id + #print "setting %s" % key + redis_conn.setex(key, 1600, message.payload) From afc07e7c6824f1b564d8e6197f07e0aee5e83d95 Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Thu, 2 May 2019 07:21:49 +0000 Subject: [PATCH 16/36] Add service to connect to redis. Add command to test service with the HubCounter service. #206 --- config/services.yaml | 6 +++++ src/Command/TestHubCounterCommand.php | 39 +++++++++++++++++++++++++++ src/Service/HubCounter.php | 9 +++---- src/Service/RedisClient.php | 29 ++++++++++++++++++++ 4 files changed, 77 insertions(+), 6 deletions(-) create mode 100644 src/Command/TestHubCounterCommand.php create mode 100644 src/Service/RedisClient.php diff --git a/config/services.yaml b/config/services.yaml index 154d6708..269d1a48 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -75,6 +75,12 @@ services: $ip_address: "%env(APNS_REDIS_IP_ADDRESS)%" $port: "%env(APNS_REDIS_PORT)%" + App\Service\RedisClient: + arguments: + $scheme: "%env(REDIS_CLIENT_SCHEME)%" + $host: "%env(REDIS_CLIENT_HOST)%" + $port: "%env(REDIS_CLIENT_PORT)%" + Catalyst\APIBundle\Security\APIKeyUserProvider: arguments: $em: "@doctrine.orm.entity_manager" diff --git a/src/Command/TestHubCounterCommand.php b/src/Command/TestHubCounterCommand.php new file mode 100644 index 00000000..e08c11dd --- /dev/null +++ b/src/Command/TestHubCounterCommand.php @@ -0,0 +1,39 @@ +setName('test:hubcounter') + ->setDescription('Test hubcounter service. Currently tests addAvailableRider and getAvailableRiderCount.') + ->setHelp('Test hubcounter service. Currently tests addAvailableRider and getAvailableRiderCount.') + ->addArgument('hub_id', InputArgument::REQUIRED, 'Hub ID'); + } + + public function __construct(HubCounter $hc) + { + $this->hc = $hc; + + parent::__construct(); + } + + public function execute(InputInterface $input, OutputInterface $output) + { + $hub_id = $input->getArgument('hub_id'); + + $this->hc->addAvailableRider($hub_id); + + $available_rc = $this->hc->getAvailableRiderCount($hub_id); + + echo "Available Riders in Hub: " . $available_rc . "\n"; + } +} diff --git a/src/Service/HubCounter.php b/src/Service/HubCounter.php index 6fa52819..13388ecc 100644 --- a/src/Service/HubCounter.php +++ b/src/Service/HubCounter.php @@ -15,13 +15,10 @@ class HubCounter protected $em; protected $redis; - public function __construct(EntityManagerInterface $em) + public function __construct(EntityManagerInterface $em, RedisClient $rc) { $this->em = $em; - - // TODO: make it read redis settings from config - // build a service maybe? - $this->redis = new Predis\Client(); + $this->redis = $rc->getRedisClient(); } // get rider key based on id @@ -45,7 +42,7 @@ class HubCounter return $value; // not in cache - $hub = $em->getRepository(Hub::class)->find($hub_id); + $hub = $this->em->getRepository(Hub::class)->find($hub_id); $riders = $hub->getActiveRiders(); $rider_count = count($riders); diff --git a/src/Service/RedisClient.php b/src/Service/RedisClient.php new file mode 100644 index 00000000..1c3c35b8 --- /dev/null +++ b/src/Service/RedisClient.php @@ -0,0 +1,29 @@ +scheme = $scheme; + $this->host = $host; + $this->port = $port; + } + + public function getRedisClient() + { + $this->redis = new PredisClient([ + "scheme"=>$this->scheme, + "host"=>$this->host, + "port"=>$this->port]); + return $this->redis; + } +} From a166a5f09ace24b8e6b5f47189e9a6037eda1c69 Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Fri, 3 May 2019 07:15:43 +0000 Subject: [PATCH 17/36] Add support for connecting to redis with an ssl file and password. #206 --- config/services.yaml | 3 +++ src/Service/RedisClient.php | 28 +++++++++++++++++++++++----- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/config/services.yaml b/config/services.yaml index 269d1a48..27efa248 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -80,6 +80,9 @@ services: $scheme: "%env(REDIS_CLIENT_SCHEME)%" $host: "%env(REDIS_CLIENT_HOST)%" $port: "%env(REDIS_CLIENT_PORT)%" + $cert_file: "%env(REDIS_CLIENT_CERTFILE)%" + $password: "%env(REDIS_CLIENT_PASSWORD)%" + $env_flag: "dev" Catalyst\APIBundle\Security\APIKeyUserProvider: arguments: diff --git a/src/Service/RedisClient.php b/src/Service/RedisClient.php index 1c3c35b8..9339a252 100644 --- a/src/Service/RedisClient.php +++ b/src/Service/RedisClient.php @@ -10,20 +10,38 @@ class RedisClient protected $scheme; protected $host; protected $port; + protected $cert_file; + protected $password; + protected $env_flag; - public function __construct($scheme, $host, $port) + public function __construct($scheme, $host, $port, $cert_file, $password, $env_flag) { $this->scheme = $scheme; $this->host = $host; $this->port = $port; + $this->cert_file = $cert_file; + $this->password = $password; + $this->env_flag = $env_flag; } public function getRedisClient() { - $this->redis = new PredisClient([ - "scheme"=>$this->scheme, - "host"=>$this->host, - "port"=>$this->port]); + if ($this->env_flag == 'dev') + { + $this->redis = new PredisClient([ + "scheme"=>$this->scheme, + "host"=>$this->host, + "port"=>$this->port]); + } + else + { + $this->redis = new PredisClient([ + "scheme"=>$this->scheme, + "host"=>$this->host, + "port"=>$this->port, + "ssl"=>["cafile"=>$cert_file, "verify_peer"=>true], + "password"=>$password]); + } return $this->redis; } } From b6591fe28e1e0ca71d218e183c49248cb04b6860 Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Fri, 3 May 2019 09:29:00 +0000 Subject: [PATCH 18/36] Add redis environment variables. #206 --- .env.dist | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.env.dist b/.env.dist index 2829219e..44bfbf42 100644 --- a/.env.dist +++ b/.env.dist @@ -28,3 +28,11 @@ RT_SHORTCODE=1234 MQTT_IP_ADDRESS=localhost MQTT_PORT=8883 MQTT_CERT=/location/of/cert/file.crt + +# redis client +REDIS_CLIENT_SCHEME=tcp +REDIS_CLIENT_HOST=127.0.0.1 +REDIS_CLIENT_PORT=6379 +REDIS_CLIENT_CERTFILE=/location/of/cert/file.crt +REDIS_CLIENT_PASSWORD=foobared +# From 161601ece5897ff8beb7f778ce9d036af7468f64 Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Mon, 6 May 2019 01:25:04 +0000 Subject: [PATCH 19/36] Remove the cert file parameter for the redis client. #206 --- .env.dist | 1 - config/services.yaml | 1 - src/Service/RedisClient.php | 7 ++----- 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/.env.dist b/.env.dist index 44bfbf42..4c0b202a 100644 --- a/.env.dist +++ b/.env.dist @@ -33,6 +33,5 @@ MQTT_CERT=/location/of/cert/file.crt REDIS_CLIENT_SCHEME=tcp REDIS_CLIENT_HOST=127.0.0.1 REDIS_CLIENT_PORT=6379 -REDIS_CLIENT_CERTFILE=/location/of/cert/file.crt REDIS_CLIENT_PASSWORD=foobared # diff --git a/config/services.yaml b/config/services.yaml index 27efa248..bf607603 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -80,7 +80,6 @@ services: $scheme: "%env(REDIS_CLIENT_SCHEME)%" $host: "%env(REDIS_CLIENT_HOST)%" $port: "%env(REDIS_CLIENT_PORT)%" - $cert_file: "%env(REDIS_CLIENT_CERTFILE)%" $password: "%env(REDIS_CLIENT_PASSWORD)%" $env_flag: "dev" diff --git a/src/Service/RedisClient.php b/src/Service/RedisClient.php index 9339a252..43323e0f 100644 --- a/src/Service/RedisClient.php +++ b/src/Service/RedisClient.php @@ -10,16 +10,14 @@ class RedisClient protected $scheme; protected $host; protected $port; - protected $cert_file; protected $password; protected $env_flag; - public function __construct($scheme, $host, $port, $cert_file, $password, $env_flag) + public function __construct($scheme, $host, $port, $password, $env_flag) { $this->scheme = $scheme; $this->host = $host; $this->port = $port; - $this->cert_file = $cert_file; $this->password = $password; $this->env_flag = $env_flag; } @@ -39,8 +37,7 @@ class RedisClient "scheme"=>$this->scheme, "host"=>$this->host, "port"=>$this->port, - "ssl"=>["cafile"=>$cert_file, "verify_peer"=>true], - "password"=>$password]); + "password"=>$this->password]); } return $this->redis; } From 712d54abc51114e9dd0d416645837fc3b7add94c Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Wed, 8 May 2019 00:22:57 +0000 Subject: [PATCH 20/36] Change link to Google Maps API in the job order form. #206 --- templates/job-order/form.html.twig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/templates/job-order/form.html.twig b/templates/job-order/form.html.twig index 352ba4e4..1d3e0275 100644 --- a/templates/job-order/form.html.twig +++ b/templates/job-order/form.html.twig @@ -893,7 +893,8 @@ {% endblock %} {% block scripts %} - + + -{% endblock %} \ No newline at end of file +{% endblock %} From 0d291b037c0b59b0547b5f04821426f30dd29302 Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Fri, 10 May 2019 07:02:37 +0000 Subject: [PATCH 22/36] Fix the error message when user tries to update the role ID. #210 --- src/Controller/RoleController.php | 15 ++++++++++++++- templates/role/form.html.twig | 3 ++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/Controller/RoleController.php b/src/Controller/RoleController.php index 49c03bc5..3d34eb50 100644 --- a/src/Controller/RoleController.php +++ b/src/Controller/RoleController.php @@ -9,6 +9,7 @@ use Doctrine\ORM\Query; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Validator\Validator\ValidatorInterface; +use Doctrine\DBAL\Exception\ForeignKeyConstraintViolationException; use App\Menu\Generator as MenuGenerator; use App\Access\Generator as ACLGenerator; @@ -275,7 +276,19 @@ class RoleController extends BaseController ], 422); } else { // validated! save the entity - $em->flush(); + // catch the exception in case user updated the id + try + { + $em->flush(); + } + catch(ForeignKeyConstraintViolationException $e) + { + $error_array['id'] = 'Role has already been assigned to user/s and id cannot be updated'; + return $this->json([ + 'success' => false, + 'errors' => $error_array + ], 403); + } // return successful response return $this->json([ diff --git a/templates/role/form.html.twig b/templates/role/form.html.twig index 7d86d28e..700356d3 100644 --- a/templates/role/form.html.twig +++ b/templates/role/form.html.twig @@ -116,7 +116,8 @@ } }); }).fail(function(response) { - if (response.status == 422) { + console.log(response.status); + if (response.status == 422 || response.status == 403) { var errors = response.responseJSON.errors; var firstfield = false; From b8a7cf6e2a51d0f9e2f97c20c87a15569b483578 Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Fri, 10 May 2019 07:09:42 +0000 Subject: [PATCH 23/36] Remove console.log message. #210 --- templates/role/form.html.twig | 1 - 1 file changed, 1 deletion(-) diff --git a/templates/role/form.html.twig b/templates/role/form.html.twig index 700356d3..e30c5789 100644 --- a/templates/role/form.html.twig +++ b/templates/role/form.html.twig @@ -116,7 +116,6 @@ } }); }).fail(function(response) { - console.log(response.status); if (response.status == 422 || response.status == 403) { var errors = response.responseJSON.errors; var firstfield = false; From 1a3263a4284cf919a181f4017ab7ad7d427663f7 Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Tue, 14 May 2019 09:16:15 +0000 Subject: [PATCH 24/36] Use redis client provider to connect to redis. #206 --- config/services.yaml | 9 +++----- src/Service/APNSClient.php | 12 ++++------ src/Service/HubCounter.php | 4 ++-- src/Service/MQTTClient.php | 23 ++++--------------- ...edisClient.php => RedisClientProvider.php} | 2 +- 5 files changed, 16 insertions(+), 34 deletions(-) rename src/Service/{RedisClient.php => RedisClientProvider.php} (97%) diff --git a/config/services.yaml b/config/services.yaml index bf607603..6c7464e2 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -66,16 +66,13 @@ services: App\Service\MQTTClient: arguments: - $ip_address: "%env(MQTT_IP_ADDRESS)%" - $port: "%env(MQTT_PORT)%" - $cert: "%env(MQTT_CERT)%" + $redis_client: "@App\\Service\\RedisClientProvider" App\Service\APNSClient: arguments: - $ip_address: "%env(APNS_REDIS_IP_ADDRESS)%" - $port: "%env(APNS_REDIS_PORT)%" + $redis_client: "@App\\Service\\RedisClientProvider" - App\Service\RedisClient: + App\Service\RedisClientProvider: arguments: $scheme: "%env(REDIS_CLIENT_SCHEME)%" $host: "%env(REDIS_CLIENT_HOST)%" diff --git a/src/Service/APNSClient.php b/src/Service/APNSClient.php index 2fc02fe9..4a1e561b 100644 --- a/src/Service/APNSClient.php +++ b/src/Service/APNSClient.php @@ -5,7 +5,6 @@ namespace App\Service; use Mosquitto\Client as MosquittoClient; use App\Entity\JobOrder; use App\Ramcar\MobileOSType; -use Redis; class APNSClient { @@ -14,16 +13,15 @@ class APNSClient // protected $mclient; protected $redis; - public function __construct($ip_address, $port) + public function __construct(RedisClientProvider $redis_client) { - $this->redis = new Redis(); - $this->redis->connect($ip_address, $port); + $this->redis = $redis_client->getRedisClient(); } - public function __destruct() - { + public function __destruct() + { // $this->mclient->disconnect(); - } + } public function push($token, $message) { diff --git a/src/Service/HubCounter.php b/src/Service/HubCounter.php index 13388ecc..62d663ac 100644 --- a/src/Service/HubCounter.php +++ b/src/Service/HubCounter.php @@ -15,10 +15,10 @@ class HubCounter protected $em; protected $redis; - public function __construct(EntityManagerInterface $em, RedisClient $rc) + public function __construct(EntityManagerInterface $em, RedisClientProvider $redis_client) { $this->em = $em; - $this->redis = $rc->getRedisClient(); + $this->redis = $redis_client->getRedisClient(); } // get rider key based on id diff --git a/src/Service/MQTTClient.php b/src/Service/MQTTClient.php index 79fa9dac..aa0932a3 100644 --- a/src/Service/MQTTClient.php +++ b/src/Service/MQTTClient.php @@ -4,7 +4,6 @@ namespace App\Service; use Mosquitto\Client as MosquittoClient; use App\Entity\JobOrder; -use Redis; class MQTTClient { @@ -15,27 +14,15 @@ class MQTTClient // protected $mclient; protected $redis; - public function __construct($ip_address, $port, $cert) + public function __construct(RedisClientProvider $redis_client) { - // we use redis now - // we have an mqtt server listening on redis and sending to mqtt - $this->redis = new Redis(); - $this->redis->connect('127.0.0.1', 6379); - - /* - error_log("connecting to mqtt server - $ip_address : $port"); - error_log("using $cert"); - $this->mclient = new MosquittoClient(); - $this->mclient->setTlsCertificates($cert); - $this->mclient->setTlsOptions(MosquittoClient::SSL_VERIFY_NONE, 'tlsv1'); - $this->mclient->connect($ip_address, $port); - */ + $this->redis = $redis_client->getRedisClient(); } - public function __destruct() - { + public function __destruct() + { // $this->mclient->disconnect(); - } + } public function publish($channel, $message) { diff --git a/src/Service/RedisClient.php b/src/Service/RedisClientProvider.php similarity index 97% rename from src/Service/RedisClient.php rename to src/Service/RedisClientProvider.php index 43323e0f..04ac1f80 100644 --- a/src/Service/RedisClient.php +++ b/src/Service/RedisClientProvider.php @@ -4,7 +4,7 @@ namespace App\Service; use Predis\Client as PredisClient; -class RedisClient +class RedisClientProvider { protected $redis; protected $scheme; From 2a501e60e4a901ae74e09d96c739aa726ad6d919 Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Wed, 15 May 2019 02:17:01 +0000 Subject: [PATCH 25/36] Update plate number validation, according to specifications. #211 --- src/Entity/Warranty.php | 47 +++++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/src/Entity/Warranty.php b/src/Entity/Warranty.php index 30d1afd4..c1e16d32 100644 --- a/src/Entity/Warranty.php +++ b/src/Entity/Warranty.php @@ -162,30 +162,37 @@ class Warranty // trim and make upper case $clean_plate = strtoupper(trim($plate)); - // remove invalid characters - $clean_plate = preg_replace("/[^A-Z0-9]/", '', $clean_plate); - - // check for 4 to 5 digit diplomatic plate - $res = preg_match("/^[0-9]{4,5}$/", $clean_plate); - if ($res) - return $clean_plate; - - // ABC-1234 or ABC-123 or ABC-12 format - $res = preg_match("/^[A-Z]{3}[0-9]{2,4}$/", $clean_plate); - if ($res) - return $clean_plate; - - // AB-123 or AB-12345 or AB-1234 format (motorcycles) - $res = preg_match("/^[A-Z]{2}[0-9]{3,5}$/", $clean_plate); - if ($res) - return $clean_plate; - - // 1234-AB format (motorcycles) - $res = preg_match("/^[0-9]{4}[A-Z]{2}$/", $clean_plate); + // check if alphanumeric, max length is 11, no spaces + $res = preg_match("/^[A-Z0-9]{1,11}+$/", $clean_plate); if ($res) return $clean_plate; return false; + + // remove invalid characters + //$clean_plate = preg_replace("/[^A-Z0-9]/", '', $clean_plate); + + // check for 4 to 5 digit diplomatic plate + //$res = preg_match("/^[0-9]{4,5}$/", $clean_plate); + //if ($res) + // return $clean_plate; + + // ABC-1234 or ABC-123 or ABC-12 format + //$res = preg_match("/^[A-Z]{3}[0-9]{2,4}$/", $clean_plate); + //if ($res) + // return $clean_plate; + + // AB-123 or AB-12345 or AB-1234 format (motorcycles) + //$res = preg_match("/^[A-Z]{2}[0-9]{3,5}$/", $clean_plate); + //if ($res) + // return $clean_plate; + + // 1234-AB format (motorcycles) + //$res = preg_match("/^[0-9]{4}[A-Z]{2}$/", $clean_plate); + //if ($res) + // return $clean_plate; + + //return false; } public function setPlateNumber($plate) From 144156e377aa4fa89955f4533298ee2f4b9eabb4 Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Thu, 16 May 2019 07:05:21 +0000 Subject: [PATCH 26/36] Create command that generates a JSON file of vehicles and their models with their compatible battery. #212 --- .../GenerateBatteryCompatibilityCommand.php | 97 +++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 src/Command/GenerateBatteryCompatibilityCommand.php diff --git a/src/Command/GenerateBatteryCompatibilityCommand.php b/src/Command/GenerateBatteryCompatibilityCommand.php new file mode 100644 index 00000000..dca7f36b --- /dev/null +++ b/src/Command/GenerateBatteryCompatibilityCommand.php @@ -0,0 +1,97 @@ +em = $om; + + parent::__construct(); + } + + protected function populateVehicleManufacturerIndex() + { + $vms = $this->em->getRepository(VehicleManufacturer::class)->findAll(); + + $this->vmfg_index = []; + foreach ($vms as $vm) + { + $mfg_name = $vm->getName(); + $this->vmfg_index[$mfg_name] = $vm; + + // get vehicles from manufacturer + $make_array = []; + $vehicles = $vm->getVehicles(); + foreach ($vehicles as $vehicle) + { + $batteries = $vehicle->getBatteries(); + $comp_batt = []; + foreach ($batteries as $battery) + { + // set to the first compatible battery found until a more expensive one is found + $comp_batt['id'] = $battery->getID(); + $comp_batt['name'] = $battery->getModel()->getName() . ' ' . + $battery->getSize()->getName(); + $comp_batt['image_url'] = $battery->getImageFile(); + //$comp_batt['description'] = $battery->getDescription(); + + // store the selling price for comparison + $batt_price = $battery->getSellingPrice(); + + // find the most expensive compatible battery + if ($battery->getSellingPrice() > $batt_price) + { + $comp_batt['id'] = $battery->getID(); + $comp_batt['name'] = $battery->getModel()->getName() . ' ' . + $battery->getSize()->getName(); + $comp_batt['image_url'] = $battery->getImageFile(); + //$comp_batt['description'] = $battery->getDescription(); + } + } + $make_array[$vehicle->getMake()][$vehicle->getModelYearFormatted()] = $comp_batt; + + } + $this->vmfg_index[$mfg_name] = $make_array; + + + } + } + + protected function configure() + { + $this->setName('battery:generate_compatibility_json') + ->setDescription('Generate a json file containing the vehicles and their compatible batteries') + ->setHelp('Generate a json file containing the vehicles and their compatible batteries') + ->addArgument('file', InputArgument::REQUIRED, 'Path and name for JSON file.'); + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $filename = $input->getArgument('file'); + $this->populateVehicleManufacturerIndex(); + + $json_file = fopen($filename, 'w'); + fwrite($json_file, json_encode($this->vmfg_index, JSON_PRETTY_PRINT)); + fclose($json_file); + + } +} From 92c0f2d1699a13b99c49c8cd1f35aae61ad9e622 Mon Sep 17 00:00:00 2001 From: Kendrick Chan Date: Mon, 27 May 2019 09:57:20 +0800 Subject: [PATCH 27/36] Fix bug in battery:generate_compatibility_json command #212 --- .../GenerateBatteryCompatibilityCommand.php | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/Command/GenerateBatteryCompatibilityCommand.php b/src/Command/GenerateBatteryCompatibilityCommand.php index dca7f36b..57e20076 100644 --- a/src/Command/GenerateBatteryCompatibilityCommand.php +++ b/src/Command/GenerateBatteryCompatibilityCommand.php @@ -36,7 +36,7 @@ class GenerateBatteryCompatibilityCommand extends Command foreach ($vms as $vm) { $mfg_name = $vm->getName(); - $this->vmfg_index[$mfg_name] = $vm; + // $this->vmfg_index[$mfg_name] = []; // get vehicles from manufacturer $make_array = []; @@ -51,7 +51,8 @@ class GenerateBatteryCompatibilityCommand extends Command $comp_batt['id'] = $battery->getID(); $comp_batt['name'] = $battery->getModel()->getName() . ' ' . $battery->getSize()->getName(); - $comp_batt['image_url'] = $battery->getImageFile(); + $comp_batt['image_url'] = '/assets/img/products/' . strtolower($battery->getModel()->getName()) . '.png'; + $comp_batt['description'] = ''; //$comp_batt['description'] = $battery->getDescription(); // store the selling price for comparison @@ -67,10 +68,16 @@ class GenerateBatteryCompatibilityCommand extends Command //$comp_batt['description'] = $battery->getDescription(); } } - $make_array[$vehicle->getMake()][$vehicle->getModelYearFormatted()] = $comp_batt; + + // check if no compatible batteries + if (!empty($comp_batt)) + $make_array[$vehicle->getMake()][$vehicle->getModelYearFormatted()] = $comp_batt; } - $this->vmfg_index[$mfg_name] = $make_array; + + // check if empty + if (!empty($make_array)) + $this->vmfg_index[$mfg_name] = $make_array; } From 8adea20f59ee0d3ea718f8e21305446d44a0b70c Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Mon, 27 May 2019 13:59:51 +0000 Subject: [PATCH 28/36] Fix memory error when querying the database. #213 --- .../GenerateWarrantyFromJobOrderCommand.php | 126 +++++++++++++----- 1 file changed, 96 insertions(+), 30 deletions(-) diff --git a/src/Command/GenerateWarrantyFromJobOrderCommand.php b/src/Command/GenerateWarrantyFromJobOrderCommand.php index 1412c706..57bf1be4 100644 --- a/src/Command/GenerateWarrantyFromJobOrderCommand.php +++ b/src/Command/GenerateWarrantyFromJobOrderCommand.php @@ -17,15 +17,21 @@ use App\Entity\Warranty; use App\Entity\SAPBattery; use App\Ramcar\ServiceType; +use App\Ramcar\WarrantyStatus; class GenerateWarrantyFromJobOrderCommand extends Command { protected $em; + protected $sapbatt_hash; + protected $warranties_hash; public function __construct(ObjectManager $em) { $this->em = $em; + $this->loadSAPBatteries(); + $this->loadWarranties(); + parent::__construct(); } @@ -43,22 +49,68 @@ class GenerateWarrantyFromJobOrderCommand extends Command return $expire_date; } + protected function loadSAPBatteries() + { + $this->sapbatt_hash = []; + + $sap_batteries = $this->em->getRepository(SAPBattery::class)->findAll(); + foreach($sap_batteries as $sap_batt) + { + $id = $sap_batt->getID(); + $brand_size = $sap_batt->getBrand()->getID() . " " . $sap_batt->getSize()->getID(); + $this->sapbatt_hash[$id] = $brand_size; + } + } + + protected function loadWarranties() + { + $this->warranties_hash = []; + + $warranties = $this->em->getRepository(Warranty::class)->findAll(); + foreach($warranties as $warranty) + { + $plate_number = $warranty->getPlateNumber(); + $date_expire = $warranty->getDateExpire(); + $expiry_date = $date_expire->format('Y-m-d'); + + $this->warranties_hash[$plate_number][$expiry_date] = $warranty->getID(); + } + } + + protected function findSAPBattery($batt_id) + { + if (!isset($this->sapbatt_hash[$batt_id])) + { + return false; + } + + return true; + } + + protected function findWarranty($plate_number, $expiry_date) + { + $date_expire = $expiry_date->format('Y-m-d'); + if (!isset($this->warranties_hash[$plate_number][$date_expire])) + { + return false; + } + + return true; + } + protected function execute(InputInterface $input, OutputInterface $output) { $em = $this->em; - $qb = $this->em->getRepository(JobOrder::class)->createQueryBuilder('j'); + $query = $em->createQuery('SELECT jo FROM App\Entity\JobOrder jo + WHERE jo.service_type = :service_type'); + $query->setParameter('service_type', ServiceType::BATTERY_REPLACEMENT_NEW); - // get all job orders with service_type='battery_replacement_new' - $qb->select('j') - ->where('j.service_type = :service_type') - ->setParameter('service_type', ServiceType::BATTERY_REPLACEMENT_NEW); + $result = $query->iterate(); - $query = $qb->getQuery(); - $result = $query->getResult(); - - foreach ($result as $jo) + foreach ($result as $row) { + $jo = $row[0]; $invoice_items = []; // For now, one invoice == one battery $invoice_items = $jo->getInvoice()->getItems(); @@ -69,8 +121,13 @@ class GenerateWarrantyFromJobOrderCommand extends Command { // manually retrieve the SAPBattery using the SAPCode $battery_sap_code = $invoice_item->getBattery()->getSAPCode(); - $sap_battery = $this->em->getRepository(SAPBattery::class)->find($battery_sap_code); - + $found_battery = $this->findSAPBattery($battery_sap_code); + $sap_code = '\'' . $battery_sap_code . '\''; + if (!$found_battery) + { + $sap_code = 'NULL'; + } + // get warranty period for battery $warranty_period = 0; if ($invoice_item->getBattery()->getWarrantyPrivate() != null) @@ -96,30 +153,39 @@ class GenerateWarrantyFromJobOrderCommand extends Command // check if warranty already exists $cleaned_plate_number = Warranty::cleanPlateNumber($jo->getCustomerVehicle()->getPlateNumber()); $expiry_date = $this->computeDateExpire($jo->getInvoice()->getDateCreate(), $warranty_period); - $found_warranty = $this->em->createQuery("SELECT count(w) FROM App\Entity\Warranty w - WHERE w.plate_number = :plate_number AND w.date_expire = :date_expire") - ->setParameter('plate_number', $cleaned_plate_number) - ->setParameter('date_expire', $expiry_date->format('Y-m-d')) - ->getSingleScalarResult(); - if ($found_warranty == 0) + $found_warranty = $this->findWarranty($cleaned_plate_number, $expiry_date); + if (!$found_warranty) { - $warranty = new Warranty(); - $warranty->setWarrantyClass($jo->getWarrantyClass()) - ->setFirstName($jo->getCustomer()->getFirstName()) - ->setLastName($jo->getCustomer()->getLastName()) - ->setMobileNumber($jo->getCustomer()->getPhoneMobile()) - ->setPlateNumber($cleaned_plate_number) - ->setDatePurchase($jo->getInvoice()->getDateCreate()) - ->setDateExpire($expiry_date) - ->setBatteryModel($invoice_item->getBattery()->getModel()) - ->setBatterySize($invoice_item->getBattery()->getSize()) - ->setSAPBattery($sap_battery); - $em->persist($warranty); + $bty_model_id = $invoice_item->getBattery()->getModel()->getID(); + $bty_size_id = $invoice_item->getBattery()->getSize()->getID(); + $warranty_class = $jo->getWarrantyClass(); + + $date = $jo->getInvoice()->getDateCreate(); + $date_purchase = $date->format('Y-m-d'); + + $date_create = date('Y-m-d H:i:s'); + + $date_expire = $expiry_date->format('Y-m-d'); + + $first_name = addslashes(trim($jo->getCustomer()->getFirstName())); + $last_name = addslashes(trim($jo->getCustomer()->getLastName())); + $mobile_number = addslashes(trim($jo->getCustomer()->getPhoneMobile())); + + $values = '(' . $bty_model_id . ',' . $bty_size_id . ',NULL,\'' . $warranty_class . '\',\'' + . $cleaned_plate_number . '\',\'' . WarrantyStatus::ACTIVE . '\',\'' . $date_create . '\',\'' . $date_purchase + . '\',\'' . $date_expire . '\',NULL,' + . $sap_code . ',NULL,\'' . $first_name . '\',\'' . $last_name . '\',\'' . $mobile_number . '\');'; + + $sql_statement = 'INSERT INTO `warranty` (bty_model_id,bty_size_id,serial,warranty_class,plate_number,status,date_create,date_purchase,date_expire,date_claim,sap_bty_id,claim_id,first_name,last_name,mobile_number) VALUES ' . $values . "\n"; + + echo $sql_statement; + } - $em->flush(); } } } + $em->detach($row[0]); + $em->clear(); } } } From ce3d69dd2022644a748ff024d3bd749fedde1b60 Mon Sep 17 00:00:00 2001 From: Kendrick Chan Date: Mon, 27 May 2019 23:39:49 +0800 Subject: [PATCH 29/36] Fix order of import queries for legacy jo #214 --- utils/legacy_load/import_legacy_data.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utils/legacy_load/import_legacy_data.sql b/utils/legacy_load/import_legacy_data.sql index 0f12390e..3f1a7055 100644 --- a/utils/legacy_load/import_legacy_data.sql +++ b/utils/legacy_load/import_legacy_data.sql @@ -1,4 +1,4 @@ load data local infile '/tmp/plate_numbers.csv' into table plate_number fields terminated by ','; +load data infile '/tmp/legacy_jo.csv' into table legacy_job_order fields terminated by '|' (id, trans_date, trans_type, origin, car_brand, car_make, car_model, car_color, cust_name, cust_first_name, cust_middle_name, cust_last_name, cust_contact, cust_mobile, cust_landline, delivery_instructions, agent_notes_1, delivery_date, delivery_time, advance_order, stage, cancel_reason, cancel_reason_specify, payment_method, prepared_by, dispatch_time, dispatch_date, dispatched_by, address, landmark, date_purchase, plate_number); load data infile '/tmp/legacy_jo_row.csv' into table legacy_job_order_row fields terminated by ',' enclosed by '"' lines terminated by '\n' (job_order_id, item, qty, price, price_level, status, account, enrollee) set id = null; load data local infile '/tmp/warranty.csv' into table warranty fields terminated by ',' (bty_model_id, bty_size_id, serial, warranty_class, plate_number, status, date_create, date_purchase, date_expire, date_claim, claim_id, sap_bty_id, first_name, last_name, mobile_number) set id = null; -load data infile '/tmp/legacy_jo.csv' into table legacy_job_order fields terminated by '|' (id, trans_date, trans_type, origin, car_brand, car_make, car_model, car_color, cust_name, cust_first_name, cust_middle_name, cust_last_name, cust_contact, cust_mobile, cust_landline, delivery_instructions, agent_notes_1, delivery_date, delivery_time, advance_order, stage, cancel_reason, cancel_reason_specify, payment_method, prepared_by, dispatch_time, dispatch_date, dispatched_by, address, landmark, date_purchase, plate_number); From b62c7da678606c816838d4064dc34edb400ee93f Mon Sep 17 00:00:00 2001 From: Kendrick Chan Date: Mon, 27 May 2019 23:40:31 +0800 Subject: [PATCH 30/36] Add SAP battery initial data #214 --- utils/legacy_load/sap_battery.sql | 104 ++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 utils/legacy_load/sap_battery.sql diff --git a/utils/legacy_load/sap_battery.sql b/utils/legacy_load/sap_battery.sql new file mode 100644 index 00000000..38302a6d --- /dev/null +++ b/utils/legacy_load/sap_battery.sql @@ -0,0 +1,104 @@ +-- MySQL dump 10.16 Distrib 10.2.12-MariaDB, for Linux (x86_64) +-- +-- Host: localhost Database: resq +-- ------------------------------------------------------ +-- Server version 10.2.12-MariaDB + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Table structure for table `sap_battery` +-- + +DROP TABLE IF EXISTS `sap_battery`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `sap_battery` ( + `id` varchar(25) COLLATE utf8_unicode_ci NOT NULL, + `brand_id` int(11) DEFAULT NULL, + `size_id` int(11) DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `IDX_385E33F44F5D008` (`brand_id`), + KEY `IDX_385E33F498DA827` (`size_id`), + CONSTRAINT `FK_385E33F44F5D008` FOREIGN KEY (`brand_id`) REFERENCES `sap_battery_brand` (`id`), + CONSTRAINT `FK_385E33F498DA827` FOREIGN KEY (`size_id`) REFERENCES `sap_battery_size` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `sap_battery` +-- + +LOCK TABLES `sap_battery` WRITE; +/*!40000 ALTER TABLE `sap_battery` DISABLE KEYS */; +INSERT INTO `sap_battery` VALUES ('ECHB20AB-CPN00-LX',3,3),('ECHB20AB-SPN00-LX',3,3),('ECHB24AB-SPN00-L',3,4),('ECHC24AL-SPN00-L',3,6),('ECHD23AL-SPN00-LX',3,5),('ECHD26AL-SPN00-L',3,2),('ECHD26AL-SPN00-LX',3,1),('ECHD31AL-SPN00-L',3,3),('ECHD31AL-SPN00-LX',3,2),('ECHE41AL-SPN00-L',3,6),('ECHE41AL-SPN00-LX',3,7),('ECHF51AL-SPN00-LX',3,8),('ECHG51AL-SPN00-L',3,4),('ECHG51AL-SPN00-LX',3,9),('ECHH52AL-SPN00-LX',3,10),('EDFB20AB-CPN00-L',18,3),('EDFB24AB-SPN00-L',18,4),('EDFD23AL-SPN00-L',18,5),('EDFD26AL-SPN00-L',18,1),('EDFD31AL-SPN00-L',18,2),('EDFE41AL-SPN00-L',18,7),('EDFF51AL-SPN00-L',18,8),('EDFG51AL-SPN00-L',18,9),('EDFH52AL-SPN00-L',18,10),('EDPB20AB-CPN00-LX',19,3),('EDPB24AB-SPN00-LX',19,4),('EDPD23AL-SPN00-LX',19,5),('EDPD26AL-SPN00-LX',19,1),('EDPD31AL-SPN00-LX',19,2),('EDPE41AL-SPN00-LX',19,7),('EDPF51AL-SPN00-LX',19,8),('EDPG51AL-SPN00-LX',19,9),('EEFB24BB-SPN00-L',12,4),('EEFD23BL-SPN00-L',12,5),('EEFD26BL-SPN00-L',12,1),('EEFD31BL-SPN00-L',12,2),('EEFE41BL-SPN00-L',12,7),('EEFF51BL-SPN00-L',12,8),('EEFG51BL-SPN00-L',12,9),('EEFH52BL-SPN00-L',12,10),('EELB20AB-CPN00-L',6,3),('EELB24AB-SPN00-L',6,4),('EELD23AL-SPN00-L',6,5),('EELD26AL-SPN00-L',6,1),('EELD31AL-SPN00-L',6,2),('EELE41AL-SPN00-L',6,7),('EELF51AL-SPN00-L',6,8),('EELG51AL-SPN00-L',6,9),('EELH52AL-SPN00-L',6,10),('EMC6TNPR-SPN00-L',11,36),('EMFD26AL-SPN00-L',10,1),('EMFD31AL-SPN00-L',10,2),('EMFE41AL-SPN00-L',10,7),('EMFF51AL-SPN00-L',10,8),('EMFG51AL-SPN00-L',10,9),('EMSD26DL-SPN00-L',13,1),('EMSD31DL-SPN00-L',13,2),('EMTD26CL-SPN00-L',16,1),('EMTD31CL-SPN00-L',16,2),('EMTE41CL-SPN00-L',16,7),('EMTF51CL-SPN00-L',16,8),('EMTG51CF-SPN00-L',16,9),('EMTG51CL-SPN00-L',16,9),('EMTH52CF-SPN00-L',16,37),('EMTH52CL-SPN00-L',16,10),('EPLD23AL-SPN00-L',14,5),('EPLD26AL-SPN00-L',14,1),('EPLD31AL-SPN00-L',14,2),('EPLE41AL-SPN00-L',14,7),('EPLF51AL-SPN00-L',14,8),('EPLG51AL-SPN00-L',14,9),('ERMB24AB-SPN00-L',15,4),('ERMD26AL-SPN00-L',15,1),('ERMD31AL-SPN00-L',15,2),('ERME41AL-SPN00-L',15,7),('ERMF51AL-SPN00-L',15,8),('ERMG51AL-SPN00-L',15,9),('ESRB24LF-SPN00-L',4,4),('ESRD31NG-SPN00-L',4,2),('ESRE41PG-SPN00-L',4,7),('ESRF51QG-SPN00-L',4,8),('ESRG51RF-SPN00-L',4,9),('ESRH52TF-SPN00-L',4,10),('EVLD26AL-SPN00-L',17,1),('EVLD31AL-SPN00-L',17,2),('EVLE41AL-SPN00-L',17,7),('EVLF51AL-SPN00-L',17,8),('EVLG51AL-SPN00-L',17,9),('EYKB20CB-SPN00-L',21,3),('EYKB24CB-SPN00-L',21,4),('EYKD26CL-SPN00-L',21,1),('EYKD31CL-SPN00-L',21,2),('EYKE41CL-SPN00-L',21,7),('EYKF51CL-SPN00-L',21,8),('EYKG51CL-SPN00-L',21,9),('EYSD26AL-CPN00-L',23,1),('EYSD31AL-CPN00-L',23,2),('EYSE41AL-CPN00-L',23,7),('EYSG51AL-CPN00-L',23,9),('EYTB20AB-CPN00-L',22,3),('EYTB20AB-CPN00-LX',22,3),('EYTD26AL-SPN00-L',22,1),('EYTD26AL-SPN00-LX',22,1),('EYTD31AL-SPN00-L',22,2),('EYTD31CL-SPN00-LX',22,2),('EYTE41AL-SPN00-L',22,7),('EYTE41AL-SPN00-LX',22,7),('EYTF51AL-SPN00-L',22,8),('EYTF51BL-SPN00-LX',22,8),('EYTG51AL-SPN00-L',22,9),('EYTG51BL-SPN00-LX',22,9),('WATB31QT-CPP00-L',4,2),('WCHB20BB-CPN00-LX',2,3),('WCHB24BB-CPN00-LX',2,4),('WCHD23BL-CPN00-LX',2,5),('WCHD26BL-CPN00-LX',2,1),('WCHD31BL-CPN00-LX',2,2),('WCMG24BL-CPN00-L',1,1),('WCMG27HL-CPN00-L',1,2),('WCYG24IL-CPN00-L',1,1),('WDPB20BB-CPN00-LX',19,3),('WDPB20CA-CPN00-LX',19,3),('WDPB24BB-CPN00-LX',19,4),('WDPB24CB-CPN00-LX',19,4),('WDPL23BL-CPN00-LX',19,5),('WDPL23CL-CPN00-LX',19,5),('WDPL26BL-CPN00-LX',19,1),('WDPL26CL-CPN00-LX',19,1),('WDPL31BL-CPN00-LX',19,2),('WDPL31CL-CPN00-LX',19,2),('WDSB24DA-CPN00-LX',20,4),('WDSB24DB-CPN00-LX',20,4),('WDSL23DL-CPN00-LX',20,5),('WDSL26DL-CPN00-LX',20,1),('WDSL26DR-CPN00-LX',20,29),('WDSL31DL-CPN00-LX',20,2),('WDSL31DR-CPN00-LX',20,17),('WEBL23EL-CPNMD-L',5,5),('WMEB20CB-CPN00-LX',7,3),('WMEB21CB-CPN00-LX',7,3),('WMEB24CA-CPN00-LX',7,15),('WMEB24CB-CPN00-LX',7,4),('WMEC24CL-CPN00-LX',7,6),('WMEL23CL-CPN00-L',7,1),('WMEL23CL-CPN00-LX',7,5),('WMEL26CL-CPN00-L',7,2),('WMEL26CL-CPN00-LX',7,1),('WMEL31CL-CPN00-L',7,3),('WMEL31CL-CPN00-LX',7,2),('WMEN44CL-CPN00-LX',7,16),('WMGB20CB-CPNHD-L',9,3),('WMGB20DA-CPN00-LX',9,18),('WMGB20DB-CPN00-LX',9,3),('WMGB20DB-CPNSZ-L',9,3),('WMGB20DI-CPNTY-L',9,3),('WMGB21DA-CPN00-LX',9,18),('WMGB21DA-CPNHY-L',9,18),('WMGB21DB-CPN00-LX',9,3),('WMGB24DA-CPN00-LX',9,15),('WMGB24DB-CPN00-LX',9,4),('WMGB24DB-CPNNI-L',9,4),('WMGB24DL-CPNTY-L',9,4),('WMGB24EB-CPNNI-L',9,4),('WMGD204L-TSP00-L',9,19),('WMGD23BL-CPN00-L',9,5),('WMGD23DL-CPNFD-L',9,5),('WMGD23ER-CPNIZ-L',9,5),('WMGD23FR-CPPIZ-L',9,5),('WMGD317R-CPNMB-L',9,2),('WMGD31EL-CPNM0-L',9,2),('WMGD31EL-CPNMB-L',9,2),('WMGD31IR-SPNIZ-L',9,17),('WMGD78DD-CPP00-L',9,20),('WMGG275R-CPNIZ-L',9,17),('WMGG47DL-CPN00-L',9,21),('WMGG47DL-CPNTY-L',9,22),('WMGG48DL-CPN00-L',9,23),('WMGG48EL-CPNTY-L',9,24),('WMGG49EL-CPN00-L',9,25),('WMGG65DE-CPP00-L',9,26),('WMGG65FR-CPPFD-L',9,26),('WMGG94DL-TSP00-L',9,27),('WMGL23DL-CPN00-L',9,1),('WMGL23DL-CPN00-LX',9,5),('WMGL23DL-CPNM0-L',9,5),('WMGL23DL-CPNMB-L',9,5),('WMGL23DR-CPN00-LX',9,28),('WMGL26DL-CPN00-L',9,2),('WMGL26DL-CPN00-LX',9,1),('WMGL26DR-CPN00-L',9,2),('WMGL26DR-CPN00-LX',9,29),('WMGL31DL-CPN00-L',9,3),('WMGL31DL-CPN00-LX',9,2),('WMGL31DL-CPNIZ-L',9,2),('WMGL31DR-CPN00-L',9,3),('WMGL31DR-CPN00-LX',9,17),('WMGLN2DL-CPNTY-L',9,1),('WMGLN3EL-CPNTY-L',9,2),('WMGN44DL-CPN00-L',9,16),('WMGN44DL-CPNFD-L',9,16),('WMGN44DL-CPNHY-L',9,16),('WMGN55DL-CPN00-L',9,30),('WMGN55DR-CPN00-L',9,31),('WMGN66DL-CPN00-L',9,32),('WMGN66DL-CPNFD-L',9,32),('WMGN66DR-CPN00-L',9,33),('WMGN77DL-CPN00L',9,2),('WMGN77DL-TSP00-L',9,34),('WMGN88DL-CPN00-L',9,35),('WMGR31DR-CPN00-L',9,3),('WMMGC2UH-SPN00-L',4,11),('WMMGC8SH-SPN00-L',4,12),('WMMGT6UH-SPN00-L',4,13),('WMMGT8SH-SPN00-L',4,14),('WMTE41CL-CPN00-L',16,38),('WMTF51CL-CPN00-L',16,39),('WMTG51CL-CPN00-L',16,40),('WMTH52CL-CPN00-L',16,41),('WMXB24EA-CPN00-LX',8,15),('WMXB24EB-CPN00-LX',8,4),('WMXB24FA-CPNSZ-L',8,15),('WMXD235L-CPNIZ-L',8,5),('WMXD23FL-CPPIZ-L',8,5),('WMXD26FL-SPNIZ-L',8,1),('WMXD31FL-CPNUM-L',8,2),('WMXD31IR-CPNFD-L',8,2),('WMXG24FI-CPNIZ-L',8,1),('WMXG24FI-CPPIZ-L',8,1),('WMXG278E-CPNFD-L',8,2),('WMXL23EL-CPN00-L',8,1),('WMXL23EL-CPN00-LX',8,5),('WMXL31EL-CPNKI-L',8,2),('WMXN87EL-CPN00-LX',8,2),('WMXX26EL-CPN00-L',1,2),('WMXX26EL-CPN00-LX',8,1),('WMXX31EL-CPN00-L',8,2),('WMXX31EL-CPN00-LX',8,2),('WMXX31ER-CPNSY-LX',8,17),('WMXY26EL-CPN00-LX',8,1),('WODD236L-CPPMB-L',9,5),('WODG247L-CPPMB-L',9,1),('WODG278L-CPPMB-L',9,2),('WODR23DI-CPNMB-L',9,5),('WODR26EL-CPNMB-L',9,1),('WODR31EL-CPNMB-L',9,2),('WOLB20DB-CPNMB-L',9,3),('WPLB24DB-CPN00-L',14,4),('WPLG24DL-CPN00-L',14,1),('WPLG27DL-CPN00-L',14,2),('WSOA465F-TSP00-L',4,5),('WSOD317M-CP403-E',4,2),('WSOD317M-CPP00-L',4,2),('WTGB20DA-CPNTY-L',9,18),('WTGB20DB-CPNTY-L',9,3),('WTGB20DL-CPNTY-L',9,18),('WTGB24DL-CPNTY-L',9,4),('WTGG47DL-CPNTY-L',9,22),('WTGG48EL-CPNTY-L',9,24),('WTGL26EL-CPNTY-LX',9,1),('WTGL26ER-CPNTY-LX',9,29),('WTGL31EL-CPNTY-LX',9,2),('WTGR23DL-CPNTY-L',9,5),('WTGR26EL-CPNTY-L',9,1),('WTGR26ER-CPNTY-L',9,29),('WTGR31EL-CPNTY-L',9,2),('WYKB20CB-CPN00-L',21,3),('WYKB20DB-CPN00-L',21,3),('WYKB24CB-CPN00-L',21,4),('WYKB24DB-CPN00-L',21,4),('WYKL26CL-CPN00-L',21,1),('WYKL26CR-CPN00-L',21,29),('WYKL26DL-CPN00-L',21,1),('WYKL26DR-CPN00-L',21,29),('WYKL31CL-CPN00-L',21,2),('WYKL31CR-CPN00-L',21,17),('WYKL31DL-CPN00-L',21,2),('WYKL31DR-CPN00-L',21,17),('WYKN44DL-CPN00-L',21,16),('WYKN55DL-CPN00-L',21,30),('WYKN66DL-CPN00-L',21,32),('WZMB31QT-CPP00-L',4,2); +/*!40000 ALTER TABLE `sap_battery` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `sap_battery_brand` +-- + +DROP TABLE IF EXISTS `sap_battery_brand`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `sap_battery_brand` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `name` varchar(50) COLLATE utf8_unicode_ci NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=24 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `sap_battery_brand` +-- + +LOCK TABLES `sap_battery_brand` WRITE; +/*!40000 ALTER TABLE `sap_battery_brand` DISABLE KEYS */; +INSERT INTO `sap_battery_brand` VALUES (1,'CENTURY MARATHONER'),(2,'CHAMPION MF12'),(3,'CHAMPION PM'),(4,'SOLAR'),(5,'EFB MAZDA'),(6,'ELECTRON'),(7,'ENDURO'),(8,'EXCEL'),(9,'GOLD'),(10,'MAGIC FORCE'),(11,'MOTOLITE'),(12,'MOTOLITE ENFORCER'),(13,'MOTOLITE SUPER PREMIUM'),(14,'POWERLAST'),(15,'ROADMASTER'),(16,'TRUCKMASTER'),(17,'VALIANT'),(18,'DYNA FORCE'),(19,'DYNA POWER'),(20,'XTP-CALCIUM'),(21,'YOKOHAMA'),(22,'YUASA MERCURY'),(23,'YUASA SUPER PREMIUM MERCURY'); +/*!40000 ALTER TABLE `sap_battery_brand` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `sap_battery_size` +-- + +DROP TABLE IF EXISTS `sap_battery_size`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `sap_battery_size` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `name` varchar(50) COLLATE utf8_unicode_ci NOT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=44 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `sap_battery_size` +-- + +LOCK TABLES `sap_battery_size` WRITE; +/*!40000 ALTER TABLE `sap_battery_size` DISABLE KEYS */; +INSERT INTO `sap_battery_size` VALUES (1,'2SMF'),(2,'3SMF'),(3,'NS40'),(4,'NS60'),(5,'1SMF'),(6,'1SNF'),(7,'6SMF'),(8,'2D'),(9,'4D'),(10,'8D'),(11,'GC2'),(12,'GC8'),(13,'GC2-TUBULAR'),(14,'GC8-TUBULAR'),(15,'NS60 REVERSE'),(16,'DIN44'),(17,'3SMF REVERSE'),(18,'NS40 REVERSE'),(19,'D20'),(20,'G34'),(21,'DIN55H'),(22,'DIN55 H'),(23,'DIN66H'),(24,'DIN66 H'),(25,'DIN110'),(26,'G65'),(27,'DIN77H'),(28,'1SMF REVERSE'),(29,'2SMF REVERSE'),(30,'DIN55'),(31,'DIN55 REVERSE'),(32,'DIN66'),(33,'DIN66 REVERSE'),(34,'DIN77'),(35,'DIN88'),(36,'6TN'),(37,'8D LUG TYPE'),(38,'6SMF MF'),(39,'2D MF'),(40,'4D MF'),(41,'8D MF'),(42,'B20'),(43,'B24'); +/*!40000 ALTER TABLE `sap_battery_size` ENABLE KEYS */; +UNLOCK TABLES; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed on 2019-05-27 23:35:07 From 754af5e1e42afe7e5cadf90b4db003e8b7090642 Mon Sep 17 00:00:00 2001 From: Kendrick Chan Date: Tue, 28 May 2019 01:20:09 +0800 Subject: [PATCH 31/36] Fix memory issue for warranty generation #213 --- .../GenerateWarrantyFromJobOrderCommand.php | 40 +++++++++++++++---- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/src/Command/GenerateWarrantyFromJobOrderCommand.php b/src/Command/GenerateWarrantyFromJobOrderCommand.php index 57bf1be4..86653d97 100644 --- a/src/Command/GenerateWarrantyFromJobOrderCommand.php +++ b/src/Command/GenerateWarrantyFromJobOrderCommand.php @@ -66,15 +66,22 @@ class GenerateWarrantyFromJobOrderCommand extends Command { $this->warranties_hash = []; + /* $warranties = $this->em->getRepository(Warranty::class)->findAll(); foreach($warranties as $warranty) { $plate_number = $warranty->getPlateNumber(); $date_expire = $warranty->getDateExpire(); + + // skip null date expire + if ($date_expire == null) + continue; + $expiry_date = $date_expire->format('Y-m-d'); $this->warranties_hash[$plate_number][$expiry_date] = $warranty->getID(); } + */ } protected function findSAPBattery($batt_id) @@ -102,19 +109,32 @@ class GenerateWarrantyFromJobOrderCommand extends Command { $em = $this->em; + // to save on joins, go with invoice item first + $query = $em->createQuery('select ii,i,jo,cv from App\Entity\InvoiceItem ii inner join ii.invoice i inner join i.job_order jo inner join jo.cus_vehicle cv join jo.customer c where ii.battery is not null and jo.service_type = :service_type'); + $query->setParameter('service_type', ServiceType::BATTERY_REPLACEMENT_NEW); + /* $query = $em->createQuery('SELECT jo FROM App\Entity\JobOrder jo WHERE jo.service_type = :service_type'); $query->setParameter('service_type', ServiceType::BATTERY_REPLACEMENT_NEW); + */ $result = $query->iterate(); foreach ($result as $row) { - $jo = $row[0]; + $invoice_item = $row[0]; + $invoice = $invoice_item->getInvoice(); + $jo = $invoice->getJobOrder(); + $cv = $jo->getCustomerVehicle(); + $customer = $jo->getCustomer(); + /* $invoice_items = []; - // For now, one invoice == one battery + // for now, one invoice == one battery + + $invoice_items = $jo->getInvoice()->getItems(); $invoice_item = $invoice_items[0]; + */ if ($invoice_item != null) { if($invoice_item->getBattery() != null) @@ -129,6 +149,7 @@ class GenerateWarrantyFromJobOrderCommand extends Command } // get warranty period for battery + // TODO: base it on the battery type $warranty_period = 0; if ($invoice_item->getBattery()->getWarrantyPrivate() != null) { @@ -143,15 +164,17 @@ class GenerateWarrantyFromJobOrderCommand extends Command $warranty_period = $invoice_item->getBattery()->getWarrantyTnv(); } - if ($jo->getInvoice()->getDateCreate() != null) + if ($invoice->getDateCreate() != null) { // check if plate number is "clean". If not, do not insert into warranty - if (!(Warranty::cleanPlateNumber($jo->getCustomerVehicle()->getPlateNumber()))) + if (!(Warranty::cleanPlateNumber($cv->getPlateNumber()))) { continue; } + // check if warranty already exists - $cleaned_plate_number = Warranty::cleanPlateNumber($jo->getCustomerVehicle()->getPlateNumber()); + $cleaned_plate_number = Warranty::cleanPlateNumber($cv->getPlateNumber()); + $expiry_date = $this->computeDateExpire($jo->getInvoice()->getDateCreate(), $warranty_period); $found_warranty = $this->findWarranty($cleaned_plate_number, $expiry_date); if (!$found_warranty) @@ -167,9 +190,9 @@ class GenerateWarrantyFromJobOrderCommand extends Command $date_expire = $expiry_date->format('Y-m-d'); - $first_name = addslashes(trim($jo->getCustomer()->getFirstName())); - $last_name = addslashes(trim($jo->getCustomer()->getLastName())); - $mobile_number = addslashes(trim($jo->getCustomer()->getPhoneMobile())); + $first_name = addslashes(trim($customer->getFirstName())); + $last_name = addslashes(trim($customer->getLastName())); + $mobile_number = addslashes(trim($customer->getPhoneMobile())); $values = '(' . $bty_model_id . ',' . $bty_size_id . ',NULL,\'' . $warranty_class . '\',\'' . $cleaned_plate_number . '\',\'' . WarrantyStatus::ACTIVE . '\',\'' . $date_create . '\',\'' . $date_purchase @@ -184,6 +207,7 @@ class GenerateWarrantyFromJobOrderCommand extends Command } } } + $em->detach($row[0]); $em->clear(); } From e4fc5f8648075b5f8c245918072bd13828f47fd3 Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Tue, 28 May 2019 00:24:22 +0000 Subject: [PATCH 32/36] Create sql script that updates warranty status. #215 --- utils/warranty_status/update_warranty_status.sql | 1 + 1 file changed, 1 insertion(+) create mode 100644 utils/warranty_status/update_warranty_status.sql diff --git a/utils/warranty_status/update_warranty_status.sql b/utils/warranty_status/update_warranty_status.sql new file mode 100644 index 00000000..6605b674 --- /dev/null +++ b/utils/warranty_status/update_warranty_status.sql @@ -0,0 +1 @@ +update warranty set status='expired' where date_expire < now() - interval 1 day; From 66ec9fc23763c48db3b4a04fca524328746179d3 Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Tue, 28 May 2019 02:37:44 +0000 Subject: [PATCH 33/36] Rename script. #215 --- utils/warranty_expire/warranty_expire.sql | 1 + utils/warranty_status/update_warranty_status.sql | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 utils/warranty_expire/warranty_expire.sql delete mode 100644 utils/warranty_status/update_warranty_status.sql diff --git a/utils/warranty_expire/warranty_expire.sql b/utils/warranty_expire/warranty_expire.sql new file mode 100644 index 00000000..c1b9a089 --- /dev/null +++ b/utils/warranty_expire/warranty_expire.sql @@ -0,0 +1 @@ +update warranty set status='expired' where date_expire is not null and date_expire < now() - interval 1 day; diff --git a/utils/warranty_status/update_warranty_status.sql b/utils/warranty_status/update_warranty_status.sql deleted file mode 100644 index 6605b674..00000000 --- a/utils/warranty_status/update_warranty_status.sql +++ /dev/null @@ -1 +0,0 @@ -update warranty set status='expired' where date_expire < now() - interval 1 day; From 89cb5ac27eecbe3f6849aab049ed37d921a9f5f5 Mon Sep 17 00:00:00 2001 From: Korina Cordero Date: Tue, 28 May 2019 04:47:35 +0000 Subject: [PATCH 34/36] Modify to use the redis client provider to connect to redis. #216 --- src/Service/RiderTracker.php | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/Service/RiderTracker.php b/src/Service/RiderTracker.php index c34d215d..1e377ec7 100644 --- a/src/Service/RiderTracker.php +++ b/src/Service/RiderTracker.php @@ -8,8 +8,6 @@ use Doctrine\ORM\EntityManagerInterface; use CrEOF\Spatial\PHP\Types\Geometry\Point; -use Predis\Client as PredisClient; - class RiderTracker { const RIDER_PREFIX_KEY = 'rider.location'; @@ -17,13 +15,10 @@ class RiderTracker protected $em; protected $redis; - public function __construct(EntityManagerInterface $em) + public function __construct(EntityManagerInterface $em, RedisClientProvider $redis_client) { $this->em = $em; - - // TODO: make it read redis settings from config - // build a service maybe? - $this->redis = new PredisClient(); + $this->redis = $redis_client->getRedisClient(); } protected function getRiderKey($rider_id) From 44ddd4775b7acaaa8f1baf2fdcfe62c11b465020 Mon Sep 17 00:00:00 2001 From: Kendrick Chan Date: Tue, 28 May 2019 20:59:39 +0800 Subject: [PATCH 35/36] Update rider location cache service for systemd #217 --- utils/rider_location_cache/daemon.py | 129 ------------------ utils/rider_location_cache/daemon.pyc | Bin 4096 -> 0 bytes .../rider_location_cache.py | 96 ++++++------- .../rider_location_daemon.py | 30 ---- utils/rider_location_cache/riderloc.py | 23 ++++ utils/rider_location_cache/riderloc.service | 12 ++ 6 files changed, 73 insertions(+), 217 deletions(-) delete mode 100644 utils/rider_location_cache/daemon.py delete mode 100644 utils/rider_location_cache/daemon.pyc delete mode 100644 utils/rider_location_cache/rider_location_daemon.py create mode 100644 utils/rider_location_cache/riderloc.py create mode 100644 utils/rider_location_cache/riderloc.service diff --git a/utils/rider_location_cache/daemon.py b/utils/rider_location_cache/daemon.py deleted file mode 100644 index f371720d..00000000 --- a/utils/rider_location_cache/daemon.py +++ /dev/null @@ -1,129 +0,0 @@ -#!/usr/bin/env python - -import sys, os, time, atexit -from signal import SIGTERM - -class Daemon: - """ - A generic daemon class. - - Usage: subclass the Daemon class and override the run() method - """ - def __init__(self, pidfile, stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'): - self.stdin = stdin - self.stdout = stdout - self.stderr = stderr - self.pidfile = pidfile - - def daemonize(self): - """ - do the UNIX double-fork magic, see Stevens' "Advanced - Programming in the UNIX Environment" for details (ISBN 0201563177) - http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC16 - """ - try: - pid = os.fork() - if pid > 0: - # exit first parent - sys.exit(0) - except OSError, e: - sys.stderr.write("fork #1 failed: %d (%s)\n" % (e.errno, e.strerror)) - sys.exit(1) - - # decouple from parent environment - os.chdir("/") - os.setsid() - os.umask(0) - - # do second fork - try: - pid = os.fork() - if pid > 0: - # exit from second parent - sys.exit(0) - except OSError, e: - sys.stderr.write("fork #2 failed: %d (%s)\n" % (e.errno, e.strerror)) - sys.exit(1) - - # redirect standard file descriptors - sys.stdout.flush() - sys.stderr.flush() - si = file(self.stdin, 'r') - so = file(self.stdout, 'a+') - se = file(self.stderr, 'a+', 0) - os.dup2(si.fileno(), sys.stdin.fileno()) - os.dup2(so.fileno(), sys.stdout.fileno()) - os.dup2(se.fileno(), sys.stderr.fileno()) - - # write pidfile - atexit.register(self.delpid) - pid = str(os.getpid()) - file(self.pidfile,'w+').write("%s\n" % pid) - - def delpid(self): - os.remove(self.pidfile) - - def start(self): - """ - Start the daemon - """ - # Check for a pidfile to see if the daemon already runs - try: - pf = file(self.pidfile,'r') - pid = int(pf.read().strip()) - pf.close() - except IOError: - pid = None - - if pid: - message = "pidfile %s already exist. Daemon already running?\n" - sys.stderr.write(message % self.pidfile) - sys.exit(1) - - # Start the daemon - self.daemonize() - self.run() - - def stop(self): - """ - Stop the daemon - """ - # Get the pid from the pidfile - try: - pf = file(self.pidfile,'r') - pid = int(pf.read().strip()) - pf.close() - except IOError: - pid = None - - if not pid: - message = "pidfile %s does not exist. Daemon not running?\n" - sys.stderr.write(message % self.pidfile) - return # not an error in a restart - - # Try killing the daemon process - try: - while 1: - os.kill(pid, SIGTERM) - time.sleep(0.1) - except OSError, err: - err = str(err) - if err.find("No such process") > 0: - if os.path.exists(self.pidfile): - os.remove(self.pidfile) - else: - print str(err) - sys.exit(1) - - def restart(self): - """ - Restart the daemon - """ - self.stop() - self.start() - - def run(self): - """ - You should override this method when you subclass Daemon. It will be called after the process has been - daemonized by start() or restart(). - """ diff --git a/utils/rider_location_cache/daemon.pyc b/utils/rider_location_cache/daemon.pyc deleted file mode 100644 index 51504185fb3183608e794c1827f259f9ab078099..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4096 zcmb_fQEwZ^5#HsIl#Z5cS+?Y)DUwAT#Z+yRwu;z+QPhbY!_`BX^w`9)kl=8>Tarf| z@2K0QWCj-ckmSASTMOieBo6`ln~J=q{brV=Tr~}f+9Yo|JG(nOyZg;Id)_}*8-Kp? z_s?Q6`*`?&5080-BEe6JOo+XOEXAIj>nmcfGM7EE=doN7SyhZ`Vy`A-0#!{URq>S& zUkdSfuTJ*5%{pwS|HP-$lo0I_itg^iKRyV4Z>jBrNRNtq;Zqf=dw9$zC^Wob4`^-( z?pG0CIS)LVYp*(+6i&ba(qQH~3riwdVqsY%%PjaJ=r(<_|2c|=|Gw($T$gFA681yI zS!7JB;Wzw`P1M(Sl$ktXow5V1oU^WzitojR|EEzF2Nps#lNX5j? zML5G7JWi8dn&~F>wKU4;tQSx%p!owj`GEA~ge%Mrr1oJ{wvUdE+NCxJ?TJk@)28K> zVOGSEO^ZB?qj;d(Zns+Fsa?jfFii8*hT#fiLkb~%{>F6Vbjma}ulfgQrq_fOVkikG z$5wZ;~SB0&JA(o6LDP%6hqx?Nl#R~QtqRfRnt_Vq8YGQ~(#wI~t;&NH^Dq@pH z%}jXCgcP6BTt0z>TTyAy#FEr!=2QJwm%jg5m!v%9Qtf|q34X7L;i_}QEofFbOUFJu zM-cw9B91*_oo0owOq%Lk1H1#^*eXvP*LX+Q2uH*7WR-T|+)TzOUM-rd&o#pV?)qFa z_H{9OE_3s`7+zqapvVE3N(zM6tcpJe)auPFD`DC(#2HD$C`U8@guZmy^|-%k#sJl2WAz>mtJUq+)*n)g+j zpBQ`t{A*x3^(rVD0!$n{eLJWrj&? zRJIbLp;lb9Cj0G4o<42&qJwa!HL#=Xa`(ago3}79h4;d|f`Yxhd{gx>iB9gQtwc4q z%yuJXj-#UeT)&6Zftwl2 zW6I!KG8ymiP$Cx?r^t>hJ3~=l>V9ghcGeS}frXsc)~Wj1Ld7)1X(6ET+=F`3j%Z%B zN!?%J{`8BJ6j8CGtn>@Lj*58~g{XUSMXppX%5zf5^WLg#$W`yOZdI=1yCL78ueSy{ zCRgcMaQQ`49Hmk4RyalyO(6ofwV*Iwt=khHoWi}gV$i{E*?gca844% zFR1q$RHpBepX4NyE+Um;m$MCc7tuTfO}dzN${JPWqx=$RxXv{E2LaXtn}UmTuq!CI z{F=C!sA`#*7X0ec8Rl?|3^kZ`#>j5^6}C%`INpQ7E~hKA2{#dIT?D1&0CxumRltdx z^3*K9sV$?Ttkh95RY0M!t$Bu?Ymt(3aK&90n4RWX3=U`p-hRd&5-Ee5%rN>9F6r3C zN>&)nakl#*#~F9*6uAy4)p67X=SW(m;xY<0Nf!aydIxYq$+#E1POWtN8EHdTix)oe znX}lYd$7uMBWfP-`HDO%f#phF*5xI+<~1A`2nY)>ybk2OG%z3mEx=%=KMw}LpgX-H zo+@F_P!a@wEFeHB>MZ9ym!}W@gxr4w(5*4(UPYppa15W|Zzh@+|8lr+)CiAEl5%7b5=*n0Ro!tEyKSGsio)Z}E7D9vo3U^Euvp8{hW z&Ch``DYQ`_##3k{%>s#?{@?yepKtFPf=;Kv6*C^FaaqIw2B#R#BF#%^J;7?QMb)>d zxIzWNC)lRqS5%zBBa;n5a6iqm0RQe9Xj9xy2?Hk6dK_>x{BqvdOY?*QK91~wnTlh| z1aF}SBb)=2K^k*yd($sBISaJ_y7EO16Q*_heF2ODI3tA|c%wG;!GY{a7 zO_LsyAGB;yodqiSzgPpcocQ|})Zp*qVxr8Tm}LL<29lcD%ZEA|=v+;y)BNqly}7j1 zu2n~XgnFV?9A&t>sHlgO&DfqnPz@r3cAaCQMbb>vlc{2V@rr}{)y(HmE5323>L&&?VMwYprd``3NX-|*k?m)soe3x_5-9NeJdRTLauChg~u3r@E6 Wa@^t@-*4Q`{FcI!v2{bPRsIF*e>fNb diff --git a/utils/rider_location_cache/rider_location_cache.py b/utils/rider_location_cache/rider_location_cache.py index 504884e3..54a47ddd 100644 --- a/utils/rider_location_cache/rider_location_cache.py +++ b/utils/rider_location_cache/rider_location_cache.py @@ -1,7 +1,5 @@ import paho.mqtt.client as mqtt import ssl -from threading import Thread -from daemon import Daemon import redis import time import signal @@ -11,79 +9,61 @@ import json class RiderLocationCache(object): - def run(self): - client = mqtt.Client() - - client.on_connect = on_connect - # client.on_publish = on_publish - client.on_message = on_message - - #client.tls_set( - # "/etc/letsencrypt/live/resqaws.jankstudio.com/fullchain.pem", cert_reqs=ssl.CERT_NONE, - # tls_version=ssl.PROTOCOL_TLSv1) - #client.tls_set( - # "/root/aws_ssl_keys/fullchain.pem", cert_reqs=ssl.CERT_NONE, - # tls_version=ssl.PROTOCOL_TLSv1) - #client.connect("resqaws.jankstudio.com", 8883, 60) - client.connect("localhost", 1883, 60) - - #t = Thread(target=getRedis, args=(1,)) - - #t.start() - - #signal.signal(signal.SIGINT, sigint_handler) + def run(self, client): + print "running loop..." client.loop_forever() +# TODO: fix this and put these guys back under the class def init_subscriptions(client): - #print "subscribing to wildcard" - client.subscribe('#') + print "subscribing to wildcard #" + client.subscribe('#') def on_connect(client, userdata, flags, rc): - init_subscriptions(client) - #print("Connected with result code "+str(rc)) - # client.subscribe("$SYS/#") + init_subscriptions(client) + #print("Connected with result code "+str(rc)) + # client.subscribe("$SYS/#") def user_data_set(userdata): - conn = redis.StrictRedis(host='localhost', port=6379, db=0) - return conn + conn = redis.StrictRedis(host='localhost', port=6379, db=0) + return conn def on_publish(client, userdata, mid): - pass + pass def on_message(client, userdata, message): - redis_conn = user_data_set(userdata) - #print("message topic=", message.topic[0:10]) + redis_conn = user_data_set(userdata) + #print("message topic=", message.topic[0:10]) - if message.topic[0:10] != 'motorider_': - return - #print repr(message) + if message.topic[0:10] != 'motorider_': + return + #print repr(message) - # check if json decodable - res = json.loads(message.payload) - #print res + # check if json decodable + res = json.loads(message.payload) + #print res - # get rider session id - sess_id = message.topic[10:] + # get rider session id + sess_id = message.topic[10:] - # check if it has event - if 'event' not in res: - return + # check if it has event + if 'event' not in res: + return - # check if event is driver_location - if res['event'] != 'driver_location': - return + # check if event is driver_location + if res['event'] != 'driver_location': + return - # save the longitude and latitude - # get the rider id from sess_id - rider_key = "rider.location.%s" % sess_id - rider_long = str(res['longitude']) - rider_lat = str(res['latitude']) + # save the longitude and latitude + # get the rider id from sess_id + rider_key = "rider.location.%s" % sess_id + rider_long = str(res['longitude']) + rider_lat = str(res['latitude']) - # set the location - redis_conn.hmset(rider_key, {'longitude': rider_long, 'latitude': rider_lat}) + # set the location + redis_conn.hmset(rider_key, {'longitude': rider_long, 'latitude': rider_lat}) - # update our redis key - key = 'location_%s' % sess_id - #print "setting %s" % key - redis_conn.setex(key, 1600, message.payload) + # update our redis key + key = 'location_%s' % sess_id + #print "setting %s" % key + redis_conn.setex(key, 1600, message.payload) diff --git a/utils/rider_location_cache/rider_location_daemon.py b/utils/rider_location_cache/rider_location_daemon.py deleted file mode 100644 index f56de6a5..00000000 --- a/utils/rider_location_cache/rider_location_daemon.py +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env python - -import sys -import time -from daemon import Daemon -import rider_location_cache - -class RiderLocationDaemon(Daemon): - def run(self): - rider_location = rider_location_cache.RiderLocationCache() - rider_location.run() - -if __name__ == "__main__": - daemon = RiderLocationDaemon('/tmp/rider_location_daemon.pid') - if len(sys.argv) == 2: - if 'start' == sys.argv[1]: - daemon.start() - elif 'stop' == sys.argv[1]: - daemon.stop() - elif 'restart' == sys.argv[1]: - daemon.restart() - elif 'foreground' == sys.argv[1]: - daemon.run() - else: - print "Unknown command" - sys.exit(2) - sys.exit(0) - else: - print "usage: %s start|stop|restart" % sys.argv[0] - sys.exit(2) diff --git a/utils/rider_location_cache/riderloc.py b/utils/rider_location_cache/riderloc.py new file mode 100644 index 00000000..26a1a92f --- /dev/null +++ b/utils/rider_location_cache/riderloc.py @@ -0,0 +1,23 @@ +import paho.mqtt.client as mqtt +import rider_location_cache as rlc +import ssl +import logging + + +client = mqtt.Client() +client.on_connect = rlc.on_connect +# client.on_publish = on_publish +client.on_message = rlc.on_message + +#client.tls_set( +# "/etc/letsencrypt/live/resqaws.jankstudio.com/fullchain.pem", cert_reqs=ssl.CERT_NONE, +# tls_version=ssl.PROTOCOL_TLSv1) +client.tls_set( + "/root/aws_ssl_keys/fullchain.pem", cert_reqs=ssl.CERT_NONE, + tls_version=ssl.PROTOCOL_TLSv1) +#client.connect("resqaws.jankstudio.com", 8883, 60) +client.connect("localhost", 8883, 60) + + +rider_location = rlc.RiderLocationCache() +rider_location.run(client) diff --git a/utils/rider_location_cache/riderloc.service b/utils/rider_location_cache/riderloc.service new file mode 100644 index 00000000..f3d43264 --- /dev/null +++ b/utils/rider_location_cache/riderloc.service @@ -0,0 +1,12 @@ +[Unit] +Description=Rider Location Cache Service +After=mosquitto.service redis.service + +[Service] +Type=simple +ExecStart=/usr/bin/python /root/www/resq/utils/rider_location_cache/riderloc.py +StandardInput=tty-force +Restart=always + +[Install] +WantedBy=multi-user.target From d9d1b3d9f50d3d5a1a4850ac82c0abfbcdf750f7 Mon Sep 17 00:00:00 2001 From: Kendrick Chan Date: Wed, 29 May 2019 23:31:34 +0800 Subject: [PATCH 36/36] Add service files for systemd #218 --- utils/apns_sender/apns_sender.service | 12 ++++++++++++ utils/mqtt_sender/mqtt_sender.service | 12 ++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 utils/apns_sender/apns_sender.service create mode 100644 utils/mqtt_sender/mqtt_sender.service diff --git a/utils/apns_sender/apns_sender.service b/utils/apns_sender/apns_sender.service new file mode 100644 index 00000000..807c33f7 --- /dev/null +++ b/utils/apns_sender/apns_sender.service @@ -0,0 +1,12 @@ +[Unit] +Description=Apple Push Notification Sender Service +After=mosquitto.service redis.service + +[Service] +Type=simple +ExecStart=/usr/bin/python /root/www/resq/utils/apns_sender/new_sender.py +StandardInput=tty-force +Restart=always + +[Install] +WantedBy=multi-user.target diff --git a/utils/mqtt_sender/mqtt_sender.service b/utils/mqtt_sender/mqtt_sender.service new file mode 100644 index 00000000..d747522d --- /dev/null +++ b/utils/mqtt_sender/mqtt_sender.service @@ -0,0 +1,12 @@ +[Unit] +Description=MQTT Sender Service +After=mosquitto.service redis.service + +[Service] +Type=simple +ExecStart=/usr/bin/python /root/www/resq/utils/mqtt_sender/mqtt_sender.py +StandardInput=tty-force +Restart=always + +[Install] +WantedBy=multi-user.target