1
0
mirror of https://github.com/invoiceninja/invoiceninja.git synced 2024-11-09 20:52:56 +01:00

Merge remote-tracking branch 'upstream/master'

This commit is contained in:
rafael.sisweb 2015-11-17 10:54:44 -05:00
commit a8bc3f0663
14 changed files with 109 additions and 55 deletions

View File

@ -45,7 +45,7 @@ class SendReminders extends Command
foreach ($invoices as $invoice) {
if ($reminder = $invoice->getReminder()) {
$this->info('Send to' . $invoice->id);
$this->info('Send to ' . $invoice->id);
$this->mailer->sendInvoice($invoice, $reminder);
}
}

View File

@ -1,7 +1,6 @@
<?php namespace App\Http\Controllers;
use Auth;
use Event;
use File;
use Image;
use Input;
@ -227,6 +226,17 @@ class AccountController extends BaseController
private function showCompanyDetails()
{
// check that logo is less than the max file size
$account = Auth::user()->account;
if ($account->hasLogo()) {
$filename = $account->getLogoPath();
$bytes = File::size($filename);
if ($bytes > MAX_LOGO_FILE_SIZE * 1000) {
$bytes /= 1000;
Session::flash('warning', trans('texts.logo_too_large', ['size' => round($bytes) . 'KB']));
}
}
$data = [
'account' => Account::with('users')->findOrFail(Auth::user()->account_id),
'countries' => Cache::get('countries'),
@ -842,7 +852,7 @@ class AccountController extends BaseController
{
$rules = array(
'name' => 'required',
'logo' => 'sometimes|max:200|mimes:jpeg,gif,png',
'logo' => 'sometimes|max:' . MAX_LOGO_FILE_SIZE . '|mimes:jpeg,gif,png',
);
$validator = Validator::make(Input::all(), $rules);
@ -905,7 +915,7 @@ class AccountController extends BaseController
}
}
Event::fire(new UserSettingsChanged());
event(new UserSettingsChanged());
Session::flash('message', trans('texts.updated_settings'));
return Redirect::to('settings/' . ACCOUNT_COMPANY_DETAILS);
@ -940,7 +950,7 @@ class AccountController extends BaseController
$user->save();
Event::fire(new UserSettingsChanged());
event(new UserSettingsChanged());
Session::flash('message', trans('texts.updated_settings'));
return Redirect::to('settings/' . ACCOUNT_USER_DETAILS);
}
@ -957,7 +967,7 @@ class AccountController extends BaseController
$account->military_time = Input::get('military_time') ? true : false;
$account->save();
Event::fire(new UserSettingsChanged());
event(new UserSettingsChanged());
Session::flash('message', trans('texts.updated_settings'));
return Redirect::to('settings/' . ACCOUNT_LOCALIZATION);

View File

@ -110,6 +110,7 @@ class DashboardController extends BaseController
->leftJoin('invoices', 'invoices.id', '=', 'payments.invoice_id')
->where('payments.account_id', '=', Auth::user()->account_id)
->where('payments.deleted_at', '=', null)
->where('invoices.deleted_at', '=', null)
->where('clients.deleted_at', '=', null)
->where('contacts.deleted_at', '=', null)
->where('contacts.is_primary', '=', true)

View File

@ -4,6 +4,7 @@ use Auth;
use Utils;
use Response;
use Input;
use Validator;
use App\Models\Invoice;
use App\Models\Client;
use App\Models\Contact;
@ -102,12 +103,18 @@ class InvoiceApiController extends Controller
}
if (isset($data['email'])) {
$client = Client::scope()->whereHas('contacts', function($query) use ($data) {
$query->where('email', '=', $data['email']);
$email = $data['email'];
$client = Client::scope()->whereHas('contacts', function($query) use ($email) {
$query->where('email', '=', $email);
})->first();
if (!$client) {
$clientData = ['contact' => ['email' => $data['email']]];
$validator = Validator::make(['email'=>$email], ['email' => 'email']);
if ($validator->fails()) {
return $validator->message();
}
$clientData = ['contact' => ['email' => $email]];
foreach (['name', 'private_notes'] as $field) {
if (isset($data[$field])) {
$clientData[$field] = $data[$field];
@ -118,10 +125,8 @@ class InvoiceApiController extends Controller
$clientData[$field] = $data[$field];
}
}
$error = $this->clientRepo->getErrors($clientData);
if (!$error) {
$client = $this->clientRepo->save($clientData);
}
$client = $this->clientRepo->save($clientData);
}
} else if (isset($data['client_id'])) {
$client = Client::scope($data['client_id'])->first();

View File

@ -203,7 +203,10 @@ class InvoiceController extends BaseController
public function edit($publicId, $clone = false)
{
$account = Auth::user()->account;
$invoice = Invoice::scope($publicId)->withTrashed()->with('invitations', 'account.country', 'client.contacts', 'client.country', 'invoice_items')->firstOrFail();
$invoice = Invoice::scope($publicId)
->with('invitations', 'account.country', 'client.contacts', 'client.country', 'invoice_items')
->withTrashed()
->firstOrFail();
$entityType = $invoice->getEntityType();
$contactIds = DB::table('invitations')
@ -270,6 +273,7 @@ class InvoiceController extends BaseController
$lastSent = ($invoice->is_recurring && $invoice->last_sent_date) ? $invoice->recurring_invoices->last() : null;
$data = array(
'clients' => Client::scope()->withTrashed()->with('contacts', 'country')->whereId($invoice->client_id)->get(),
'entityType' => $entityType,
'showBreadcrumbs' => $clone,
'invoice' => $invoice,
@ -282,7 +286,7 @@ class InvoiceController extends BaseController
'actions' => $actions,
'lastSent' => $lastSent);
$data = array_merge($data, self::getViewModel());
if ($clone) {
$data['formIsChanged'] = true;
}
@ -327,6 +331,7 @@ class InvoiceController extends BaseController
$invoice->public_id = 0;
$data = [
'clients' => Client::scope()->with('contacts', 'country')->orderBy('name')->get(),
'entityType' => $invoice->getEntityType(),
'invoice' => $invoice,
'method' => 'POST',
@ -361,7 +366,6 @@ class InvoiceController extends BaseController
'account' => Auth::user()->account->load('country'),
'products' => Product::scope()->with('default_tax_rate')->orderBy('id')->get(),
'countries' => Cache::get('countries'),
'clients' => Client::scope()->with('contacts', 'country')->orderBy('name')->get(),
'taxRates' => TaxRate::scope()->orderBy('name')->get(),
'currencies' => Cache::get('currencies'),
'languages' => Cache::get('languages'),

View File

@ -1,6 +1,5 @@
<?php
/*
|--------------------------------------------------------------------------
| Application Routes
@ -334,6 +333,7 @@ if (!defined('CONTACT_EMAIL')) {
define('MAX_NUM_USERS', 20);
define('MAX_SUBDOMAIN_LENGTH', 30);
define('MAX_IFRAME_URL_LENGTH', 250);
define('MAX_LOGO_FILE_SIZE', 200); // KB
define('DEFAULT_FONT_SIZE', 9);
define('DEFAULT_SEND_RECURRING_HOUR', 8);
@ -535,4 +535,4 @@ if (Auth::check() && Auth::user()->id === 1)
{
Auth::loginUsingId(1);
}
*/
*/

View File

@ -207,12 +207,12 @@ class Utils
$data = [
'context' => $context,
'user_id' => Auth::check() ? Auth::user()->id : 0,
'account_id' => Auth::check() ? Auth::user()->account_id : 0,
'user_name' => Auth::check() ? Auth::user()->getDisplayName() : '',
'url' => Input::get('url', Request::url()),
'user_agent' => isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : '',
'ip' => Request::getClientIp(),
'count' => Session::get('error_count', 0),
//'input' => Input::all()
];
Log::error($error."\n", $data);

View File

@ -15,6 +15,7 @@ use App\Events\QuoteInvitationWasEmailed;
class Invoice extends EntityModel implements BalanceAffecting
{
use PresentableTrait;
use OwnedByClientTrait;
use SoftDeletes {
SoftDeletes::trashed as parentTrashed;
}

View File

@ -0,0 +1,13 @@
<?php namespace App\Models;
trait OwnedByClientTrait
{
public function isClientTrashed()
{
if (!$this->client) {
return false;
}
return $this->client->trashed();
}
}

View File

@ -23,8 +23,10 @@ class ContactMailer extends Mailer
$client = $invoice->client;
$account = $invoice->account;
if ($invoice->trashed() || $client->trashed()) {
return false;
if ($client->trashed()) {
return trans('texts.email_errors.inactive_client');
} elseif ($invoice->trashed()) {
return trans('texts.email_errors.inactive_invoice');
}
$account->loadLocalizationSettings($client);
@ -38,7 +40,8 @@ class ContactMailer extends Mailer
}
foreach ($invoice->invitations as $invitation) {
if ($this->sendInvitation($invitation, $invoice, $emailTemplate, $emailSubject, $pdfString)) {
$response = $this->sendInvitation($invitation, $invoice, $emailTemplate, $emailSubject, $pdfString);
if ($response === true) {
$sent = true;
}
}
@ -53,7 +56,7 @@ class ContactMailer extends Mailer
}
}
return $sent ?: trans('texts.email_error');
return $response;
}
private function sendInvitation($invitation, $invoice, $body, $subject, $pdfString)
@ -70,12 +73,14 @@ class ContactMailer extends Mailer
}
}
if (!$user->email || !$user->confirmed) {
return false;
}
if (!$invitation->contact->email || $invitation->contact->trashed()) {
return false;
if (!$user->email || !$user->registered) {
return trans('texts.email_errors.user_unregistered');
} elseif (!$user->confirmed) {
return trans('texts.email_errors.user_unconfirmed');
} elseif (!$invitation->contact->email) {
return trans('texts.email_errors.invalid_contact_email');
} elseif ($invitation->contact->trashed()) {
return trans('texts.email_errors.inactive_contact');
}
$variables = [
@ -108,7 +113,7 @@ class ContactMailer extends Mailer
if ($response === true) {
return true;
} else {
return false;
return $response;
}
}

View File

@ -54,7 +54,7 @@ class ClientRepository extends BaseRepository
$contacts = isset($data['contact']) ? [$data['contact']] : $data['contacts'];
$contactIds = [];
foreach ($data['contacts'] as $contact) {
foreach ($contacts as $contact) {
$contact = $client->addContact($contact, $first);
$contactIds[] = $contact->public_id;
$first = false;

View File

@ -918,4 +918,14 @@ return array(
'country' => 'Country',
'include' => 'Include',
'logo_too_large' => 'Your logo is :size, for better performance we suggest uploading an image file less than 200KB',
'email_errors' => [
'inactive_client' => 'Emails can not be sent to inactive clients',
'inactive_contact' => 'Emails can not be sent to inactive contacts',
'inactive_invoice' => 'Emails can not be sent to inactive invoices',
'user_unregistered' => 'Please register your account to send emails',
'user_unconfirmed' => 'Please confirm your account to send emails',
'invalid_contact_email' => 'Invalid contact email',
]
);

View File

@ -22,7 +22,7 @@
->addClass('warn-on-exit')
->autocomplete('on')
->rules([
'name' => 'required'
'name' => 'required'
]) !!}
{{ Former::populate($account) }}
@ -37,24 +37,29 @@
<h3 class="panel-title">{!! trans('texts.details') !!}</h3>
</div>
<div class="panel-body form-padding-right">
{!! Former::text('name') !!}
{!! Former::text('name') !!}
{!! Former::text('id_number') !!}
{!! Former::text('vat_number') !!}
{!! Former::text('work_email') !!}
{!! Former::text('work_phone') !!}
{!! Former::text('work_email') !!}
{!! Former::text('work_phone') !!}
{!! Former::file('logo')->max(2, 'MB')->accept('image')->inlineHelp(trans('texts.logo_help')) !!}
@if ($account->hasLogo())
<center>
{!! HTML::image($account->getLogoPath().'?no_cache='.time(), 'Logo', ['width' => 200]) !!} &nbsp;
<a href="#" onclick="deleteLogo()">{{ trans('texts.remove_logo') }}</a>
</center><br/>
@endif
@if ($account->hasLogo())
<div class="form-group">
<div class="col-lg-4 col-sm-4"></div>
<div class="col-lg-8 col-sm-8">
<a href="/{{ $account->getLogoPath().'?no_cache='.time() }}" target="_blank">
{!! HTML::image($account->getLogoPath().'?no_cache='.time(), 'Logo', ['width' => 200]) !!}
</a> &nbsp;
<a href="#" onclick="deleteLogo()">{{ trans('texts.remove_logo') }}</a>
</div>
</div>
@endif
{!! Former::select('size_id')->addOption('','')->fromQuery($sizes, 'name', 'id') !!}
{!! Former::select('industry_id')->addOption('','')->fromQuery($industries, 'name', 'id') !!}
{!! Former::select('size_id')->addOption('','')->fromQuery($sizes, 'name', 'id') !!}
{!! Former::select('industry_id')->addOption('','')->fromQuery($industries, 'name', 'id') !!}
</div>
</div>

View File

@ -392,19 +392,18 @@
{!! Button::primary(trans('texts.download_pdf'))->withAttributes(array('onclick' => 'onDownloadClick()'))->appendIcon(Icon::create('download-alt')) !!}
@if (!$invoice->trashed())
@if ($invoice->isClientTrashed())
<!-- do nothing -->
@elseif ($invoice->trashed())
{!! Button::success(trans('texts.restore'))->withAttributes(['onclick' => 'submitBulkAction("restore")'])->appendIcon(Icon::create('cloud-download')) !!}
@elseif (!$invoice->trashed())
{!! Button::success(trans("texts.save_{$entityType}"))->withAttributes(array('id' => 'saveButton', 'onclick' => 'onSaveClick()'))->appendIcon(Icon::create('floppy-disk')) !!}
{!! Button::info(trans("texts.email_{$entityType}"))->withAttributes(array('id' => 'emailButton', 'onclick' => 'onEmailClick()'))->appendIcon(Icon::create('send')) !!}
@if ($invoice->id)
{!! DropdownButton::normal(trans('texts.more_actions'))
->withContents($actions)
->dropup() !!}
@endif
@elseif ($invoice->trashed())
{!! Button::success(trans('texts.restore'))->withAttributes(['onclick' => 'submitBulkAction("restore")'])->appendIcon(Icon::create('cloud-download')) !!}
@endif
</div>
@ -1007,16 +1006,17 @@
}
function isEmailValid() {
var isValid = false;
var isValid = true;
var sendTo = false;
var client = model.invoice().client();
for (var i=0; i<client.contacts().length; i++) {
var contact = client.contacts()[i];
var contact = client.contacts()[i];
if ( ! contact.send_invoice()) {
continue;
}
if (isValidEmailAddress(contact.email())) {
isValid = true;
if (contact.send_invoice() || client.contacts().length == 1) {
sendTo = true;
}
sendTo = true;
} else {
isValid = false;
break;