diff --git a/.env.dist b/.env.dist index 30f9a925..831c5f98 100644 --- a/.env.dist +++ b/.env.dist @@ -57,3 +57,9 @@ COUNTRY_CODE=+insert_country_code_here # dashboard DASHBOARD_ENABLE=set_to_true_or_false + +# auth token for Inventory API +INVENTORY_API_URL=insert_api_url_here +INVENTORY_API_OCP=insert_ocp_text_here +INVENTORY_API_AUTH_TOKEN_PREFIX=Bearer +INVENTORY_API_AUTH_TOKEN=insert_auth_token_here diff --git a/config/resq.services.yaml b/config/resq.services.yaml index f38949c5..0c927f98 100644 --- a/config/resq.services.yaml +++ b/config/resq.services.yaml @@ -230,5 +230,7 @@ services: # inventory manager App\Service\InventoryManager: arguments: - $em: "@doctrine.orm.entity_manager" - $map_tools: "@App\\Service\\MapTools" + $api_url: "%env(INVENTORY_API_URL)%" + $api_ocp_key: "%env(INVENTORY_API_OCP)%" + $api_auth_prefix: "%env(INVENTORY_API_AUTH_TOKEN_PREFIX)%" + $api_auth_token: "%env(INVENTORY_API_AUTH_TOKEN)%" diff --git a/config/services.yaml b/config/services.yaml index f38949c5..d3d6bd5a 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -230,5 +230,7 @@ services: # inventory manager App\Service\InventoryManager: arguments: - $em: "@doctrine.orm.entity_manager" - $map_tools: "@App\\Service\\MapTools" + $api_url: "%env(INVENTORY_API_URL)%" + $api_ocp_key: "%env(INVENTORY_API_OCP)%" + $api_auth_prefix: "%env(INVENTORY_API_AUTH_TOKEN_PREFIX)%" + $api_auth_token: "%env(INVENTORY_API_AUTH_TOKEN)%" diff --git a/src/Controller/JobOrderController.php b/src/Controller/JobOrderController.php index 97b49565..26c9cb88 100644 --- a/src/Controller/JobOrderController.php +++ b/src/Controller/JobOrderController.php @@ -1079,6 +1079,7 @@ class JobOrderController extends Controller } public function autoAssignSubmit(Request $req, JobOrderHandlerInterface $jo_handler, + EntityManagerInterface $em, MapTools $map_tools, InventoryManager $im) { $this->denyAccessUnlessGranted('jo_autoassign.test', null, 'No access.'); @@ -1104,7 +1105,7 @@ class JobOrderController extends Controller if (($jo->getServiceType() == ServiceType::BATTERY_REPLACEMENT_NEW) || ($jo->getServicetype() == ServiceType::BATTERY_REPLACEMENT_WARRANTY)) - $im->autoAssignHubAndRider($jo); + $this->autoAssignHubAndRider($jo, $em, $map_tools, $im); // return successful response return $this->json([ @@ -1112,4 +1113,126 @@ class JobOrderController extends Controller ]); } + + protected function autoAssignHubAndRider($jo, EntityManagerInterface $em, + MapTools $map_tools, InventoryManager $im) + { + // get the nearest 10 hubs + // TODO: move this snippet to a function + $hubs = $map_tools->getClosestHubs($jo->getCoordinates(), 10, date("H:i:s")); + + $nearest_hubs = []; + $nearest_hubs_with_distance = []; + + foreach ($hubs as $hub) + { + $nearest_hubs_with_distance[] = $hub; + // TODO: uncomment this when we have branch codes in data + // and when they have real codes and not test ones + //$nearest_branch_codes[] = $hub['hub']->getBranchCode(); + $nearest_branch_codes[] = $hub['hub']; + $nearest_branch_codes = ['WestAve','jay_franchise']; + } + + // get battery sku + $invoice = $jo->getInvoice(); + if ($invoice != null) + { + $items = $invoice->getItems(); + $skus = []; + foreach ($items as $item) + { + // TODO: uncomment this when they have real codes and not test ones + //$skus[] = $item->getBattery()->getSAPCode(); + $skus[] = 'WMGD31EL-CPNM0-L'; + } + + // api call to check inventory + // pass the list of branch codes of nearest hubs and the skus + // go through returned list of branch codes + $hubs_with_inventory = $im->getBranchInventory($nearest_branch_codes, $skus); + // TODO: check for empty result for now. + if (!empty($hubs_with_inventory)) + { + $nearest = []; + $flag_hub_found = false; + foreach ($hubs_with_inventory as $hub_with_inventory) + { + error_log($hub_with_inventory['BranchCode']); + // find hub according to branch code + $found_hub = $em->getRepository(Hub::class)->findOneBy(['branch_code' => $hub_with_inventory['BranchCode']]); + if ($found_hub != null) + { + // check rider availability + if (count($found_hub->getAvailableRiders()) > 0) + { + // check against nearest hubs with distance + foreach ($nearest_hubs_with_distance as $nhd) + { + // get distance of hub from location, compare with $nearest. if less, replace nearest + if ($found_hub->getID() == $nhd['hub']->getID()) + { + if (empty($nearest)) + { + $nearest = $nhd; + $flag_hub_found = true; + } + else + { + if ($nhd['distance'] < $nearest['distance']) + { + $nearest = $nhd; + $flag_hub_found = true; + } + } + } + } + } + } + } + + if ($flag_hub_found) + { + $jo->setHub($nearest['hub']); + + $hub_riders = $nearest['hub']->getAvailableRiders(); + $rider = null; + if (count($hub_riders) > 1) + { + // TODO: this will no longer be necessary when the contents + // of randomizeRider changes + $available_riders = []; + foreach ($hub_riders as $rider) + { + $available_riders[] = $rider; + } + + $rider = $this->randomizeRider($available_riders); + } + else + $rider = $hub_riders[0]; + + $jo->setRider($rider); + + $jo->setStatus(JOStatus::ASSIGNED); + + $em->persist($jo); + $em->flush(); + } + } + } + } + + protected function randomizeRider($riders) + { + // TODO: get redis to track the sales per rider per day + // check the time they came in + // for now, randomize the rider + $selected_index = array_rand($riders); + + $selected_rider = $riders[$selected_index]; + + return $selected_rider; + } + } diff --git a/src/Service/InventoryManager.php b/src/Service/InventoryManager.php index 6620e9ab..7a3250c5 100644 --- a/src/Service/InventoryManager.php +++ b/src/Service/InventoryManager.php @@ -2,121 +2,72 @@ namespace App\Service; -use Doctrine\ORM\EntityManagerInterface; - -use App\Entity\JobOrder; -use App\Entity\Hub; - -use App\Ramcar\JOStatus; - class InventoryManager { - protected $em; - protected $map_tools; + protected $api_url; + protected $api_ocp_key; + protected $api_auth_prefix; + protected $api_auth_token; - public function __construct(EntityManagerInterface $em, MapTools $map_tools) + public function __construct($api_url, $api_ocp_key, $api_auth_prefix, $api_auth_token) { - $this->em = $em; - $this->map_tools = $map_tools; + $this->api_url = $api_url; + $this->api_ocp_key = $api_ocp_key; + $this->api_auth_prefix = $api_auth_prefix; + $this->api_auth_token = $api_auth_token; } - public function autoAssignHubAndRider(JobOrder $jo) + public function getBranchInventory($nearest_branch_codes, $skus) { - // get the nearest 10 hubs - // TODO: move this snippet to a function - $hubs = $this->map_tools->getClosestHubs($jo->getCoordinates(), 10, date("H:i:s")); + // api call to check inventory + // pass the list of branch codes and the skus + $data = [ + "BranchCodes" => $nearest_branch_codes, + "Skus" => $skus, + ]; - $nearest_hubs = []; - $nearest_hubs_with_distance = []; + $json_data = json_encode($data); + error_log('JSON ' . $json_data); - foreach ($hubs as $hub) - { - $nearest_hubs_with_distance[] = $hub; - // TODO: uncomment this when we have branch codes in data - //$nearest_hubs[] = $hub['hub']->getBranchCode(); - $nearest_hubs[] = $hub['hub']; - } + // initializes a new cURL session + $curl = curl_init($this->api_url); - // get battery sku - $invoice = $jo->getInvoice(); - if ($invoice != null) - { - $items = $invoice->getItems(); - $sku = ''; - foreach ($items as $item) - { - $sku = $item->getBattery()->getSAPCode(); - } + // Set the CURLOPT_RETURNTRANSFER option to true + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); - // api call to check inventory - // pass the list of nearest hubs and the sku - // go through returned list of hubs for available riders - // for now, use all hubs - $hubs_with_inventory = $this->em->getRepository(Hub::class)->findAll(); - $nearest = []; - foreach ($hubs_with_inventory as $hub_with_inventory) - { - // check rider availability - if (count($hub_with_inventory->getAvailableRiders()) > 0) - { - // check against nearest hubs with distance - foreach ($nearest_hubs_with_distance as $nhd) - { - // get distance of hub from location, compare with $nearest. if less, replace nearest - if ($hub_with_inventory->getID() == $nhd['hub']->getID()) - { - if (empty($nearest)) - { - $nearest = $nhd; - } - else - { - if ($nhd['distance'] < $nearest['distance']) - $nearest = $nhd; - } - } - } - } - } + // Set the CURLOPT_POST option to true for POST request + curl_setopt($curl, CURLOPT_POST, true); - $jo->setHub($nearest['hub']); + // Set the request data as JSON using json_encode function + curl_setopt($curl, CURLOPT_POSTFIELDS, $json_data); - $hub_riders = $nearest['hub']->getAvailableRiders(); - $rider = null; - if (count($hub_riders) > 1) - { - // this will no longer be necessary when the contents - // of randomizeRider changes - $available_riders = []; - foreach ($hub_riders as $rider) - { - $available_riders[] = $rider; - } + // set timeout + curl_setopt($curl, CURLOPT_TIMEOUT, 300); - $rider = $this->randomizeRider($available_riders); - } - else - $rider = $hub_riders[0]; + $authorization = $this->api_auth_prefix . ' ' . $this->api_auth_token; + $ocp = $this->api_ocp_key; - $jo->setRider($rider); + curl_setopt($curl, CURLOPT_HTTPHEADER, [ + 'Authorization: ' . $authorization, + 'Content-Type: application/json', + 'Ocp-Apim-Subscription-Key: ' . $ocp, + ]); - $jo->setStatus(JOStatus::ASSIGNED); + $response = curl_exec($curl); - $this->em->persist($jo); - $this->em->flush(); + // close cURL session + curl_close($curl); - } + // response is array of these + // { + // "BranchCode": "TestBranch1", + // "BranchName": "Test Branch", + // "SapCode": "WMGD31EL-CPNM0-L", + // "Quantity": 4 + // }, + $results = json_decode($response, true); + + return $results; } - protected function randomizeRider($riders) - { - // TODO: get redis to track the sales per rider per day - // check the time they came in - // for now, randomize the rider - $selected_index = array_rand($riders); - - $selected_rider = $riders[$selected_index]; - - return $selected_rider; - } }