mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2024-11-08 20:22:42 +01:00
Working on the bot
This commit is contained in:
parent
325aaa3272
commit
f8fda5f241
File diff suppressed because one or more lines are too long
@ -627,9 +627,11 @@ if (!defined('CONTACT_EMAIL')) {
|
|||||||
define('EMAIL_MARKUP_URL', env('EMAIL_MARKUP_URL', 'https://developers.google.com/gmail/markup'));
|
define('EMAIL_MARKUP_URL', env('EMAIL_MARKUP_URL', 'https://developers.google.com/gmail/markup'));
|
||||||
define('OFX_HOME_URL', env('OFX_HOME_URL', 'http://www.ofxhome.com/index.php/home/directory/all'));
|
define('OFX_HOME_URL', env('OFX_HOME_URL', 'http://www.ofxhome.com/index.php/home/directory/all'));
|
||||||
define('GOOGLE_ANALYITCS_URL', env('GOOGLE_ANALYITCS_URL', 'https://www.google-analytics.com/collect'));
|
define('GOOGLE_ANALYITCS_URL', env('GOOGLE_ANALYITCS_URL', 'https://www.google-analytics.com/collect'));
|
||||||
|
|
||||||
define('MSBOT_LOGIN_URL', 'https://login.microsoftonline.com/common/oauth2/v2.0/token');
|
define('MSBOT_LOGIN_URL', 'https://login.microsoftonline.com/common/oauth2/v2.0/token');
|
||||||
define('MSBOT_LUIS_URL', 'https://api.projectoxford.ai/luis/v1/application');
|
define('MSBOT_LUIS_URL', 'https://api.projectoxford.ai/luis/v1/application');
|
||||||
define('SKYPE_API_URL', 'https://apis.skype.com/v3');
|
define('SKYPE_API_URL', 'https://apis.skype.com/v3');
|
||||||
|
define('MSBOT_STATE_URL', 'https://state.botframework.com/v3');
|
||||||
|
|
||||||
define('BLANK_IMAGE', 'data:image/png;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=');
|
define('BLANK_IMAGE', 'data:image/png;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=');
|
||||||
|
|
||||||
|
36
app/Libraries/CurlUtils.php
Normal file
36
app/Libraries/CurlUtils.php
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?php namespace App\Libraries;
|
||||||
|
|
||||||
|
class CurlUtils
|
||||||
|
{
|
||||||
|
public static function post($url, $data, $headers = false)
|
||||||
|
{
|
||||||
|
return self::exec('POST', $url, $data, $headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function get($url, $headers = false)
|
||||||
|
{
|
||||||
|
return self::exec('GET', $url, null, $headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function exec($method, $url, $data, $headers = false)
|
||||||
|
{
|
||||||
|
$curl = curl_init();
|
||||||
|
|
||||||
|
$opts = [
|
||||||
|
CURLOPT_URL => $url,
|
||||||
|
CURLOPT_RETURNTRANSFER => true,
|
||||||
|
CURLOPT_POST => $method,
|
||||||
|
CURLOPT_HTTPHEADER => $headers ?: [],
|
||||||
|
];
|
||||||
|
|
||||||
|
if ($data) {
|
||||||
|
$opts[CURLOPT_POSTFIELDS] = $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
curl_setopt_array($curl, $opts);
|
||||||
|
$response = curl_exec($curl);
|
||||||
|
curl_close($curl);
|
||||||
|
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
}
|
@ -3,6 +3,7 @@
|
|||||||
use Auth;
|
use Auth;
|
||||||
use Eloquent;
|
use Eloquent;
|
||||||
use Utils;
|
use Utils;
|
||||||
|
use Validator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class EntityModel
|
* Class EntityModel
|
||||||
@ -86,6 +87,11 @@ class EntityModel extends Eloquent
|
|||||||
return '[' . $this->getEntityType().':'.$this->public_id.':'.$this->getDisplayName() . ']';
|
return '[' . $this->getEntityType().':'.$this->public_id.':'.$this->getDisplayName() . ']';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function entityKey()
|
||||||
|
{
|
||||||
|
return $this->public_id . ':' . $this->getEntityType();
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
public function getEntityType()
|
public function getEntityType()
|
||||||
{
|
{
|
||||||
@ -190,4 +196,35 @@ class EntityModel extends Eloquent
|
|||||||
$name = $parts[count($parts)-1];
|
$name = $parts[count($parts)-1];
|
||||||
return strtolower($name) . '_id';
|
return strtolower($name) . '_id';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $data
|
||||||
|
* @param $entityType
|
||||||
|
* @return bool|string
|
||||||
|
*/
|
||||||
|
public static function validate($data, $entityType, $action = 'create')
|
||||||
|
{
|
||||||
|
// Use the API request if it exists
|
||||||
|
$requestClass = sprintf('App\\Http\\Requests\\%s%sAPIRequest', ucwords($action), ucwords($entityType));
|
||||||
|
if ( ! class_exists($requestClass)) {
|
||||||
|
$requestClass = sprintf('App\\Http\\Requests\\%s%sRequest', ucwords($action), ucwords($entityType));
|
||||||
|
}
|
||||||
|
|
||||||
|
$request = new $requestClass();
|
||||||
|
$request->setUserResolver(function() { return Auth::user(); });
|
||||||
|
$request->replace($data);
|
||||||
|
|
||||||
|
if ( ! $request->authorize()) {
|
||||||
|
return trans('texts.not_allowed');
|
||||||
|
}
|
||||||
|
|
||||||
|
$validator = Validator::make($data, $request->rules());
|
||||||
|
|
||||||
|
if ($validator->fails()) {
|
||||||
|
return $validator->messages()->first();
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,21 @@
|
|||||||
<?php namespace App\Ninja\Intents;
|
<?php namespace App\Ninja\Intents;
|
||||||
|
|
||||||
|
use stdClass;
|
||||||
use Exception;
|
use Exception;
|
||||||
|
use App\Libraries\CurlUtils;
|
||||||
|
|
||||||
class BaseIntent
|
class BaseIntent
|
||||||
{
|
{
|
||||||
|
protected $state;
|
||||||
protected $parameters;
|
protected $parameters;
|
||||||
|
|
||||||
public function __construct($data)
|
public function __construct($state, $data)
|
||||||
{
|
{
|
||||||
|
$this->state = $state ?: new stdClass;
|
||||||
$this->data = $data;
|
$this->data = $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function createIntent($data)
|
public static function createIntent($state, $data)
|
||||||
{
|
{
|
||||||
if ( ! count($data->intents)) {
|
if ( ! count($data->intents)) {
|
||||||
throw new Exception(trans('texts.intent_not_found'));
|
throw new Exception(trans('texts.intent_not_found'));
|
||||||
@ -19,14 +23,14 @@ class BaseIntent
|
|||||||
|
|
||||||
$intent = $data->intents[0];
|
$intent = $data->intents[0];
|
||||||
$intentType = $intent->intent;
|
$intentType = $intent->intent;
|
||||||
|
|
||||||
$className = "App\\Ninja\\Intents\\{$intentType}Intent";
|
$className = "App\\Ninja\\Intents\\{$intentType}Intent";
|
||||||
|
|
||||||
if ( ! class_exists($className)) {
|
if ( ! class_exists($className)) {
|
||||||
throw new Exception(trans('texts.intent_not_supported'));
|
throw new Exception(trans('texts.intent_not_supported'));
|
||||||
}
|
}
|
||||||
|
|
||||||
return (new $className($data));
|
return (new $className($state, $data));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function process()
|
public function process()
|
||||||
@ -34,4 +38,62 @@ class BaseIntent
|
|||||||
// do nothing by default
|
// do nothing by default
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function addState($entities)
|
||||||
|
{
|
||||||
|
var_dump($this->state);
|
||||||
|
if (isset($this->state->current)) {
|
||||||
|
$this->state->previous = $this->state->current;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$this->state->current = $entities;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getState()
|
||||||
|
{
|
||||||
|
return $this->state;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function parseClient()
|
||||||
|
{
|
||||||
|
$clientRepo = app('App\Ninja\Repositories\ClientRepository');
|
||||||
|
|
||||||
|
$client = false;
|
||||||
|
|
||||||
|
foreach ($this->data->entities as $param) {
|
||||||
|
if ($param->type == 'Client') {
|
||||||
|
$client = $clientRepo->findPhonetically($param->entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $client;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function parseInvoiceItems()
|
||||||
|
{
|
||||||
|
$productRepo = app('App\Ninja\Repositories\ProductRepository');
|
||||||
|
|
||||||
|
$invoiceItems = [];
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
<?php namespace App\Ninja\Intents;
|
<?php namespace App\Ninja\Intents;
|
||||||
|
|
||||||
|
use App\Models\EntityModel;
|
||||||
|
|
||||||
class CreateInvoiceIntent extends BaseIntent
|
class CreateInvoiceIntent extends BaseIntent
|
||||||
{
|
{
|
||||||
public function process()
|
public function process()
|
||||||
@ -9,64 +11,31 @@ class CreateInvoiceIntent extends BaseIntent
|
|||||||
$client = $this->parseClient();
|
$client = $this->parseClient();
|
||||||
$invoiceItems = $this->parseInvoiceItems();
|
$invoiceItems = $this->parseInvoiceItems();
|
||||||
|
|
||||||
if ($client) {
|
if ( ! $client) {
|
||||||
$data = [
|
|
||||||
'client_id' => $client->id,
|
|
||||||
'invoice_items' => $invoiceItems,
|
|
||||||
];
|
|
||||||
|
|
||||||
$invoice = $invoiceRepo->save($data);
|
|
||||||
|
|
||||||
return view('bots.skype.invoice', [
|
|
||||||
'invoice' => $invoice
|
|
||||||
])->render();
|
|
||||||
} else {
|
|
||||||
return view('bots.skype.message', [
|
return view('bots.skype.message', [
|
||||||
'message' => trans('texts.client_not_found')
|
'message' => trans('texts.client_not_found')
|
||||||
])->render();
|
])->render();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private function parseClient()
|
$data = [
|
||||||
{
|
'client_id' => $client->id,
|
||||||
$clientRepo = app('App\Ninja\Repositories\ClientRepository');
|
'invoice_items' => $invoiceItems,
|
||||||
|
];
|
||||||
|
|
||||||
$client = false;
|
$valid = EntityModel::validate($data, ENTITY_INVOICE);
|
||||||
|
|
||||||
foreach ($this->data->entities as $param) {
|
if ($valid !== true) {
|
||||||
if ($param->type == 'Client') {
|
return view('bots.skype.message', [
|
||||||
$client = $clientRepo->findPhonetically($param->entity);
|
'message' => $valid
|
||||||
}
|
])->render();
|
||||||
}
|
}
|
||||||
|
|
||||||
return $client;
|
$invoice = $invoiceRepo->save($data);
|
||||||
|
|
||||||
|
$this->addState([$invoice->entityKey()]);
|
||||||
|
|
||||||
|
return view('bots.skype.invoice', [
|
||||||
|
'invoice' => $invoice
|
||||||
|
])->render();
|
||||||
}
|
}
|
||||||
|
|
||||||
private function parseInvoiceItems()
|
|
||||||
{
|
|
||||||
$productRepo = app('App\Ninja\Repositories\ProductRepository');
|
|
||||||
|
|
||||||
$invoiceItems = [];
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,22 @@ class ClientPresenter extends EntityPresenter {
|
|||||||
return $this->entity->country ? $this->entity->country->name : '';
|
return $this->entity->country ? $this->entity->country->name : '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function balance()
|
||||||
|
{
|
||||||
|
$client = $this->entity;
|
||||||
|
$account = $client->account;
|
||||||
|
|
||||||
|
return $account->formatMoney($client->balance, $client);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function paid_to_date()
|
||||||
|
{
|
||||||
|
$client = $this->entity;
|
||||||
|
$account = $client->account;
|
||||||
|
|
||||||
|
return $account->formatMoney($client->paid_to_date, $client);
|
||||||
|
}
|
||||||
|
|
||||||
public function status()
|
public function status()
|
||||||
{
|
{
|
||||||
$class = $text = '';
|
$class = $text = '';
|
||||||
|
@ -9,7 +9,6 @@ use Auth;
|
|||||||
use Utils;
|
use Utils;
|
||||||
use parsecsv;
|
use parsecsv;
|
||||||
use Session;
|
use Session;
|
||||||
use Validator;
|
|
||||||
use League\Fractal\Manager;
|
use League\Fractal\Manager;
|
||||||
use App\Ninja\Repositories\ContactRepository;
|
use App\Ninja\Repositories\ContactRepository;
|
||||||
use App\Ninja\Repositories\ClientRepository;
|
use App\Ninja\Repositories\ClientRepository;
|
||||||
@ -141,7 +140,7 @@ class ImportService
|
|||||||
|
|
||||||
foreach ($json['clients'] as $jsonClient) {
|
foreach ($json['clients'] as $jsonClient) {
|
||||||
|
|
||||||
if ($this->validate($jsonClient, ENTITY_CLIENT) === true) {
|
if (EntityModel::validate($jsonClient, ENTITY_CLIENT) === true) {
|
||||||
$client = $this->clientRepo->save($jsonClient);
|
$client = $this->clientRepo->save($jsonClient);
|
||||||
$this->addSuccess($client);
|
$this->addSuccess($client);
|
||||||
} else {
|
} else {
|
||||||
@ -151,7 +150,7 @@ class ImportService
|
|||||||
|
|
||||||
foreach ($jsonClient['invoices'] as $jsonInvoice) {
|
foreach ($jsonClient['invoices'] as $jsonInvoice) {
|
||||||
$jsonInvoice['client_id'] = $client->id;
|
$jsonInvoice['client_id'] = $client->id;
|
||||||
if ($this->validate($jsonInvoice, ENTITY_INVOICE) === true) {
|
if (EntityModel::validate($jsonInvoice, ENTITY_INVOICE) === true) {
|
||||||
$invoice = $this->invoiceRepo->save($jsonInvoice);
|
$invoice = $this->invoiceRepo->save($jsonInvoice);
|
||||||
$this->addSuccess($invoice);
|
$this->addSuccess($invoice);
|
||||||
} else {
|
} else {
|
||||||
@ -162,7 +161,7 @@ class ImportService
|
|||||||
foreach ($jsonInvoice['payments'] as $jsonPayment) {
|
foreach ($jsonInvoice['payments'] as $jsonPayment) {
|
||||||
$jsonPayment['client_id'] = $jsonPayment['client'] = $client->id; // TODO: change to client_id once views are updated
|
$jsonPayment['client_id'] = $jsonPayment['client'] = $client->id; // TODO: change to client_id once views are updated
|
||||||
$jsonPayment['invoice_id'] = $jsonPayment['invoice'] = $invoice->id; // TODO: change to invoice_id once views are updated
|
$jsonPayment['invoice_id'] = $jsonPayment['invoice'] = $invoice->id; // TODO: change to invoice_id once views are updated
|
||||||
if ($this->validate($jsonPayment, ENTITY_PAYMENT) === true) {
|
if (EntityModel::validate($jsonPayment, ENTITY_PAYMENT) === true) {
|
||||||
$payment = $this->paymentRepo->save($jsonPayment);
|
$payment = $this->paymentRepo->save($jsonPayment);
|
||||||
$this->addSuccess($payment);
|
$this->addSuccess($payment);
|
||||||
} else {
|
} else {
|
||||||
@ -280,7 +279,7 @@ class ImportService
|
|||||||
$data['invoice_number'] = $account->getNextInvoiceNumber($invoice);
|
$data['invoice_number'] = $account->getNextInvoiceNumber($invoice);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($this->validate($data, $entityType) !== true) {
|
if (EntityModel::validate($data, $entityType) !== true) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -396,26 +395,6 @@ class ImportService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param $data
|
|
||||||
* @param $entityType
|
|
||||||
* @return bool|string
|
|
||||||
*/
|
|
||||||
private function validate($data, $entityType)
|
|
||||||
{
|
|
||||||
$requestClass = 'App\\Http\\Requests\\Create' . ucwords($entityType) . 'Request';
|
|
||||||
$request = new $requestClass();
|
|
||||||
$request->setUserResolver(function() { return Auth::user(); });
|
|
||||||
$request->replace($data);
|
|
||||||
|
|
||||||
$validator = Validator::make($data, $request->rules());
|
|
||||||
|
|
||||||
if ($validator->fails()) {
|
|
||||||
return $validator->messages()->first();
|
|
||||||
} else {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param array $files
|
* @param array $files
|
||||||
|
@ -2055,6 +2055,7 @@ $LANG = array(
|
|||||||
'intent_not_found' => 'Sorry, I\'m not sure what you\'re asking.',
|
'intent_not_found' => 'Sorry, I\'m not sure what you\'re asking.',
|
||||||
'intent_not_supported' => 'Sorry, I\'m not able to do that.',
|
'intent_not_supported' => 'Sorry, I\'m not able to do that.',
|
||||||
'client_not_found' => 'We weren\'t able to find the client',
|
'client_not_found' => 'We weren\'t able to find the client',
|
||||||
|
'not_allowed' => 'Sorry, you don\'t have the needed permissions',
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -8,6 +8,20 @@
|
|||||||
'invoice' => link_to($invoice->getRoute(), $invoice->invoice_number),
|
'invoice' => link_to($invoice->getRoute(), $invoice->invoice_number),
|
||||||
'client' => link_to($invoice->client->getRoute(), $invoice->client->getDisplayName())
|
'client' => link_to($invoice->client->getRoute(), $invoice->client->getDisplayName())
|
||||||
]) !!}',
|
]) !!}',
|
||||||
|
"facts": [
|
||||||
|
{
|
||||||
|
"key": "{{ trans('texts.email') }}:",
|
||||||
|
"value": "{!! addslashes(HTML::mailto($invoice->client->contacts[0]->email)->toHtml()) !!}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "{{ trans('texts.paid_to_date') }}:",
|
||||||
|
"value": "{{ $invoice->client->present()->paid_to_date }}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "{{ trans('texts.balance') }}:",
|
||||||
|
"value": "{{ $invoice->client->present()->balance }}"
|
||||||
|
}
|
||||||
|
],
|
||||||
"items":[
|
"items":[
|
||||||
@foreach ($invoice->invoice_items as $item)
|
@foreach ($invoice->invoice_items as $item)
|
||||||
@if ($invoice->invoice_items[0] != $item)
|
@if ($invoice->invoice_items[0] != $item)
|
||||||
|
Loading…
Reference in New Issue
Block a user