diff --git a/app/Http/Controllers/BotController.php b/app/Http/Controllers/BotController.php
index 1bd9be85bc55..c6663d0077cf 100644
--- a/app/Http/Controllers/BotController.php
+++ b/app/Http/Controllers/BotController.php
@@ -6,6 +6,7 @@ use App\Libraries\CurlUtils;
use App\Libraries\Skype\SkypeResponse;
use App\Models\SecurityCode;
use App\Models\User;
+use App\Models\Client;
use App\Ninja\Intents\BaseIntent;
use App\Ninja\Mailers\UserMailer;
use Auth;
@@ -100,9 +101,28 @@ class BotController extends Controller
public function handleCommand()
{
$data = $this->parseMessage(request()->command);
- //dd($data);
- $intent = BaseIntent::createIntent(BOT_PLATFORM_WEB_APP, false, $data);
- return $intent->process();
+
+ // If they're viewing a client set it as the current state
+ $state = false;
+ $url = url()->previous();
+ preg_match('/clients\/(\d*)/', $url, $matches);
+ if (count($matches) >= 2) {
+ if ($client = Client::scope($matches[1])->first()) {
+ $state = BaseIntent::blankState();
+ $state->current->client = $client;
+ }
+ }
+
+ try {
+ $intent = BaseIntent::createIntent(BOT_PLATFORM_WEB_APP, $state, $data);
+ return $intent->process();
+ } catch (Exception $exception) {
+ $message = $exception->getMessage();
+ if (env('APP_DEBUG')) {
+ $message .= '
' . request()->command . ' => ' . json_encode($data);
+ }
+ return redirect()->back()->withWarning($message);
+ }
}
private function authenticate($input)
diff --git a/app/Models/InvoiceStatus.php b/app/Models/InvoiceStatus.php
index 4a4dddb5eecb..302b79ca9fc3 100644
--- a/app/Models/InvoiceStatus.php
+++ b/app/Models/InvoiceStatus.php
@@ -13,4 +13,26 @@ class InvoiceStatus extends Eloquent
* @var bool
*/
public $timestamps = false;
+
+ public static function getIdFromAlias($status)
+ {
+ switch ($status) {
+ case 'draft':
+ return INVOICE_STATUS_DRAFT;
+ case 'sent':
+ return INVOICE_STATUS_SENT;
+ case 'viewed':
+ return INVOICE_STATUS_VIEWED;
+ case 'approved':
+ return INVOICE_STATUS_APPROVED;
+ case 'partial':
+ return INVOICE_STATUS_PARTIAL;
+ case 'overdue':
+ return INVOICE_STATUS_OVERDUE;
+ case 'unpaid':
+ return INVOICE_STATUS_UNPAID;
+ default:
+ return false;
+ }
+ }
}
diff --git a/app/Ninja/Intents/BaseIntent.php b/app/Ninja/Intents/BaseIntent.php
index 4c170bba7311..97efae3dae5c 100644
--- a/app/Ninja/Intents/BaseIntent.php
+++ b/app/Ninja/Intents/BaseIntent.php
@@ -16,14 +16,7 @@ class BaseIntent
{
//if (true) {
if (! $state || is_string($state)) {
- $state = new stdClass();
- foreach (['current', 'previous'] as $reference) {
- $state->$reference = new stdClass();
- $state->$reference->entityType = false;
- foreach ([ENTITY_INVOICE, ENTITY_CLIENT, ENTITY_INVOICE_ITEM] as $entityType) {
- $state->$reference->$entityType = [];
- }
- }
+ $state = static::blankState();
}
$this->state = $state;
@@ -32,6 +25,20 @@ class BaseIntent
//var_dump($state);
}
+ public static function blankState()
+ {
+ $state = new stdClass();
+ foreach (['current', 'previous'] as $reference) {
+ $state->$reference = new stdClass();
+ $state->$reference->entityType = false;
+ foreach ([ENTITY_INVOICE, ENTITY_CLIENT, ENTITY_INVOICE_ITEM] as $entityType) {
+ $state->$reference->$entityType = [];
+ }
+ }
+
+ return $state;
+ }
+
public static function createIntent($platform, $state, $data)
{
if (! count($data->intents)) {
@@ -67,7 +74,7 @@ class BaseIntent
//echo "Intent: $intent
"; if (! class_exists($className)) { - throw new Exception($intent . ': ' . trans('texts.intent_not_supported')); + throw new Exception($intent . '... ' . trans('texts.intent_not_supported')); } return new $className($state, $data); @@ -84,6 +91,30 @@ class BaseIntent return false; } + protected function getFields($field) + { + $data = []; + + foreach ($this->data->entities as $entity) { + if ($entity->type === $field) { + $data[] = $entity->entity; + } + } + + return $data; + } + + protected function loadStates($entityType) + { + $states = array_filter($this->getFields('State'), function($state) { + return in_array($state, [STATUS_ACTIVE, STATUS_ARCHIVED, STATUS_DELETED]); + }); + + if (count($states)) { + session(['entity_state_filter:' . $entityType => join(',', $states)]); + } + } + protected function hasField($field, $value = false) { $fieldValue = $this->getField($field); @@ -158,10 +189,15 @@ class BaseIntent foreach ($this->data->entities as $param) { if ($param->type == 'Name') { + $param->type = rtrim($param->type, ' \' s'); $client = $clientRepo->findPhonetically($param->entity); } } + if (! $client) { + $client = $this->state->current->client; + } + return $client; } diff --git a/app/Ninja/Intents/InvoiceIntent.php b/app/Ninja/Intents/InvoiceIntent.php index 9421e32e0a4e..ccf6ecb4d8a8 100644 --- a/app/Ninja/Intents/InvoiceIntent.php +++ b/app/Ninja/Intents/InvoiceIntent.php @@ -3,6 +3,7 @@ namespace App\Ninja\Intents; use App\Models\Invoice; +use App\Models\InvoiceStatus; use Auth; use Exception; @@ -104,4 +105,20 @@ class InvoiceIntent extends BaseIntent return $invoiceItems; } + + protected function loadStatuses($entityType) + { + $statusIds = []; + $statuses = $this->getFields('State'); + + foreach ($statuses as $status) { + if ($statusId = InvoiceStatus::getIdFromAlias($status)) { + $statusIds[] = $statusId; + } + } + + if (count($statusIds)) { + session(['entity_status_filter:' . $entityType => join(',', $statusIds)]); + } + } } diff --git a/app/Ninja/Intents/WebApp/CreateCreditIntent.php b/app/Ninja/Intents/WebApp/CreateCreditIntent.php index 147ed99d4491..dc3bec7c0c0c 100644 --- a/app/Ninja/Intents/WebApp/CreateCreditIntent.php +++ b/app/Ninja/Intents/WebApp/CreateCreditIntent.php @@ -13,7 +13,7 @@ class CreateCreditIntent extends BaseIntent //$invoiceItems = $this->requestInvoiceItems(); - $url = '/credits/create/' . $clientPublicId . '?'; + $url = '/credits/create/' . $clientPublicId; //$url .= $this->requestFieldsAsString(Invoice::$requestFields); return redirect($url); diff --git a/app/Ninja/Intents/WebApp/CreateInvoiceIntent.php b/app/Ninja/Intents/WebApp/CreateInvoiceIntent.php index 24982099d251..395b5a78ca08 100644 --- a/app/Ninja/Intents/WebApp/CreateInvoiceIntent.php +++ b/app/Ninja/Intents/WebApp/CreateInvoiceIntent.php @@ -19,6 +19,9 @@ class CreateInvoiceIntent extends InvoiceIntent $url = '/invoices/create/' . $clientPublicId . '?'; $url .= $this->requestFieldsAsString(Invoice::$requestFields); + $url = rtrim($url, '?'); + $url = rtrim($url, '&'); + return redirect($url); } } diff --git a/app/Ninja/Intents/WebApp/CreateQuoteIntent.php b/app/Ninja/Intents/WebApp/CreateQuoteIntent.php index e3a46b0707d5..cd93d4a06d61 100644 --- a/app/Ninja/Intents/WebApp/CreateQuoteIntent.php +++ b/app/Ninja/Intents/WebApp/CreateQuoteIntent.php @@ -17,6 +17,9 @@ class CreateQuoteIntent extends BaseIntent $url = '/quotes/create/' . $clientPublicId . '?'; $url .= $this->requestFieldsAsString(Invoice::$requestFields); + $url = rtrim($url, '?'); + $url = rtrim($url, '&'); + return redirect($url); } } diff --git a/app/Ninja/Intents/WebApp/CreateRecurringInvoiceIntent.php b/app/Ninja/Intents/WebApp/CreateRecurringInvoiceIntent.php index bbf04871696c..db09f8ff4778 100644 --- a/app/Ninja/Intents/WebApp/CreateRecurringInvoiceIntent.php +++ b/app/Ninja/Intents/WebApp/CreateRecurringInvoiceIntent.php @@ -17,6 +17,9 @@ class CreateRecurringInvoiceIntent extends BaseIntent $url = '/recurring_invoices/create/' . $clientPublicId . '?'; $url .= $this->requestFieldsAsString(Invoice::$requestFields); + $url = rtrim($url, '?'); + $url = rtrim($url, '&'); + return redirect($url); } } diff --git a/app/Ninja/Intents/WebApp/ListClientIntent.php b/app/Ninja/Intents/WebApp/ListClientIntent.php index d10e42bf2015..6cb087d2af59 100644 --- a/app/Ninja/Intents/WebApp/ListClientIntent.php +++ b/app/Ninja/Intents/WebApp/ListClientIntent.php @@ -8,6 +8,8 @@ class ListClientIntent extends BaseIntent { public function process() { + $this->loadStates(ENTITY_CLIENT); + return redirect('/clients'); } } diff --git a/app/Ninja/Intents/WebApp/ListCreditIntent.php b/app/Ninja/Intents/WebApp/ListCreditIntent.php index b4f9412cf3c2..dadc36080189 100644 --- a/app/Ninja/Intents/WebApp/ListCreditIntent.php +++ b/app/Ninja/Intents/WebApp/ListCreditIntent.php @@ -8,6 +8,8 @@ class ListCreditIntent extends BaseIntent { public function process() { + $this->loadStates(ENTITY_CREDIT); + if ($client = $this->requestClient()) { $url = $client->present()->url . '#credits'; } else { diff --git a/app/Ninja/Intents/WebApp/ListExpenseIntent.php b/app/Ninja/Intents/WebApp/ListExpenseIntent.php index 03751a97e58d..5b6e6f7dff3c 100644 --- a/app/Ninja/Intents/WebApp/ListExpenseIntent.php +++ b/app/Ninja/Intents/WebApp/ListExpenseIntent.php @@ -8,6 +8,8 @@ class ListExpenseIntent extends BaseIntent { public function process() { + $this->loadStates(ENTITY_EXPENSE); + return redirect('/expenses'); } } diff --git a/app/Ninja/Intents/WebApp/ListInvoiceIntent.php b/app/Ninja/Intents/WebApp/ListInvoiceIntent.php index 477258f94f66..339493bb00f9 100644 --- a/app/Ninja/Intents/WebApp/ListInvoiceIntent.php +++ b/app/Ninja/Intents/WebApp/ListInvoiceIntent.php @@ -8,6 +8,9 @@ class ListInvoiceIntent extends InvoiceIntent { public function process() { + $this->loadStates(ENTITY_INVOICE); + $this->loadStatuses(ENTITY_INVOICE); + if ($client = $this->requestClient()) { $url = $client->present()->url . '#invoices'; } else { diff --git a/app/Ninja/Intents/WebApp/ListPaymentIntent.php b/app/Ninja/Intents/WebApp/ListPaymentIntent.php index 40f2f3688e88..a545bd8559b3 100644 --- a/app/Ninja/Intents/WebApp/ListPaymentIntent.php +++ b/app/Ninja/Intents/WebApp/ListPaymentIntent.php @@ -8,6 +8,8 @@ class ListPaymentIntent extends BaseIntent { public function process() { + $this->loadStates(ENTITY_PAYMENT); + if ($client = $this->requestClient()) { $url = $client->present()->url . '#payments'; } else { diff --git a/app/Ninja/Intents/WebApp/ListProductIntent.php b/app/Ninja/Intents/WebApp/ListProductIntent.php index 613601411228..70bfac9c6703 100644 --- a/app/Ninja/Intents/WebApp/ListProductIntent.php +++ b/app/Ninja/Intents/WebApp/ListProductIntent.php @@ -8,6 +8,8 @@ class ListProductIntent extends BaseIntent { public function process() { + $this->loadStates(ENTITY_PRODUCT); + return redirect('/products'); } } diff --git a/app/Ninja/Intents/WebApp/ListQuoteIntent.php b/app/Ninja/Intents/WebApp/ListQuoteIntent.php index 76bae43d0575..1867d34e0dfe 100644 --- a/app/Ninja/Intents/WebApp/ListQuoteIntent.php +++ b/app/Ninja/Intents/WebApp/ListQuoteIntent.php @@ -2,12 +2,15 @@ namespace App\Ninja\Intents\WebApp; -use App\Ninja\Intents\BaseIntent; +use App\Ninja\Intents\InvoiceIntent; -class ListQuotesIntent extends BaseIntent +class ListQuoteIntent extends InvoiceIntent { public function process() { + $this->loadStates(ENTITY_QUOTE); + $this->loadStatuses(ENTITY_QUOTE); + if ($client = $this->requestClient()) { $url = $client->present()->url . '#quotes'; } else { diff --git a/app/Ninja/Intents/WebApp/ListRecurringInvoiceIntent.php b/app/Ninja/Intents/WebApp/ListRecurringInvoiceIntent.php index d0233c6db7fb..d8823dd7bbcb 100644 --- a/app/Ninja/Intents/WebApp/ListRecurringInvoiceIntent.php +++ b/app/Ninja/Intents/WebApp/ListRecurringInvoiceIntent.php @@ -8,6 +8,8 @@ class ListRecurringInvoiceIntent extends BaseIntent { public function process() { + $this->loadStates(ENTITY_RECURRING_INVOICE); + if ($client = $this->requestClient()) { $url = $client->present()->url . '#recurring_invoices'; } else { diff --git a/app/Ninja/Intents/WebApp/ListTaskIntent.php b/app/Ninja/Intents/WebApp/ListTaskIntent.php index f8c68626cd58..05574761c836 100644 --- a/app/Ninja/Intents/WebApp/ListTaskIntent.php +++ b/app/Ninja/Intents/WebApp/ListTaskIntent.php @@ -8,6 +8,8 @@ class ListTaskIntent extends BaseIntent { public function process() { + $this->loadStates(ENTITY_TASK); + if ($client = $this->requestClient()) { $url = $client->present()->url . '#tasks'; } else { diff --git a/app/Ninja/Intents/WebApp/ListVendorIntent.php b/app/Ninja/Intents/WebApp/ListVendorIntent.php index 2f3f819dec14..0b98d5cbdd3c 100644 --- a/app/Ninja/Intents/WebApp/ListVendorIntent.php +++ b/app/Ninja/Intents/WebApp/ListVendorIntent.php @@ -8,6 +8,8 @@ class ListVendorIntent extends BaseIntent { public function process() { + $this->loadStates(ENTITY_VENDOR); + return redirect('/vendors'); } } diff --git a/resources/views/partials/speech_recognition.blade.php b/resources/views/partials/speech_recognition.blade.php index bc3ffeaca483..d6519905135f 100644 --- a/resources/views/partials/speech_recognition.blade.php +++ b/resources/views/partials/speech_recognition.blade.php @@ -173,9 +173,10 @@ function onMicrophoneClick() { //$('#search').val("show me all of edgar's credits"); - $('#search').val("show me edgar's credits"); - $('#search-form').submit(); - return; + //$('#search').val("new invoice for joe, set the due date to today and the discount to ten percent"); + //$('#search').val("list joe's active and approved quotes"); + //$('#search-form').submit(); + //return; $('.fa-microphone').hide(); $('#search').val("{{ trans('texts.listening') }}");