Merge remote-tracking branch 'upstream/develop' into develop

This commit is contained in:
David Bomba 2016-05-09 09:03:39 +10:00
commit 5197db449e
18 changed files with 1386 additions and 21 deletions

View File

@ -477,6 +477,7 @@ class PaymentController extends BaseController
if ($account->account_key == NINJA_ACCOUNT_KEY) {
Session::flash('trackEventCategory', '/account');
Session::flash('trackEventAction', '/buy_pro_plan');
Session::flash('trackEventAmount', $payment->amount);
}
return Redirect::to('view/'.$payment->invitation->invitation_key);

View File

@ -573,6 +573,7 @@ if (!defined('CONTACT_EMAIL')) {
define('REFERRAL_PROGRAM_URL', env('REFERRAL_PROGRAM_URL', 'https://www.invoiceninja.com/referral-program/'));
define('EMAIL_MARKUP_URL', env('EMAIL_MARKUP_URL', 'https://developers.google.com/gmail/markup'));
define('OFX_HOME_URL', env('OFX_HOME_URL', 'http://www.ofxhome.com/index.php/home/directory/all'));
define('GOOGLE_ANALYITCS_URL', env('GOOGLE_ANALYITCS_URL', 'https://www.google-analytics.com/collect'));
define('BLANK_IMAGE', 'data:image/png;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=');
@ -586,7 +587,6 @@ if (!defined('CONTACT_EMAIL')) {
define('INVOICE_DESIGNS_AFFILIATE_KEY', 'T3RS74');
define('SELF_HOST_AFFILIATE_KEY', '8S69AD');
define('PRO_PLAN_PRICE', env('PRO_PLAN_PRICE', 50));
define('PLAN_PRICE_PRO_MONTHLY', env('PLAN_PRICE_PRO_MONTHLY', 5));
define('PLAN_PRICE_PRO_YEARLY', env('PLAN_PRICE_PRO_YEARLY', 50));
define('PLAN_PRICE_ENTERPRISE_MONTHLY', env('PLAN_PRICE_ENTERPRISE_MONTHLY', 10));

View File

@ -0,0 +1,54 @@
<?php namespace App\Listeners;
use Log;
use Utils;
use App\Events\PaymentWasCreated;
class AnalyticsListener
{
public function trackRevenue(PaymentWasCreated $event)
{
if ( ! Utils::isNinja() || ! env('ANALYTICS_KEY')) {
return;
}
$payment = $event->payment;
$invoice = $payment->invoice;
$account = $payment->account;
if ($account->account_key != NINJA_ACCOUNT_KEY) {
return;
}
$analyticsId = env('ANALYTICS_KEY');
$client = $payment->client;
$amount = $payment->amount;
$base = "v=1&tid={$analyticsId}&cid{$client->public_id}&cu=USD&ti={$invoice->invoice_number}";
$url = $base . "&t=transaction&ta=ninja&tr={$amount}";
$this->sendAnalytics($url);
//Log::info($url);
$url = $base . "&t=item&in=plan&ip={$amount}&iq=1";
$this->sendAnalytics($url);
//Log::info($url);
}
private function sendAnalytics($data)
{
$data = json_encode($data);
$curl = curl_init();
$opts = [
CURLOPT_URL => GOOGLE_ANALYITCS_URL,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => 'POST',
CURLOPT_POSTFIELDS => $data,
];
curl_setopt_array($curl, $opts);
$response = curl_exec($curl);
curl_close($curl);
}
}

View File

@ -470,6 +470,13 @@ class Account extends Eloquent
return Document::getDirectFileUrl($this->logo, $this->getLogoDisk());
}
public function getPrimaryUser()
{
return $this->users()
->orderBy('id')
->first();
}
public function getToken($userId, $name)
{
foreach ($this->account_tokens as $token) {

View File

@ -199,6 +199,13 @@ class Client extends EntityModel
return $this->name;
}
public function getPrimaryContact()
{
return $this->contacts()
->whereIsPrimary(true)
->first();
}
public function getDisplayName()
{
if ($this->name) {

View File

@ -799,7 +799,6 @@ class Invoice extends EntityModel implements BalanceAffecting
$invitation = $this->invitations[0];
$link = $invitation->getLink('view', true);
$key = env('PHANTOMJS_CLOUD_KEY');
$curl = curl_init();
if (Utils::isNinjaDev()) {
$link = env('TEST_LINK');

View File

@ -333,28 +333,42 @@ class AccountRepository
{
$account->load('users');
$ninjaAccount = $this->getNinjaAccount();
$client = Client::whereAccountId($ninjaAccount->id)->wherePublicId($account->id)->first();
$ninjaUser = $ninjaAccount->getPrimaryUser();
$client = Client::whereAccountId($ninjaAccount->id)
->wherePublicId($account->id)
->first();
$clientExists = $client ? true : false;
if (!$client) {
$client = new Client();
$client->public_id = $account->id;
$client->user_id = $ninjaAccount->users()->first()->id;
$client->account_id = $ninjaAccount->id;
$client->user_id = $ninjaUser->id;
$client->currency_id = 1;
foreach (['name', 'address1', 'address2', 'city', 'state', 'postal_code', 'country_id', 'work_phone', 'language_id', 'vat_number'] as $field) {
$client->$field = $account->$field;
}
$ninjaAccount->clients()->save($client);
}
foreach (['name', 'address1', 'address2', 'city', 'state', 'postal_code', 'country_id', 'work_phone', 'language_id', 'vat_number'] as $field) {
$client->$field = $account->$field;
}
$client->save();
if ($clientExists) {
$contact = $client->getPrimaryContact();
} else {
$contact = new Contact();
$contact->user_id = $ninjaAccount->users()->first()->id;
$contact->user_id = $ninjaUser->id;
$contact->account_id = $ninjaAccount->id;
$contact->public_id = $account->id;
$contact->is_primary = true;
foreach (['first_name', 'last_name', 'email', 'phone'] as $field) {
$contact->$field = $account->users()->first()->$field;
}
$client->contacts()->save($contact);
}
$user = $account->getPrimaryUser();
foreach (['first_name', 'last_name', 'email', 'phone'] as $field) {
$contact->$field = $user->$field;
}
$client->contacts()->save($contact);
return $client;
}

View File

@ -98,6 +98,7 @@ class EventServiceProvider extends ServiceProvider {
'App\Listeners\SubscriptionListener@createdPayment',
'App\Listeners\InvoiceListener@createdPayment',
'App\Listeners\NotificationListener@createdPayment',
'App\Listeners\AnalyticsListener@trackRevenue',
],
'App\Events\PaymentWasArchived' => [
'App\Listeners\ActivityListener@archivedPayment',

View File

@ -24,6 +24,7 @@ class LanguageSeeder extends Seeder
['name' => 'French - Canada', 'locale' => 'fr_CA'],
['name' => 'Lithuanian', 'locale' => 'lt'],
['name' => 'Polish', 'locale' => 'pl'],
['name' => 'Czech', 'locale' => 'cs'],
];
foreach ($languages as $language) {

View File

@ -3,7 +3,7 @@
</p>
# Invoice Ninja
### [https://www.invoiceninja.com](https://www.invoiceninja.com)
### [http://www.invoiceninja.org](http://www.invoiceninja.org)
[![Build Status](https://travis-ci.org/invoiceninja/invoiceninja.svg?branch=develop)](https://travis-ci.org/invoiceninja/invoiceninja)
[![Join the chat at https://gitter.im/hillelcoren/invoice-ninja](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/hillelcoren/invoice-ninja?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)

View File

@ -0,0 +1,19 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Authentication Language Lines
|--------------------------------------------------------------------------
|
| The following language lines are used during authentication for various
| messages that we need to display to the user. You are free to modify
| these language lines according to your application's requirements.
|
*/
'failed' => 'Tyto přihlašovací údajě neodpovídají žadnému záznamu.',
'throttle' => 'Příliš mnoho pokusů o přihlášení. Zkuste to prosím znovu za :seconds vteřin.',
];

View File

@ -0,0 +1,19 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Pagination Language Lines
|--------------------------------------------------------------------------
|
| The following language lines are used by the paginator library to build
| the simple pagination links. You are free to change them to anything
| you want to customize your views to better match your application.
|
*/
'previous' => '&laquo; předchozí',
'next' => 'další &raquo;',
];

View File

@ -0,0 +1,22 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Password Reminder Language Lines
|--------------------------------------------------------------------------
|
| The following language lines are the default lines which match reasons
| that are given by the password broker for a password update attempt
| has failed, such as for an invalid token or invalid new password.
|
*/
'password' => 'Heslo musí obsahovat alespoň 6 znaků a musí odpovídat.',
'reset' => 'Heslo bylo obnoveno!',
'sent' => 'Upomínka ke změně hesla byla odeslána!',
'token' => 'Klíč pro obnovu hesla je nesprávný.',
'user' => 'Nepodařilo se najít uživatele s touto e-mailovou adresou.',
];

1106
resources/lang/cs/texts.php Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,115 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Validation Language Lines
|--------------------------------------------------------------------------
|
| The following language lines contain the default error messages used by
| the validator class. Some of these rules have multiple versions such
| such as the size rules. Feel free to tweak each of these messages.
|
*/
'accepted' => ':attribute musí být akceptován.',
'active_url' => ':attribute není platnou URL adresou.',
'after' => ':attribute musí být datum po :date.',
'alpha' => ':attribute může obsahovat pouze písmena.',
'alpha_dash' => ':attribute může obsahovat pouze písmena, číslice, pomlčky a podtržítka. České znaky (á, é, í, ó, ú, ů, ž, š, č, ř, ď, ť, ň) nejsou podporovány.',
'alpha_num' => ':attribute může obsahovat pouze písmena a číslice.',
'array' => ':attribute musí být pole.',
'before' => ':attribute musí být datum před :date.',
'between' => [
'numeric' => ':attribute musí být hodnota mezi :min a :max.',
'file' => ':attribute musí být větší než :min a menší než :max Kilobytů.',
'string' => ':attribute musí být delší než :min a kratší než :max znaků.',
'array' => ':attribute musí obsahovat nejméně :min a nesmí obsahovat více než :max prvků.',
],
'boolean' => ':attribute musí být true nebo false',
'confirmed' => ':attribute nebylo odsouhlaseno.',
'date' => ':attribute musí být platné datum.',
'date_format' => ':attribute není platný formát data podle :format.',
'different' => ':attribute a :other se musí lišit.',
'digits' => ':attribute musí být :digits pozic dlouhé.',
'digits_between' => ':attribute musí být dlouhé nejméně :min a nejvíce :max pozic.',
'distinct' => 'The :attribute field has a duplicate value.',
'email' => ':attribute není platný formát.',
'exists' => 'Zvolená hodnota pro :attribute není platná.',
'filled' => ':attribute musí být vyplněno.',
'image' => ':attribute musí být obrázek.',
'in' => 'Zvolená hodnota pro :attribute není platná.',
'in_array' => 'The :attribute field does not exist in :other.',
'integer' => ':attribute musí být celé číslo.',
'ip' => ':attribute musí být platnou IP adresou.',
'json' => ':attribute musí být platný JSON řetězec.',
'max' => [
'numeric' => ':attribute musí být nižší než :max.',
'file' => ':attribute musí být menší než :max Kilobytů.',
'string' => ':attribute musí být kratší než :max znaků.',
'array' => ':attribute nesmí obsahovat více než :max prvků.',
],
'mimes' => ':attribute musí být jeden z následujících datových typů :values.',
'min' => [
'numeric' => ':attribute musí být větší než :min.',
'file' => ':attribute musí být větší než :min Kilobytů.',
'string' => ':attribute musí být delší než :min znaků.',
'array' => ':attribute musí obsahovat více než :min prvků.',
],
'not_in' => 'Zvolená hodnota pro :attribute je neplatná.',
'numeric' => ':attribute musí být číslo.',
'present' => 'The :attribute field must be present.',
'regex' => ':attribute nemá správný formát.',
'required' => ':attribute musí být vyplněno.',
'required_if' => ':attribute musí být vyplněno pokud :other je :value.',
'required_unless' => 'The :attribute field is required unless :other is in :values.',
'required_with' => ':attribute musí být vyplněno pokud :values je vyplněno.',
'required_with_all' => ':attribute musí být vyplněno pokud :values je zvoleno.',
'required_without' => ':attribute musí být vyplněno pokud :values není vyplněno.',
'required_without_all' => ':attribute musí být vyplněno pokud není žádné z :values zvoleno.',
'same' => ':attribute a :other se musí shodovat.',
'size' => [
'numeric' => ':attribute musí být přesně :size.',
'file' => ':attribute musí mít přesně :size Kilobytů.',
'string' => ':attribute musí být přesně :size znaků dlouhý.',
'array' => ':attribute musí obsahovat právě :size prvků.',
],
'string' => ':attribute musí být řetězec znaků.',
'timezone' => ':attribute musí být platná časová zóna.',
'unique' => ':attribute musí být unikátní.',
'url' => 'Formát :attribute je neplatný.',
/*
|--------------------------------------------------------------------------
| Custom Validation Language Lines
|--------------------------------------------------------------------------
|
| Here you may specify custom validation messages for attributes using the
| convention "attribute.rule" to name the lines. This makes it quick to
| specify a specific custom language line for a given attribute rule.
|
*/
'custom' => [
'attribute-name' => [
'rule-name' => 'custom-message',
],
],
/*
|--------------------------------------------------------------------------
| Custom Validation Attributes
|--------------------------------------------------------------------------
|
| The following language lines are used to swap attribute place-holders
| with something more reader friendly such as E-Mail Address instead
| of "email". This simply helps us make messages a little cleaner.
|
*/
'attributes' => [
//
],
];

View File

@ -1178,6 +1178,7 @@ $LANG = array(
'invoice_number_padding' => 'Padding',
'preview' => 'Preview',
'list_vendors' => 'List Vendors',
'add_users_not_supported' => 'Upgrade to the Enterprise plan to add additional users to your account.',
);

View File

@ -4,13 +4,13 @@
@parent
@include('accounts.nav', ['selected' => ACCOUNT_USER_MANAGEMENT, 'advanced' => true])
<div class="pull-right">
@if (Utils::hasFeature(FEATURE_USERS))
{!! Button::primary(trans('texts.add_user'))->asLinkTo(URL::to('/users/create'))->appendIcon(Icon::create('plus-sign')) !!}
<div class="pull-right">
{!! Button::primary(trans('texts.add_user'))->asLinkTo(URL::to('/users/create'))->appendIcon(Icon::create('plus-sign')) !!}
</div>
@else
<div class="alert alert-warning">{!! trans('texts.add_users_not_supported') !!}</div>
@endif
</div>
<label for="trashed" style="font-weight:normal; margin-left: 10px;">
<input id="trashed" type="checkbox" onclick="setTrashVisible()"

View File

@ -177,9 +177,8 @@
});
@if (Session::has('trackEventCategory') && Session::has('trackEventAction'))
trackEvent('{{ session('trackEventCategory') }}', '{{ session('trackEventAction') }}');
@if (Session::get('trackEventAction') === '/buy_pro_plan')
window._fbq.push(['track', '{{ env('FACEBOOK_PIXEL_BUY_PRO') }}', {'value':'{{ PRO_PLAN_PRICE }}.00','currency':'USD'}]);
window._fbq.push(['track', '{{ env('FACEBOOK_PIXEL_BUY_PRO') }}', {'value':'{{ session('trackEventAmount') }}','currency':'USD'}]);
@endif
@endif