From d374843e50dce213f0593d3197d068948f7bbaee Mon Sep 17 00:00:00 2001 From: Hillel Coren Date: Tue, 9 Aug 2016 23:06:24 +0300 Subject: [PATCH] Working on the bot --- app/Http/Controllers/BotController.php | 13 +- app/Ninja/Intents/BaseIntent.php | 160 ++++++++++++------ app/Ninja/Intents/CreateInvoiceIntent.php | 19 +-- .../Intents/CreateInvoiceItemsIntent.php | 24 ++- app/Ninja/Intents/DownloadInvoiceIntent.php | 20 +++ app/Ninja/Intents/EmailInvoiceIntent.php | 27 +++ app/Ninja/Intents/InvoiceIntent.php | 68 ++++++++ app/Ninja/Intents/UpdateInvoiceIntent.php | 21 +++ resources/lang/en/texts.php | 1 + resources/views/bots/skype/message.blade.php | 2 +- 10 files changed, 271 insertions(+), 84 deletions(-) create mode 100644 app/Ninja/Intents/DownloadInvoiceIntent.php create mode 100644 app/Ninja/Intents/EmailInvoiceIntent.php create mode 100644 app/Ninja/Intents/InvoiceIntent.php create mode 100644 app/Ninja/Intents/UpdateInvoiceIntent.php diff --git a/app/Http/Controllers/BotController.php b/app/Http/Controllers/BotController.php index 87ddab7baa79..b44c0065d1cf 100644 --- a/app/Http/Controllers/BotController.php +++ b/app/Http/Controllers/BotController.php @@ -11,17 +11,19 @@ class BotController extends Controller public function handleMessage($platform) { $to = '29:1C-OsU7OWBEDOYJhQUsDkYHmycOwOq9QOg5FVTwRX9ts'; - //$message = 'create a new invoice for Jenifer Altenwerth '; - $message = 'add 2 items'; + //$message = 'create a new invoice for Mr. Gino '; + $message = 'add 1 item'; + //$message = 'set the cost to 20'; + //$message = 'send the invoice'; + //$message = view('bots.skype.message', ['message' => $message])->render(); //return $this->sendResponse($to, $message); + echo "Message: $message

"; $token = $this->authenticate(); //try { $state = $this->loadState($token); - var_dump($state); - $data = $this->parseMessage($message); $intent = BaseIntent::createIntent($state, $data); @@ -78,8 +80,6 @@ class BotController extends Controller $data = file_get_contents($url); $data = json_decode($data); - var_dump($data); - return $data; } @@ -111,6 +111,7 @@ class BotController extends Controller $response = CurlUtils::post($url, $message, $headers); + var_dump($message); var_dump($response); } diff --git a/app/Ninja/Intents/BaseIntent.php b/app/Ninja/Intents/BaseIntent.php index 222cb1d3d9a6..66c60b69d6a3 100644 --- a/app/Ninja/Intents/BaseIntent.php +++ b/app/Ninja/Intents/BaseIntent.php @@ -11,8 +11,22 @@ class BaseIntent public function __construct($state, $data) { - $this->state = $state ?: new stdClass; + //if (true) { + if ( ! $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 = []; + } + } + } + + $this->state = $state; $this->data = $data; + + var_dump($state); } public static function createIntent($state, $data) @@ -21,10 +35,11 @@ class BaseIntent throw new Exception(trans('texts.intent_not_found')); } - $intent = $data->intents[0]; - $intentType = $intent->intent; + $intent = $data->intents[0]->intent; + $entityType = false; - $className = "App\\Ninja\\Intents\\{$intentType}Intent"; + echo "Intent: $intent

"; + $className = "App\\Ninja\\Intents\\{$intent}Intent"; if ( ! class_exists($className)) { throw new Exception(trans('texts.intent_not_supported')); @@ -33,53 +48,64 @@ class BaseIntent return (new $className($state, $data)); } + public function process() { // do nothing by default } - public function setState($entityType, $entities) + public function setEntities($entityType, $entities) + { + if ( ! is_array($entities)) { + $entities = [$entities]; + } + + $state = $this->state; + + $state->previous->$entityType = $state->current->$entityType; + $state->current->$entityType = $entities; + } + + public function setEntityType($entityType) { $state = $this->state; - if (isset($state->current->$entityType)) { - if ( ! isset($state->previous)) { - $state->previous = new stdClass; - } - - $state->previous->$entityType = $state->current->$entityType; + if ($state->current->entityType == $entityType) { + return; } - if ( ! isset($state->current)) { - $state->current = new stdClass; - } - - if ($entities) { - $state->current->$entityType = $entities; - } + $state->previous->entityType = $state->current->entityType; + $state->current->entityType = $entityType; } + public function entities($entityType) + { + return $this->state->current->$entityType; + } + + public function entity($entityType) + { + $entities = $this->state->current->$entityType; + + return count($entities) ? $entities[0] : false; + } + + public function previousEntities($entityType) + { + return $this->state->previous->$entityType; + } + + public function entityType() + { + return $this->state->current->entityType; + } + + public function getState() { return $this->state; } - public function getCurrentState($entityType = false, $first = false) - { - $current = $this->state->current; - $value = $entityType ? $current->$entityType : $current; - - if ($value) { - if ($first && count($value)) { - return $value[0]; - } else { - return $value; - } - } else { - return []; - } - } - protected function parseClient() { $clientRepo = app('App\Ninja\Repositories\ClientRepository'); @@ -95,35 +121,61 @@ class BaseIntent return $client; } - protected function parseInvoiceItems() + protected function parseFields() { - $productRepo = app('App\Ninja\Repositories\ProductRepository'); + $data = []; - $invoiceItems = []; + foreach ($this->data->compositeEntities as $compositeEntity) { + if ($compositeEntity->parentType != 'FieldValuePair') { + continue; + } - if ( ! isset($this->data->compositeEntities) || ! count($this->data->compositeEntities)) { - return []; - } + $field = false; + $value = false; - foreach ($this->data->compositeEntities as $entity) { - if ($entity->parentType == 'InvoiceItem') { - $product = false; - $qty = 1; - foreach ($entity->children as $child) { - if ($child->type == 'Product') { - $product = $productRepo->findPhonetically($child->value); - } else { - $qty = $child->value; - } + foreach ($compositeEntity->children as $child) { + if ($child->type == 'Field') { + $field = $child->value;; + } elseif ($child->type == 'Value') { + $value = $child->value; } + } - $item = $product->toArray(); - $item['qty'] = $qty; - $invoiceItems[] = $item; + if ($field && $value) { + $field = $this->processField($field); + $value = $this->processValue($value); + + $data[$field] = $value; } } - return $invoiceItems; + return $data; + } + + protected function processField($field) + { + $field = str_replace(' ', '_', $field); + + if (strpos($field, 'date') !== false) { + $field .= '_sql'; + } + + return $field; + } + + protected function processValue($value) + { + // look for LUIS pre-built entity matches + foreach ($this->data->entities as $entity) { + if ($entity->entity === $value) { + if ($entity->type == 'builtin.datetime.date') { + $value = $entity->resolution->date; + $value = str_replace('XXXX', date('Y'), $value); + } + } + } + + return $value; } } diff --git a/app/Ninja/Intents/CreateInvoiceIntent.php b/app/Ninja/Intents/CreateInvoiceIntent.php index 59ae3809db1c..24d5dc5bac0d 100644 --- a/app/Ninja/Intents/CreateInvoiceIntent.php +++ b/app/Ninja/Intents/CreateInvoiceIntent.php @@ -1,13 +1,12 @@ parseClient(); $invoiceItems = $this->parseInvoiceItems(); @@ -22,22 +21,22 @@ class CreateInvoiceIntent extends BaseIntent 'invoice_items' => $invoiceItems, ]; + var_dump($data); $valid = EntityModel::validate($data, ENTITY_INVOICE); if ($valid !== true) { - return view('bots.skype.message', [ - 'message' => $valid - ])->render(); + throw new Exception($valid); } - $invoice = $invoiceRepo->save($data); + $invoice = $this->invoiceRepo->save($data); $invoiceItemIds = array_map(function($item) { return $item['public_id']; }, $invoice->invoice_items->toArray()); - $this->setState(ENTITY_CLIENT, [$client->public_id]); - $this->setState(ENTITY_INVOICE, [$invoice->public_id]); - $this->setState(ENTITY_INVOICE_ITEM, $invoiceItemIds); + $this->setEntityType(ENTITY_INVOICE); + $this->setEntities(ENTITY_CLIENT, $client->public_id); + $this->setEntities(ENTITY_INVOICE, $invoice->public_id); + $this->setEntities(ENTITY_INVOICE_ITEM, $invoiceItemIds); return view('bots.skype.invoice', [ 'invoice' => $invoice diff --git a/app/Ninja/Intents/CreateInvoiceItemsIntent.php b/app/Ninja/Intents/CreateInvoiceItemsIntent.php index 174f1f262542..eeb61703de12 100644 --- a/app/Ninja/Intents/CreateInvoiceItemsIntent.php +++ b/app/Ninja/Intents/CreateInvoiceItemsIntent.php @@ -1,41 +1,39 @@ getCurrentState(ENTITY_INVOICE, true); - $invoice = Invoice::scope($invoiceId)->first(); - + $invoice = $this->invoice(); $invoiceItems = $this->parseInvoiceItems(); + $data = [ - 'invoice_items' => $invoiceItems + 'public_id' => $invoice->public_id, + 'invoice_items' => array_merge($invoice->invoice_items->toArray(), $invoiceItems), ]; + var_dump($data); $valid = EntityModel::validate($data, ENTITY_INVOICE, $invoice); if ($valid !== true) { - return view('bots.skype.message', [ - 'message' => $valid - ])->render(); + throw new Exception($valid); } - $invoice = $invoiceRepo->save($data, $invoice); + $invoice = $this->invoiceRepo->save($data, $invoice); $invoiceItems = array_slice($invoice->invoice_items->toArray(), count($invoiceItems) * -1); $invoiceItemIds = array_map(function($item) { return $item['public_id']; }, $invoiceItems); - $this->setState(ENTITY_INVOICE_ITEM, $invoiceItemIds); + $this->setEntities(ENTITY_INVOICE_ITEM, $invoiceItemIds); return view('bots.skype.invoice', [ - 'invoice' => $invoice + 'invoice' => $invoice->load('invoice_items') ])->render(); } } diff --git a/app/Ninja/Intents/DownloadInvoiceIntent.php b/app/Ninja/Intents/DownloadInvoiceIntent.php new file mode 100644 index 000000000000..7ccd14e71ef1 --- /dev/null +++ b/app/Ninja/Intents/DownloadInvoiceIntent.php @@ -0,0 +1,20 @@ +invoice(); + + $message = trans('texts.' . $invoice->getEntityType()) . ' ' . $invoice->invoice_number; + $message = link_to('/download/' . $invoice->invitations[0]->invitation_key, $message); + + return view('bots.skype.message', [ + 'message' => $message + ])->render(); + } +} diff --git a/app/Ninja/Intents/EmailInvoiceIntent.php b/app/Ninja/Intents/EmailInvoiceIntent.php new file mode 100644 index 000000000000..1c0d72843736 --- /dev/null +++ b/app/Ninja/Intents/EmailInvoiceIntent.php @@ -0,0 +1,27 @@ +invoice(); + + if ( ! Auth::user()->can('edit', $invoice)) { + throw new Exception(trans('texts.not_allowed')); + } + + $contactMailer = app('App\Ninja\Mailers\ContactMailer'); + $contactMailer->sendInvoice($invoice); + + $message = trans('texts.bot_emailed_' . $invoice->getEntityType()); + + return view('bots.skype.message', [ + 'message' => $message + ])->render(); + } +} diff --git a/app/Ninja/Intents/InvoiceIntent.php b/app/Ninja/Intents/InvoiceIntent.php new file mode 100644 index 000000000000..4e6c9a7f6212 --- /dev/null +++ b/app/Ninja/Intents/InvoiceIntent.php @@ -0,0 +1,68 @@ +invoiceRepo = app('App\Ninja\Repositories\InvoiceRepository'); + + parent::__construct($state, $data); + } + + protected function invoice() + { + $invoiceId = $this->entity(ENTITY_INVOICE); + + if ( ! $invoiceId) { + throw new Exception(trans('texts.intent_not_supported')); + } + + $invoice = Invoice::scope($invoiceId)->first(); + + if ( ! $invoice) { + throw new Exception(trans('texts.intent_not_supported')); + } + + if ( ! Auth::user()->can('view', $invoice)) { + throw new Exception(trans('texts.not_allowed')); + } + + return $invoice; + } + + protected function parseInvoiceItems() + { + $productRepo = app('App\Ninja\Repositories\ProductRepository'); + + $invoiceItems = []; + + if ( ! isset($this->data->compositeEntities) || ! count($this->data->compositeEntities)) { + return []; + } + + foreach ($this->data->compositeEntities as $entity) { + if ($entity->parentType == 'InvoiceItem') { + $product = false; + $qty = 1; + foreach ($entity->children as $child) { + if ($child->type == 'Product') { + $product = $productRepo->findPhonetically($child->value); + } else { + $qty = $child->value; + } + } + + $item = $product->toArray(); + $item['qty'] = $qty; + $invoiceItems[] = $item; + } + } + + return $invoiceItems; + } + +} diff --git a/app/Ninja/Intents/UpdateInvoiceIntent.php b/app/Ninja/Intents/UpdateInvoiceIntent.php new file mode 100644 index 000000000000..b0611475907f --- /dev/null +++ b/app/Ninja/Intents/UpdateInvoiceIntent.php @@ -0,0 +1,21 @@ +invoice(); + + $data = $this->parseFields(); + + dd($data); + + return view('bots.skype.invoice', [ + 'invoice' => $invoice + ])->render(); + } +} diff --git a/resources/lang/en/texts.php b/resources/lang/en/texts.php index ac613dda096b..b1321471f82b 100644 --- a/resources/lang/en/texts.php +++ b/resources/lang/en/texts.php @@ -2056,6 +2056,7 @@ $LANG = array( 'intent_not_supported' => 'Sorry, I\'m not able to do that.', 'client_not_found' => 'We weren\'t able to find the client', 'not_allowed' => 'Sorry, you don\'t have the needed permissions', + 'bot_emailed_invoice' => 'Your invoice has been emailed', ); diff --git a/resources/views/bots/skype/message.blade.php b/resources/views/bots/skype/message.blade.php index d33830c20871..831f98433577 100644 --- a/resources/views/bots/skype/message.blade.php +++ b/resources/views/bots/skype/message.blade.php @@ -1,4 +1,4 @@ { "type": "message/text", - "text": "{!! $message !!}" + "text": "{!! addslashes($message) !!}" }