diff --git a/.env.example b/.env.example index 20c977c663..66d2d5251b 100644 --- a/.env.example +++ b/.env.example @@ -20,11 +20,25 @@ MAIL_FROM_ADDRESS MAIL_FROM_NAME MAIL_PASSWORD +#POSTMARK_API_TOKEN= + PHANTOMJS_CLOUD_KEY='a-demo-key-with-low-quota-per-ip-address' LOG=single REQUIRE_HTTPS=false API_SECRET=password -GOOGLE_CLIENT_ID -GOOGLE_CLIENT_SECRET -GOOGLE_OAUTH_REDIRECT=http://ninja.dev/auth/google \ No newline at end of file +#TRUSTED_PROXIES= + +#SESSION_DRIVER= +#SESSION_DOMAIN= +#SESSION_ENCRYPT= +#SESSION_SECURE= + +#CACHE_DRIVER= +#CACHE_HOST= +#CACHE_PORT1= +#CACHE_PORT2= + +#GOOGLE_CLIENT_ID= +#GOOGLE_CLIENT_SECRET= +#GOOGLE_OAUTH_REDIRECT=http://ninja.dev/auth/google \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index c7dd08d994..84f209b3dd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,7 @@ language: php sudo: true php: - - 5.5 + - 5.5.9 # - 5.6 # - 7.0 # - hhvm @@ -64,16 +64,17 @@ before_script: script: - php ./vendor/codeception/codeception/codecept run --debug acceptance AllPagesCept.php - #- php ./vendor/codeception/codeception/codecept run --debug acceptance APICest.php - #- php ./vendor/codeception/codeception/codecept run --debug acceptance CheckBalanceCest.php - #- php ./vendor/codeception/codeception/codecept run --debug acceptance ClientCest.php - #- php ./vendor/codeception/codeception/codecept run --debug acceptance CreditCest.php - #- php ./vendor/codeception/codeception/codecept run --debug acceptance InvoiceCest.php - #- php ./vendor/codeception/codeception/codecept run --debug acceptance InvoiceDesignCest.php - #- php ./vendor/codeception/codeception/codecept run acceptance OnlinePaymentCest.php - #- php ./vendor/codeception/codeception/codecept run --debug acceptance PaymentCest.php - #- php ./vendor/codeception/codeception/codecept run --debug acceptance TaskCest.php - #- php ./vendor/codeception/codeception/codecept run --debug acceptance TaxRatesCest.php + - php ./vendor/codeception/codeception/codecept run --debug acceptance APICest.php + - php ./vendor/codeception/codeception/codecept run --debug acceptance CheckBalanceCest.php + - php ./vendor/codeception/codeception/codecept run --debug acceptance ClientCest.php + - php ./vendor/codeception/codeception/codecept run --debug acceptance ExpenseCest.php + - php ./vendor/codeception/codeception/codecept run --debug acceptance CreditCest.php + - php ./vendor/codeception/codeception/codecept run --debug acceptance InvoiceCest.php + - php ./vendor/codeception/codeception/codecept run --debug acceptance InvoiceDesignCest.php + - php ./vendor/codeception/codeception/codecept run acceptance OnlinePaymentCest.php + - php ./vendor/codeception/codeception/codecept run --debug acceptance PaymentCest.php + - php ./vendor/codeception/codeception/codecept run --debug acceptance TaskCest.php + - php ./vendor/codeception/codeception/codecept run --debug acceptance TaxRatesCest.php #- sed -i 's/NINJA_DEV=true/NINJA_PROD=true/g' .env #- php ./vendor/codeception/codeception/codecept run acceptance GoProCest.php diff --git a/Gruntfile.js b/Gruntfile.js index 05dab35047..e0a13ccd6a 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -95,19 +95,19 @@ module.exports = function(grunt) { 'public/vendor/bootstrap-datepicker/dist/locales/bootstrap-datepicker.no.min.js', 'public/vendor/bootstrap-datepicker/dist/locales/bootstrap-datepicker.es.min.js', 'public/vendor/bootstrap-datepicker/dist/locales/bootstrap-datepicker.sv.min.js', - 'public/vendor/typeahead.js/dist/typeahead.min.js', + 'public/vendor/typeahead.js/dist/typeahead.jquery.min.js', 'public/vendor/accounting/accounting.min.js', 'public/vendor/spectrum/spectrum.js', 'public/vendor/jspdf/dist/jspdf.min.js', 'public/vendor/moment/min/moment.min.js', 'public/vendor/moment-timezone/builds/moment-timezone-with-data.min.js', 'public/vendor/stacktrace-js/dist/stacktrace-with-polyfills.min.js', + 'public/vendor/fuse.js/src/fuse.min.js', //'public/vendor/moment-duration-format/lib/moment-duration-format.js', //'public/vendor/handsontable/dist/jquery.handsontable.full.min.js', //'public/vendor/pdfmake/build/pdfmake.min.js', //'public/vendor/pdfmake/build/vfs_fonts.js', //'public/js/vfs_fonts.js', - 'public/js/lightbox.min.js', 'public/js/bootstrap-combobox.js', 'public/js/script.js', 'public/js/pdf.pdfmake.js', @@ -140,7 +140,6 @@ module.exports = function(grunt) { 'public/vendor/spectrum/spectrum.css', 'public/css/bootstrap-combobox.css', 'public/css/typeahead.js-bootstrap.css', - 'public/css/lightbox.css', //'public/vendor/handsontable/dist/jquery.handsontable.full.css', 'public/css/style.css', ], diff --git a/app/Console/Commands/ChargeRenewalInvoices.php b/app/Console/Commands/ChargeRenewalInvoices.php new file mode 100644 index 0000000000..39d63ee44c --- /dev/null +++ b/app/Console/Commands/ChargeRenewalInvoices.php @@ -0,0 +1,63 @@ +mailer = $mailer; + $this->accountRepo = $repo; + $this->paymentService = $paymentService; + } + + public function fire() + { + $this->info(date('Y-m-d').' ChargeRenewalInvoices...'); + + $account = $this->accountRepo->getNinjaAccount(); + $invoices = Invoice::whereAccountId($account->id) + ->whereDueDate(date('Y-m-d')) + ->with('client') + ->orderBy('id') + ->get(); + + $this->info(count($invoices).' invoices found'); + + foreach ($invoices as $invoice) { + $this->info("Charging invoice {$invoice->invoice_number}"); + $this->paymentService->autoBillInvoice($invoice); + } + + $this->info('Done'); + } + + protected function getArguments() + { + return array( + //array('example', InputArgument::REQUIRED, 'An example argument.'), + ); + } + + protected function getOptions() + { + return array( + //array('example', null, InputOption::VALUE_OPTIONAL, 'An example option.', null), + ); + } +} diff --git a/app/Console/Commands/SendRenewalInvoices.php b/app/Console/Commands/SendRenewalInvoices.php index 1e8ea1b49e..0faf1304a9 100644 --- a/app/Console/Commands/SendRenewalInvoices.php +++ b/app/Console/Commands/SendRenewalInvoices.php @@ -47,7 +47,7 @@ class SendRenewalInvoices extends Command } $client = $this->accountRepo->getNinjaClient($account); - $invitation = $this->accountRepo->createNinjaInvoice($client); + $invitation = $this->accountRepo->createNinjaInvoice($client, $account); // set the due date to 10 days from now $invoice = $invitation->invoice; diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index bd2720afa9..d04eab9fad 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -16,6 +16,7 @@ class Kernel extends ConsoleKernel 'App\Console\Commands\ResetData', 'App\Console\Commands\CheckData', 'App\Console\Commands\SendRenewalInvoices', + 'App\Console\Commands\ChargeRenewalInvoices', 'App\Console\Commands\SendReminders', 'App\Console\Commands\TestOFX', 'App\Console\Commands\GenerateResources', diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php index ba656f6c01..9d17fb0990 100644 --- a/app/Exceptions/Handler.php +++ b/app/Exceptions/Handler.php @@ -47,13 +47,16 @@ class Handler extends ExceptionHandler { if ($e instanceof ModelNotFoundException) { return Redirect::to('/'); } elseif ($e instanceof \Illuminate\Session\TokenMismatchException) { - // https://gist.github.com/jrmadsen67/bd0f9ad0ef1ed6bb594e - return redirect() - ->back() - ->withInput($request->except('password', '_token')) - ->with([ - 'warning' => trans('texts.token_expired') - ]); + // prevent loop since the page auto-submits + if ($request->path() != 'get_started') { + // https://gist.github.com/jrmadsen67/bd0f9ad0ef1ed6bb594e + return redirect() + ->back() + ->withInput($request->except('password', '_token')) + ->with([ + 'warning' => trans('texts.token_expired') + ]); + } } // In production, except for maintenance mode, we'll show a custom error screen diff --git a/app/Http/Controllers/AccountApiController.php b/app/Http/Controllers/AccountApiController.php index 77e85243d7..6d4ef0ccf1 100644 --- a/app/Http/Controllers/AccountApiController.php +++ b/app/Http/Controllers/AccountApiController.php @@ -117,4 +117,77 @@ class AccountApiController extends BaseAPIController return $this->response($account); } + + public function addDeviceToken(Request $request) + { + $account = Auth::user()->account; + + //scan if this user has a token already registered (tokens can change, so we need to use the users email as key) + $devices = json_decode($account->devices,TRUE); + + + for($x=0; $xusername) { + $devices[$x]['token'] = $request->token; //update + $account->devices = json_encode($devices); + $account->save(); + return $this->response($account); + } + } + + //User does not have a device, create new record + + $newDevice = [ + 'token' => $request->token, + 'email' => $request->email, + 'device' => $request->device, + 'notify_sent' => TRUE, + 'notify_viewed' => TRUE, + 'notify_approved' => TRUE, + 'notify_paid' => TRUE, + ]; + + $devices[] = $newDevice; + $account->devices = json_encode($devices); + $account->save(); + + return $this->response($account); + + } + + public function updatePushNotifications(Request $request) + { + $account = Auth::user()->account; + + $devices = json_decode($account->devices, TRUE); + + if(count($devices)<1) + return $this->errorResponse(['message'=>'no devices exist'], 400); + + for($x=0; $xusername) + { + unset($devices[$x]); + + $newDevice = [ + 'token' => $request->token, + 'email' => $request->email, + 'device' => $request->device, + 'notify_sent' => $request->notify_sent, + 'notify_viewed' => $request->notify_viewed, + 'notify_approved' => $request->notify_approved, + 'notify_paid' => $request->notify_paid, + ]; + + $devices[] = $newDevice; + $account->devices = json_encode($devices); + $account->save(); + + return $this->response($account); + } + } + + } } diff --git a/app/Http/Controllers/AccountController.php b/app/Http/Controllers/AccountController.php index 6c0f59a3ba..0a5d89262a 100644 --- a/app/Http/Controllers/AccountController.php +++ b/app/Http/Controllers/AccountController.php @@ -15,6 +15,7 @@ use Response; use Request; use App\Models\Affiliate; use App\Models\License; +use App\Models\Invoice; use App\Models\User; use App\Models\Account; use App\Models\Gateway; @@ -393,6 +394,21 @@ class AccountController extends BaseController if ($section == ACCOUNT_CUSTOMIZE_DESIGN) { $data['customDesign'] = ($account->custom_design && !$design) ? $account->custom_design : $design; + + // sample invoice to help determine variables + $invoice = Invoice::scope() + ->with('client', 'account') + ->where('is_quote', '=', false) + ->where('is_recurring', '=', false) + ->first(); + + if ($invoice) { + $invoice->hidePrivateFields(); + unset($invoice->account); + unset($invoice->invoice_items); + unset($invoice->client->contacts); + $data['sampleInvoice'] = $invoice; + } } return View::make("accounts.{$section}", $data); @@ -416,6 +432,7 @@ class AccountController extends BaseController 'client_view_css' => $css, 'title' => trans("texts.client_portal"), 'section' => ACCOUNT_CLIENT_PORTAL, + 'account' => $account, ]; return View::make("accounts.client_portal", $data); @@ -528,6 +545,7 @@ class AccountController extends BaseController $account = Auth::user()->account; $account->client_view_css = $sanitized_css; + $account->enable_client_portal = Input::get('enable_client_portal') ? true : false; $account->save(); Session::flash('message', trans('texts.updated_settings')); @@ -668,6 +686,8 @@ class AccountController extends BaseController $account->custom_invoice_taxes2 = Input::get('custom_invoice_taxes2') ? true : false; $account->custom_invoice_text_label1 = trim(Input::get('custom_invoice_text_label1')); $account->custom_invoice_text_label2 = trim(Input::get('custom_invoice_text_label2')); + $account->custom_invoice_item_label1 = trim(Input::get('custom_invoice_item_label1')); + $account->custom_invoice_item_label2 = trim(Input::get('custom_invoice_item_label2')); $account->invoice_number_counter = Input::get('invoice_number_counter'); $account->quote_number_prefix = Input::get('quote_number_prefix'); @@ -676,6 +696,7 @@ class AccountController extends BaseController $account->invoice_footer = Input::get('invoice_footer'); $account->quote_terms = Input::get('quote_terms'); $account->auto_convert_quote = Input::get('auto_convert_quote'); + $account->recurring_invoice_number_prefix = Input::get('recurring_invoice_number_prefix'); if (Input::has('recurring_hour')) { $account->recurring_hour = Input::get('recurring_hour'); diff --git a/app/Http/Controllers/AppController.php b/app/Http/Controllers/AppController.php index 606374a0d5..60583b7231 100644 --- a/app/Http/Controllers/AppController.php +++ b/app/Http/Controllers/AppController.php @@ -243,6 +243,7 @@ class AppController extends BaseController if (!Utils::isNinjaProd()) { try { set_time_limit(60 * 5); + Artisan::call('optimize', array('--force' => true)); Cache::flush(); Session::flush(); Artisan::call('migrate', array('--force' => true)); @@ -250,11 +251,14 @@ class AppController extends BaseController 'PaymentLibraries', 'Fonts', 'Banks', - 'InvoiceStatus' + 'InvoiceStatus', + 'Currencies', + 'DateFormats', + 'InvoiceDesigns', + 'PaymentTerms', ] as $seeder) { Artisan::call('db:seed', array('--force' => true, '--class' => "{$seeder}Seeder")); } - Artisan::call('optimize', array('--force' => true)); Event::fire(new UserSettingsChanged()); Session::flash('message', trans('texts.processed_updates')); } catch (Exception $e) { @@ -288,7 +292,7 @@ class AppController extends BaseController } if (Utils::getResllerType() == RESELLER_REVENUE_SHARE) { - $payments = DB::table('accounts') + $data = DB::table('accounts') ->leftJoin('payments', 'payments.account_id', '=', 'accounts.id') ->leftJoin('clients', 'clients.id', '=', 'payments.client_id') ->where('accounts.account_key', '=', NINJA_ACCOUNT_KEY) @@ -300,15 +304,9 @@ class AppController extends BaseController 'payments.amount' ]); } else { - $payments = DB::table('accounts') - ->leftJoin('payments', 'payments.account_id', '=', 'accounts.id') - ->leftJoin('clients', 'clients.id', '=', 'payments.client_id') - ->where('accounts.account_key', '=', NINJA_ACCOUNT_KEY) - ->where('payments.is_deleted', '=', false) - ->groupBy('clients.id') - ->count(); + $data = DB::table('users')->count(); } - return json_encode($payments); + return json_encode($data); } } \ No newline at end of file diff --git a/app/Http/Controllers/Auth/AuthController.php b/app/Http/Controllers/Auth/AuthController.php index 5ed231cedc..62bae4cbdd 100644 --- a/app/Http/Controllers/Auth/AuthController.php +++ b/app/Http/Controllers/Auth/AuthController.php @@ -10,8 +10,6 @@ use App\Events\UserLoggedIn; use App\Http\Controllers\Controller; use App\Ninja\Repositories\AccountRepository; use App\Services\AuthService; -use Illuminate\Contracts\Auth\Guard; -use Illuminate\Contracts\Auth\Registrar; use Illuminate\Foundation\Auth\AuthenticatesAndRegistersUsers; class AuthController extends Controller { @@ -41,16 +39,38 @@ class AuthController extends Controller { * @param \Illuminate\Contracts\Auth\Registrar $registrar * @return void */ - public function __construct(Guard $auth, Registrar $registrar, AccountRepository $repo, AuthService $authService) + public function __construct(AccountRepository $repo, AuthService $authService) { - $this->auth = $auth; - $this->registrar = $registrar; $this->accountRepo = $repo; $this->authService = $authService; //$this->middleware('guest', ['except' => 'getLogout']); } + public function validator(array $data) + { + return Validator::make($data, [ + 'name' => 'required|max:255', + 'email' => 'required|email|max:255|unique:users', + 'password' => 'required|confirmed|min:6', + ]); + } + + /** + * Create a new user instance after a valid registration. + * + * @param array $data + * @return User + */ + public function create(array $data) + { + return User::create([ + 'name' => $data['name'], + 'email' => $data['email'], + 'password' => bcrypt($data['password']), + ]); + } + public function authLogin($provider, Request $request) { return $this->authService->execute($provider, $request->has('code')); diff --git a/app/Http/Controllers/Auth/PasswordController.php b/app/Http/Controllers/Auth/PasswordController.php index 3741a81579..bd7d0bb0ef 100644 --- a/app/Http/Controllers/Auth/PasswordController.php +++ b/app/Http/Controllers/Auth/PasswordController.php @@ -1,8 +1,6 @@ auth = $auth; - $this->passwords = $passwords; - $this->middleware('guest'); } diff --git a/app/Http/Controllers/ExportController.php b/app/Http/Controllers/ExportController.php index 540e38d972..a7f5db4b57 100644 --- a/app/Http/Controllers/ExportController.php +++ b/app/Http/Controllers/ExportController.php @@ -109,8 +109,7 @@ class ExportController extends BaseController if ($request->input(ENTITY_CLIENT)) { $data['clients'] = Client::scope() ->with('user', 'contacts', 'country') - ->withTrashed() - ->where('is_deleted', '=', false) + ->withArchived() ->get(); $data['contacts'] = Contact::scope() @@ -126,33 +125,36 @@ class ExportController extends BaseController if ($request->input(ENTITY_TASK)) { $data['tasks'] = Task::scope() ->with('user', 'client.contacts') - ->withTrashed() - ->where('is_deleted', '=', false) + ->withArchived() ->get(); } if ($request->input(ENTITY_INVOICE)) { $data['invoices'] = Invoice::scope() ->with('user', 'client.contacts', 'invoice_status') - ->withTrashed() - ->where('is_deleted', '=', false) + ->withArchived() ->where('is_quote', '=', false) ->where('is_recurring', '=', false) ->get(); $data['quotes'] = Invoice::scope() ->with('user', 'client.contacts', 'invoice_status') - ->withTrashed() - ->where('is_deleted', '=', false) + ->withArchived() ->where('is_quote', '=', true) ->where('is_recurring', '=', false) ->get(); + + $data['recurringInvoices'] = Invoice::scope() + ->with('user', 'client.contacts', 'invoice_status', 'frequency') + ->withArchived() + ->where('is_quote', '=', false) + ->where('is_recurring', '=', true) + ->get(); } if ($request->input(ENTITY_PAYMENT)) { $data['payments'] = Payment::scope() - ->withTrashed() - ->where('is_deleted', '=', false) + ->withArchived() ->with('user', 'client.contacts', 'payment_type', 'invoice', 'account_gateway.gateway') ->get(); } @@ -161,14 +163,14 @@ class ExportController extends BaseController if ($request->input(ENTITY_VENDOR)) { $data['clients'] = Vendor::scope() ->with('user', 'vendorcontacts', 'country') - ->withTrashed() - ->where('is_deleted', '=', false) + ->withArchived() ->get(); $data['vendor_contacts'] = VendorContact::scope() ->with('user', 'vendor.contacts') ->withTrashed() ->get(); + /* $data['expenses'] = Credit::scope() ->with('user', 'client.contacts') diff --git a/app/Http/Controllers/PublicClientController.php b/app/Http/Controllers/PublicClientController.php index 9d806061d8..d9a11e5c94 100644 --- a/app/Http/Controllers/PublicClientController.php +++ b/app/Http/Controllers/PublicClientController.php @@ -34,10 +34,7 @@ class PublicClientController extends BaseController public function view($invitationKey) { if (!$invitation = $this->invoiceRepo->findInvoiceByInvitation($invitationKey)) { - return response()->view('error', [ - 'error' => trans('texts.invoice_not_found'), - 'hideHeader' => true, - ]); + return $this->returnError(); } $invoice = $invitation->invoice; @@ -118,6 +115,7 @@ class PublicClientController extends BaseController 'showBreadcrumbs' => false, 'hideLogo' => $account->isWhiteLabel(), 'hideHeader' => $account->isNinjaAccount(), + 'hideDashboard' => !$account->enable_client_portal, 'clientViewCSS' => $account->clientViewCSS(), 'clientFontUrl' => $account->getFontsUrl(), 'invoice' => $invoice->hidePrivateFields(), @@ -188,11 +186,16 @@ class PublicClientController extends BaseController if (!$invitation = $this->getInvitation()) { return $this->returnError(); } + $account = $invitation->account; $invoice = $invitation->invoice; $client = $invoice->client; $color = $account->primary_color ? $account->primary_color : '#0b4d78'; + if (!$account->enable_client_portal) { + return $this->returnError(); + } + $data = [ 'color' => $color, 'account' => $account, @@ -244,6 +247,7 @@ class PublicClientController extends BaseController $data = [ 'color' => $color, 'hideLogo' => $account->isWhiteLabel(), + 'hideDashboard' => !$account->enable_client_portal, 'clientViewCSS' => $account->clientViewCSS(), 'clientFontUrl' => $account->getFontsUrl(), 'title' => trans('texts.invoices'), @@ -275,6 +279,7 @@ class PublicClientController extends BaseController $data = [ 'color' => $color, 'hideLogo' => $account->isWhiteLabel(), + 'hideDashboard' => !$account->enable_client_portal, 'clientViewCSS' => $account->clientViewCSS(), 'clientFontUrl' => $account->getFontsUrl(), 'entityType' => ENTITY_PAYMENT, @@ -312,6 +317,7 @@ class PublicClientController extends BaseController $data = [ 'color' => $color, 'hideLogo' => $account->isWhiteLabel(), + 'hideDashboard' => !$account->enable_client_portal, 'clientViewCSS' => $account->clientViewCSS(), 'clientFontUrl' => $account->getFontsUrl(), 'title' => trans('texts.quotes'), @@ -332,13 +338,11 @@ class PublicClientController extends BaseController return $this->invoiceRepo->getClientDatatable($invitation->contact_id, ENTITY_QUOTE, Input::get('sSearch')); } - private function returnError() + private function returnError($error = false) { return response()->view('error', [ - 'error' => trans('texts.invoice_not_found'), + 'error' => $error ?: trans('texts.invoice_not_found'), 'hideHeader' => true, - 'clientViewCSS' => $account->clientViewCSS(), - 'clientFontUrl' => $account->getFontsUrl(), ]); } diff --git a/app/Http/Controllers/ReportController.php b/app/Http/Controllers/ReportController.php index 1757cb5850..1c4c033b9e 100644 --- a/app/Http/Controllers/ReportController.php +++ b/app/Http/Controllers/ReportController.php @@ -10,6 +10,9 @@ use DatePeriod; use Session; use View; use App\Models\Account; +use App\Models\Client; +use App\Models\Payment; +use App\Models\Expense; class ReportController extends BaseController { @@ -47,6 +50,7 @@ class ReportController extends BaseController $groupBy = Input::get('group_by'); $chartType = Input::get('chart_type'); $reportType = Input::get('report_type'); + $dateField = Input::get('date_field'); $startDate = Utils::toSqlDate(Input::get('start_date'), false); $endDate = Utils::toSqlDate(Input::get('end_date'), false); $enableReport = Input::get('enable_report') ? true : false; @@ -55,6 +59,7 @@ class ReportController extends BaseController $groupBy = 'MONTH'; $chartType = 'Bar'; $reportType = ENTITY_INVOICE; + $dateField = FILTER_INVOICE_DATE; $startDate = Utils::today(false)->modify('-3 month'); $endDate = Utils::today(false); $enableReport = true; @@ -76,6 +81,8 @@ class ReportController extends BaseController ENTITY_CLIENT => trans('texts.client'), ENTITY_INVOICE => trans('texts.invoice'), ENTITY_PAYMENT => trans('texts.payment'), + ENTITY_EXPENSE => trans('texts.expenses'), + ENTITY_TAX_RATE => trans('texts.taxes'), ]; $params = [ @@ -94,10 +101,11 @@ class ReportController extends BaseController if (Auth::user()->account->isPro()) { if ($enableReport) { - $params = array_merge($params, self::generateReport($reportType, $groupBy, $startDate, $endDate)); + $isExport = $action == 'export'; + $params = array_merge($params, self::generateReport($reportType, $startDate, $endDate, $dateField, $isExport)); - if ($action == 'export') { - self::export($params['exportData'], $params['reportTotals']); + if ($isExport) { + self::export($params['displayData'], $params['columns'], $params['reportTotals']); } } if ($enableChart) { @@ -106,11 +114,7 @@ class ReportController extends BaseController } else { $params['columns'] = []; $params['displayData'] = []; - $params['reportTotals'] = [ - 'amount' => [], - 'balance' => [], - 'paid' => [], - ]; + $params['reportTotals'] = []; $params['labels'] = []; $params['datasets'] = []; $params['scaleStepWidth'] = 100; @@ -212,165 +216,314 @@ class ReportController extends BaseController ]; } - private function generateReport($reportType, $groupBy, $startDate, $endDate) + private function generateReport($reportType, $startDate, $endDate, $dateField, $isExport) { if ($reportType == ENTITY_CLIENT) { - $columns = ['client', 'amount', 'paid', 'balance']; + return $this->generateClientReport($startDate, $endDate, $isExport); } elseif ($reportType == ENTITY_INVOICE) { - $columns = ['client', 'invoice_number', 'invoice_date', 'amount', 'paid', 'balance']; - } else { - $columns = ['client', 'invoice_number', 'invoice_date', 'amount', 'payment_date', 'paid', 'method']; + return $this->generateInvoiceReport($startDate, $endDate, $isExport); + } elseif ($reportType == ENTITY_PAYMENT) { + return $this->generatePaymentReport($startDate, $endDate, $isExport); + } elseif ($reportType == ENTITY_TAX_RATE) { + return $this->generateTaxRateReport($startDate, $endDate, $dateField, $isExport); + } elseif ($reportType == ENTITY_EXPENSE) { + return $this->generateExpenseReport($startDate, $endDate, $isExport); } + } - $query = DB::table('invoices') - ->join('accounts', 'accounts.id', '=', 'invoices.account_id') - ->join('clients', 'clients.id', '=', 'invoices.client_id') - ->join('contacts', 'contacts.client_id', '=', 'clients.id') - ->where('invoices.account_id', '=', Auth::user()->account_id) - ->where('invoices.is_deleted', '=', false) - ->where('clients.is_deleted', '=', false) - ->where('contacts.deleted_at', '=', null) - ->where('invoices.invoice_date', '>=', $startDate->format('Y-m-d')) - ->where('invoices.invoice_date', '<=', $endDate->format('Y-m-d')) - ->where('invoices.is_quote', '=', false) - ->where('invoices.is_recurring', '=', false) - ->where('contacts.is_primary', '=', true); + private function generateTaxRateReport($startDate, $endDate, $dateField, $isExport) + { + $columns = ['tax_name', 'tax_rate', 'amount', 'paid']; - $select = [ - DB::raw('COALESCE(clients.currency_id, accounts.currency_id) currency_id'), - 'accounts.country_id', - 'contacts.first_name', - 'contacts.last_name', - 'contacts.email', - 'clients.name as client_name', - 'clients.public_id as client_public_id', - 'invoices.public_id as invoice_public_id' - ]; - - if ($reportType == ENTITY_CLIENT) { - $query->groupBy('clients.id'); - array_push($select, DB::raw('sum(invoices.amount) amount'), DB::raw('sum(invoices.balance) balance'), DB::raw('sum(invoices.amount - invoices.balance) paid')); - } else { - $query->orderBy('invoices.id'); - array_push($select, 'invoices.invoice_number', 'invoices.amount', 'invoices.balance', 'invoices.invoice_date'); - if ($reportType == ENTITY_INVOICE) { - array_push($select, DB::raw('(invoices.amount - invoices.balance) paid')); - } else { - $query->join('payments', 'payments.invoice_id', '=', 'invoices.id') - ->leftJoin('payment_types', 'payment_types.id', '=', 'payments.payment_type_id') - ->leftJoin('account_gateways', 'account_gateways.id', '=', 'payments.account_gateway_id') - ->leftJoin('gateways', 'gateways.id', '=', 'account_gateways.gateway_id'); - array_push($select, 'payments.payment_date', 'payments.amount as paid', 'payment_types.name as payment_type', 'gateways.name as gateway'); - } - } - - $query->select($select); - $data = $query->get(); - - $lastInvoiceId = null; - $sameAsLast = false; + $account = Auth::user()->account; $displayData = []; + $reportTotals = []; - $exportData = []; - $reportTotals = [ - 'amount' => [], - 'balance' => [], - 'paid' => [], - ]; + $clients = Client::scope() + ->withArchived() + ->with('contacts') + ->with(['invoices' => function($query) use ($startDate, $endDate, $dateField) { + $query->withArchived(); + if ($dateField == FILTER_PAYMENT_DATE) { + $query->where('invoice_date', '>=', $startDate) + ->where('invoice_date', '<=', $endDate) + ->whereHas('payments', function($query) use ($startDate, $endDate) { + $query->where('payment_date', '>=', $startDate) + ->where('payment_date', '<=', $endDate) + ->withArchived(); + }) + ->with(['payments' => function($query) use ($startDate, $endDate) { + $query->where('payment_date', '>=', $startDate) + ->where('payment_date', '<=', $endDate) + ->withArchived() + ->with('payment_type', 'account_gateway.gateway'); + }, 'invoice_items']); + } + }]); - foreach ($data as $record) { - $sameAsLast = ($lastInvoiceId == $record->invoice_public_id); - $lastInvoiceId = $record->invoice_public_id; + foreach ($clients->get() as $client) { + $currencyId = $client->currency_id ?: Auth::user()->account->getCurrencyId(); + $amount = 0; + $paid = 0; + $taxTotals = []; - $displayRow = []; - if ($sameAsLast) { - array_push($displayRow, '', '', '', ''); - } else { - array_push($displayRow, link_to('/clients/'.$record->client_public_id, Utils::getClientDisplayName($record))); - if ($reportType != ENTITY_CLIENT) { - array_push($displayRow, - link_to('/invoices/'.$record->invoice_public_id, $record->invoice_number), - Utils::fromSqlDate($record->invoice_date, true) - ); + foreach ($client->invoices as $invoice) { + foreach ($invoice->getTaxes(true) as $key => $tax) { + if ( ! isset($taxTotals[$currencyId])) { + $taxTotals[$currencyId] = []; + } + if (isset($taxTotals[$currencyId][$key])) { + $taxTotals[$currencyId][$key]['amount'] += $tax['amount']; + $taxTotals[$currencyId][$key]['paid'] += $tax['paid']; + } else { + $taxTotals[$currencyId][$key] = $tax; + } } - array_push($displayRow, Utils::formatMoney($record->amount, $record->currency_id, $record->country_id)); - } - if ($reportType != ENTITY_PAYMENT) { - array_push($displayRow, Utils::formatMoney($record->paid, $record->currency_id, $record->country_id)); - } - if ($reportType == ENTITY_PAYMENT) { - array_push($displayRow, - Utils::fromSqlDate($record->payment_date, true), - Utils::formatMoney($record->paid, $record->currency_id, $record->country_id), - $record->gateway ?: $record->payment_type - ); - } else { - array_push($displayRow, Utils::formatMoney($record->balance, $record->currency_id, $record->country_id)); + + $amount += $invoice->amount; + $paid += $invoice->getAmountPaid(); } - // export data - $exportRow = []; - if ($sameAsLast) { - $exportRow[trans('texts.client')] = ' '; - $exportRow[trans('texts.invoice_number')] = ' '; - $exportRow[trans('texts.invoice_date')] = ' '; - $exportRow[trans('texts.amount')] = ' '; - } else { - $exportRow[trans('texts.client')] = Utils::getClientDisplayName($record); - if ($reportType != ENTITY_CLIENT) { - $exportRow[trans('texts.invoice_number')] = $record->invoice_number; - $exportRow[trans('texts.invoice_date')] = Utils::fromSqlDate($record->invoice_date, true); + foreach ($taxTotals as $currencyId => $taxes) { + foreach ($taxes as $tax) { + $displayData[] = [ + $tax['name'], + $tax['rate'] . '%', + $account->formatMoney($tax['amount'], $client), + $account->formatMoney($tax['paid'], $client) + ]; } - $exportRow[trans('texts.amount')] = Utils::formatMoney($record->amount, $record->currency_id, $record->country_id); + + $reportTotals = $this->addToTotals($reportTotals, $client->currency_id, 'amount', $tax['amount']); + $reportTotals = $this->addToTotals($reportTotals, $client->currency_id, 'paid', $tax['paid']); } - if ($reportType != ENTITY_PAYMENT) { - $exportRow[trans('texts.paid')] = Utils::formatMoney($record->paid, $record->currency_id, $record->country_id); - } - if ($reportType == ENTITY_PAYMENT) { - $exportRow[trans('texts.payment_date')] = Utils::fromSqlDate($record->payment_date, true); - $exportRow[trans('texts.payment_amount')] = Utils::formatMoney($record->paid, $record->currency_id, $record->country_id); - $exportRow[trans('texts.method')] = $record->gateway ?: $record->payment_type; - } else { - $exportRow[trans('texts.balance')] = Utils::formatMoney($record->balance, $record->currency_id, $record->country_id); - } - - $displayData[] = $displayRow; - $exportData[] = $exportRow; - - $accountCurrencyId = Auth::user()->account->currency_id; - $currencyId = $record->currency_id ? $record->currency_id : ($accountCurrencyId ? $accountCurrencyId : DEFAULT_CURRENCY); - if (!isset($reportTotals['amount'][$currencyId])) { - $reportTotals['amount'][$currencyId] = 0; - $reportTotals['balance'][$currencyId] = 0; - $reportTotals['paid'][$currencyId] = 0; - } - if (!$sameAsLast) { - $reportTotals['amount'][$currencyId] += $record->amount; - $reportTotals['balance'][$currencyId] += $record->balance; - } - $reportTotals['paid'][$currencyId] += $record->paid; } return [ 'columns' => $columns, 'displayData' => $displayData, 'reportTotals' => $reportTotals, - 'exportData' => $exportData + ]; + + } + + private function generatePaymentReport($startDate, $endDate, $isExport) + { + $columns = ['client', 'invoice_number', 'invoice_date', 'amount', 'payment_date', 'paid', 'method']; + + $account = Auth::user()->account; + $displayData = []; + $reportTotals = []; + + $payments = Payment::scope() + ->withTrashed() + ->where('is_deleted', '=', false) + ->whereHas('client', function($query) { + $query->where('is_deleted', '=', false); + }) + ->whereHas('invoice', function($query) { + $query->where('is_deleted', '=', false); + }) + ->with('client.contacts', 'invoice', 'payment_type', 'account_gateway.gateway') + ->where('payment_date', '>=', $startDate) + ->where('payment_date', '<=', $endDate); + + foreach ($payments->get() as $payment) { + $invoice = $payment->invoice; + $client = $payment->client; + $displayData[] = [ + $isExport ? $client->getDisplayName() : $client->present()->link, + $isExport ? $invoice->invoice_number : $invoice->present()->link, + $invoice->present()->invoice_date, + $account->formatMoney($invoice->amount, $client), + $payment->present()->payment_date, + $account->formatMoney($payment->amount, $client), + $payment->present()->method, + ]; + + $reportTotals = $this->addToTotals($reportTotals, $client->currency_id, 'amount', $invoice->amount); + $reportTotals = $this->addToTotals($reportTotals, $client->currency_id, 'paid', $payment->amount); + } + + return [ + 'columns' => $columns, + 'displayData' => $displayData, + 'reportTotals' => $reportTotals, ]; } - private function export($data, $totals) + private function generateInvoiceReport($startDate, $endDate, $isExport) + { + $columns = ['client', 'invoice_number', 'invoice_date', 'amount', 'paid', 'balance']; + + $account = Auth::user()->account; + $displayData = []; + $reportTotals = []; + + $clients = Client::scope() + ->withTrashed() + ->with('contacts') + ->where('is_deleted', '=', false) + ->with(['invoices' => function($query) use ($startDate, $endDate) { + $query->where('invoice_date', '>=', $startDate) + ->where('invoice_date', '<=', $endDate) + ->where('is_deleted', '=', false) + ->where('is_quote', '=', false) + ->where('is_recurring', '=', false) + ->with(['payments' => function($query) { + $query->withTrashed() + ->with('payment_type', 'account_gateway.gateway') + ->where('is_deleted', '=', false); + }, 'invoice_items']) + ->withTrashed(); + }]); + + foreach ($clients->get() as $client) { + $currencyId = $client->currency_id ?: Auth::user()->account->getCurrencyId(); + + foreach ($client->invoices as $invoice) { + $displayData[] = [ + $isExport ? $client->getDisplayName() : $client->present()->link, + $isExport ? $invoice->invoice_number : $invoice->present()->link, + $invoice->present()->invoice_date, + $account->formatMoney($invoice->amount, $client), + $account->formatMoney($invoice->getAmountPaid(), $client), + $account->formatMoney($invoice->balance, $client), + ]; + $reportTotals = $this->addToTotals($reportTotals, $client->currency_id, 'amount', $invoice->amount); + $reportTotals = $this->addToTotals($reportTotals, $client->currency_id, 'paid', $invoice->getAmountPaid()); + $reportTotals = $this->addToTotals($reportTotals, $client->currency_id, 'balance', $invoice->balance); + } + } + + return [ + 'columns' => $columns, + 'displayData' => $displayData, + 'reportTotals' => $reportTotals, + ]; + } + + private function generateClientReport($startDate, $endDate, $isExport) + { + $columns = ['client', 'amount', 'paid', 'balance']; + + $account = Auth::user()->account; + $displayData = []; + $reportTotals = []; + + $clients = Client::scope() + ->withArchived() + ->with('contacts') + ->with(['invoices' => function($query) use ($startDate, $endDate) { + $query->where('invoice_date', '>=', $startDate) + ->where('invoice_date', '<=', $endDate) + ->where('is_quote', '=', false) + ->where('is_recurring', '=', false) + ->withArchived(); + }]); + + foreach ($clients->get() as $client) { + $amount = 0; + $paid = 0; + + foreach ($client->invoices as $invoice) { + $amount += $invoice->amount; + $paid += $invoice->getAmountPaid(); + } + + $displayData[] = [ + $isExport ? $client->getDisplayName() : $client->present()->link, + $account->formatMoney($amount, $client), + $account->formatMoney($paid, $client), + $account->formatMoney($amount - $paid, $client) + ]; + + $reportTotals = $this->addToTotals($reportTotals, $client->currency_id, 'amount', $amount); + $reportTotals = $this->addToTotals($reportTotals, $client->currency_id, 'paid', $paid); + $reportTotals = $this->addToTotals($reportTotals, $client->currency_id, 'balance', $amount - $paid); + } + + return [ + 'columns' => $columns, + 'displayData' => $displayData, + 'reportTotals' => $reportTotals, + ]; + } + + private function generateExpenseReport($startDate, $endDate, $isExport) + { + $columns = ['vendor', 'client', 'date', 'expense_amount', 'invoiced_amount']; + + $account = Auth::user()->account; + $displayData = []; + $reportTotals = []; + + $expenses = Expense::scope() + ->withTrashed() + ->with('client.contacts', 'vendor') + ->where('expense_date', '>=', $startDate) + ->where('expense_date', '<=', $endDate); + + + foreach ($expenses->get() as $expense) { + $amount = $expense->amount; + $invoiced = $expense->present()->invoiced_amount; + + $displayData[] = [ + $expense->vendor ? ($isExport ? $expense->vendor->name : $expense->vendor->present()->link) : '', + $expense->client ? ($isExport ? $expense->client->getDisplayName() : $expense->client->present()->link) : '', + $expense->present()->expense_date, + Utils::formatMoney($amount, $expense->currency_id), + Utils::formatMoney($invoiced, $expense->invoice_currency_id), + ]; + + $reportTotals = $this->addToTotals($reportTotals, $expense->expense_currency_id, 'amount', $amount); + $reportTotals = $this->addToTotals($reportTotals, $expense->invoice_currency_id, 'amount', 0); + + $reportTotals = $this->addToTotals($reportTotals, $expense->invoice_currency_id, 'invoiced', $invoiced); + $reportTotals = $this->addToTotals($reportTotals, $expense->expense_currency_id, 'invoiced', 0); + } + + return [ + 'columns' => $columns, + 'displayData' => $displayData, + 'reportTotals' => $reportTotals, + ]; + } + + private function addToTotals($data, $currencyId, $field, $value) { + $currencyId = $currencyId ?: Auth::user()->account->getCurrencyId(); + + if (!isset($data[$currencyId][$field])) { + $data[$currencyId][$field] = 0; + } + + $data[$currencyId][$field] += $value; + + return $data; + } + + private function export($data, $columns, $totals) { $output = fopen('php://output', 'w') or Utils::fatalError(); header('Content-Type:application/csv'); header('Content-Disposition:attachment;filename=ninja-report.csv'); - Utils::exportData($output, $data); + Utils::exportData($output, $data, Utils::trans($columns)); + + fwrite($output, trans('texts.totals')); + foreach ($totals as $currencyId => $fields) { + foreach ($fields as $key => $value) { + fwrite($output, ',' . trans("texts.{$key}")); + } + fwrite($output, "\n"); + break; + } - foreach (['amount', 'paid', 'balance'] as $type) { - $csv = trans("texts.{$type}").','; - foreach ($totals[$type] as $currencyId => $amount) { - $csv .= Utils::formatMoney($amount, $currencyId).','; + foreach ($totals as $currencyId => $fields) { + $csv = Utils::getFromCache($currencyId, 'currencies')->name . ','; + foreach ($fields as $key => $value) { + $csv .= '"' . Utils::formatMoney($value, $currencyId).'",'; } fwrite($output, $csv."\n"); } diff --git a/app/Http/Middleware/StartupCheck.php b/app/Http/Middleware/StartupCheck.php index dc9f9420f9..14344e10e9 100644 --- a/app/Http/Middleware/StartupCheck.php +++ b/app/Http/Middleware/StartupCheck.php @@ -48,6 +48,9 @@ class StartupCheck $file = storage_path() . '/version.txt'; $version = @file_get_contents($file); if ($version != NINJA_VERSION) { + if (version_compare(phpversion(), '5.5.9', '<')) { + dd('Please update PHP to >= 5.5.9'); + } $handle = fopen($file, 'w'); fwrite($handle, NINJA_VERSION); fclose($handle); diff --git a/app/Http/routes.php b/app/Http/routes.php index f7bed59f68..c00eb8f8e9 100644 --- a/app/Http/routes.php +++ b/app/Http/routes.php @@ -1,5 +1,6 @@ 'api', 'prefix' => 'api/v1'], function() Route::resource('tax_rates', 'TaxRateApiController'); Route::resource('users', 'UserApiController'); Route::resource('expenses','ExpenseApiController'); + Route::post('add_token', 'AccountApiController@addDeviceToken'); + Route::post('update_notifications', 'AccountApiController@updatePushNotifications'); // Vendor Route::resource('vendors', 'VendorApiController'); @@ -527,6 +530,8 @@ if (!defined('CONTACT_EMAIL')) { define('EMAIL_MARKUP_URL', 'https://developers.google.com/gmail/markup'); define('OFX_HOME_URL', 'http://www.ofxhome.com/index.php/home/directory/all'); + define('BLANK_IMAGE', 'data:image/png;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs='); + define('COUNT_FREE_DESIGNS', 4); define('COUNT_FREE_DESIGNS_SELF_HOST', 5); // include the custom design define('PRODUCT_ONE_CLICK_INSTALL', 1); @@ -549,6 +554,9 @@ if (!defined('CONTACT_EMAIL')) { define('TEST_PASSWORD', 'password'); define('API_SECRET', 'API_SECRET'); + define('IOS_PRODUCTION_PUSH','ninjaIOS'); + define('IOS_DEV_PUSH','devNinjaIOS'); + define('TOKEN_BILLING_DISABLED', 1); define('TOKEN_BILLING_OPT_IN', 2); define('TOKEN_BILLING_OPT_OUT', 3); @@ -572,6 +580,9 @@ if (!defined('CONTACT_EMAIL')) { define('REMINDER_FIELD_DUE_DATE', 1); define('REMINDER_FIELD_INVOICE_DATE', 2); + define('FILTER_INVOICE_DATE', 'invoice_date'); + define('FILTER_PAYMENT_DATE', 'payment_date'); + define('SOCIAL_GOOGLE', 'Google'); define('SOCIAL_FACEBOOK', 'Facebook'); define('SOCIAL_GITHUB', 'GitHub'); diff --git a/app/Libraries/Utils.php b/app/Libraries/Utils.php index 027f512a47..c7e003b020 100644 --- a/app/Libraries/Utils.php +++ b/app/Libraries/Utils.php @@ -72,7 +72,7 @@ class Utils public static function requireHTTPS() { - if (Request::root() === 'http://ninja.dev:8000') { + if (Request::root() === 'http://ninja.dev' || Request::root() === 'http://ninja.dev:8000') { return false; } @@ -767,9 +767,11 @@ class Utils return $str; } - public static function exportData($output, $data) + public static function exportData($output, $data, $headers = false) { - if (count($data) > 0) { + if ($headers) { + fputcsv($output, $headers); + } elseif (count($data) > 0) { fputcsv($output, array_keys($data[0])); } diff --git a/app/Listeners/NotificationListener.php b/app/Listeners/NotificationListener.php index aba3044575..c7b58fe30b 100644 --- a/app/Listeners/NotificationListener.php +++ b/app/Listeners/NotificationListener.php @@ -9,16 +9,19 @@ use App\Events\InvoiceInvitationWasViewed; use App\Events\QuoteInvitationWasViewed; use App\Events\QuoteInvitationWasApproved; use App\Events\PaymentWasCreated; +use App\Ninja\Notifications; class NotificationListener { protected $userMailer; protected $contactMailer; + protected $pushService; - public function __construct(UserMailer $userMailer, ContactMailer $contactMailer) + public function __construct(UserMailer $userMailer, ContactMailer $contactMailer, Notifications\PushService $pushService) { $this->userMailer = $userMailer; $this->contactMailer = $contactMailer; + $this->pushService = $pushService; } private function sendEmails($invoice, $type, $payment = null) @@ -35,26 +38,31 @@ class NotificationListener public function emailedInvoice(InvoiceWasEmailed $event) { $this->sendEmails($event->invoice, 'sent'); + $this->pushService->sendNotification($event->invoice, 'sent'); } public function emailedQuote(QuoteWasEmailed $event) { $this->sendEmails($event->quote, 'sent'); + $this->pushService->sendNotification($event->quote, 'sent'); } public function viewedInvoice(InvoiceInvitationWasViewed $event) { $this->sendEmails($event->invoice, 'viewed'); + $this->pushService->sendNotification($event->invoice, 'viewed'); } public function viewedQuote(QuoteInvitationWasViewed $event) { $this->sendEmails($event->quote, 'viewed'); + $this->pushService->sendNotification($event->quote, 'viewed'); } public function approvedQuote(QuoteInvitationWasApproved $event) { $this->sendEmails($event->quote, 'approved'); + $this->pushService->sendNotification($event->quote, 'approved'); } public function createdPayment(PaymentWasCreated $event) @@ -66,6 +74,8 @@ class NotificationListener $this->contactMailer->sendPaymentConfirmation($event->payment); $this->sendEmails($event->payment->invoice, 'paid', $event->payment); + + $this->pushService->sendNotification($event->payment->invoice, 'paid'); } } \ No newline at end of file diff --git a/app/Listeners/SubscriptionListener.php b/app/Listeners/SubscriptionListener.php index 2d12fcaeb9..0949e6de9c 100644 --- a/app/Listeners/SubscriptionListener.php +++ b/app/Listeners/SubscriptionListener.php @@ -24,29 +24,49 @@ class SubscriptionListener { public function createdClient(ClientWasCreated $event) { + if ( ! Auth::check()) { + return; + } + $transformer = new ClientTransformer(Auth::user()->account); $this->checkSubscriptions(ACTIVITY_TYPE_CREATE_CLIENT, $event->client, $transformer); } public function createdQuote(QuoteWasCreated $event) { + if ( ! Auth::check()) { + return; + } + $transformer = new InvoiceTransformer(Auth::user()->account); $this->checkSubscriptions(ACTIVITY_TYPE_CREATE_QUOTE, $event->quote, $transformer, ENTITY_CLIENT); } public function createdPayment(PaymentWasCreated $event) { + if ( ! Auth::check()) { + return; + } + $transformer = new PaymentTransformer(Auth::user()->account); $this->checkSubscriptions(ACTIVITY_TYPE_CREATE_PAYMENT, $event->payment, $transformer, [ENTITY_CLIENT, ENTITY_INVOICE]); } public function createdCredit(CreditWasCreated $event) { + if ( ! Auth::check()) { + return; + } + //$this->checkSubscriptions(ACTIVITY_TYPE_CREATE_CREDIT, $event->credit); } public function createdInvoice(InvoiceWasCreated $event) { + if ( ! Auth::check()) { + return; + } + $transformer = new InvoiceTransformer(Auth::user()->account); $this->checkSubscriptions(ACTIVITY_TYPE_CREATE_INVOICE, $event->invoice, $transformer, ENTITY_CLIENT); } diff --git a/app/Models/Account.php b/app/Models/Account.php index d3f64bb2ee..b729f46ffb 100644 --- a/app/Models/Account.php +++ b/app/Models/Account.php @@ -439,7 +439,7 @@ class Account extends Eloquent return $height; } - public function createInvoice($entityType, $clientId = null) + public function createInvoice($entityType = ENTITY_INVOICE, $clientId = null) { $invoice = Invoice::createNew(); diff --git a/app/Models/Client.php b/app/Models/Client.php index 2167af0ddf..61194fe93c 100644 --- a/app/Models/Client.php +++ b/app/Models/Client.php @@ -272,6 +272,11 @@ class Client extends EntityModel return $token ? "https://dashboard.stripe.com/customers/{$token}" : false; } + public function getAmount() + { + return $this->balance + $this->paid_to_date; + } + public function getCurrencyId() { if ($this->currency_id) { diff --git a/app/Models/EntityModel.php b/app/Models/EntityModel.php index 9e3fd6ec53..71905d000b 100644 --- a/app/Models/EntityModel.php +++ b/app/Models/EntityModel.php @@ -81,6 +81,11 @@ class EntityModel extends Eloquent return $query; } + public function scopeWithArchived($query) + { + return $query->withTrashed()->where('is_deleted', '=', false); + } + public function getName() { return $this->public_id; diff --git a/app/Models/Invoice.php b/app/Models/Invoice.php index 4e15934efe..340ce419b7 100644 --- a/app/Models/Invoice.php +++ b/app/Models/Invoice.php @@ -129,13 +129,21 @@ class Invoice extends EntityModel implements BalanceAffecting return false; } - public function getAmountPaid() + public function getAmountPaid($calculate = false) { if ($this->is_quote || $this->is_recurring) { return 0; } - return ($this->amount - $this->balance); + if ($calculate) { + $amount = 0; + foreach ($this->payments as $payment) { + $amount += $payment->amount; + } + return $amount; + } else { + return ($this->amount - $this->balance); + } } public function trashed() @@ -192,6 +200,11 @@ class Invoice extends EntityModel implements BalanceAffecting return $this->hasMany('App\Models\Invoice', 'recurring_invoice_id'); } + public function frequency() + { + return $this->belongsTo('App\Models\Frequency'); + } + public function invitations() { return $this->hasMany('App\Models\Invitation')->orderBy('invitations.contact_id'); @@ -442,12 +455,16 @@ class Invoice extends EntityModel implements BalanceAffecting 'show_item_taxes', 'custom_invoice_text_label1', 'custom_invoice_text_label2', + 'custom_invoice_item_label1', + 'custom_invoice_item_label2', ]); foreach ($this->invoice_items as $invoiceItem) { $invoiceItem->setVisible([ 'product_key', 'notes', + 'custom_value1', + 'custom_value2', 'cost', 'qty', 'tax_name', @@ -752,6 +769,98 @@ class Invoice extends EntityModel implements BalanceAffecting return Utils::decodePDF($pdfString); } + + public function getItemTaxable($invoiceItem, $invoiceTotal) + { + $total = $invoiceItem->qty * $invoiceItem->cost; + + if ($this->discount > 0) { + if ($this->is_amount_discount) { + $total -= $invoiceTotal ? ($total / $invoiceTotal * $this->discount) : 0; + } else { + $total *= (100 - $this->discount) / 100; + $total = round($total, 2); + } + } + + return $total; + } + + public function getTaxable() + { + $total = 0; + + foreach ($this->invoice_items as $invoiceItem) { + $total += $invoiceItem->qty * $invoiceItem->cost; + } + + if ($this->discount > 0) { + if ($this->is_amount_discount) { + $total -= $this->discount; + } else { + $total *= (100 - $this->discount) / 100; + $total = round($total, 2); + } + } + + if ($this->custom_value1 && $this->custom_taxes1) { + $total += $this->custom_value1; + } + + if ($this->custom_value2 && $this->custom_taxes2) { + $total += $this->custom_value2; + } + + return $total; + } + + public function getTaxes($calculatePaid = false) + { + $taxes = []; + $taxable = $this->getTaxable(); + + if ($this->tax_rate && $this->tax_name) { + $taxAmount = $taxable * ($this->tax_rate / 100); + $taxAmount = round($taxAmount, 2); + + if ($taxAmount) { + $taxes[$this->tax_name.$this->tax_rate] = [ + 'name' => $this->tax_name, + 'rate' => $this->tax_rate, + 'amount' => $taxAmount, + 'paid' => round($this->getAmountPaid($calculatePaid) / $this->amount * $taxAmount, 2) + ]; + } + } + + foreach ($this->invoice_items as $invoiceItem) { + if ( ! $invoiceItem->tax_rate || ! $invoiceItem->tax_name) { + continue; + } + + $taxAmount = $this->getItemTaxable($invoiceItem, $taxable); + $taxAmount = $taxable * ($invoiceItem->tax_rate / 100); + $taxAmount = round($taxAmount, 2); + + if ($taxAmount) { + $key = $invoiceItem->tax_name.$invoiceItem->tax_rate; + + if ( ! isset($taxes[$key])) { + $taxes[$key] = [ + 'amount' => 0, + 'paid' => 0 + ]; + } + + $taxes[$key]['amount'] += $taxAmount; + $taxes[$key]['paid'] += $this->amount && $taxAmount ? round($this->getAmountPaid($calculatePaid) / $this->amount * $taxAmount, 2) : 0; + $taxes[$key]['name'] = $invoiceItem->tax_name; + $taxes[$key]['rate'] = $invoiceItem->tax_rate; + } + } + + return $taxes; + } } Invoice::creating(function ($invoice) { diff --git a/app/Ninja/Notifications/PushFactory.php b/app/Ninja/Notifications/PushFactory.php new file mode 100644 index 0000000000..7f882ff1d0 --- /dev/null +++ b/app/Ninja/Notifications/PushFactory.php @@ -0,0 +1,96 @@ +certificate - Development or production. + * + * Static variables defined in routes.php + * + * IOS_PRODUCTION_PUSH + * IOS_DEV_PUSH + */ + + public function __construct() + { + $this->certificate = IOS_DEV_PUSH; + } + + /** + * customMessage function + * + * Send a message with a nested custom payload to perform additional trickery within application + * + * @access public + * + * @param $token + * @param $message + * @param $messageArray + * + * @return void + */ + public function customMessage($token, $message, $messageArray) + { + $customMessage = PushNotification::Message($message, $messageArray); + + $this->message($token, $customMessage); + } + + /** + * message function + * + * Send a plain text only message to a single device. + * + * @access public + * + * @param $token - device token + * @param $message - user specific message + * + * @return void + * + */ + + public function message($token, $message) + { + PushNotification::app($this->certificate) + ->to($token) + ->send($message); + } + + /** + * getFeedback function + * + * Returns an array of expired/invalid tokens to be removed from iOS PUSH notifications. + * + * We need to run this once ~ 24hrs + * + * @access public + * + * @param string $token - A valid token (can be any valid token) + * @param string $message - Nil value for message + * + * @return array + */ + public function getFeedback($token, $message = '') + { + + $feedback = PushNotification::app($this->certificate) + ->to($token) + ->send($message); + + return $feedback->getFeedback(); + } + +} \ No newline at end of file diff --git a/app/Ninja/Presenters/ClientPresenter.php b/app/Ninja/Presenters/ClientPresenter.php index 97551185d5..bb32a8b62f 100644 --- a/app/Ninja/Presenters/ClientPresenter.php +++ b/app/Ninja/Presenters/ClientPresenter.php @@ -1,5 +1,6 @@ {$text}"; + } + public function url() + { + return URL::to('/clients/' . $this->entity->public_id); + } + + public function link() + { + return link_to('/clients/' . $this->entity->public_id, $this->entity->getDisplayName()); } } \ No newline at end of file diff --git a/app/Ninja/Presenters/ExpensePresenter.php b/app/Ninja/Presenters/ExpensePresenter.php index 9cede24d03..6b66080ded 100644 --- a/app/Ninja/Presenters/ExpensePresenter.php +++ b/app/Ninja/Presenters/ExpensePresenter.php @@ -20,4 +20,14 @@ class ExpensePresenter extends Presenter { { return round($this->entity->amount * $this->entity->exchange_rate, 2); } + + public function invoiced_amount() + { + return $this->entity->invoice_id ? $this->converted_amount() : 0; + } + + public function link() + { + return link_to('/expenses/' . $this->entity->public_id, $this->entity->name); + } } \ No newline at end of file diff --git a/app/Ninja/Presenters/InvoicePresenter.php b/app/Ninja/Presenters/InvoicePresenter.php index fb292a8859..560f2d49e6 100644 --- a/app/Ninja/Presenters/InvoicePresenter.php +++ b/app/Ninja/Presenters/InvoicePresenter.php @@ -1,5 +1,6 @@ entity->invoice_status ? $this->entity->invoice_status->name : 'draft'; - $status = strtolower($status); - return trans("texts.status_{$status}"); + if ($this->entity->is_deleted) { + return trans('texts.deleted'); + } elseif ($this->entity->trashed()) { + return trans('texts.archived'); + } else { + $status = $this->entity->invoice_status ? $this->entity->invoice_status->name : 'draft'; + $status = strtolower($status); + return trans("texts.status_{$status}"); + } } public function invoice_date() @@ -55,4 +62,24 @@ class InvoicePresenter extends Presenter { return Utils::fromSqlDate($this->entity->due_date); } + public function frequency() + { + return $this->entity->frequency ? $this->entity->frequency->name : ''; + } + + public function url() + { + return URL::to('/invoices/' . $this->entity->public_id); + } + + public function link() + { + return link_to('/invoices/' . $this->entity->public_id, $this->entity->invoice_number); + } + + public function email() + { + $client = $this->entity->client; + return count($client->contacts) ? $client->contacts[0]->email : ''; + } } \ No newline at end of file diff --git a/app/Ninja/Presenters/VendorPresenter.php b/app/Ninja/Presenters/VendorPresenter.php index b3da402bec..d0bef4e0c8 100644 --- a/app/Ninja/Presenters/VendorPresenter.php +++ b/app/Ninja/Presenters/VendorPresenter.php @@ -9,4 +9,9 @@ class VendorPresenter extends Presenter { { return $this->entity->country ? $this->entity->country->name : ''; } + + public function link() + { + return link_to('/vendors/' . $this->entity->public_id, $this->entity->name); + } } \ No newline at end of file diff --git a/app/Ninja/Repositories/AccountRepository.php b/app/Ninja/Repositories/AccountRepository.php index 62c924d545..c215f69a97 100644 --- a/app/Ninja/Repositories/AccountRepository.php +++ b/app/Ninja/Repositories/AccountRepository.php @@ -5,6 +5,7 @@ use Request; use Session; use Utils; use DB; +use URL; use stdClass; use Validator; use Schema; @@ -71,47 +72,104 @@ class AccountRepository public function getSearchData() { - $clients = \DB::table('clients') - ->where('clients.deleted_at', '=', null) - ->where('clients.account_id', '=', \Auth::user()->account_id) - ->whereRaw("clients.name <> ''") - ->select(\DB::raw("'clients' as type, '" . trans('texts.clients') . "' as trans_type, clients.public_id, clients.name, '' as token")); + $data = $this->getAccountSearchData(); - $contacts = \DB::table('clients') - ->join('contacts', 'contacts.client_id', '=', 'clients.id') - ->where('clients.deleted_at', '=', null) - ->where('clients.account_id', '=', \Auth::user()->account_id) - ->whereRaw("CONCAT(contacts.first_name, contacts.last_name, contacts.email) <> ''") - ->select(\DB::raw("'clients' as type, '" . trans('texts.contacts') . "' as trans_type, clients.public_id, CONCAT(contacts.first_name, ' ', contacts.last_name, ' ', contacts.email) as name, '' as token")); + $data['navigation'] = $this->getNavigationSearchData(); - $invoices = \DB::table('clients') - ->join('invoices', 'invoices.client_id', '=', 'clients.id') - ->where('clients.account_id', '=', \Auth::user()->account_id) - ->where('clients.deleted_at', '=', null) - ->where('invoices.deleted_at', '=', null) - ->select(\DB::raw("'invoices' as type, '" . trans('texts.invoices') . "' as trans_type, invoices.public_id, CONCAT(invoices.invoice_number, ': ', clients.name) as name, invoices.invoice_number as token")); + return $data; + } - $data = []; + private function getAccountSearchData() + { + $data = [ + 'clients' => [], + 'contacts' => [], + 'invoices' => [], + 'quotes' => [], + ]; - foreach ($clients->union($contacts)->union($invoices)->get() as $row) { - $type = $row->trans_type; + $clients = Client::scope() + ->with('contacts', 'invoices') + ->get(); - if (!isset($data[$type])) { - $data[$type] = []; + foreach ($clients as $client) { + if ($client->name) { + $data['clients'][] = [ + 'value' => $client->name, + 'url' => $client->present()->url, + ]; } - $tokens = explode(' ', $row->name); - $tokens[] = $type; - - if ($type == 'Invoices') { - $tokens[] = intVal($row->token).''; + foreach ($client->contacts as $contact) { + if ($contact->getFullName()) { + $data['contacts'][] = [ + 'value' => $contact->getDisplayName(), + 'url' => $client->present()->url, + ]; + } + if ($contact->email) { + $data[trans('texts.contacts')][] = [ + 'value' => $contact->email, + 'url' => $client->present()->url, + ]; + } } - $data[$type][] = [ - 'value' => $row->name, - 'public_id' => $row->public_id, - 'tokens' => $tokens, - 'entity_type' => $row->type, + foreach ($client->invoices as $invoice) { + $entityType = $invoice->getEntityType(); + $data["{$entityType}s"][] = [ + 'value' => $invoice->getDisplayName() . ': ' . $client->getDisplayName(), + 'url' => $invoice->present()->url, + ]; + } + } + + return $data; + } + + private function getNavigationSearchData() + { + $entityTypes = [ + ENTITY_INVOICE, + ENTITY_CLIENT, + ENTITY_QUOTE, + ENTITY_TASK, + ENTITY_EXPENSE, + ENTITY_RECURRING_INVOICE, + ENTITY_PAYMENT, + ENTITY_CREDIT + ]; + + foreach ($entityTypes as $entityType) { + $features[] = [ + "new_{$entityType}", + "/{$entityType}s/create", + ]; + $features[] = [ + "list_{$entityType}s", + "/{$entityType}s", + ]; + } + + $features[] = ['dashboard', '/dashboard']; + $features[] = ['customize_design', '/settings/customize_design']; + $features[] = ['new_tax_rate', '/tax_rates/create']; + $features[] = ['new_product', '/products/create']; + $features[] = ['new_user', '/users/create']; + + $settings = array_merge(Account::$basicSettings, Account::$advancedSettings); + + foreach ($settings as $setting) { + $features[] = [ + $setting, + "/settings/{$setting}", + ]; + } + + foreach ($features as $feature) { + $data[] = [ + 'value' => trans('texts.' . $feature[0]), + 'url' => URL::to($feature[1]) ]; } @@ -127,8 +185,10 @@ class AccountRepository $account = Auth::user()->account; $client = $this->getNinjaClient($account); $invitation = $this->createNinjaInvoice($client, $account); + return $invitation; } + public function createNinjaInvoice($client, $clientAccount) { $account = $this->getNinjaAccount(); diff --git a/app/Ninja/Repositories/ClientRepository.php b/app/Ninja/Repositories/ClientRepository.php index 324d62a459..2e8ce31b5c 100644 --- a/app/Ninja/Repositories/ClientRepository.php +++ b/app/Ninja/Repositories/ClientRepository.php @@ -1,6 +1,7 @@ with('contacts')->firstOrFail(); } + // convert currency code to id + if (isset($data['currency_code'])) { + $currencyCode = strtolower($data['currency_code']); + $currency = Cache::get('currencies')->filter(function($item) use ($currencyCode) { + return strtolower($item->code) == $currencyCode; + })->first(); + if ($currency) { + $data['currency_id'] = $currency->id; + } + } + $client->fill($data); $client->save(); diff --git a/app/Ninja/Repositories/InvoiceRepository.php b/app/Ninja/Repositories/InvoiceRepository.php index 3c4072122d..52b47998b5 100644 --- a/app/Ninja/Repositories/InvoiceRepository.php +++ b/app/Ninja/Repositories/InvoiceRepository.php @@ -398,7 +398,7 @@ class InvoiceRepository extends BaseRepository foreach ($data['invoice_items'] as $item) { $item = (array) $item; - if (!$item['cost'] && !$item['product_key'] && !$item['notes']) { + if (empty($item['cost']) && empty($item['product_key']) && empty($item['notes']) && empty($item['custom_value1']) && empty($item['custom_value2'])) { continue; } @@ -439,6 +439,13 @@ class InvoiceRepository extends BaseRepository $invoiceItem->qty = Utils::parseFloat($item['qty']); $invoiceItem->tax_rate = 0; + if (isset($item['custom_value1'])) { + $invoiceItem->custom_value1 = $item['custom_value1']; + } + if (isset($item['custom_value2'])) { + $invoiceItem->custom_value2 = $item['custom_value2']; + } + if (isset($item['tax_rate']) && isset($item['tax_name']) && $item['tax_name']) { $invoiceItem['tax_rate'] = Utils::parseFloat($item['tax_rate']); $invoiceItem['tax_name'] = trim($item['tax_name']); @@ -603,7 +610,7 @@ class InvoiceRepository extends BaseRepository $invoice = Invoice::createNew($recurInvoice); $invoice->client_id = $recurInvoice->client_id; $invoice->recurring_invoice_id = $recurInvoice->id; - $invoice->invoice_number = 'R'.$recurInvoice->account->getNextInvoiceNumber($recurInvoice); + $invoice->invoice_number = $recurInvoice->account->recurring_invoice_number_prefix . $recurInvoice->account->getNextInvoiceNumber($recurInvoice); $invoice->amount = $recurInvoice->amount; $invoice->balance = $recurInvoice->amount; $invoice->invoice_date = date_create()->format('Y-m-d'); diff --git a/app/Ninja/Transformers/UserTransformer.php b/app/Ninja/Transformers/UserTransformer.php index d700c579ba..532c1f6fa4 100644 --- a/app/Ninja/Transformers/UserTransformer.php +++ b/app/Ninja/Transformers/UserTransformer.php @@ -21,7 +21,11 @@ class UserTransformer extends EntityTransformer 'registered' => (bool) $user->registered, 'confirmed' => (bool) $user->confirmed, 'oauth_user_id' => $user->oauth_user_id, - 'oauth_provider_id' => $user->oauth_provider_id + 'oauth_provider_id' => $user->oauth_provider_id, + 'notify_sent' => (bool) $user->notify_sent, + 'notify_viewed' => (bool) $user->notify_viewed, + 'notify_paid' => (bool) $user->notify_paid, + 'notify_approved' => (bool) $user->notify_approved, ]; } } \ No newline at end of file diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 0309b6a8fe..2d6689b554 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -223,11 +223,6 @@ class AppServiceProvider extends ServiceProvider { 'Illuminate\Contracts\Auth\Registrar', 'App\Services\Registrar' ); - - $this->app->bind( - 'App\Ninja\Import\DataImporterServiceInterface', - 'App\Ninja\Import\FreshBooks\FreshBooksDataImporterService' - ); } } diff --git a/app/Services/BankAccountService.php b/app/Services/BankAccountService.php index 622c759c82..c1da419600 100644 --- a/app/Services/BankAccountService.php +++ b/app/Services/BankAccountService.php @@ -4,7 +4,6 @@ use stdClass; use Utils; use URL; use Hash; -use App\Models\Gateway; use App\Models\BankSubaccount; use App\Models\Vendor; use App\Models\Expense; @@ -37,7 +36,7 @@ class BankAccountService extends BaseService public function loadBankAccounts($bankId, $username, $password, $includeTransactions = true) { - if ( ! $bankId || ! $username || ! $password) { + if (! $bankId || ! $username || ! $password) { return false; } @@ -47,12 +46,13 @@ class BankAccountService extends BaseService ->withTrashed() ->get(['transaction_id']) ->toArray(); - $expenses = array_flip(array_map(function($val) { + $expenses = array_flip(array_map(function ($val) { return $val['transaction_id']; }, $expenses)); + $vendorMap = $this->createVendorMap(); $bankAccounts = BankSubaccount::scope() - ->whereHas('bank_account', function($query) use ($bankId) { + ->whereHas('bank_account', function ($query) use ($bankId) { $query->where('bank_id', '=', $bankId); }) ->get(); @@ -64,13 +64,13 @@ class BankAccountService extends BaseService $finance = new Finance(); $finance->banks[$bankId] = $bank->getOFXBank($finance); $finance->banks[$bankId]->logins[] = new Login($finance->banks[$bankId], $username, $password); - + foreach ($finance->banks as $bank) { foreach ($bank->logins as $login) { $login->setup(); foreach ($login->accounts as $account) { $account->setup($includeTransactions); - if ($account = $this->parseBankAccount($account, $bankAccounts, $expenses, $includeTransactions)) { + if ($account = $this->parseBankAccount($account, $bankAccounts, $expenses, $includeTransactions, $vendorMap)) { $data[] = $account; } } @@ -83,9 +83,9 @@ class BankAccountService extends BaseService } } - private function parseBankAccount($account, $bankAccounts, $expenses, $includeTransactions) + private function parseBankAccount($account, $bankAccounts, $expenses, $includeTransactions, $vendorMap) { - $obj = new stdClass; + $obj = new stdClass(); $obj->account_name = ''; // look up bank account name @@ -106,7 +106,7 @@ class BankAccountService extends BaseService $obj->balance = Utils::formatMoney($account->ledgerBalance, CURRENCY_DOLLAR); if ($includeTransactions) { - $ofxParser = new \OfxParser\Parser; + $ofxParser = new \OfxParser\Parser(); $ofx = $ofxParser->loadFromString($account->response); $obj->start_date = $ofx->BankAccount->Statement->startDate; @@ -121,7 +121,13 @@ class BankAccountService extends BaseService if ($transaction->amount >= 0) { continue; } - $transaction->vendor = $this->prepareValue(substr($transaction->name, 0, 20)); + + // if vendor has already been imported use current name + $vendorName = trim(substr($transaction->name, 0, 20)); + $key = strtolower($vendorName); + $vendor = isset($vendorMap[$key]) ? $vendorMap[$key] : null; + + $transaction->vendor = $vendor ? $vendor->name : $this->prepareValue($vendorName); $transaction->info = $this->prepareValue(substr($transaction->name, 20)); $transaction->memo = $this->prepareValue($transaction->memo); $transaction->date = \Auth::user()->account->formatDate($transaction->date); @@ -133,15 +139,13 @@ class BankAccountService extends BaseService return $obj; } - private function prepareValue($value) { + private function prepareValue($value) + { return ucwords(strtolower(trim($value))); } - public function importExpenses($bankId, $input) { - $countVendors = 0; - $countExpenses = 0; - - // create a vendor map + private function createVendorMap() + { $vendorMap = []; $vendors = Vendor::scope() ->withTrashed() @@ -151,6 +155,15 @@ class BankAccountService extends BaseService $vendorMap[strtolower($vendor->transaction_name)] = $vendor; } + return $vendorMap; + } + + public function importExpenses($bankId, $input) + { + $vendorMap = $this->createVendorMap(); + $countVendors = 0; + $countExpenses = 0; + foreach ($input as $transaction) { $vendorName = $transaction['vendor']; $key = strtolower($vendorName); @@ -165,7 +178,7 @@ class BankAccountService extends BaseService $field => $info, 'name' => $vendorName, 'transaction_name' => $transaction['vendor_orig'], - 'vendorcontact' => [] + 'vendorcontact' => [], ]); $vendorMap[$key] = $vendor; $vendorMap[$transaction['vendor_orig']] = $vendor; @@ -191,7 +204,8 @@ class BankAccountService extends BaseService ]); } - private function determineInfoField($value) { + private function determineInfoField($value) + { if (preg_match("/^[0-9\-\(\)\.]+$/", $value)) { return 'work_phone'; } elseif (strpos($value, '.') !== false) { @@ -215,7 +229,7 @@ class BankAccountService extends BaseService 'bank_name', function ($model) { return link_to("bank_accounts/{$model->public_id}/edit", $model->bank_name); - } + }, ], [ 'bank_library_id', @@ -233,9 +247,8 @@ class BankAccountService extends BaseService uctrans('texts.edit_bank_account'), function ($model) { return URL::to("bank_accounts/{$model->public_id}/edit"); - } + }, ] ]; } - -} \ No newline at end of file +} diff --git a/app/Services/PushService.php b/app/Services/PushService.php new file mode 100644 index 0000000000..00591e2633 --- /dev/null +++ b/app/Services/PushService.php @@ -0,0 +1,171 @@ +devices Definition + * + * @param string token (push notification device token) + * @param string email (user email address - required for use as key) + * @param string device (ios, gcm etc etc) + * @param bool notify_sent + * @param bool notify_paid + * @param bool notify_approved + * @param bool notify_viewed + */ + +class PushService +{ + protected $pushFactory; + + /** + * @param PushFactory $pushFactory + */ + public function __construct(PushFactory $pushFactory) + { + $this->pushFactory = $pushFactory; + } + + /** + * @param $invoice - Invoice object + * @param $type - Type of notification, ie. Quote APPROVED, Invoice PAID, Invoice/Quote SENT, Invoice/Quote VIEWED + */ + + public function sendNotification($invoice, $type) + { + //check user has registered for push notifications + if(!$this->checkDeviceExists($invoice->account)) + return; + + //Harvest an array of devices that are registered for this notification type + $devices = json_decode($invoice->account->devices, TRUE); + + foreach($devices as $device) + { + if(($device["notify_{$type}"] == TRUE) && ($device['device'] == 'ios')) + $this->pushMessage($invoice, $device['token'], $device["notify_{$type}"]); + } + + + } + + + /** + * pushMessage function + * + * method to dispatch iOS notifications + * + * @param $invoice + * @param $token + * @param $type + */ + private function pushMessage($invoice, $token, $type) + { + $this->pushFactory->message($token, $this->messageType($invoice, $type)); + } + + + /** + * checkDeviceExists function + * + * Returns a boolean if this account has devices registered for PUSH notifications + * + * @param $account + * @return bool + */ + private function checkDeviceExists($account) + { + $devices = json_decode($account->devices, TRUE); + + if(count($devices) >= 1) + return TRUE; + else + return FALSE; + } + + /** + * messageType function + * + * method which formats an appropriate message depending on message type + * + * @param $invoice + * @param $type + * @return string + */ + private function messageType($invoice, $type) + { + switch($type) + { + case 'notify_sent': + return $this->entitySentMessage($invoice); + break; + + case 'notify_paid': + return $this->invoicePaidMessage($invoice); + break; + + case 'notify_approved': + return $this->quoteApprovedMessage($invoice); + break; + + case 'notify_viewed': + return $this->entityViewedMessage($invoice); + break; + } + } + + /** + * @param $invoice + * @return string + */ + private function entitySentMessage($invoice) + { + if($invoice->is_quote) + return 'Quote #{$invoice->invoice_number} sent!'; + else + return 'Invoice #{$invoice->invoice_number} sent!'; + + } + + /** + * @param $invoice + * @return string + */ + private function invoicePaidMessage($invoice) + { + return 'Invoice #{$invoice->invoice_number} paid!'; + } + + /** + * @param $invoice + * @return string + */ + private function quoteApprovedMessage($invoice) + { + return 'Quote #{$invoice->invoice_number} approved!'; + } + + /** + * @param $invoice + * @return string + */ + private function entityViewedMessage($invoice) + { + if($invoice->is_quote) + return 'Quote #{$invoice->invoice_number} viewed!'; + else + return 'Invoice #{$invoice->invoice_number} viewed!'; + + } + + + +} \ No newline at end of file diff --git a/app/Services/Registrar.php b/app/Services/Registrar.php deleted file mode 100644 index cf19d6f4b7..0000000000 --- a/app/Services/Registrar.php +++ /dev/null @@ -1,39 +0,0 @@ - 'required|max:255', - 'email' => 'required|email|max:255|unique:users', - 'password' => 'required|confirmed|min:6', - ]); - } - - /** - * Create a new user instance after a valid registration. - * - * @param array $data - * @return User - */ - public function create(array $data) - { - return User::create([ - 'name' => $data['name'], - 'email' => $data['email'], - 'password' => bcrypt($data['password']), - ]); - } - -} diff --git a/bootstrap/autoload.php b/bootstrap/autoload.php index f6387198c2..d1a406d259 100644 --- a/bootstrap/autoload.php +++ b/bootstrap/autoload.php @@ -30,7 +30,7 @@ require __DIR__.'/../vendor/autoload.php'; | */ -$compiledPath = __DIR__.'/../vendor/compiled.php'; +$compiledPath = __DIR__.'/cache/compiled.php'; if (file_exists($compiledPath)) { diff --git a/bootstrap/cache/.gitignore b/bootstrap/cache/.gitignore new file mode 100755 index 0000000000..d6b7ef32c8 --- /dev/null +++ b/bootstrap/cache/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/bower.json b/bower.json index c48c74feec..c395df6715 100644 --- a/bower.json +++ b/bower.json @@ -14,7 +14,7 @@ "underscore": "1.7.0", "jspdf": "1.0.272", "bootstrap-datepicker": "1.4.0", - "typeahead.js": "0.9.3", + "typeahead.js": "0.11.1", "accounting": "0.3.2", "spectrum": "1.3.4", "d3": "3.4.11", @@ -25,7 +25,8 @@ "moment-timezone": "~0.4.0", "quill": "~0.20.0", "datetimepicker": "~2.4.5", - "stacktrace-js": "~1.0.1" + "stacktrace-js": "~1.0.1", + "fuse.js": "~2.0.2" }, "resolutions": { "jquery": "~1.11" diff --git a/composer.json b/composer.json index 68d48cd648..599bb86582 100644 --- a/composer.json +++ b/composer.json @@ -10,11 +10,12 @@ } ], "require": { + "turbo124/laravel-push-notification": "dev-laravel5", "omnipay/mollie": "dev-master#22956c1a62a9662afa5f5d119723b413770ac525", "omnipay/2checkout": "dev-master#e9c079c2dde0d7ba461903b3b7bd5caf6dee1248", "omnipay/gocardless": "dev-master", "omnipay/stripe": "2.3.0", - "laravel/framework": "5.0.*", + "laravel/framework": "5.1.*", "patricktalmadge/bootstrapper": "5.5.x", "anahkiasen/former": "4.0.*@dev", "barryvdh/laravel-debugbar": "~2.0.2", @@ -27,7 +28,6 @@ "jsanc623/phpbenchtime": "2.x", "lokielse/omnipay-alipay": "dev-master", "coatesap/omnipay-datacash": "~2.0", - "alfaproject/omnipay-neteller": "1.0.*@dev", "mfauveau/omnipay-pacnet": "~2.0", "coatesap/omnipay-paymentsense": "2.0.0", "coatesap/omnipay-realex": "~2.0", diff --git a/composer.lock b/composer.lock index 5957493167..01454a6d58 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "fceb9a043eac244cb01d8e8378e6d66a", - "content-hash": "f717dc8e67caa65002f0f0689d4a5478", + "hash": "334783c40534b498757994eefba6b9d2", + "content-hash": "be4521507359c58fe19eb34102e78202", "packages": [ { "name": "agmscode/omnipay-agms", @@ -63,60 +63,6 @@ ], "time": "2015-03-21 20:06:25" }, - { - "name": "alfaproject/omnipay-neteller", - "version": "dev-master", - "source": { - "type": "git", - "url": "https://github.com/alfaproject/omnipay-neteller.git", - "reference": "e2b9129936cf45bf10e0dd406f897d2852e3d567" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/alfaproject/omnipay-neteller/zipball/e2b9129936cf45bf10e0dd406f897d2852e3d567", - "reference": "e2b9129936cf45bf10e0dd406f897d2852e3d567", - "shasum": "" - }, - "require": { - "omnipay/common": "~2.0" - }, - "require-dev": { - "omnipay/tests": "~2.0", - "satooshi/php-coveralls": "dev-master" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0.x-dev" - } - }, - "autoload": { - "psr-0": { - "Omnipay\\Neteller\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Joao Dias", - "email": "joao.dias@cherrygroup.com" - } - ], - "description": "Neteller driver for the Omnipay payment processing library", - "homepage": "https://github.com/alfaproject/omnipay-neteller", - "keywords": [ - "gateway", - "merchant", - "neteller", - "omnipay", - "pay", - "payment" - ], - "time": "2014-02-25 10:03:25" - }, { "name": "alfaproject/omnipay-skrill", "version": "dev-master", @@ -637,35 +583,29 @@ }, { "name": "classpreloader/classpreloader", - "version": "1.4.0", + "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/ClassPreloader/ClassPreloader.git", - "reference": "b76f3f4f603ebbe7e64351a7ef973431ddaf7b27" + "reference": "9b10b913c2bdf90c3d2e0d726b454fb7f77c552a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ClassPreloader/ClassPreloader/zipball/b76f3f4f603ebbe7e64351a7ef973431ddaf7b27", - "reference": "b76f3f4f603ebbe7e64351a7ef973431ddaf7b27", + "url": "https://api.github.com/repos/ClassPreloader/ClassPreloader/zipball/9b10b913c2bdf90c3d2e0d726b454fb7f77c552a", + "reference": "9b10b913c2bdf90c3d2e0d726b454fb7f77c552a", "shasum": "" }, "require": { - "nikic/php-parser": "~1.3", - "php": ">=5.3.3", - "symfony/console": "~2.1", - "symfony/filesystem": "~2.1", - "symfony/finder": "~2.1" + "nikic/php-parser": "^1.0|^2.0", + "php": ">=5.5.9" }, "require-dev": { - "phpunit/phpunit": "~4.0" + "phpunit/phpunit": "^4.8|^5.0" }, - "bin": [ - "classpreloader.php" - ], "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4-dev" + "dev-master": "3.0-dev" } }, "autoload": { @@ -684,7 +624,7 @@ }, { "name": "Graham Campbell", - "email": "graham@cachethq.io" + "email": "graham@alt-three.com" } ], "description": "Helps class loading performance by generating a single PHP file containing all of the autoloaded files for a specific use case", @@ -693,7 +633,7 @@ "class", "preload" ], - "time": "2015-05-26 10:57:51" + "time": "2015-11-09 22:51:51" }, { "name": "coatesap/omnipay-datacash", @@ -907,6 +847,33 @@ ], "time": "2015-12-15 20:31:39" }, + { + "name": "container-interop/container-interop", + "version": "1.1.0", + "source": { + "type": "git", + "url": "https://github.com/container-interop/container-interop.git", + "reference": "fc08354828f8fd3245f77a66b9e23a6bca48297e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/container-interop/container-interop/zipball/fc08354828f8fd3245f77a66b9e23a6bca48297e", + "reference": "fc08354828f8fd3245f77a66b9e23a6bca48297e", + "shasum": "" + }, + "type": "library", + "autoload": { + "psr-4": { + "Interop\\Container\\": "src/Interop/Container/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Promoting the interoperability of container objects (DIC, SL, etc.)", + "time": "2014-12-30 15:22:37" + }, { "name": "danielstjules/stringy", "version": "1.10.0", @@ -2143,16 +2110,16 @@ }, { "name": "guzzlehttp/psr7", - "version": "1.2.2", + "version": "1.2.3", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "f5d04bdd2881ac89abde1fb78cc234bce24327bb" + "reference": "2e89629ff057ebb49492ba08e6995d3a6a80021b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/f5d04bdd2881ac89abde1fb78cc234bce24327bb", - "reference": "f5d04bdd2881ac89abde1fb78cc234bce24327bb", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/2e89629ff057ebb49492ba08e6995d3a6a80021b", + "reference": "2e89629ff057ebb49492ba08e6995d3a6a80021b", "shasum": "" }, "require": { @@ -2197,7 +2164,7 @@ "stream", "uri" ], - "time": "2016-01-23 01:23:02" + "time": "2016-02-18 21:54:00" }, { "name": "illuminate/html", @@ -2306,12 +2273,12 @@ "source": { "type": "git", "url": "https://github.com/Intervention/image.git", - "reference": "86dfe2f2a95aa9eed58faf1cc1dae6534a6ce931" + "reference": "e368d262887dbb2fdfaf710880571ede51e9c0e6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Intervention/image/zipball/86dfe2f2a95aa9eed58faf1cc1dae6534a6ce931", - "reference": "86dfe2f2a95aa9eed58faf1cc1dae6534a6ce931", + "url": "https://api.github.com/repos/Intervention/image/zipball/e368d262887dbb2fdfaf710880571ede51e9c0e6", + "reference": "e368d262887dbb2fdfaf710880571ede51e9c0e6", "shasum": "" }, "require": { @@ -2360,49 +2327,7 @@ "thumbnail", "watermark" ], - "time": "2016-01-10 11:20:02" - }, - { - "name": "ircmaxell/password-compat", - "version": "v1.0.4", - "source": { - "type": "git", - "url": "https://github.com/ircmaxell/password_compat.git", - "reference": "5c5cde8822a69545767f7c7f3058cb15ff84614c" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/ircmaxell/password_compat/zipball/5c5cde8822a69545767f7c7f3058cb15ff84614c", - "reference": "5c5cde8822a69545767f7c7f3058cb15ff84614c", - "shasum": "" - }, - "require-dev": { - "phpunit/phpunit": "4.*" - }, - "type": "library", - "autoload": { - "files": [ - "lib/password.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Anthony Ferrara", - "email": "ircmaxell@php.net", - "homepage": "http://blog.ircmaxell.com" - } - ], - "description": "A compatibility library for the proposed simplified password hashing algorithm: https://wiki.php.net/rfc/password_hash", - "homepage": "https://github.com/ircmaxell/password_compat", - "keywords": [ - "hashing", - "password" - ], - "time": "2014-11-20 16:49:30" + "time": "2016-02-26 18:18:19" }, { "name": "jakub-onderka/php-console-color", @@ -2786,48 +2711,49 @@ }, { "name": "laravel/framework", - "version": "v5.0.35", + "version": "v5.1.31", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "37151cf533f468e2227605e4b9ac596154f6b92b" + "reference": "d899fbda59bf3ffcde11a9b443c01043b76f40b3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/37151cf533f468e2227605e4b9ac596154f6b92b", - "reference": "37151cf533f468e2227605e4b9ac596154f6b92b", + "url": "https://api.github.com/repos/laravel/framework/zipball/d899fbda59bf3ffcde11a9b443c01043b76f40b3", + "reference": "d899fbda59bf3ffcde11a9b443c01043b76f40b3", "shasum": "" }, "require": { - "classpreloader/classpreloader": "~1.2", + "classpreloader/classpreloader": "~2.0|~3.0", "danielstjules/stringy": "~1.8", "doctrine/inflector": "~1.0", "ext-mbstring": "*", - "ext-mcrypt": "*", "ext-openssl": "*", - "ircmaxell/password-compat": "~1.0", "jeremeamia/superclosure": "~2.0", "league/flysystem": "~1.0", "monolog/monolog": "~1.11", "mtdowling/cron-expression": "~1.0", - "nesbot/carbon": "~1.0", - "php": ">=5.4.0", - "psy/psysh": "0.4.*", + "nesbot/carbon": "~1.19", + "paragonie/random_compat": "~1.1", + "php": ">=5.5.9", + "psy/psysh": "0.7.*", "swiftmailer/swiftmailer": "~5.1", - "symfony/console": "2.6.*", - "symfony/debug": "2.6.*", - "symfony/finder": "2.6.*", - "symfony/http-foundation": "2.6.*", - "symfony/http-kernel": "2.6.*", - "symfony/process": "2.6.*", - "symfony/routing": "2.6.*", - "symfony/security-core": "2.6.*", - "symfony/translation": "2.6.*", - "symfony/var-dumper": "2.6.*", + "symfony/console": "2.7.*", + "symfony/css-selector": "2.7.*", + "symfony/debug": "2.7.*", + "symfony/dom-crawler": "2.7.*", + "symfony/finder": "2.7.*", + "symfony/http-foundation": "2.7.*", + "symfony/http-kernel": "2.7.*", + "symfony/process": "2.7.*", + "symfony/routing": "2.7.*", + "symfony/translation": "2.7.*", + "symfony/var-dumper": "2.7.*", "vlucas/phpdotenv": "~1.0" }, "replace": { "illuminate/auth": "self.version", + "illuminate/broadcasting": "self.version", "illuminate/bus": "self.version", "illuminate/cache": "self.version", "illuminate/config": "self.version", @@ -2840,7 +2766,6 @@ "illuminate/events": "self.version", "illuminate/exception": "self.version", "illuminate/filesystem": "self.version", - "illuminate/foundation": "self.version", "illuminate/hashing": "self.version", "illuminate/http": "self.version", "illuminate/log": "self.version", @@ -2857,27 +2782,29 @@ "illuminate/view": "self.version" }, "require-dev": { - "aws/aws-sdk-php": "~2.4", - "iron-io/iron_mq": "~1.5", - "mockery/mockery": "~0.9", + "aws/aws-sdk-php": "~3.0", + "iron-io/iron_mq": "~2.0", + "mockery/mockery": "~0.9.2", "pda/pheanstalk": "~3.0", "phpunit/phpunit": "~4.0", "predis/predis": "~1.0" }, "suggest": { - "aws/aws-sdk-php": "Required to use the SQS queue driver and SES mail driver (~2.4).", + "aws/aws-sdk-php": "Required to use the SQS queue driver and SES mail driver (~3.0).", "doctrine/dbal": "Required to rename columns and drop SQLite columns (~2.4).", - "guzzlehttp/guzzle": "Required to use the Mailgun and Mandrill mail drivers (~5.0).", - "iron-io/iron_mq": "Required to use the iron queue driver (~1.5).", - "league/flysystem-aws-s3-v2": "Required to use the Flysystem S3 driver (~1.0).", + "fzaninotto/faker": "Required to use the eloquent factory builder (~1.4).", + "guzzlehttp/guzzle": "Required to use the Mailgun and Mandrill mail drivers and the ping methods on schedules (~5.3|~6.0).", + "iron-io/iron_mq": "Required to use the iron queue driver (~2.0).", + "league/flysystem-aws-s3-v3": "Required to use the Flysystem S3 driver (~1.0).", "league/flysystem-rackspace": "Required to use the Flysystem Rackspace driver (~1.0).", "pda/pheanstalk": "Required to use the beanstalk queue driver (~3.0).", - "predis/predis": "Required to use the redis cache and queue drivers (~1.0)." + "predis/predis": "Required to use the redis cache and queue drivers (~1.0).", + "pusher/pusher-php-server": "Required to use the Pusher broadcast driver (~2.0)." }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0-dev" + "dev-master": "5.1-dev" } }, "autoload": { @@ -2908,7 +2835,7 @@ "framework", "laravel" ], - "time": "2016-02-02 14:55:52" + "time": "2016-02-24 15:13:21" }, { "name": "laravel/socialite", @@ -2966,24 +2893,24 @@ }, { "name": "laravelcollective/html", - "version": "v5.0.4", + "version": "v5.1.9", "source": { "type": "git", "url": "https://github.com/LaravelCollective/html.git", - "reference": "c55fda58b1a9a1b58bd04f97e0fb9ebc238a0a94" + "reference": "f62269629b2a1093039733517bd7e75b3f98dffb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/LaravelCollective/html/zipball/c55fda58b1a9a1b58bd04f97e0fb9ebc238a0a94", - "reference": "c55fda58b1a9a1b58bd04f97e0fb9ebc238a0a94", + "url": "https://api.github.com/repos/LaravelCollective/html/zipball/f62269629b2a1093039733517bd7e75b3f98dffb", + "reference": "f62269629b2a1093039733517bd7e75b3f98dffb", "shasum": "" }, "require": { - "illuminate/http": "~5.0", - "illuminate/routing": "~5.0", - "illuminate/session": "~5.0", - "illuminate/support": "~5.0", - "php": ">=5.4.0" + "illuminate/http": "5.1.*", + "illuminate/routing": "5.1.*", + "illuminate/session": "5.1.*", + "illuminate/support": "5.1.*", + "php": ">=5.5.9" }, "require-dev": { "mockery/mockery": "~0.9", @@ -3012,20 +2939,20 @@ "email": "adam@laravelcollective.com" } ], - "time": "2015-05-06 14:23:37" + "time": "2015-11-28 08:27:09" }, { "name": "league/flysystem", - "version": "1.0.16", + "version": "1.0.17", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem.git", - "reference": "183e1a610664baf6dcd6fceda415baf43cbdc031" + "reference": "02f5b6c9a8b9278c8381e3361e7bd9d641c740ca" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/183e1a610664baf6dcd6fceda415baf43cbdc031", - "reference": "183e1a610664baf6dcd6fceda415baf43cbdc031", + "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/02f5b6c9a8b9278c8381e3361e7bd9d641c740ca", + "reference": "02f5b6c9a8b9278c8381e3361e7bd9d641c740ca", "shasum": "" }, "require": { @@ -3038,8 +2965,7 @@ "ext-fileinfo": "*", "mockery/mockery": "~0.9", "phpspec/phpspec": "^2.2", - "phpspec/prophecy-phpunit": "~1.0", - "phpunit/phpunit": "~4.8" + "phpunit/phpunit": "~4.8 || ~5.0" }, "suggest": { "ext-fileinfo": "Required for MimeType", @@ -3096,7 +3022,7 @@ "sftp", "storage" ], - "time": "2015-12-19 20:16:43" + "time": "2016-02-19 15:35:38" }, { "name": "league/fractal", @@ -3792,32 +3718,38 @@ }, { "name": "nikic/php-parser", - "version": "v1.4.1", + "version": "v2.0.1", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "f78af2c9c86107aa1a34cd1dbb5bbe9eeb0d9f51" + "reference": "ce5be709d59b32dd8a88c80259028759991a4206" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/f78af2c9c86107aa1a34cd1dbb5bbe9eeb0d9f51", - "reference": "f78af2c9c86107aa1a34cd1dbb5bbe9eeb0d9f51", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/ce5be709d59b32dd8a88c80259028759991a4206", + "reference": "ce5be709d59b32dd8a88c80259028759991a4206", "shasum": "" }, "require": { "ext-tokenizer": "*", - "php": ">=5.3" + "php": ">=5.4" }, + "require-dev": { + "phpunit/phpunit": "~4.0" + }, + "bin": [ + "bin/php-parse" + ], "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4-dev" + "dev-master": "2.0-dev" } }, "autoload": { - "files": [ - "lib/bootstrap.php" - ] + "psr-4": { + "PhpParser\\": "lib/PhpParser" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -3833,7 +3765,7 @@ "parser", "php" ], - "time": "2015-09-19 14:15:08" + "time": "2016-02-28 19:48:28" }, { "name": "omnipay/2checkout", @@ -4654,7 +4586,7 @@ }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/omnipay-mollie/zipball/a89cb0d15447023b24c03f86873c1c1489cd021b", + "url": "https://api.github.com/repos/thephpleague/omnipay-mollie/zipball/efd491fdac7d1243e2dd1da5a964514e3aab2a5a", "reference": "22956c1a62a9662afa5f5d119723b413770ac525", "shasum": "" }, @@ -4703,16 +4635,16 @@ }, { "name": "omnipay/multisafepay", - "version": "V2.2.0", + "version": "v2.3.0", "source": { "type": "git", "url": "https://github.com/thephpleague/omnipay-multisafepay.git", - "reference": "a0f09abf404ca0dd21b553578d7f95df2bfa5318" + "reference": "342d0a3ba1a5ef0d788f20d23d0c70ce04ec3de1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/omnipay-multisafepay/zipball/a0f09abf404ca0dd21b553578d7f95df2bfa5318", - "reference": "a0f09abf404ca0dd21b553578d7f95df2bfa5318", + "url": "https://api.github.com/repos/thephpleague/omnipay-multisafepay/zipball/342d0a3ba1a5ef0d788f20d23d0c70ce04ec3de1", + "reference": "342d0a3ba1a5ef0d788f20d23d0c70ce04ec3de1", "shasum": "" }, "require": { @@ -4757,7 +4689,7 @@ "pay", "payment" ], - "time": "2015-01-14 04:01:43" + "time": "2016-02-18 00:06:08" }, { "name": "omnipay/netaxept", @@ -5164,16 +5096,16 @@ }, { "name": "omnipay/paypal", - "version": "v2.5.1", + "version": "v2.5.3", "source": { "type": "git", "url": "https://github.com/thephpleague/omnipay-paypal.git", - "reference": "b546d24241725061d44e60516f0fbce202336963" + "reference": "97fc3b1ff43e130ee911b35e139dcc853488d07a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/omnipay-paypal/zipball/b546d24241725061d44e60516f0fbce202336963", - "reference": "b546d24241725061d44e60516f0fbce202336963", + "url": "https://api.github.com/repos/thephpleague/omnipay-paypal/zipball/97fc3b1ff43e130ee911b35e139dcc853488d07a", + "reference": "97fc3b1ff43e130ee911b35e139dcc853488d07a", "shasum": "" }, "require": { @@ -5218,7 +5150,7 @@ "paypal", "purchase" ], - "time": "2016-01-13 07:03:27" + "time": "2016-02-29 00:06:43" }, { "name": "omnipay/pin", @@ -5566,16 +5498,16 @@ }, { "name": "paragonie/random_compat", - "version": "v1.2.0", + "version": "v1.2.1", "source": { "type": "git", "url": "https://github.com/paragonie/random_compat.git", - "reference": "b0e69d10852716b2ccbdff69c75c477637220790" + "reference": "f078eba3bcf140fd69b5fcc3ea5ac809abf729dc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/paragonie/random_compat/zipball/b0e69d10852716b2ccbdff69c75c477637220790", - "reference": "b0e69d10852716b2ccbdff69c75c477637220790", + "url": "https://api.github.com/repos/paragonie/random_compat/zipball/f078eba3bcf140fd69b5fcc3ea5ac809abf729dc", + "reference": "f078eba3bcf140fd69b5fcc3ea5ac809abf729dc", "shasum": "" }, "require": { @@ -5610,7 +5542,7 @@ "pseudorandom", "random" ], - "time": "2016-02-06 03:52:05" + "time": "2016-02-29 17:25:04" }, { "name": "patricktalmadge/bootstrapper", @@ -5866,28 +5798,29 @@ }, { "name": "psy/psysh", - "version": "v0.4.4", + "version": "v0.7.1", "source": { "type": "git", "url": "https://github.com/bobthecow/psysh.git", - "reference": "489816db71649bd95b416e3ed9062d40528ab0ac" + "reference": "5e8cedbe0a3681f18782594eefc78423f8401fc8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/bobthecow/psysh/zipball/489816db71649bd95b416e3ed9062d40528ab0ac", - "reference": "489816db71649bd95b416e3ed9062d40528ab0ac", + "url": "https://api.github.com/repos/bobthecow/psysh/zipball/5e8cedbe0a3681f18782594eefc78423f8401fc8", + "reference": "5e8cedbe0a3681f18782594eefc78423f8401fc8", "shasum": "" }, "require": { "dnoegel/php-xdg-base-dir": "0.1", "jakub-onderka/php-console-highlighter": "0.3.*", - "nikic/php-parser": "~1.0", - "php": ">=5.3.0", - "symfony/console": "~2.3.10|~2.4.2|~2.5" + "nikic/php-parser": "^1.2.1|~2.0", + "php": ">=5.3.9", + "symfony/console": "~2.3.10|^2.4.2|~3.0", + "symfony/var-dumper": "~2.7|~3.0" }, "require-dev": { "fabpot/php-cs-fixer": "~1.5", - "phpunit/phpunit": "~3.7|~4.0", + "phpunit/phpunit": "~3.7|~4.0|~5.0", "squizlabs/php_codesniffer": "~2.0", "symfony/finder": "~2.1|~3.0" }, @@ -5903,15 +5836,15 @@ "type": "library", "extra": { "branch-alias": { - "dev-develop": "0.4.x-dev" + "dev-develop": "0.8.x-dev" } }, "autoload": { "files": [ "src/Psy/functions.php" ], - "psr-0": { - "Psy\\": "src/" + "psr-4": { + "Psy\\": "src/Psy/" } }, "notification-url": "https://packagist.org/downloads/", @@ -5933,7 +5866,7 @@ "interactive", "shell" ], - "time": "2015-03-26 18:43:54" + "time": "2016-02-27 18:59:18" }, { "name": "samvaughton/omnipay-barclays-epdq", @@ -6003,12 +5936,12 @@ "source": { "type": "git", "url": "https://github.com/simshaun/recurr.git", - "reference": "53c1ddacc7c91b25cc21983731bc2c8137d143f6" + "reference": "4d875b0237dcef75ee0de80d9bd63609349568d4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/simshaun/recurr/zipball/53c1ddacc7c91b25cc21983731bc2c8137d143f6", - "reference": "53c1ddacc7c91b25cc21983731bc2c8137d143f6", + "url": "https://api.github.com/repos/simshaun/recurr/zipball/4d875b0237dcef75ee0de80d9bd63609349568d4", + "reference": "4d875b0237dcef75ee0de80d9bd63609349568d4", "shasum": "" }, "require": { @@ -6049,7 +5982,71 @@ "recurring", "rrule" ], - "time": "2015-12-10 10:27:22" + "time": "2016-02-22 17:40:00" + }, + { + "name": "sly/notification-pusher", + "version": "v2.2.12", + "source": { + "type": "git", + "url": "https://github.com/Ph3nol/NotificationPusher.git", + "reference": "f9a99edb4e26254baf1f7fb1354aa5a3f2c3b0ae" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Ph3nol/NotificationPusher/zipball/f9a99edb4e26254baf1f7fb1354aa5a3f2c3b0ae", + "reference": "f9a99edb4e26254baf1f7fb1354aa5a3f2c3b0ae", + "shasum": "" + }, + "require": { + "doctrine/inflector": "~1.0", + "php": ">=5.5", + "symfony/console": "~2.3", + "symfony/options-resolver": "~2.3", + "symfony/process": "~2.3", + "zendframework/zendservice-apple-apns": "^1.1.0", + "zendframework/zendservice-google-gcm": "1.*" + }, + "require-dev": { + "atoum/atoum": "dev-master" + }, + "bin": [ + "np" + ], + "type": "standalone", + "autoload": { + "psr-0": { + "Sly": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Cédric Dugat", + "email": "cedric@dugat.me" + }, + { + "name": "Contributors", + "homepage": "https://github.com/Ph3nol/NotificationPusher/contributors" + } + ], + "description": "Standalone PHP library for easy devices notifications push.", + "homepage": "https://github.com/Ph3nol/NotificationPusher", + "keywords": [ + "android", + "apns", + "apple", + "gcm", + "iphone", + "message", + "notification", + "push", + "pusher" + ], + "time": "2015-10-01 07:56:41" }, { "name": "softcommerce/omnipay-paytrace", @@ -6158,7 +6155,7 @@ }, { "name": "symfony/class-loader", - "version": "v3.0.2", + "version": "v3.0.3", "source": { "type": "git", "url": "https://github.com/symfony/class-loader.git", @@ -6214,26 +6211,24 @@ }, { "name": "symfony/console", - "version": "v2.6.13", - "target-dir": "Symfony/Component/Console", + "version": "v2.7.10", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "0e5e18ae09d3f5c06367759be940e9ed3f568359" + "reference": "ee91ec301cd88ee38ab14505025fe94bbc19a9c1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/0e5e18ae09d3f5c06367759be940e9ed3f568359", - "reference": "0e5e18ae09d3f5c06367759be940e9ed3f568359", + "url": "https://api.github.com/repos/symfony/console/zipball/ee91ec301cd88ee38ab14505025fe94bbc19a9c1", + "reference": "ee91ec301cd88ee38ab14505025fe94bbc19a9c1", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=5.3.9" }, "require-dev": { "psr/log": "~1.0", "symfony/event-dispatcher": "~2.1", - "symfony/phpunit-bridge": "~2.7", "symfony/process": "~2.1" }, "suggest": { @@ -6244,13 +6239,16 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "2.7-dev" } }, "autoload": { - "psr-0": { + "psr-4": { "Symfony\\Component\\Console\\": "" - } + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -6268,29 +6266,29 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2015-07-26 09:08:40" + "time": "2016-02-28 16:19:47" }, { "name": "symfony/css-selector", - "version": "v3.0.2", + "version": "v2.7.10", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "6605602690578496091ac20ec7a5cbd160d4dff4" + "reference": "5377825bb6496514f63603af417fa07afaa12357" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/6605602690578496091ac20ec7a5cbd160d4dff4", - "reference": "6605602690578496091ac20ec7a5cbd160d4dff4", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/5377825bb6496514f63603af417fa07afaa12357", + "reference": "5377825bb6496514f63603af417fa07afaa12357", "shasum": "" }, "require": { - "php": ">=5.5.9" + "php": ">=5.3.9" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "2.7-dev" } }, "autoload": { @@ -6321,25 +6319,24 @@ ], "description": "Symfony CssSelector Component", "homepage": "https://symfony.com", - "time": "2016-01-27 05:14:46" + "time": "2016-01-27 05:09:39" }, { "name": "symfony/debug", - "version": "v2.6.13", - "target-dir": "Symfony/Component/Debug", + "version": "v2.7.10", "source": { "type": "git", "url": "https://github.com/symfony/debug.git", - "reference": "fca5696e0c9787722baa8f2ad6940dfd7a6a6941" + "reference": "e96f1ff28e2b8b2f3b906245b18d5e6a52e73648" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/debug/zipball/fca5696e0c9787722baa8f2ad6940dfd7a6a6941", - "reference": "fca5696e0c9787722baa8f2ad6940dfd7a6a6941", + "url": "https://api.github.com/repos/symfony/debug/zipball/e96f1ff28e2b8b2f3b906245b18d5e6a52e73648", + "reference": "e96f1ff28e2b8b2f3b906245b18d5e6a52e73648", "shasum": "" }, "require": { - "php": ">=5.3.3", + "php": ">=5.3.9", "psr/log": "~1.0" }, "conflict": { @@ -6347,24 +6344,21 @@ }, "require-dev": { "symfony/class-loader": "~2.2", - "symfony/http-foundation": "~2.1", - "symfony/http-kernel": "~2.3.24|~2.5.9|~2.6,>=2.6.2", - "symfony/phpunit-bridge": "~2.7" - }, - "suggest": { - "symfony/http-foundation": "", - "symfony/http-kernel": "" + "symfony/http-kernel": "~2.3.24|~2.5.9|~2.6,>=2.6.2" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "2.7-dev" } }, "autoload": { - "psr-0": { + "psr-4": { "Symfony\\Component\\Debug\\": "" - } + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -6382,20 +6376,75 @@ ], "description": "Symfony Debug Component", "homepage": "https://symfony.com", - "time": "2015-07-08 05:59:48" + "time": "2016-01-25 23:34:19" }, { - "name": "symfony/event-dispatcher", - "version": "v2.8.2", + "name": "symfony/dom-crawler", + "version": "v2.7.10", "source": { "type": "git", - "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "ee278f7c851533e58ca307f66305ccb9188aceda" + "url": "https://github.com/symfony/dom-crawler.git", + "reference": "c7a6dfd2720581a61d06c04489e9b3df1e4f7eaf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/ee278f7c851533e58ca307f66305ccb9188aceda", - "reference": "ee278f7c851533e58ca307f66305ccb9188aceda", + "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/c7a6dfd2720581a61d06c04489e9b3df1e4f7eaf", + "reference": "c7a6dfd2720581a61d06c04489e9b3df1e4f7eaf", + "shasum": "" + }, + "require": { + "php": ">=5.3.9" + }, + "require-dev": { + "symfony/css-selector": "~2.3" + }, + "suggest": { + "symfony/css-selector": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\DomCrawler\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony DomCrawler Component", + "homepage": "https://symfony.com", + "time": "2016-02-28 16:19:47" + }, + { + "name": "symfony/event-dispatcher", + "version": "v2.8.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "78c468665c9568c3faaa9c416a7134308f2d85c3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/78c468665c9568c3faaa9c416a7134308f2d85c3", + "reference": "78c468665c9568c3faaa9c416a7134308f2d85c3", "shasum": "" }, "require": { @@ -6442,20 +6491,20 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", - "time": "2016-01-13 10:28:07" + "time": "2016-01-27 05:14:19" }, { - "name": "symfony/filesystem", - "version": "v2.8.2", + "name": "symfony/finder", + "version": "v2.7.10", "source": { "type": "git", - "url": "https://github.com/symfony/filesystem.git", - "reference": "637b64d0ee10f44ae98dbad651b1ecdf35a11e8c" + "url": "https://github.com/symfony/finder.git", + "reference": "addcb70b33affbca4f3979b0d000259b63dd6711" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/637b64d0ee10f44ae98dbad651b1ecdf35a11e8c", - "reference": "637b64d0ee10f44ae98dbad651b1ecdf35a11e8c", + "url": "https://api.github.com/repos/symfony/finder/zipball/addcb70b33affbca4f3979b0d000259b63dd6711", + "reference": "addcb70b33affbca4f3979b0d000259b63dd6711", "shasum": "" }, "require": { @@ -6464,12 +6513,12 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.8-dev" + "dev-master": "2.7-dev" } }, "autoload": { "psr-4": { - "Symfony\\Component\\Filesystem\\": "" + "Symfony\\Component\\Finder\\": "" }, "exclude-from-classmap": [ "/Tests/" @@ -6489,94 +6538,45 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony Filesystem Component", - "homepage": "https://symfony.com", - "time": "2016-01-13 10:28:07" - }, - { - "name": "symfony/finder", - "version": "v2.6.13", - "target-dir": "Symfony/Component/Finder", - "source": { - "type": "git", - "url": "https://github.com/symfony/finder.git", - "reference": "203a10f928ae30176deeba33512999233181dd28" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/203a10f928ae30176deeba33512999233181dd28", - "reference": "203a10f928ae30176deeba33512999233181dd28", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "symfony/phpunit-bridge": "~2.7" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.6-dev" - } - }, - "autoload": { - "psr-0": { - "Symfony\\Component\\Finder\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], "description": "Symfony Finder Component", "homepage": "https://symfony.com", - "time": "2015-07-09 16:02:48" + "time": "2016-02-22 16:12:29" }, { "name": "symfony/http-foundation", - "version": "v2.6.13", - "target-dir": "Symfony/Component/HttpFoundation", + "version": "v2.7.10", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "e8fd1b73ac1c3de1f76c73801ddf1a8ecb1c1c9c" + "reference": "6aeb70d26da8f30753111b3f9cf47eb0421c0735" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/e8fd1b73ac1c3de1f76c73801ddf1a8ecb1c1c9c", - "reference": "e8fd1b73ac1c3de1f76c73801ddf1a8ecb1c1c9c", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/6aeb70d26da8f30753111b3f9cf47eb0421c0735", + "reference": "6aeb70d26da8f30753111b3f9cf47eb0421c0735", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=5.3.9" }, "require-dev": { - "symfony/expression-language": "~2.4", - "symfony/phpunit-bridge": "~2.7" + "symfony/expression-language": "~2.4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "2.7-dev" } }, "autoload": { - "psr-0": { + "psr-4": { "Symfony\\Component\\HttpFoundation\\": "" }, "classmap": [ - "Symfony/Component/HttpFoundation/Resources/stubs" + "Resources/stubs" + ], + "exclude-from-classmap": [ + "/Tests/" ] }, "notification-url": "https://packagist.org/downloads/", @@ -6595,41 +6595,42 @@ ], "description": "Symfony HttpFoundation Component", "homepage": "https://symfony.com", - "time": "2015-07-22 10:08:40" + "time": "2016-02-28 16:19:47" }, { "name": "symfony/http-kernel", - "version": "v2.6.13", - "target-dir": "Symfony/Component/HttpKernel", + "version": "v2.7.10", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "cdd991d304fed833514dc44d6aafcf19397c26cb" + "reference": "11082f03c03e17dd2ca9c149988b229e04829fdc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/cdd991d304fed833514dc44d6aafcf19397c26cb", - "reference": "cdd991d304fed833514dc44d6aafcf19397c26cb", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/11082f03c03e17dd2ca9c149988b229e04829fdc", + "reference": "11082f03c03e17dd2ca9c149988b229e04829fdc", "shasum": "" }, "require": { - "php": ">=5.3.3", + "php": ">=5.3.9", "psr/log": "~1.0", "symfony/debug": "~2.6,>=2.6.2", "symfony/event-dispatcher": "~2.6,>=2.6.7", "symfony/http-foundation": "~2.5,>=2.5.4" }, + "conflict": { + "symfony/config": "<2.7" + }, "require-dev": { "symfony/browser-kit": "~2.3", "symfony/class-loader": "~2.1", - "symfony/config": "~2.0,>=2.0.5", + "symfony/config": "~2.7", "symfony/console": "~2.3", "symfony/css-selector": "~2.0,>=2.0.5", "symfony/dependency-injection": "~2.2", "symfony/dom-crawler": "~2.0,>=2.0.5", "symfony/expression-language": "~2.4", "symfony/finder": "~2.0,>=2.0.5", - "symfony/phpunit-bridge": "~2.7", "symfony/process": "~2.0,>=2.0.5", "symfony/routing": "~2.2", "symfony/stopwatch": "~2.3", @@ -6649,13 +6650,16 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "2.7-dev" } }, "autoload": { - "psr-0": { + "psr-4": { "Symfony\\Component\\HttpKernel\\": "" - } + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -6673,7 +6677,61 @@ ], "description": "Symfony HttpKernel Component", "homepage": "https://symfony.com", - "time": "2016-01-14 10:11:16" + "time": "2016-02-28 20:37:08" + }, + { + "name": "symfony/options-resolver", + "version": "v2.8.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/options-resolver.git", + "reference": "d1e6e9182d9e5af6367bf85175e708f8b4a828c0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/d1e6e9182d9e5af6367bf85175e708f8b4a828c0", + "reference": "d1e6e9182d9e5af6367bf85175e708f8b4a828c0", + "shasum": "" + }, + "require": { + "php": ">=5.3.9" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.8-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\OptionsResolver\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony OptionsResolver Component", + "homepage": "https://symfony.com", + "keywords": [ + "config", + "configuration", + "options" + ], + "time": "2016-01-21 09:05:51" }, { "name": "symfony/polyfill-php56", @@ -6785,35 +6843,34 @@ }, { "name": "symfony/process", - "version": "v2.6.13", - "target-dir": "Symfony/Component/Process", + "version": "v2.7.10", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "57f1e88bb5dafa449b83f9f265b11d52d517b3e9" + "reference": "faa89438017392585abdf7f5a47f3f5f282d93c1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/57f1e88bb5dafa449b83f9f265b11d52d517b3e9", - "reference": "57f1e88bb5dafa449b83f9f265b11d52d517b3e9", + "url": "https://api.github.com/repos/symfony/process/zipball/faa89438017392585abdf7f5a47f3f5f282d93c1", + "reference": "faa89438017392585abdf7f5a47f3f5f282d93c1", "shasum": "" }, "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "symfony/phpunit-bridge": "~2.7" + "php": ">=5.3.9" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "2.7-dev" } }, "autoload": { - "psr-0": { + "psr-4": { "Symfony\\Component\\Process\\": "" - } + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -6831,52 +6888,57 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", - "time": "2015-06-30 16:10:16" + "time": "2016-02-02 13:32:58" }, { "name": "symfony/routing", - "version": "v2.6.13", - "target-dir": "Symfony/Component/Routing", + "version": "v2.7.10", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "0a1764d41bbb54f3864808c50569ac382b44d128" + "reference": "c63128f6dd5095351a87cd7c8801963001e22aff" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/0a1764d41bbb54f3864808c50569ac382b44d128", - "reference": "0a1764d41bbb54f3864808c50569ac382b44d128", + "url": "https://api.github.com/repos/symfony/routing/zipball/c63128f6dd5095351a87cd7c8801963001e22aff", + "reference": "c63128f6dd5095351a87cd7c8801963001e22aff", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=5.3.9" + }, + "conflict": { + "symfony/config": "<2.7" }, "require-dev": { "doctrine/annotations": "~1.0", "doctrine/common": "~2.2", "psr/log": "~1.0", - "symfony/config": "~2.2", + "symfony/config": "~2.7", "symfony/expression-language": "~2.4", "symfony/http-foundation": "~2.3", - "symfony/phpunit-bridge": "~2.7", "symfony/yaml": "~2.0,>=2.0.5" }, "suggest": { "doctrine/annotations": "For using the annotation loader", "symfony/config": "For using the all-in-one router or any loader", "symfony/expression-language": "For using expression matching", + "symfony/http-foundation": "For using a Symfony Request object", "symfony/yaml": "For using the YAML loader" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "2.7-dev" } }, "autoload": { - "psr-0": { + "psr-4": { "Symfony\\Component\\Routing\\": "" - } + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -6900,96 +6962,32 @@ "uri", "url" ], - "time": "2015-07-09 16:02:48" - }, - { - "name": "symfony/security-core", - "version": "v2.6.13", - "target-dir": "Symfony/Component/Security/Core", - "source": { - "type": "git", - "url": "https://github.com/symfony/security-core.git", - "reference": "813cf2aaacccbbe1a4705aef8d4ac0d79d993a76" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/security-core/zipball/813cf2aaacccbbe1a4705aef8d4ac0d79d993a76", - "reference": "813cf2aaacccbbe1a4705aef8d4ac0d79d993a76", - "shasum": "" - }, - "require": { - "paragonie/random_compat": "~1.0", - "php": ">=5.3.3" - }, - "require-dev": { - "ircmaxell/password-compat": "1.0.*", - "psr/log": "~1.0", - "symfony/event-dispatcher": "~2.1", - "symfony/expression-language": "~2.6", - "symfony/http-foundation": "~2.4", - "symfony/phpunit-bridge": "~2.7", - "symfony/translation": "~2.0,>=2.0.5", - "symfony/validator": "~2.5,>=2.5.5" - }, - "suggest": { - "ircmaxell/password-compat": "For using the BCrypt password encoder in PHP <5.5", - "symfony/event-dispatcher": "", - "symfony/expression-language": "For using the expression voter", - "symfony/http-foundation": "", - "symfony/validator": "For using the user password constraint" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.6-dev" - } - }, - "autoload": { - "psr-0": { - "Symfony\\Component\\Security\\Core\\": "" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony Security Component - Core Library", - "homepage": "https://symfony.com", - "time": "2016-01-14 09:04:34" + "time": "2016-02-04 13:52:46" }, { "name": "symfony/translation", - "version": "v2.6.13", - "target-dir": "Symfony/Component/Translation", + "version": "v2.7.10", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "d84291215b5892834dd8ca8ee52f9cbdb8274904" + "reference": "4c61cf815af17eee4cebf0e4c66f56a2f704cfd8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/d84291215b5892834dd8ca8ee52f9cbdb8274904", - "reference": "d84291215b5892834dd8ca8ee52f9cbdb8274904", + "url": "https://api.github.com/repos/symfony/translation/zipball/4c61cf815af17eee4cebf0e4c66f56a2f704cfd8", + "reference": "4c61cf815af17eee4cebf0e4c66f56a2f704cfd8", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=5.3.9" + }, + "conflict": { + "symfony/config": "<2.7" }, "require-dev": { "psr/log": "~1.0", - "symfony/config": "~2.3,>=2.3.12", - "symfony/intl": "~2.3", - "symfony/phpunit-bridge": "~2.7", + "symfony/config": "~2.7", + "symfony/intl": "~2.4", "symfony/yaml": "~2.2" }, "suggest": { @@ -7000,13 +6998,16 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "2.7-dev" } }, "autoload": { - "psr-0": { + "psr-4": { "Symfony\\Component\\Translation\\": "" - } + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -7024,28 +7025,24 @@ ], "description": "Symfony Translation Component", "homepage": "https://symfony.com", - "time": "2015-07-08 05:59:48" + "time": "2016-02-01 20:45:15" }, { "name": "symfony/var-dumper", - "version": "v2.6.13", - "target-dir": "Symfony/Component/VarDumper", + "version": "v2.7.10", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "5fba957a30161d8724aade093593cd22f815bea2" + "reference": "e4fdc92abb3dae0d840f4276af701d58ddc9b733" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/5fba957a30161d8724aade093593cd22f815bea2", - "reference": "5fba957a30161d8724aade093593cd22f815bea2", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/e4fdc92abb3dae0d840f4276af701d58ddc9b733", + "reference": "e4fdc92abb3dae0d840f4276af701d58ddc9b733", "shasum": "" }, "require": { - "php": ">=5.3.3" - }, - "require-dev": { - "symfony/phpunit-bridge": "~2.7" + "php": ">=5.3.9" }, "suggest": { "ext-symfony_debug": "" @@ -7053,16 +7050,19 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.6-dev" + "dev-master": "2.7-dev" } }, "autoload": { "files": [ "Resources/functions/dump.php" ], - "psr-0": { + "psr-4": { "Symfony\\Component\\VarDumper\\": "" - } + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -7084,7 +7084,7 @@ "debug", "dump" ], - "time": "2015-07-01 10:03:42" + "time": "2016-02-12 17:39:33" }, { "name": "tijsverkoyen/css-to-inline-styles", @@ -7179,6 +7179,48 @@ ], "time": "2016-01-07 17:12:58" }, + { + "name": "turbo124/laravel-push-notification", + "version": "dev-laravel5", + "source": { + "type": "git", + "url": "https://github.com/turbo124/laravel-push-notification.git", + "reference": "b703b0fe02719a540139f5d26b73ac53a198b50d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/turbo124/laravel-push-notification/zipball/b703b0fe02719a540139f5d26b73ac53a198b50d", + "reference": "b703b0fe02719a540139f5d26b73ac53a198b50d", + "shasum": "" + }, + "require": { + "illuminate/support": "5.*", + "php": ">=5.3.0", + "sly/notification-pusher": "2.*" + }, + "type": "library", + "autoload": { + "psr-0": { + "Davibennun\\LaravelPushNotification": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "authors": [ + { + "name": "DaviBenNun", + "email": "davi@andradenunes.org" + } + ], + "description": "Laravel package to send push notifications to mobile devices (apns, gcm)", + "keywords": [ + "apns", + "gcm", + "laravel", + "notification", + "push" + ], + "time": "2015-06-15 13:11:17" + }, { "name": "twbs/bootstrap", "version": "v3.3.6", @@ -7330,12 +7372,12 @@ "source": { "type": "git", "url": "https://github.com/webpatser/laravel-countries.git", - "reference": "e29dcce821f2c4a522e35483c38632ca534db4ee" + "reference": "2a310c0ff1b112d3710223d3bd51e8a30c5a304d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webpatser/laravel-countries/zipball/e29dcce821f2c4a522e35483c38632ca534db4ee", - "reference": "e29dcce821f2c4a522e35483c38632ca534db4ee", + "url": "https://api.github.com/repos/webpatser/laravel-countries/zipball/2a310c0ff1b112d3710223d3bd51e8a30c5a304d", + "reference": "2a310c0ff1b112d3710223d3bd51e8a30c5a304d", "shasum": "" }, "require": { @@ -7374,7 +7416,7 @@ "iso_3166_3", "laravel" ], - "time": "2015-08-21 12:12:14" + "time": "2016-02-25 10:29:59" }, { "name": "wildbit/laravel-postmark-provider", @@ -7450,6 +7492,445 @@ "description": "A Swiftmailer Transport for Postmark.", "time": "2015-11-30 18:23:03" }, + { + "name": "zendframework/zend-escaper", + "version": "2.5.1", + "source": { + "type": "git", + "url": "https://github.com/zendframework/zend-escaper.git", + "reference": "a4b227d8a477f4e7e9073f8e0a7ae7dbd3104a73" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/zend-escaper/zipball/a4b227d8a477f4e7e9073f8e0a7ae7dbd3104a73", + "reference": "a4b227d8a477f4e7e9073f8e0a7ae7dbd3104a73", + "shasum": "" + }, + "require": { + "php": ">=5.3.23" + }, + "require-dev": { + "fabpot/php-cs-fixer": "1.7.*", + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.5-dev", + "dev-develop": "2.6-dev" + } + }, + "autoload": { + "psr-4": { + "Zend\\Escaper\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "homepage": "https://github.com/zendframework/zend-escaper", + "keywords": [ + "escaper", + "zf2" + ], + "time": "2015-06-03 14:05:37" + }, + { + "name": "zendframework/zend-http", + "version": "2.5.4", + "source": { + "type": "git", + "url": "https://github.com/zendframework/zend-http.git", + "reference": "7b920b4ec34b5ee58f76eb4e8c408b083121953c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/zend-http/zipball/7b920b4ec34b5ee58f76eb4e8c408b083121953c", + "reference": "7b920b4ec34b5ee58f76eb4e8c408b083121953c", + "shasum": "" + }, + "require": { + "php": "^5.5 || ^7.0", + "zendframework/zend-loader": "^2.5", + "zendframework/zend-stdlib": "^2.5 || ^3.0", + "zendframework/zend-uri": "^2.5", + "zendframework/zend-validator": "^2.5" + }, + "require-dev": { + "fabpot/php-cs-fixer": "1.7.*", + "phpunit/phpunit": "^4.0", + "zendframework/zend-config": "^2.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.5-dev", + "dev-develop": "2.6-dev" + } + }, + "autoload": { + "psr-4": { + "Zend\\Http\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "provides an easy interface for performing Hyper-Text Transfer Protocol (HTTP) requests", + "homepage": "https://github.com/zendframework/zend-http", + "keywords": [ + "http", + "zf2" + ], + "time": "2016-02-04 20:36:48" + }, + { + "name": "zendframework/zend-json", + "version": "2.6.1", + "source": { + "type": "git", + "url": "https://github.com/zendframework/zend-json.git", + "reference": "4c8705dbe4ad7d7e51b2876c5b9eea0ef916ba28" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/zend-json/zipball/4c8705dbe4ad7d7e51b2876c5b9eea0ef916ba28", + "reference": "4c8705dbe4ad7d7e51b2876c5b9eea0ef916ba28", + "shasum": "" + }, + "require": { + "php": "^5.5 || ^7.0" + }, + "require-dev": { + "fabpot/php-cs-fixer": "1.7.*", + "phpunit/phpunit": "~4.0", + "zendframework/zend-http": "^2.5.4", + "zendframework/zend-server": "^2.6.1", + "zendframework/zend-stdlib": "^2.5 || ^3.0", + "zendframework/zendxml": "^1.0.2" + }, + "suggest": { + "zendframework/zend-http": "Zend\\Http component, required to use Zend\\Json\\Server", + "zendframework/zend-server": "Zend\\Server component, required to use Zend\\Json\\Server", + "zendframework/zend-stdlib": "Zend\\Stdlib component, for use with caching Zend\\Json\\Server responses", + "zendframework/zendxml": "To support Zend\\Json\\Json::fromXml() usage" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.6-dev", + "dev-develop": "2.7-dev" + } + }, + "autoload": { + "psr-4": { + "Zend\\Json\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "provides convenience methods for serializing native PHP to JSON and decoding JSON to native PHP", + "homepage": "https://github.com/zendframework/zend-json", + "keywords": [ + "json", + "zf2" + ], + "time": "2016-02-04 21:20:26" + }, + { + "name": "zendframework/zend-loader", + "version": "2.5.1", + "source": { + "type": "git", + "url": "https://github.com/zendframework/zend-loader.git", + "reference": "c5fd2f071bde071f4363def7dea8dec7393e135c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/zend-loader/zipball/c5fd2f071bde071f4363def7dea8dec7393e135c", + "reference": "c5fd2f071bde071f4363def7dea8dec7393e135c", + "shasum": "" + }, + "require": { + "php": ">=5.3.23" + }, + "require-dev": { + "fabpot/php-cs-fixer": "1.7.*", + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.5-dev", + "dev-develop": "2.6-dev" + } + }, + "autoload": { + "psr-4": { + "Zend\\Loader\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "homepage": "https://github.com/zendframework/zend-loader", + "keywords": [ + "loader", + "zf2" + ], + "time": "2015-06-03 14:05:47" + }, + { + "name": "zendframework/zend-stdlib", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/zendframework/zend-stdlib.git", + "reference": "22eb098958980fbbe6b9a06f209f5a4b496cc0c1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/zend-stdlib/zipball/22eb098958980fbbe6b9a06f209f5a4b496cc0c1", + "reference": "22eb098958980fbbe6b9a06f209f5a4b496cc0c1", + "shasum": "" + }, + "require": { + "php": "^5.5 || ^7.0" + }, + "require-dev": { + "athletic/athletic": "~0.1", + "fabpot/php-cs-fixer": "1.7.*", + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.0-dev", + "dev-develop": "3.1-dev" + } + }, + "autoload": { + "psr-4": { + "Zend\\Stdlib\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "homepage": "https://github.com/zendframework/zend-stdlib", + "keywords": [ + "stdlib", + "zf2" + ], + "time": "2016-02-03 16:53:37" + }, + { + "name": "zendframework/zend-uri", + "version": "2.5.2", + "source": { + "type": "git", + "url": "https://github.com/zendframework/zend-uri.git", + "reference": "0bf717a239432b1a1675ae314f7c4acd742749ed" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/zend-uri/zipball/0bf717a239432b1a1675ae314f7c4acd742749ed", + "reference": "0bf717a239432b1a1675ae314f7c4acd742749ed", + "shasum": "" + }, + "require": { + "php": "^5.5 || ^7.0", + "zendframework/zend-escaper": "^2.5", + "zendframework/zend-validator": "^2.5" + }, + "require-dev": { + "fabpot/php-cs-fixer": "1.7.*", + "phpunit/phpunit": "~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.5-dev", + "dev-develop": "2.6-dev" + } + }, + "autoload": { + "psr-4": { + "Zend\\Uri\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "a component that aids in manipulating and validating » Uniform Resource Identifiers (URIs)", + "homepage": "https://github.com/zendframework/zend-uri", + "keywords": [ + "uri", + "zf2" + ], + "time": "2016-02-17 22:38:51" + }, + { + "name": "zendframework/zend-validator", + "version": "2.6.0", + "source": { + "type": "git", + "url": "https://github.com/zendframework/zend-validator.git", + "reference": "1315fead53358054e3f5fcf440c1a4cd5f0724db" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/zend-validator/zipball/1315fead53358054e3f5fcf440c1a4cd5f0724db", + "reference": "1315fead53358054e3f5fcf440c1a4cd5f0724db", + "shasum": "" + }, + "require": { + "container-interop/container-interop": "^1.1", + "php": "^5.5 || ^7.0", + "zendframework/zend-stdlib": "^2.7 || ^3.0" + }, + "require-dev": { + "fabpot/php-cs-fixer": "1.7.*", + "phpunit/phpunit": "^4.0", + "zendframework/zend-cache": "^2.6.1", + "zendframework/zend-config": "^2.6", + "zendframework/zend-db": "^2.5", + "zendframework/zend-filter": "^2.6", + "zendframework/zend-http": "^2.5.4", + "zendframework/zend-i18n": "^2.6", + "zendframework/zend-math": "^2.6", + "zendframework/zend-servicemanager": "^2.7.5 || ^3.0.3", + "zendframework/zend-session": "^2.5", + "zendframework/zend-uri": "^2.5" + }, + "suggest": { + "zendframework/zend-db": "Zend\\Db component", + "zendframework/zend-filter": "Zend\\Filter component, required by the Digits validator", + "zendframework/zend-i18n": "Zend\\I18n component to allow translation of validation error messages as well as to use the various Date validators", + "zendframework/zend-i18n-resources": "Translations of validator messages", + "zendframework/zend-math": "Zend\\Math component", + "zendframework/zend-servicemanager": "Zend\\ServiceManager component to allow using the ValidatorPluginManager and validator chains", + "zendframework/zend-session": "Zend\\Session component", + "zendframework/zend-uri": "Zend\\Uri component, required by the Uri and Sitemap\\Loc validators" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.6-dev", + "dev-develop": "2.7-dev" + } + }, + "autoload": { + "psr-4": { + "Zend\\Validator\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "provides a set of commonly needed validators", + "homepage": "https://github.com/zendframework/zend-validator", + "keywords": [ + "validator", + "zf2" + ], + "time": "2016-02-17 17:59:34" + }, + { + "name": "zendframework/zendservice-apple-apns", + "version": "1.2.0", + "source": { + "type": "git", + "url": "https://github.com/zendframework/ZendService_Apple_Apns.git", + "reference": "ee2c44ee833206c1eb95b2fb7be1e2335e7570eb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/ZendService_Apple_Apns/zipball/ee2c44ee833206c1eb95b2fb7be1e2335e7570eb", + "reference": "ee2c44ee833206c1eb95b2fb7be1e2335e7570eb", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "zendframework/zend-json": "~2.0" + }, + "require-dev": { + "phpunit/phpunit": "3.7.*" + }, + "type": "library", + "autoload": { + "psr-0": { + "ZendService\\Apple\\Apns\\": "library/", + "ZendService\\Apple\\Exception\\": "library/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "OOP Zend Framework 2 wrapper for Apple Push Notification Service", + "homepage": "http://packages.zendframework.com/", + "keywords": [ + "apns", + "apple", + "notification", + "push", + "zf2" + ], + "time": "2015-12-09 22:55:07" + }, + { + "name": "zendframework/zendservice-google-gcm", + "version": "1.0.3", + "source": { + "type": "git", + "url": "https://github.com/zendframework/ZendService_Google_Gcm.git", + "reference": "86d16e9dcb4d41677e6f691642856b3eb95a1073" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/ZendService_Google_Gcm/zipball/86d16e9dcb4d41677e6f691642856b3eb95a1073", + "reference": "86d16e9dcb4d41677e6f691642856b3eb95a1073", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "zendframework/zend-http": ">=2.0.0", + "zendframework/zend-json": ">=2.0.0" + }, + "require-dev": { + "phpunit/phpunit": "3.7.*" + }, + "type": "library", + "autoload": { + "psr-0": { + "ZendService\\Google\\Gcm\\": "library/", + "ZendService\\Google\\Exception\\": "library/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "OOP wrapper for Google Cloud Messaging", + "homepage": "http://packages.zendframework.com/", + "keywords": [ + "gcm", + "google", + "notification", + "push", + "zf2" + ], + "time": "2015-10-14 03:18:56" + }, { "name": "zircote/swagger-php", "version": "2.0.6", @@ -8452,16 +8933,16 @@ }, { "name": "sebastian/environment", - "version": "1.3.3", + "version": "1.3.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "6e7133793a8e5a5714a551a8324337374be209df" + "reference": "dc7a29032cf72b54f36dac15a1ca5b3a1b6029bf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/6e7133793a8e5a5714a551a8324337374be209df", - "reference": "6e7133793a8e5a5714a551a8324337374be209df", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/dc7a29032cf72b54f36dac15a1ca5b3a1b6029bf", + "reference": "dc7a29032cf72b54f36dac15a1ca5b3a1b6029bf", "shasum": "" }, "require": { @@ -8498,7 +8979,7 @@ "environment", "hhvm" ], - "time": "2015-12-02 08:37:27" + "time": "2016-02-26 18:40:46" }, { "name": "sebastian/exporter", @@ -8707,25 +9188,25 @@ }, { "name": "symfony/browser-kit", - "version": "v3.0.2", + "version": "v2.8.3", "source": { "type": "git", "url": "https://github.com/symfony/browser-kit.git", - "reference": "dde849a0485b70a24b36f826ed3fb95b904d80c3" + "reference": "6b2085020b4e86fcb7ae44c3ab8ddb91774b33d2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/browser-kit/zipball/dde849a0485b70a24b36f826ed3fb95b904d80c3", - "reference": "dde849a0485b70a24b36f826ed3fb95b904d80c3", + "url": "https://api.github.com/repos/symfony/browser-kit/zipball/6b2085020b4e86fcb7ae44c3ab8ddb91774b33d2", + "reference": "6b2085020b4e86fcb7ae44c3ab8ddb91774b33d2", "shasum": "" }, "require": { - "php": ">=5.5.9", - "symfony/dom-crawler": "~2.8|~3.0" + "php": ">=5.3.9", + "symfony/dom-crawler": "~2.0,>=2.0.5|~3.0.0" }, "require-dev": { - "symfony/css-selector": "~2.8|~3.0", - "symfony/process": "~2.8|~3.0" + "symfony/css-selector": "~2.0,>=2.0.5|~3.0.0", + "symfony/process": "~2.3.34|~2.7,>=2.7.6|~3.0.0" }, "suggest": { "symfony/process": "" @@ -8733,7 +9214,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "2.8-dev" } }, "autoload": { @@ -8760,135 +9241,20 @@ ], "description": "Symfony BrowserKit Component", "homepage": "https://symfony.com", - "time": "2016-01-27 11:34:55" - }, - { - "name": "symfony/dom-crawler", - "version": "v3.0.2", - "source": { - "type": "git", - "url": "https://github.com/symfony/dom-crawler.git", - "reference": "b693a9650aa004576b593ff2e91ae749dc90123d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/dom-crawler/zipball/b693a9650aa004576b593ff2e91ae749dc90123d", - "reference": "b693a9650aa004576b593ff2e91ae749dc90123d", - "shasum": "" - }, - "require": { - "php": ">=5.5.9", - "symfony/polyfill-mbstring": "~1.0" - }, - "require-dev": { - "symfony/css-selector": "~2.8|~3.0" - }, - "suggest": { - "symfony/css-selector": "" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.0-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Component\\DomCrawler\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony DomCrawler Component", - "homepage": "https://symfony.com", - "time": "2016-01-25 09:56:57" - }, - { - "name": "symfony/polyfill-mbstring", - "version": "v1.1.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "1289d16209491b584839022f29257ad859b8532d" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/1289d16209491b584839022f29257ad859b8532d", - "reference": "1289d16209491b584839022f29257ad859b8532d", - "shasum": "" - }, - "require": { - "php": ">=5.3.3" - }, - "suggest": { - "ext-mbstring": "For best performance" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.1-dev" - } - }, - "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Mbstring\\": "" - }, - "files": [ - "bootstrap.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill for the Mbstring extension", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "mbstring", - "polyfill", - "portable", - "shim" - ], - "time": "2016-01-20 09:13:37" + "time": "2016-01-27 11:34:40" }, { "name": "symfony/yaml", - "version": "v3.0.2", + "version": "v3.0.3", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "3cf0709d7fe936e97bee9e954382e449003f1d9a" + "reference": "b5ba64cd67ecd6887f63868fa781ca094bd1377c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/3cf0709d7fe936e97bee9e954382e449003f1d9a", - "reference": "3cf0709d7fe936e97bee9e954382e449003f1d9a", + "url": "https://api.github.com/repos/symfony/yaml/zipball/b5ba64cd67ecd6887f63868fa781ca094bd1377c", + "reference": "b5ba64cd67ecd6887f63868fa781ca094bd1377c", "shasum": "" }, "require": { @@ -8924,12 +9290,13 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2016-02-02 13:44:19" + "time": "2016-02-23 15:16:06" } ], "aliases": [], "minimum-stability": "stable", "stability-flags": { + "turbo124/laravel-push-notification": 20, "omnipay/mollie": 20, "omnipay/2checkout": 20, "omnipay/gocardless": 20, @@ -8939,7 +9306,6 @@ "webpatser/laravel-countries": 20, "barryvdh/laravel-ide-helper": 20, "lokielse/omnipay-alipay": 20, - "alfaproject/omnipay-neteller": 20, "alfaproject/omnipay-skrill": 20, "omnipay/bitpay": 20, "dwolla/omnipay-dwolla": 20, diff --git a/config/app.php b/config/app.php index cd55e8ee96..59a67d6777 100644 --- a/config/app.php +++ b/config/app.php @@ -137,7 +137,8 @@ return [ 'Illuminate\Translation\TranslationServiceProvider', 'Illuminate\Validation\ValidationServiceProvider', 'Illuminate\View\ViewServiceProvider', - + 'Illuminate\Broadcasting\BroadcastServiceProvider', + /* * Additional Providers */ @@ -163,6 +164,7 @@ return [ 'App\Providers\RouteServiceProvider', 'Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider', + 'Davibennun\LaravelPushNotification\LaravelPushNotificationServiceProvider', ], /* @@ -248,6 +250,7 @@ return [ 'Rocketeer' => 'Rocketeer\Facades\Rocketeer', 'Socialite' => 'Laravel\Socialite\Facades\Socialite', 'Excel' => 'Maatwebsite\Excel\Facades\Excel', + 'PushNotification' => 'Davibennun\LaravelPushNotification\Facades\PushNotification', ], diff --git a/config/push-notification.php b/config/push-notification.php new file mode 100644 index 0000000000..89dd441ab5 --- /dev/null +++ b/config/push-notification.php @@ -0,0 +1,23 @@ + [ + 'environment' =>'development', + 'certificate'=>app_path().'/certs/ninjaIOS.pem', + 'passPhrase' =>'', + 'service' =>'apns' + ], + 'ninjaIOS' => [ + 'environment' =>'production', + 'certificate'=>app_path().'/certs/productionNinjaIOS.pem', + 'passPhrase' =>'', + 'service' =>'apns' + ], + 'ninjaAndroid' => [ + 'environment' =>'production', + 'apiKey' =>'yourAPIKey', + 'service' =>'gcm' + ] + +]; \ No newline at end of file diff --git a/database/migrations/2016_02_28_081424_add_custom_invoice_fields.php b/database/migrations/2016_02_28_081424_add_custom_invoice_fields.php new file mode 100644 index 0000000000..3364261e33 --- /dev/null +++ b/database/migrations/2016_02_28_081424_add_custom_invoice_fields.php @@ -0,0 +1,51 @@ +string('custom_invoice_item_label1')->nullable(); + $table->string('custom_invoice_item_label2')->nullable(); + $table->string('recurring_invoice_number_prefix')->default('R'); + $table->boolean('enable_client_portal')->default(true); + $table->text('invoice_fields')->nullable(); + $table->text('devices')->nullable(); + }); + + Schema::table('invoice_items', function($table) { + $table->string('custom_value1')->nullable(); + $table->string('custom_value2')->nullable(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('accounts', function($table) { + $table->dropColumn('custom_invoice_item_label1'); + $table->dropColumn('custom_invoice_item_label2'); + $table->dropColumn('recurring_invoice_number_prefix'); + $table->dropColumn('enable_client_portal'); + $table->dropColumn('invoice_fields'); + $table->dropColumn('devices'); + }); + + Schema::table('accounts', function($table) { + $table->dropColumn('custom_value1'); + $table->dropColumn('custom_value2'); + }); + } +} diff --git a/database/seeds/CountriesSeeder.php b/database/seeds/CountriesSeeder.php index 7fe9c9e3fb..ff5c0e9948 100644 --- a/database/seeds/CountriesSeeder.php +++ b/database/seeds/CountriesSeeder.php @@ -1,5 +1,6 @@ delete(); - //Get all of the countries - $countries = Countries::getList(); - foreach ($countries as $countryId => $country){ - DB::table('countries')->insert(array( - 'id' => $countryId, - 'capital' => ((isset($country['capital'])) ? $country['capital'] : null), - 'citizenship' => ((isset($country['citizenship'])) ? $country['citizenship'] : null), - 'country_code' => $country['country-code'], - 'currency' => ((isset($country['currency'])) ? $country['currency'] : null), - 'currency_code' => ((isset($country['currency_code'])) ? $country['currency_code'] : null), - 'currency_sub_unit' => ((isset($country['currency_sub_unit'])) ? $country['currency_sub_unit'] : null), - 'full_name' => ((isset($country['full_name'])) ? $country['full_name'] : null), - 'iso_3166_2' => $country['iso_3166_2'], - 'iso_3166_3' => $country['iso_3166_3'], - 'name' => $country['name'], - 'region_code' => $country['region-code'], - 'sub_region_code' => $country['sub-region-code'], - 'eea' => (bool)$country['eea'] - )); + if (DB::table('countries')->count() == 0) { + //Get all of the countries + $countries = Countries::getList(); + foreach ($countries as $countryId => $country){ + DB::table('countries')->insert(array( + 'id' => $countryId, + 'capital' => ((isset($country['capital'])) ? $country['capital'] : null), + 'citizenship' => ((isset($country['citizenship'])) ? $country['citizenship'] : null), + 'country_code' => $country['country-code'], + 'currency' => ((isset($country['currency'])) ? $country['currency'] : null), + 'currency_code' => ((isset($country['currency_code'])) ? $country['currency_code'] : null), + 'currency_sub_unit' => ((isset($country['currency_sub_unit'])) ? $country['currency_sub_unit'] : null), + 'full_name' => ((isset($country['full_name'])) ? $country['full_name'] : null), + 'iso_3166_2' => $country['iso_3166_2'], + 'iso_3166_3' => $country['iso_3166_3'], + 'name' => $country['name'], + 'region_code' => $country['region-code'], + 'sub_region_code' => $country['sub-region-code'], + 'eea' => (bool)$country['eea'] + )); + } + } + + // Source: http://www.bitboost.com/ref/international-address-formats.html + // Source: https://en.wikipedia.org/wiki/Linguistic_issues_concerning_the_euro + $countries = [ + 'AR' => [ + 'swap_postal_code' => true, + ], + 'AT' => [ // Austria + 'swap_postal_code' => true, + 'swap_currency_symbol' => true, + ], + 'BE' => [ + 'swap_postal_code' => true, + ], + 'BG' => [ // Belgium + 'swap_currency_symbol' => true, + ], + 'CH' => [ + 'swap_postal_code' => true, + ], + 'CZ' => [ // Czech Republic + 'swap_currency_symbol' => true, + ], + 'DE' => [ // Germany + 'swap_postal_code' => true, + 'swap_currency_symbol' => true, + ], + 'DK' => [ + 'swap_postal_code' => true, + ], + 'EE' => [ // Estonia + 'swap_currency_symbol' => true, + ], + 'ES' => [ // Spain + 'swap_postal_code' => true, + 'swap_currency_symbol' => true, + ], + 'FI' => [ // Finland + 'swap_postal_code' => true, + 'swap_currency_symbol' => true, + ], + 'FR' => [ // France + 'swap_postal_code' => true, + 'swap_currency_symbol' => true, + ], + 'GR' => [ // Greece + 'swap_currency_symbol' => true, + ], + 'HR' => [ // Croatia + 'swap_currency_symbol' => true, + ], + 'HU' => [ // Hungary + 'swap_currency_symbol' => true, + ], + 'GL' => [ + 'swap_postal_code' => true, + ], + 'IE' => [ // Ireland + 'thousand_separator' => ',', + 'decimal_separator' => '.', + ], + 'IL' => [ + 'swap_postal_code' => true, + ], + 'IS' => [ // Iceland + 'swap_postal_code' => true, + 'swap_currency_symbol' => true, + ], + 'IT' => [ // Italy + 'swap_postal_code' => true, + 'swap_currency_symbol' => true, + ], + 'LT' => [ // Lithuania + 'swap_currency_symbol' => true, + ], + 'LU' => [ + 'swap_postal_code' => true, + ], + 'MY' => [ + 'swap_postal_code' => true, + ], + 'MX' => [ + 'swap_postal_code' => true, + ], + 'NL' => [ + 'swap_postal_code' => true, + ], + 'PL' => [ // Poland + 'swap_postal_code' => true, + 'swap_currency_symbol' => true, + ], + 'PT' => [ // Portugal + 'swap_postal_code' => true, + 'swap_currency_symbol' => true, + ], + 'RO' => [ // Romania + 'swap_currency_symbol' => true, + ], + 'SE' => [ // Sweden + 'swap_postal_code' => true, + 'swap_currency_symbol' => true, + ], + 'SI' => [ // Slovenia + 'swap_currency_symbol' => true, + ], + 'SK' => [ // Slovakia + 'swap_currency_symbol' => true, + ], + 'UY' => [ + 'swap_postal_code' => true, + ], + ]; + + foreach ($countries as $code => $data) { + $country = Country::where('iso_3166_2', '=', $code)->first(); + if (isset($data['swap_postal_code'])) { + $country->swap_postal_code = true; + } + if (isset($data['swap_currency_symbol'])) { + $country->swap_currency_symbol = true; + } + if (isset($data['thousand_separator'])) { + $country->thousand_separator = $data['thousand_separator']; + } + if (isset($data['decimal_separator'])) { + $country->decimal_separator = $data['decimal_separator']; + } + $country->save(); } } } \ No newline at end of file diff --git a/database/seeds/CurrenciesSeeder.php b/database/seeds/CurrenciesSeeder.php new file mode 100644 index 0000000000..9d46bbd123 --- /dev/null +++ b/database/seeds/CurrenciesSeeder.php @@ -0,0 +1,69 @@ + 'US Dollar', 'code' => 'USD', 'symbol' => '$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], + ['name' => 'Pound Sterling', 'code' => 'GBP', 'symbol' => '£', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], + ['name' => 'Euro', 'code' => 'EUR', 'symbol' => '€', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => ','], + ['name' => 'South African Rand', 'code' => 'ZAR', 'symbol' => 'R', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => ','], + ['name' => 'Danish Krone', 'code' => 'DKK', 'symbol' => 'kr ', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => ','], + ['name' => 'Israeli Shekel', 'code' => 'ILS', 'symbol' => 'NIS ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], + ['name' => 'Swedish Krona', 'code' => 'SEK', 'symbol' => 'kr ', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => ','], + ['name' => 'Kenyan Shilling', 'code' => 'KES', 'symbol' => 'KSh ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], + ['name' => 'Canadian Dollar', 'code' => 'CAD', 'symbol' => 'C$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], + ['name' => 'Philippine Peso', 'code' => 'PHP', 'symbol' => 'P ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], + ['name' => 'Indian Rupee', 'code' => 'INR', 'symbol' => 'Rs. ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], + ['name' => 'Australian Dollar', 'code' => 'AUD', 'symbol' => '$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], + ['name' => 'Singapore Dollar', 'code' => 'SGD', 'symbol' => '', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], + ['name' => 'Norske Kroner', 'code' => 'NOK', 'symbol' => 'kr ', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => ','], + ['name' => 'New Zealand Dollar', 'code' => 'NZD', 'symbol' => '$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], + ['name' => 'Vietnamese Dong', 'code' => 'VND', 'symbol' => '', 'precision' => '0', 'thousand_separator' => '.', 'decimal_separator' => ','], + ['name' => 'Swiss Franc', 'code' => 'CHF', 'symbol' => '', 'precision' => '2', 'thousand_separator' => '\'', 'decimal_separator' => '.'], + ['name' => 'Guatemalan Quetzal', 'code' => 'GTQ', 'symbol' => 'Q', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], + ['name' => 'Malaysian Ringgit', 'code' => 'MYR', 'symbol' => 'RM', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], + ['name' => 'Brazilian Real', 'code' => 'BRL', 'symbol' => 'R$', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => ','], + ['name' => 'Thai Baht', 'code' => 'THB', 'symbol' => '', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], + ['name' => 'Nigerian Naira', 'code' => 'NGN', 'symbol' => '', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], + ['name' => 'Argentine Peso', 'code' => 'ARS', 'symbol' => '$', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => ','], + ['name' => 'Bangladeshi Taka', 'code' => 'BDT', 'symbol' => 'Tk', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], + ['name' => 'United Arab Emirates Dirham', 'code' => 'AED', 'symbol' => 'DH ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], + ['name' => 'Hong Kong Dollar', 'code' => 'HKD', 'symbol' => '', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], + ['name' => 'Indonesian Rupiah', 'code' => 'IDR', 'symbol' => 'Rp', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], + ['name' => 'Mexican Peso', 'code' => 'MXN', 'symbol' => '$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], + ['name' => 'Egyptian Pound', 'code' => 'EGP', 'symbol' => 'E£', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], + ['name' => 'Colombian Peso', 'code' => 'COP', 'symbol' => '$', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => ','], + ['name' => 'West African Franc', 'code' => 'XOF', 'symbol' => 'CFA ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], + ['name' => 'Chinese Renminbi', 'code' => 'CNY', 'symbol' => 'RMB ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], + ['name' => 'Rwandan Franc', 'code' => 'RWF', 'symbol' => 'RF ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], + ['name' => 'Tanzanian Shilling', 'code' => 'TZS', 'symbol' => 'TSh ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], + ['name' => 'Netherlands Antillean Guilder', 'code' => 'ANG', 'symbol' => '', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => ','], + ['name' => 'Trinidad and Tobago Dollar', 'code' => 'TTD', 'symbol' => 'TT$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], + ['name' => 'East Caribbean Dollar', 'code' => 'XCD', 'symbol' => 'EC$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], + ['name' => 'Ghanaian Cedi', 'code' => 'GHS', 'symbol' => '', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], + ['name' => 'Bulgarian Lev', 'code' => 'BGN', 'symbol' => '', 'precision' => '2', 'thousand_separator' => ' ', 'decimal_separator' => '.'], + ['name' => 'Aruban Florin', 'code' => 'AWG', 'symbol' => 'Afl. ', 'precision' => '2', 'thousand_separator' => ' ', 'decimal_separator' => '.'], + ['name' => 'Turkish Lira', 'code' => 'TRY', 'symbol' => 'TL ', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => ','], + ['name' => 'Romanian New Leu', 'code' => 'RON', 'symbol' => '', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], + ]; + + foreach ($currencies as $currency) { + $record = Currency::whereCode($currency['code'])->first(); + if ($record) { + $record->name = $currency['name']; + $record->symbol = $currency['symbol']; + $record->thousand_separator = $currency['thousand_separator']; + $record->decimal_separator = $currency['decimal_separator']; + $record->save(); + } else { + Currency::create($currency); + } + } + } +} diff --git a/database/seeds/DatabaseSeeder.php b/database/seeds/DatabaseSeeder.php index 3584253c47..8791f30e71 100644 --- a/database/seeds/DatabaseSeeder.php +++ b/database/seeds/DatabaseSeeder.php @@ -19,5 +19,9 @@ class DatabaseSeeder extends Seeder $this->call('FontsSeeder'); $this->call('BanksSeeder'); $this->call('InvoiceStatusSeeder'); + $this->call('CurrenciesSeeder'); + $this->call('DateFormatsSeeder'); + $this->call('InvoiceDesignsSeeder'); + $this->call('PaymentTermsSeeder'); } } diff --git a/database/seeds/DateFormatsSeeder.php b/database/seeds/DateFormatsSeeder.php new file mode 100644 index 0000000000..40568ca300 --- /dev/null +++ b/database/seeds/DateFormatsSeeder.php @@ -0,0 +1,102 @@ + 'd/M/Y', 'picker_format' => 'dd/M/yyyy', 'label' => '10/Mar/2013'], + ['format' => 'd-M-Y', 'picker_format' => 'dd-M-yyyy', 'label' => '10-Mar-2013'], + ['format' => 'd/F/Y', 'picker_format' => 'dd/MM/yyyy', 'label' => '10/March/2013'], + ['format' => 'd-F-Y', 'picker_format' => 'dd-MM-yyyy', 'label' => '10-March-2013'], + ['format' => 'M j, Y', 'picker_format' => 'M d, yyyy', 'label' => 'Mar 10, 2013'], + ['format' => 'F j, Y', 'picker_format' => 'MM d, yyyy', 'label' => 'March 10, 2013'], + ['format' => 'D M j, Y', 'picker_format' => 'D MM d, yyyy', 'label' => 'Mon March 10, 2013'], + ['format' => 'Y-m-d', 'picker_format' => 'yyyy-mm-dd', 'label' => '2013-03-10'], + ['format' => 'd-m-Y', 'picker_format' => 'dd-mm-yyyy', 'label' => '20-03-2013'], + ['format' => 'm/d/Y', 'picker_format' => 'mm/dd/yyyy', 'label' => '03/20/2013'] + ]; + + foreach ($formats as $format) { + $record = DateFormat::whereLabel($format['label'])->first(); + if ($record) { + $record->format = $format['format']; + $record->picker_format = $format['picker_format']; + $record->save(); + } else { + DateFormat::create($format); + } + } + + // Date/time formats + $formats = [ + [ + 'format' => 'd/M/Y g:i a', + 'format_moment' => 'DD/MMM/YYYY h:mm:ss a', + 'label' => '10/Mar/2013' + ], + [ + 'format' => 'd-M-Y g:i a', + 'format_moment' => 'DD-MMM-YYYY h:mm:ss a', + 'label' => '10-Mar-2013' + ], + [ + 'format' => 'd/F/Y g:i a', + 'format_moment' => 'DD/MMMM/YYYY h:mm:ss a', + 'label' => '10/March/2013' + ], + [ + 'format' => 'd-F-Y g:i a', + 'format_moment' => 'DD-MMMM-YYYY h:mm:ss a', + 'label' => '10-March-2013' + ], + [ + 'format' => 'M j, Y g:i a', + 'format_moment' => 'MMM D, YYYY h:mm:ss a', + 'label' => 'Mar 10, 2013 6:15 pm' + ], + [ + 'format' => 'F j, Y g:i a', + 'format_moment' => 'MMMM D, YYYY h:mm:ss a', + 'label' => 'March 10, 2013 6:15 pm' + ], + [ + 'format' => 'D M jS, Y g:i a', + 'format_moment' => 'ddd MMM Do, YYYY h:mm:ss a', + 'label' => 'Mon March 10th, 2013 6:15 pm' + ], + [ + 'format' => 'Y-m-d g:i a', + 'format_moment' => 'YYYY-MMM-DD h:mm:ss a', + 'label' => '2013-03-10 6:15 pm' + ], + [ + 'format' => 'd-m-Y g:i a', + 'format_moment' => 'DD-MM-YYYY h:mm:ss a', + 'label' => '20-03-2013 6:15 pm' + ], + [ + 'format' => 'm/d/Y g:i a', + 'format_moment' => 'MM/DD/YYYY h:mm:ss a', + 'label' => '03/20/2013 6:15 pm' + ] + ]; + + foreach ($formats as $format) { + $record = DatetimeFormat::whereLabel($format['label'])->first(); + if ($record) { + $record->format = $format['format']; + $record->format_moment = $format['format_moment']; + $record->save(); + } else { + DatetimeFormat::create($format); + } + } + } +} diff --git a/database/seeds/InvoiceDesignsSeeder.php b/database/seeds/InvoiceDesignsSeeder.php new file mode 100644 index 0000000000..0e07067e1e --- /dev/null +++ b/database/seeds/InvoiceDesignsSeeder.php @@ -0,0 +1,43 @@ +first(); + if (!$record) { + $record = new InvoiceDesign; + $record->id = $i + 1; + $record->name = $design; + } + $record->pdfmake = $pdfmake; + $record->save(); + } + } + } + } + +} diff --git a/database/seeds/PaymentLibrariesSeeder.php b/database/seeds/PaymentLibrariesSeeder.php index d4d01c76fd..654ad9fe0e 100644 --- a/database/seeds/PaymentLibrariesSeeder.php +++ b/database/seeds/PaymentLibrariesSeeder.php @@ -14,16 +14,6 @@ class PaymentLibrariesSeeder extends Seeder { Eloquent::unguard(); - $this->createGateways(); - $this->createPaymentTerms(); - $this->createDateFormats(); - $this->createDatetimeFormats(); - $this->createInvoiceDesigns(); - $this->updateLocalization(); - } - - private function createGateways() { - $gateways = [ ['name' => 'BeanStream', 'provider' => 'BeanStream', 'payment_library_id' => 2], ['name' => 'Psigate', 'provider' => 'Psigate', 'payment_library_id' => 2], @@ -32,7 +22,7 @@ class PaymentLibrariesSeeder extends Seeder ['name' => 'Buckaroo', 'provider' => 'Buckaroo_CreditCard', 'payment_library_id' => 1], ['name' => 'Coinbase', 'provider' => 'Coinbase', 'payment_library_id' => 1], ['name' => 'DataCash', 'provider' => 'DataCash', 'payment_library_id' => 1], - ['name' => 'Neteller', 'provider' => 'Neteller', 'payment_library_id' => 1], + ['name' => 'Neteller', 'provider' => 'Neteller', 'payment_library_id' => 2], ['name' => 'Pacnet', 'provider' => 'Pacnet', 'payment_library_id' => 1], ['name' => 'PaymentSense', 'provider' => 'PaymentSense', 'payment_library_id' => 1], ['name' => 'Realex', 'provider' => 'Realex_Remote', 'payment_library_id' => 1], @@ -71,334 +61,4 @@ class PaymentLibrariesSeeder extends Seeder } } - - private function createPaymentTerms() { - - $paymentTerms = [ - ['num_days' => -1, 'name' => 'Net 0'], - ]; - - foreach ($paymentTerms as $paymentTerm) { - if (!DB::table('payment_terms')->where('name', '=', $paymentTerm['name'])->get()) { - PaymentTerm::create($paymentTerm); - } - } - - $currencies = [ - ['name' => 'US Dollar', 'code' => 'USD', 'symbol' => '$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], - ['name' => 'Pound Sterling', 'code' => 'GBP', 'symbol' => '£', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], - ['name' => 'Euro', 'code' => 'EUR', 'symbol' => '€', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => ','], - ['name' => 'South African Rand', 'code' => 'ZAR', 'symbol' => 'R', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => ','], - ['name' => 'Danish Krone', 'code' => 'DKK', 'symbol' => 'kr ', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => ','], - ['name' => 'Israeli Shekel', 'code' => 'ILS', 'symbol' => 'NIS ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], - ['name' => 'Swedish Krona', 'code' => 'SEK', 'symbol' => 'kr ', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => ','], - ['name' => 'Kenyan Shilling', 'code' => 'KES', 'symbol' => 'KSh ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], - ['name' => 'Canadian Dollar', 'code' => 'CAD', 'symbol' => 'C$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], - ['name' => 'Philippine Peso', 'code' => 'PHP', 'symbol' => 'P ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], - ['name' => 'Indian Rupee', 'code' => 'INR', 'symbol' => 'Rs. ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], - ['name' => 'Australian Dollar', 'code' => 'AUD', 'symbol' => '$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], - ['name' => 'Singapore Dollar', 'code' => 'SGD', 'symbol' => '', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], - ['name' => 'Norske Kroner', 'code' => 'NOK', 'symbol' => 'kr ', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => ','], - ['name' => 'New Zealand Dollar', 'code' => 'NZD', 'symbol' => '$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], - ['name' => 'Vietnamese Dong', 'code' => 'VND', 'symbol' => '', 'precision' => '0', 'thousand_separator' => '.', 'decimal_separator' => ','], - ['name' => 'Swiss Franc', 'code' => 'CHF', 'symbol' => '', 'precision' => '2', 'thousand_separator' => '\'', 'decimal_separator' => '.'], - ['name' => 'Guatemalan Quetzal', 'code' => 'GTQ', 'symbol' => 'Q', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], - ['name' => 'Malaysian Ringgit', 'code' => 'MYR', 'symbol' => 'RM', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], - ['name' => 'Brazilian Real', 'code' => 'BRL', 'symbol' => 'R$', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => ','], - ['name' => 'Thai Baht', 'code' => 'THB', 'symbol' => '', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], - ['name' => 'Nigerian Naira', 'code' => 'NGN', 'symbol' => '', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], - ['name' => 'Argentine Peso', 'code' => 'ARS', 'symbol' => '$', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => ','], - ['name' => 'Bangladeshi Taka', 'code' => 'BDT', 'symbol' => 'Tk', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], - ['name' => 'United Arab Emirates Dirham', 'code' => 'AED', 'symbol' => 'DH ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], - ['name' => 'Hong Kong Dollar', 'code' => 'HKD', 'symbol' => '', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], - ['name' => 'Indonesian Rupiah', 'code' => 'IDR', 'symbol' => 'Rp', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], - ['name' => 'Mexican Peso', 'code' => 'MXN', 'symbol' => '$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], - ['name' => 'Egyptian Pound', 'code' => 'EGP', 'symbol' => 'E£', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], - ['name' => 'Colombian Peso', 'code' => 'COP', 'symbol' => '$', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => ','], - ['name' => 'West African Franc', 'code' => 'XOF', 'symbol' => 'CFA ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], - ['name' => 'Chinese Renminbi', 'code' => 'CNY', 'symbol' => 'RMB ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], - ['name' => 'Rwandan Franc', 'code' => 'RWF', 'symbol' => 'RF ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], - ['name' => 'Tanzanian Shilling', 'code' => 'TZS', 'symbol' => 'TSh ', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], - ['name' => 'Netherlands Antillean Guilder', 'code' => 'ANG', 'symbol' => '', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => ','], - ['name' => 'Trinidad and Tobago Dollar', 'code' => 'TTD', 'symbol' => 'TT$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], - ['name' => 'East Caribbean Dollar', 'code' => 'XCD', 'symbol' => 'EC$', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], - ['name' => 'Ghanaian Cedi', 'code' => 'GHS', 'symbol' => '', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], - ['name' => 'Bulgarian Lev', 'code' => 'BGN', 'symbol' => '', 'precision' => '2', 'thousand_separator' => ' ', 'decimal_separator' => '.'], - ['name' => 'Aruban Florin', 'code' => 'AWG', 'symbol' => 'Afl. ', 'precision' => '2', 'thousand_separator' => ' ', 'decimal_separator' => '.'], - ['name' => 'Turkish Lira', 'code' => 'TRY', 'symbol' => 'TL ', 'precision' => '2', 'thousand_separator' => '.', 'decimal_separator' => ','], - ['name' => 'Romanian New Leu', 'code' => 'RON', 'symbol' => '', 'precision' => '2', 'thousand_separator' => ',', 'decimal_separator' => '.'], - ]; - - foreach ($currencies as $currency) { - $record = Currency::whereCode($currency['code'])->first(); - if ($record) { - $record->name = $currency['name']; - $record->symbol = $currency['symbol']; - $record->thousand_separator = $currency['thousand_separator']; - $record->decimal_separator = $currency['decimal_separator']; - $record->save(); - } else { - Currency::create($currency); - } - } - } - - private function createDateFormats() { - - $formats = [ - ['format' => 'd/M/Y', 'picker_format' => 'dd/M/yyyy', 'label' => '10/Mar/2013'], - ['format' => 'd-M-Y', 'picker_format' => 'dd-M-yyyy', 'label' => '10-Mar-2013'], - ['format' => 'd/F/Y', 'picker_format' => 'dd/MM/yyyy', 'label' => '10/March/2013'], - ['format' => 'd-F-Y', 'picker_format' => 'dd-MM-yyyy', 'label' => '10-March-2013'], - ['format' => 'M j, Y', 'picker_format' => 'M d, yyyy', 'label' => 'Mar 10, 2013'], - ['format' => 'F j, Y', 'picker_format' => 'MM d, yyyy', 'label' => 'March 10, 2013'], - ['format' => 'D M j, Y', 'picker_format' => 'D MM d, yyyy', 'label' => 'Mon March 10, 2013'], - ['format' => 'Y-m-d', 'picker_format' => 'yyyy-mm-dd', 'label' => '2013-03-10'], - ['format' => 'd-m-Y', 'picker_format' => 'dd-mm-yyyy', 'label' => '20-03-2013'], - ['format' => 'm/d/Y', 'picker_format' => 'mm/dd/yyyy', 'label' => '03/20/2013'] - ]; - - foreach ($formats as $format) { - $record = DateFormat::whereLabel($format['label'])->first(); - if ($record) { - $record->format = $format['format']; - $record->picker_format = $format['picker_format']; - $record->save(); - } else { - DateFormat::create($format); - } - } - } - - private function createDatetimeFormats() { - - $formats = [ - [ - 'format' => 'd/M/Y g:i a', - 'format_moment' => 'DD/MMM/YYYY h:mm:ss a', - 'label' => '10/Mar/2013' - ], - [ - 'format' => 'd-M-Y g:i a', - 'format_moment' => 'DD-MMM-YYYY h:mm:ss a', - 'label' => '10-Mar-2013' - ], - [ - 'format' => 'd/F/Y g:i a', - 'format_moment' => 'DD/MMMM/YYYY h:mm:ss a', - 'label' => '10/March/2013' - ], - [ - 'format' => 'd-F-Y g:i a', - 'format_moment' => 'DD-MMMM-YYYY h:mm:ss a', - 'label' => '10-March-2013' - ], - [ - 'format' => 'M j, Y g:i a', - 'format_moment' => 'MMM D, YYYY h:mm:ss a', - 'label' => 'Mar 10, 2013 6:15 pm' - ], - [ - 'format' => 'F j, Y g:i a', - 'format_moment' => 'MMMM D, YYYY h:mm:ss a', - 'label' => 'March 10, 2013 6:15 pm' - ], - [ - 'format' => 'D M jS, Y g:i a', - 'format_moment' => 'ddd MMM Do, YYYY h:mm:ss a', - 'label' => 'Mon March 10th, 2013 6:15 pm' - ], - [ - 'format' => 'Y-m-d g:i a', - 'format_moment' => 'YYYY-MMM-DD h:mm:ss a', - 'label' => '2013-03-10 6:15 pm' - ], - [ - 'format' => 'd-m-Y g:i a', - 'format_moment' => 'DD-MM-YYYY h:mm:ss a', - 'label' => '20-03-2013 6:15 pm' - ], - [ - 'format' => 'm/d/Y g:i a', - 'format_moment' => 'MM/DD/YYYY h:mm:ss a', - 'label' => '03/20/2013 6:15 pm' - ] - ]; - - foreach ($formats as $format) { - $record = DatetimeFormat::whereLabel($format['label'])->first(); - if ($record) { - $record->format = $format['format']; - $record->format_moment = $format['format_moment']; - $record->save(); - } else { - DatetimeFormat::create($format); - } - } - } - - private function createInvoiceDesigns() { - $designs = [ - 'Clean', - 'Bold', - 'Modern', - 'Plain', - 'Business', - 'Creative', - 'Elegant', - 'Hipster', - 'Playful', - 'Photo', - ]; - - for ($i=0; $ifirst(); - if (!$record) { - $record = new InvoiceDesign; - $record->id = $i + 1; - $record->name = $design; - } - $record->pdfmake = $pdfmake; - $record->save(); - } - } - } - } - - private function updateLocalization() { - // Source: http://www.bitboost.com/ref/international-address-formats.html - // Source: https://en.wikipedia.org/wiki/Linguistic_issues_concerning_the_euro - $countries = [ - 'AR' => [ - 'swap_postal_code' => true, - ], - 'AT' => [ // Austria - 'swap_postal_code' => true, - 'swap_currency_symbol' => true, - ], - 'BE' => [ - 'swap_postal_code' => true, - ], - 'BG' => [ // Belgium - 'swap_currency_symbol' => true, - ], - 'CH' => [ - 'swap_postal_code' => true, - ], - 'CZ' => [ // Czech Republic - 'swap_currency_symbol' => true, - ], - 'DE' => [ // Germany - 'swap_postal_code' => true, - 'swap_currency_symbol' => true, - ], - 'DK' => [ - 'swap_postal_code' => true, - ], - 'EE' => [ // Estonia - 'swap_currency_symbol' => true, - ], - 'ES' => [ // Spain - 'swap_postal_code' => true, - 'swap_currency_symbol' => true, - ], - 'FI' => [ // Finland - 'swap_postal_code' => true, - 'swap_currency_symbol' => true, - ], - 'FR' => [ // France - 'swap_postal_code' => true, - 'swap_currency_symbol' => true, - ], - 'GR' => [ // Greece - 'swap_currency_symbol' => true, - ], - 'HR' => [ // Croatia - 'swap_currency_symbol' => true, - ], - 'HU' => [ // Hungary - 'swap_currency_symbol' => true, - ], - 'GL' => [ - 'swap_postal_code' => true, - ], - 'IE' => [ // Ireland - 'thousand_separator' => ',', - 'decimal_separator' => '.', - ], - 'IL' => [ - 'swap_postal_code' => true, - ], - 'IS' => [ // Iceland - 'swap_postal_code' => true, - 'swap_currency_symbol' => true, - ], - 'IT' => [ // Italy - 'swap_postal_code' => true, - 'swap_currency_symbol' => true, - ], - 'LT' => [ // Lithuania - 'swap_currency_symbol' => true, - ], - 'LU' => [ - 'swap_postal_code' => true, - ], - 'MY' => [ - 'swap_postal_code' => true, - ], - 'MX' => [ - 'swap_postal_code' => true, - ], - 'NL' => [ - 'swap_postal_code' => true, - ], - 'PL' => [ // Poland - 'swap_postal_code' => true, - 'swap_currency_symbol' => true, - ], - 'PT' => [ // Portugal - 'swap_postal_code' => true, - 'swap_currency_symbol' => true, - ], - 'RO' => [ // Romania - 'swap_currency_symbol' => true, - ], - 'SE' => [ // Sweden - 'swap_postal_code' => true, - 'swap_currency_symbol' => true, - ], - 'SI' => [ // Slovenia - 'swap_currency_symbol' => true, - ], - 'SK' => [ // Slovakia - 'swap_currency_symbol' => true, - ], - 'UY' => [ - 'swap_postal_code' => true, - ], - ]; - - foreach ($countries as $code => $data) { - $country = Country::where('iso_3166_2', '=', $code)->first(); - if (isset($data['swap_postal_code'])) { - $country->swap_postal_code = true; - } - if (isset($data['swap_currency_symbol'])) { - $country->swap_currency_symbol = true; - } - if (isset($data['thousand_separator'])) { - $country->thousand_separator = $data['thousand_separator']; - } - if (isset($data['decimal_separator'])) { - $country->decimal_separator = $data['decimal_separator']; - } - $country->save(); - } - } - } diff --git a/database/seeds/PaymentTermsSeeder.php b/database/seeds/PaymentTermsSeeder.php new file mode 100644 index 0000000000..3dd8c48533 --- /dev/null +++ b/database/seeds/PaymentTermsSeeder.php @@ -0,0 +1,22 @@ + -1, 'name' => 'Net 0'], + ]; + + foreach ($paymentTerms as $paymentTerm) { + if (!DB::table('payment_terms')->where('name', '=', $paymentTerm['name'])->get()) { + PaymentTerm::create($paymentTerm); + } + } + } + +} diff --git a/public/built.js b/public/built.js index ec11a94ceb..5e28b8fb3f 100644 --- a/public/built.js +++ b/public/built.js @@ -27171,12 +27171,12 @@ d[b]="undefined"!==f.getType(g)?g:f.visitModel(j,c,a);break;default:d[b]=c(j,a.p !function(a){a.fn.datepicker.dates.es={days:["Domingo","Lunes","Martes","Miércoles","Jueves","Viernes","Sábado","Domingo"],daysShort:["Dom","Lun","Mar","Mié","Jue","Vie","Sáb","Dom"],daysMin:["Do","Lu","Ma","Mi","Ju","Vi","Sa","Do"],months:["Enero","Febrero","Marzo","Abril","Mayo","Junio","Julio","Agosto","Septiembre","Octubre","Noviembre","Diciembre"],monthsShort:["Ene","Feb","Mar","Abr","May","Jun","Jul","Ago","Sep","Oct","Nov","Dic"],today:"Hoy",clear:"Borrar",weekStart:1,format:"dd/mm/yyyy"}}(jQuery); !function(a){a.fn.datepicker.dates.sv={days:["Söndag","Måndag","Tisdag","Onsdag","Torsdag","Fredag","Lördag","Söndag"],daysShort:["Sön","Mån","Tis","Ons","Tor","Fre","Lör","Sön"],daysMin:["Sö","Må","Ti","On","To","Fr","Lö","Sö"],months:["Januari","Februari","Mars","April","Maj","Juni","Juli","Augusti","September","Oktober","November","December"],monthsShort:["Jan","Feb","Mar","Apr","Maj","Jun","Jul","Aug","Sep","Okt","Nov","Dec"],today:"Idag",format:"yyyy-mm-dd",weekStart:1,clear:"Rensa"}}(jQuery); /*! - * typeahead.js 0.9.3 - * https://github.com/twitter/typeahead - * Copyright 2013 Twitter, Inc. and other contributors; Licensed MIT + * typeahead.js 0.11.1 + * https://github.com/twitter/typeahead.js + * Copyright 2013-2015 Twitter, Inc. and other contributors; Licensed MIT */ -!function(a){var b="0.9.3",c={isMsie:function(){var a=/(msie) ([\w.]+)/i.exec(navigator.userAgent);return a?parseInt(a[2],10):!1},isBlankString:function(a){return!a||/^\s*$/.test(a)},escapeRegExChars:function(a){return a.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&")},isString:function(a){return"string"==typeof a},isNumber:function(a){return"number"==typeof a},isArray:a.isArray,isFunction:a.isFunction,isObject:a.isPlainObject,isUndefined:function(a){return"undefined"==typeof a},bind:a.proxy,bindAll:function(b){var c;for(var d in b)a.isFunction(c=b[d])&&(b[d]=a.proxy(c,b))},indexOf:function(a,b){for(var c=0;c=j?(clearTimeout(e),e=null,g=i,f=a.apply(c,d)):e||(e=setTimeout(h,j)),f}},tokenizeQuery:function(b){return a.trim(b).toLowerCase().split(/[\s]+/)},tokenizeText:function(b){return a.trim(b).toLowerCase().split(/[\s\-_]+/)},getProtocol:function(){return location.protocol},noop:function(){}},d=function(){var a=/\s+/;return{on:function(b,c){var d;if(!c)return this;for(this._callbacks=this._callbacks||{},b=b.split(a);d=b.shift();)this._callbacks[d]=this._callbacks[d]||[],this._callbacks[d].push(c);return this},trigger:function(b,c){var d,e;if(!this._callbacks)return this;for(b=b.split(a);d=b.shift();)if(e=this._callbacks[d])for(var f=0;fa;a++)(b=f.key(a)).match(this.keyMatcher)&&c.push(b.replace(this.keyMatcher,""));for(a=c.length;a--;)this.remove(c[a]);return this},isExpired:function(a){var d=e(f.getItem(this._ttlKey(a)));return c.isNumber(d)&&b()>d?!0:!1}}:{get:c.noop,set:c.noop,remove:c.noop,clear:c.noop,isExpired:c.noop},c.mixin(a.prototype,g),a}(),g=function(){function a(a){c.bindAll(this),a=a||{},this.sizeLimit=a.sizeLimit||10,this.cache={},this.cachedKeysByAge=[]}return c.mixin(a.prototype,{get:function(a){return this.cache[a]},set:function(a,b){var c;this.cachedKeysByAge.length===this.sizeLimit&&(c=this.cachedKeysByAge.shift(),delete this.cache[c]),this.cache[a]=b,this.cachedKeysByAge.push(a)}}),a}(),h=function(){function b(a){c.bindAll(this),a=c.isString(a)?{url:a}:a,i=i||new g,h=c.isNumber(a.maxParallelRequests)?a.maxParallelRequests:h||6,this.url=a.url,this.wildcard=a.wildcard||"%QUERY",this.filter=a.filter,this.replace=a.replace,this.ajaxSettings={type:"get",cache:a.cache,timeout:a.timeout,dataType:a.dataType||"json",beforeSend:a.beforeSend},this._get=(/^throttle$/i.test(a.rateLimitFn)?c.throttle:c.debounce)(this._get,a.rateLimitWait||300)}function d(){j++}function e(){j--}function f(){return h>j}var h,i,j=0,k={};return c.mixin(b.prototype,{_get:function(a,b){function c(c){var e=d.filter?d.filter(c):c;b&&b(e),i.set(a,c)}var d=this;f()?this._sendRequest(a).done(c):this.onDeckRequestArgs=[].slice.call(arguments,0)},_sendRequest:function(b){function c(){e(),k[b]=null,f.onDeckRequestArgs&&(f._get.apply(f,f.onDeckRequestArgs),f.onDeckRequestArgs=null)}var f=this,g=k[b];return g||(d(),g=k[b]=a.ajax(b,this.ajaxSettings).always(c)),g},get:function(a,b){var d,e,f=this,g=encodeURIComponent(a||"");return b=b||c.noop,d=this.replace?this.replace(this.url,g):this.url.replace(this.wildcard,g),(e=i.get(d))?c.defer(function(){b(f.filter?f.filter(e):e)}):this._get(d,b),!!e}}),b}(),i=function(){function d(b){c.bindAll(this),c.isString(b.template)&&!b.engine&&a.error("no template engine specified"),b.local||b.prefetch||b.remote||a.error("one of local, prefetch, or remote is required"),this.name=b.name||c.getUniqueId(),this.limit=b.limit||5,this.minLength=b.minLength||1,this.header=b.header,this.footer=b.footer,this.valueKey=b.valueKey||"value",this.template=e(b.template,b.engine,this.valueKey),this.local=b.local,this.prefetch=b.prefetch,this.remote=b.remote,this.itemHash={},this.adjacencyList={},this.storage=b.name?new f(b.name):null}function e(a,b,d){var e,f;return c.isFunction(a)?e=a:c.isString(a)?(f=b.compile(a),e=c.bind(f.render,f)):e=function(a){return"

"+a[d]+"

"},e}var g={thumbprint:"thumbprint",protocol:"protocol",itemHash:"itemHash",adjacencyList:"adjacencyList"};return c.mixin(d.prototype,{_processLocalData:function(a){this._mergeProcessedData(this._processData(a))},_loadPrefetchData:function(d){function e(a){var b=d.filter?d.filter(a):a,e=m._processData(b),f=e.itemHash,h=e.adjacencyList;m.storage&&(m.storage.set(g.itemHash,f,d.ttl),m.storage.set(g.adjacencyList,h,d.ttl),m.storage.set(g.thumbprint,n,d.ttl),m.storage.set(g.protocol,c.getProtocol(),d.ttl)),m._mergeProcessedData(e)}var f,h,i,j,k,l,m=this,n=b+(d.thumbprint||"");return this.storage&&(f=this.storage.get(g.thumbprint),h=this.storage.get(g.protocol),i=this.storage.get(g.itemHash),j=this.storage.get(g.adjacencyList)),k=f!==n||h!==c.getProtocol(),d=c.isString(d)?{url:d}:d,d.ttl=c.isNumber(d.ttl)?d.ttl:864e5,i&&j&&!k?(this._mergeProcessedData({itemHash:i,adjacencyList:j}),l=a.Deferred().resolve()):l=a.getJSON(d.url).done(e),l},_transformDatum:function(a){var b=c.isString(a)?a:a[this.valueKey],d=a.tokens||c.tokenizeText(b),e={value:b,tokens:d};return c.isString(a)?(e.datum={},e.datum[this.valueKey]=a):e.datum=a,e.tokens=c.filter(e.tokens,function(a){return!c.isBlankString(a)}),e.tokens=c.map(e.tokens,function(a){return a.toLowerCase()}),e},_processData:function(a){var b=this,d={},e={};return c.each(a,function(a,f){var g=b._transformDatum(f),h=c.getUniqueId(g.value);d[h]=g,c.each(g.tokens,function(a,b){var d=b.charAt(0),f=e[d]||(e[d]=[h]);!~c.indexOf(f,h)&&f.push(h)})}),{itemHash:d,adjacencyList:e}},_mergeProcessedData:function(a){var b=this;c.mixin(this.itemHash,a.itemHash),c.each(a.adjacencyList,function(a,c){var d=b.adjacencyList[a];b.adjacencyList[a]=d?d.concat(c):c})},_getLocalSuggestions:function(a){var b,d=this,e=[],f=[],g=[];return c.each(a,function(a,b){var d=b.charAt(0);!~c.indexOf(e,d)&&e.push(d)}),c.each(e,function(a,c){var e=d.adjacencyList[c];return e?(f.push(e),(!b||e.length").css({position:"absolute",left:"-9999px",visibility:"hidden",whiteSpace:"nowrap",fontFamily:b.css("font-family"),fontSize:b.css("font-size"),fontStyle:b.css("font-style"),fontVariant:b.css("font-variant"),fontWeight:b.css("font-weight"),wordSpacing:b.css("word-spacing"),letterSpacing:b.css("letter-spacing"),textIndent:b.css("text-indent"),textRendering:b.css("text-rendering"),textTransform:b.css("text-transform")}).insertAfter(b)}function f(a,b){return a=(a||"").replace(/^\s*/g,"").replace(/\s{2,}/g," "),b=(b||"").replace(/^\s*/g,"").replace(/\s{2,}/g," "),a===b}return c.mixin(b.prototype,d,{_handleFocus:function(){this.trigger("focused")},_handleBlur:function(){this.trigger("blured")},_handleSpecialKeyEvent:function(a){var b=this.specialKeyCodeMap[a.which||a.keyCode];b&&this.trigger(b+"Keyed",a)},_compareQueryToInputValue:function(){var a=this.getInputValue(),b=f(this.query,a),c=b?this.query.length!==a.length:!1;c?this.trigger("whitespaceChanged",{value:this.query}):b||this.trigger("queryChanged",{value:this.query=a})},destroy:function(){this.$hint.off(".tt"),this.$input.off(".tt"),this.$hint=this.$input=this.$overflowHelper=null},focus:function(){this.$input.focus()},blur:function(){this.$input.blur()},getQuery:function(){return this.query},setQuery:function(a){this.query=a},getInputValue:function(){return this.$input.val()},setInputValue:function(a,b){this.$input.val(a),!b&&this._compareQueryToInputValue()},getHintValue:function(){return this.$hint.val()},setHintValue:function(a){this.$hint.val(a)},getLanguageDirection:function(){return(this.$input.css("direction")||"ltr").toLowerCase()},isOverflow:function(){return this.$overflowHelper.text(this.getInputValue()),this.$overflowHelper.width()>this.$input.width()},isCursorAtEnd:function(){var a,b=this.$input.val().length,d=this.$input[0].selectionStart;return c.isNumber(d)?d===b:document.selection?(a=document.selection.createRange(),a.moveStart("character",-b),b===a.text.length):!0}}),b}(),k=function(){function b(b){c.bindAll(this),this.isOpen=!1,this.isEmpty=!0,this.isMouseOverDropdown=!1,this.$menu=a(b.menu).on("mouseenter.tt",this._handleMouseenter).on("mouseleave.tt",this._handleMouseleave).on("click.tt",".tt-suggestion",this._handleSelection).on("mouseover.tt",".tt-suggestion",this._handleMouseover)}function e(a){return a.data("suggestion")}var f={suggestionsList:''},g={suggestionsList:{display:"block"},suggestion:{whiteSpace:"nowrap",cursor:"pointer"},suggestionChild:{whiteSpace:"normal"}};return c.mixin(b.prototype,d,{_handleMouseenter:function(){this.isMouseOverDropdown=!0},_handleMouseleave:function(){this.isMouseOverDropdown=!1},_handleMouseover:function(b){var c=a(b.currentTarget);this._getSuggestions().removeClass("tt-is-under-cursor"),c.addClass("tt-is-under-cursor")},_handleSelection:function(b){var c=a(b.currentTarget);this.trigger("suggestionSelected",e(c))},_show:function(){this.$menu.css("display","block")},_hide:function(){this.$menu.hide()},_moveCursor:function(a){var b,c,d,f;if(this.isVisible()){if(b=this._getSuggestions(),c=b.filter(".tt-is-under-cursor"),c.removeClass("tt-is-under-cursor"),d=b.index(c)+a,d=(d+1)%(b.length+1)-1,-1===d)return this.trigger("cursorRemoved"),void 0;-1>d&&(d=b.length-1),f=b.eq(d).addClass("tt-is-under-cursor"),this._ensureVisibility(f),this.trigger("cursorMoved",e(f))}},_getSuggestions:function(){return this.$menu.find(".tt-suggestions > .tt-suggestion")},_ensureVisibility:function(a){var b=this.$menu.height()+parseInt(this.$menu.css("paddingTop"),10)+parseInt(this.$menu.css("paddingBottom"),10),c=this.$menu.scrollTop(),d=a.position().top,e=d+a.outerHeight(!0);0>d?this.$menu.scrollTop(c+d):e>b&&this.$menu.scrollTop(c+(e-b))},destroy:function(){this.$menu.off(".tt"),this.$menu=null},isVisible:function(){return this.isOpen&&!this.isEmpty},closeUnlessMouseIsOverDropdown:function(){this.isMouseOverDropdown||this.close()},close:function(){this.isOpen&&(this.isOpen=!1,this.isMouseOverDropdown=!1,this._hide(),this.$menu.find(".tt-suggestions > .tt-suggestion").removeClass("tt-is-under-cursor"),this.trigger("closed"))},open:function(){this.isOpen||(this.isOpen=!0,!this.isEmpty&&this._show(),this.trigger("opened"))},setLanguageDirection:function(a){var b={left:"0",right:"auto"},c={left:"auto",right:" 0"};"ltr"===a?this.$menu.css(b):this.$menu.css(c)},moveCursorUp:function(){this._moveCursor(-1)},moveCursorDown:function(){this._moveCursor(1)},getSuggestionUnderCursor:function(){var a=this._getSuggestions().filter(".tt-is-under-cursor").first();return a.length>0?e(a):null},getFirstSuggestion:function(){var a=this._getSuggestions().first();return a.length>0?e(a):null},renderSuggestions:function(b,d){var e,h,i,j,k,l="tt-dataset-"+b.name,m='
%body
',n=this.$menu.find("."+l);0===n.length&&(h=a(f.suggestionsList).css(g.suggestionsList),n=a("
").addClass(l).append(b.header).append(h).append(b.footer).appendTo(this.$menu)),d.length>0?(this.isEmpty=!1,this.isOpen&&this._show(),i=document.createElement("div"),j=document.createDocumentFragment(),c.each(d,function(c,d){d.dataset=b.name,e=b.template(d.datum),i.innerHTML=m.replace("%body",e),k=a(i.firstChild).css(g.suggestion).data("suggestion",d),k.children().each(function(){a(this).css(g.suggestionChild)}),j.appendChild(k[0])}),n.show().find(".tt-suggestions").html(j)):this.clearSuggestions(b.name),this.trigger("suggestionsRendered")},clearSuggestions:function(a){var b=a?this.$menu.find(".tt-dataset-"+a):this.$menu.find('[class^="tt-dataset-"]'),c=b.find(".tt-suggestions");b.hide(),c.empty(),0===this._getSuggestions().length&&(this.isEmpty=!0,this._hide())}}),b}(),l=function(){function b(a){var b,d,f;c.bindAll(this),this.$node=e(a.input),this.datasets=a.datasets,this.dir=null,this.eventBus=a.eventBus,b=this.$node.find(".tt-dropdown-menu"),d=this.$node.find(".tt-query"),f=this.$node.find(".tt-hint"),this.dropdownView=new k({menu:b}).on("suggestionSelected",this._handleSelection).on("cursorMoved",this._clearHint).on("cursorMoved",this._setInputValueToSuggestionUnderCursor).on("cursorRemoved",this._setInputValueToQuery).on("cursorRemoved",this._updateHint).on("suggestionsRendered",this._updateHint).on("opened",this._updateHint).on("closed",this._clearHint).on("opened closed",this._propagateEvent),this.inputView=new j({input:d,hint:f}).on("focused",this._openDropdown).on("blured",this._closeDropdown).on("blured",this._setInputValueToQuery).on("enterKeyed tabKeyed",this._handleSelection).on("queryChanged",this._clearHint).on("queryChanged",this._clearSuggestions).on("queryChanged",this._getSuggestions).on("whitespaceChanged",this._updateHint).on("queryChanged whitespaceChanged",this._openDropdown).on("queryChanged whitespaceChanged",this._setLanguageDirection).on("escKeyed",this._closeDropdown).on("escKeyed",this._setInputValueToQuery).on("tabKeyed upKeyed downKeyed",this._managePreventDefault).on("upKeyed downKeyed",this._moveDropdownCursor).on("upKeyed downKeyed",this._openDropdown).on("tabKeyed leftKeyed rightKeyed",this._autocomplete)}function e(b){var c=a(g.wrapper),d=a(g.dropdown),e=a(b),f=a(g.hint);c=c.css(h.wrapper),d=d.css(h.dropdown),f.css(h.hint).css({backgroundAttachment:e.css("background-attachment"),backgroundClip:e.css("background-clip"),backgroundColor:e.css("background-color"),backgroundImage:e.css("background-image"),backgroundOrigin:e.css("background-origin"),backgroundPosition:e.css("background-position"),backgroundRepeat:e.css("background-repeat"),backgroundSize:e.css("background-size")}),e.data("ttAttrs",{dir:e.attr("dir"),autocomplete:e.attr("autocomplete"),spellcheck:e.attr("spellcheck"),style:e.attr("style")}),e.addClass("tt-query").attr({autocomplete:"off",spellcheck:!1}).css(h.query);try{!e.attr("dir")&&e.attr("dir","auto")}catch(i){}return e.wrap(c).parent().prepend(f).append(d)}function f(a){var b=a.find(".tt-query");c.each(b.data("ttAttrs"),function(a,d){c.isUndefined(d)?b.removeAttr(a):b.attr(a,d)}),b.detach().removeData("ttAttrs").removeClass("tt-query").insertAfter(a),a.remove()}var g={wrapper:'',hint:'',dropdown:''},h={wrapper:{position:"relative",display:"inline-block"},hint:{position:"absolute",top:"0",left:"0",borderColor:"transparent",boxShadow:"none"},query:{position:"relative",verticalAlign:"top",backgroundColor:"transparent"},dropdown:{position:"absolute",top:"100%",left:"0",zIndex:"100",display:"none"}};return c.isMsie()&&c.mixin(h.query,{backgroundImage:"url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)"}),c.isMsie()&&c.isMsie()<=7&&(c.mixin(h.wrapper,{display:"inline",zoom:"1"}),c.mixin(h.query,{marginTop:"-1px"})),c.mixin(b.prototype,d,{_managePreventDefault:function(a){var b,c,d=a.data,e=!1;switch(a.type){case"tabKeyed":b=this.inputView.getHintValue(),c=this.inputView.getInputValue(),e=b&&b!==c;break;case"upKeyed":case"downKeyed":e=!d.shiftKey&&!d.ctrlKey&&!d.metaKey}e&&d.preventDefault()},_setLanguageDirection:function(){var a=this.inputView.getLanguageDirection();a!==this.dir&&(this.dir=a,this.$node.css("direction",a),this.dropdownView.setLanguageDirection(a))},_updateHint:function(){var a,b,d,e,f,g=this.dropdownView.getFirstSuggestion(),h=g?g.value:null,i=this.dropdownView.isVisible(),j=this.inputView.isOverflow();h&&i&&!j&&(a=this.inputView.getInputValue(),b=a.replace(/\s{2,}/g," ").replace(/^\s+/g,""),d=c.escapeRegExChars(b),e=new RegExp("^(?:"+d+")(.*$)","i"),f=e.exec(h),this.inputView.setHintValue(a+(f?f[1]:"")))},_clearHint:function(){this.inputView.setHintValue("")},_clearSuggestions:function(){this.dropdownView.clearSuggestions()},_setInputValueToQuery:function(){this.inputView.setInputValue(this.inputView.getQuery())},_setInputValueToSuggestionUnderCursor:function(a){var b=a.data;this.inputView.setInputValue(b.value,!0)},_openDropdown:function(){this.dropdownView.open()},_closeDropdown:function(a){this.dropdownView["blured"===a.type?"closeUnlessMouseIsOverDropdown":"close"]()},_moveDropdownCursor:function(a){var b=a.data;b.shiftKey||b.ctrlKey||b.metaKey||this.dropdownView["upKeyed"===a.type?"moveCursorUp":"moveCursorDown"]()},_handleSelection:function(a){var b="suggestionSelected"===a.type,d=b?a.data:this.dropdownView.getSuggestionUnderCursor();d&&(this.inputView.setInputValue(d.value),b?this.inputView.focus():a.data.preventDefault(),b&&c.isMsie()?c.defer(this.dropdownView.close):this.dropdownView.close(),this.eventBus.trigger("selected",d.datum,d.dataset))},_getSuggestions:function(){var a=this,b=this.inputView.getQuery();c.isBlankString(b)||c.each(this.datasets,function(c,d){d.getSuggestions(b,function(c){b===a.inputView.getQuery()&&a.dropdownView.renderSuggestions(d,c)})})},_autocomplete:function(a){var b,c,d,e,f;("rightKeyed"!==a.type&&"leftKeyed"!==a.type||(b=this.inputView.isCursorAtEnd(),c="ltr"===this.inputView.getLanguageDirection()?"leftKeyed"===a.type:"rightKeyed"===a.type,b&&!c))&&(d=this.inputView.getQuery(),e=this.inputView.getHintValue(),""!==e&&d!==e&&(f=this.dropdownView.getFirstSuggestion(),this.inputView.setInputValue(f.value),this.eventBus.trigger("autocompleted",f.datum,f.dataset)))},_propagateEvent:function(a){this.eventBus.trigger(a.type)},destroy:function(){this.inputView.destroy(),this.dropdownView.destroy(),f(this.$node),this.$node=null},setQuery:function(a){this.inputView.setQuery(a),this.inputView.setInputValue(a),this._clearHint(),this._clearSuggestions(),this._getSuggestions()}}),b}();!function(){var b,d={},f="ttView";b={initialize:function(b){function g(){var b,d=a(this),g=new e({el:d});b=c.map(h,function(a){return a.initialize()}),d.data(f,new l({input:d,eventBus:g=new e({el:d}),datasets:h})),a.when.apply(a,b).always(function(){c.defer(function(){g.trigger("initialized")})})}var h;return b=c.isArray(b)?b:[b],0===b.length&&a.error("no datasets provided"),h=c.map(b,function(a){var b=d[a.name]?d[a.name]:new i(a);return a.name&&(d[a.name]=b),b}),this.each(g)},destroy:function(){function b(){var b=a(this),c=b.data(f);c&&(c.destroy(),b.removeData(f))}return this.each(b)},setQuery:function(b){function c(){var c=a(this).data(f);c&&c.setQuery(b)}return this.each(c)}},jQuery.fn.typeahead=function(a){return b[a]?b[a].apply(this,[].slice.call(arguments,1)):b.initialize.apply(this,arguments)}}()}(window.jQuery); +!function(a,b){"function"==typeof define&&define.amd?define("typeahead.js",["jquery"],function(a){return b(a)}):"object"==typeof exports?module.exports=b(require("jquery")):b(jQuery)}(this,function(a){var b=function(){"use strict";return{isMsie:function(){return/(msie|trident)/i.test(navigator.userAgent)?navigator.userAgent.match(/(msie |rv:)(\d+(.\d+)?)/i)[2]:!1},isBlankString:function(a){return!a||/^\s*$/.test(a)},escapeRegExChars:function(a){return a.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&")},isString:function(a){return"string"==typeof a},isNumber:function(a){return"number"==typeof a},isArray:a.isArray,isFunction:a.isFunction,isObject:a.isPlainObject,isUndefined:function(a){return"undefined"==typeof a},isElement:function(a){return!(!a||1!==a.nodeType)},isJQuery:function(b){return b instanceof a},toStr:function(a){return b.isUndefined(a)||null===a?"":a+""},bind:a.proxy,each:function(b,c){function d(a,b){return c(b,a)}a.each(b,d)},map:a.map,filter:a.grep,every:function(b,c){var d=!0;return b?(a.each(b,function(a,e){return(d=c.call(null,e,a,b))?void 0:!1}),!!d):d},some:function(b,c){var d=!1;return b?(a.each(b,function(a,e){return(d=c.call(null,e,a,b))?!1:void 0}),!!d):d},mixin:a.extend,identity:function(a){return a},clone:function(b){return a.extend(!0,{},b)},getIdGenerator:function(){var a=0;return function(){return a++}},templatify:function(b){function c(){return String(b)}return a.isFunction(b)?b:c},defer:function(a){setTimeout(a,0)},debounce:function(a,b,c){var d,e;return function(){var f,g,h=this,i=arguments;return f=function(){d=null,c||(e=a.apply(h,i))},g=c&&!d,clearTimeout(d),d=setTimeout(f,b),g&&(e=a.apply(h,i)),e}},throttle:function(a,b){var c,d,e,f,g,h;return g=0,h=function(){g=new Date,e=null,f=a.apply(c,d)},function(){var i=new Date,j=b-(i-g);return c=this,d=arguments,0>=j?(clearTimeout(e),e=null,g=i,f=a.apply(c,d)):e||(e=setTimeout(h,j)),f}},stringify:function(a){return b.isString(a)?a:JSON.stringify(a)},noop:function(){}}}(),c=function(){"use strict";function a(a){var g,h;return h=b.mixin({},f,a),g={css:e(),classes:h,html:c(h),selectors:d(h)},{css:g.css,html:g.html,classes:g.classes,selectors:g.selectors,mixin:function(a){b.mixin(a,g)}}}function c(a){return{wrapper:'',menu:'
'}}function d(a){var c={};return b.each(a,function(a,b){c[b]="."+a}),c}function e(){var a={wrapper:{position:"relative",display:"inline-block"},hint:{position:"absolute",top:"0",left:"0",borderColor:"transparent",boxShadow:"none",opacity:"1"},input:{position:"relative",verticalAlign:"top",backgroundColor:"transparent"},inputWithNoHint:{position:"relative",verticalAlign:"top"},menu:{position:"absolute",top:"100%",left:"0",zIndex:"100",display:"none"},ltr:{left:"0",right:"auto"},rtl:{left:"auto",right:" 0"}};return b.isMsie()&&b.mixin(a.input,{backgroundImage:"url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)"}),a}var f={wrapper:"twitter-typeahead",input:"tt-input",hint:"tt-hint",menu:"tt-menu",dataset:"tt-dataset",suggestion:"tt-suggestion",selectable:"tt-selectable",empty:"tt-empty",open:"tt-open",cursor:"tt-cursor",highlight:"tt-highlight"};return a}(),d=function(){"use strict";function c(b){b&&b.el||a.error("EventBus initialized without el"),this.$el=a(b.el)}var d,e;return d="typeahead:",e={render:"rendered",cursorchange:"cursorchanged",select:"selected",autocomplete:"autocompleted"},b.mixin(c.prototype,{_trigger:function(b,c){var e;return e=a.Event(d+b),(c=c||[]).unshift(e),this.$el.trigger.apply(this.$el,c),e},before:function(a){var b,c;return b=[].slice.call(arguments,1),c=this._trigger("before"+a,b),c.isDefaultPrevented()},trigger:function(a){var b;this._trigger(a,[].slice.call(arguments,1)),(b=e[a])&&this._trigger(b,[].slice.call(arguments,1))}}),c}(),e=function(){"use strict";function a(a,b,c,d){var e;if(!c)return this;for(b=b.split(i),c=d?h(c,d):c,this._callbacks=this._callbacks||{};e=b.shift();)this._callbacks[e]=this._callbacks[e]||{sync:[],async:[]},this._callbacks[e][a].push(c);return this}function b(b,c,d){return a.call(this,"async",b,c,d)}function c(b,c,d){return a.call(this,"sync",b,c,d)}function d(a){var b;if(!this._callbacks)return this;for(a=a.split(i);b=a.shift();)delete this._callbacks[b];return this}function e(a){var b,c,d,e,g;if(!this._callbacks)return this;for(a=a.split(i),d=[].slice.call(arguments,1);(b=a.shift())&&(c=this._callbacks[b]);)e=f(c.sync,this,[b].concat(d)),g=f(c.async,this,[b].concat(d)),e()&&j(g);return this}function f(a,b,c){function d(){for(var d,e=0,f=a.length;!d&&f>e;e+=1)d=a[e].apply(b,c)===!1;return!d}return d}function g(){var a;return a=window.setImmediate?function(a){setImmediate(function(){a()})}:function(a){setTimeout(function(){a()},0)}}function h(a,b){return a.bind?a.bind(b):function(){a.apply(b,[].slice.call(arguments,0))}}var i=/\s+/,j=g();return{onSync:c,onAsync:b,off:d,trigger:e}}(),f=function(a){"use strict";function c(a,c,d){for(var e,f=[],g=0,h=a.length;h>g;g++)f.push(b.escapeRegExChars(a[g]));return e=d?"\\b("+f.join("|")+")\\b":"("+f.join("|")+")",c?new RegExp(e):new RegExp(e,"i")}var d={node:null,pattern:null,tagName:"strong",className:null,wordsOnly:!1,caseSensitive:!1};return function(e){function f(b){var c,d,f;return(c=h.exec(b.data))&&(f=a.createElement(e.tagName),e.className&&(f.className=e.className),d=b.splitText(c.index),d.splitText(c[0].length),f.appendChild(d.cloneNode(!0)),b.parentNode.replaceChild(f,d)),!!c}function g(a,b){for(var c,d=3,e=0;e