diff --git a/app/Http/Controllers/ImportController.php b/app/Http/Controllers/ImportController.php
index eb400a5e3d9b..b078fb6f955e 100644
--- a/app/Http/Controllers/ImportController.php
+++ b/app/Http/Controllers/ImportController.php
@@ -22,7 +22,6 @@ class ImportController extends BaseController
{
$source = Input::get('source');
$files = [];
- $skipped = [];
foreach (ImportService::$entityTypes as $entityType) {
if (Input::file("{$entityType}_file")) {
@@ -38,8 +37,8 @@ class ImportController extends BaseController
$data = $this->importService->mapCSV($files);
return View::make('accounts.import_map', ['data' => $data]);
} else {
- $skipped = $this->importService->import($source, $files);
- return $this->showResult($skipped);
+ $results = $this->importService->import($source, $files);
+ return $this->showResult($results);
}
} catch (Exception $exception) {
Utils::logError($exception);
@@ -52,11 +51,10 @@ class ImportController extends BaseController
{
$map = Input::get('map');
$headers = Input::get('headers');
- $skipped = [];
try {
- $skipped = $this->importService->importCSV($map, $headers);
- return $this->showResult($skipped);
+ $results = $this->importService->importCSV($map, $headers);
+ return $this->showResult($results);
} catch (Exception $exception) {
Utils::logError($exception);
Session::flash('error', $exception->getMessage());
@@ -64,16 +62,29 @@ class ImportController extends BaseController
}
}
- private function showResult($skipped)
+ private function showResult($results)
{
- if (count($skipped)) {
- $message = trans('texts.failed_to_import');
- foreach ($skipped as $skip) {
- $message .= '
' . json_encode($skip);
+ $message = '';
+ $skipped = [];
+
+ foreach ($results as $entityType => $entityResults) {
+ if ($count = count($entityResults[RESULT_SUCCESS])) {
+ $message .= trans("texts.created_{$entityType}s", ['count' => $count]) . '
';
}
+ if (count($entityResults[RESULT_FAILURE])) {
+ $skipped = array_merge($skipped, $entityResults[RESULT_FAILURE]);
+ }
+ }
+
+ if (count($skipped)) {
+ $message .= '
' . trans('texts.failed_to_import') . '
';
+ foreach ($skipped as $skip) {
+ $message .= json_encode($skip) . '
';
+ }
+ }
+
+ if ($message) {
Session::flash('warning', $message);
- } else {
- Session::flash('message', trans('texts.imported_file'));
}
return Redirect::to('/settings/' . ACCOUNT_IMPORT_EXPORT);
diff --git a/app/Http/Controllers/PaymentController.php b/app/Http/Controllers/PaymentController.php
index 989a4649174e..6476d1af98c7 100644
--- a/app/Http/Controllers/PaymentController.php
+++ b/app/Http/Controllers/PaymentController.php
@@ -512,21 +512,20 @@ class PaymentController extends BaseController
try {
if (method_exists($gateway, 'completePurchase')
- && !$accountGateway->isGateway(GATEWAY_TWO_CHECKOUT)
- && !$accountGateway->isGateway(GATEWAY_MOLLIE)) { // TODO: implement webhook
+ && !$accountGateway->isGateway(GATEWAY_TWO_CHECKOUT)) {
$details = $this->paymentService->getPaymentDetails($invitation, $accountGateway);
- $response = $gateway->completePurchase($details)->send();
+ $response = $this->paymentService->completePurchase($gateway, $accountGateway, $details, $token);
$ref = $response->getTransactionReference() ?: $token;
- if ($response->isSuccessful()) {
+ if ($response->isCancelled()) {
+ // do nothing
+ } elseif ($response->isSuccessful()) {
$payment = $this->paymentService->createPayment($invitation, $ref, $payerId);
Session::flash('message', trans('texts.applied_payment'));
-
- return Redirect::to($invitation->getLink());
} else {
$this->error('offsite', $response->getMessage(), $accountGateway);
- return Redirect::to($invitation->getLink());
}
+ return Redirect::to($invitation->getLink());
} else {
$payment = $this->paymentService->createPayment($invitation, $token, $payerId);
Session::flash('message', trans('texts.applied_payment'));
diff --git a/app/Http/routes.php b/app/Http/routes.php
index dc981679a93d..0bab329d247c 100644
--- a/app/Http/routes.php
+++ b/app/Http/routes.php
@@ -63,7 +63,6 @@ Route::get('/auth_unlink', 'Auth\AuthController@authUnlink');
Route::post('/hook/email_bounced', 'AppController@emailBounced');
Route::post('/hook/email_opened', 'AppController@emailOpened');
-
// Laravel auth routes
get('/signup', array('as' => 'signup', 'uses' => 'Auth\AuthController@getRegister'));
post('/signup', array('as' => 'signup', 'uses' => 'Auth\AuthController@postRegister'));
diff --git a/app/Ninja/Mailers/ContactMailer.php b/app/Ninja/Mailers/ContactMailer.php
index b92fc1811c0e..7efc52bfb8d9 100644
--- a/app/Ninja/Mailers/ContactMailer.php
+++ b/app/Ninja/Mailers/ContactMailer.php
@@ -25,6 +25,7 @@ class ContactMailer extends Mailer
'firstName',
'invoice',
'quote',
+ 'dueDate',
'viewLink',
'viewButton',
'paymentLink',
@@ -234,6 +235,7 @@ class ContactMailer extends Mailer
'$invoice' => $invoice->invoice_number,
'$quote' => $invoice->invoice_number,
'$link' => $invitation->getLink(),
+ '$dueDate' => $account->formatDate($invoice->due_date),
'$viewLink' => $invitation->getLink(),
'$viewButton' => HTML::emailViewButton($invitation->getLink(), $invoice->getEntityType()),
'$paymentLink' => $invitation->getLink('payment'),
diff --git a/app/Ninja/Repositories/ClientRepository.php b/app/Ninja/Repositories/ClientRepository.php
index 58b4bc09b37b..3e43d8f34f5f 100644
--- a/app/Ninja/Repositories/ClientRepository.php
+++ b/app/Ninja/Repositories/ClientRepository.php
@@ -75,10 +75,12 @@ class ClientRepository extends BaseRepository
$client->fill($data);
$client->save();
+ /*
if ( ! isset($data['contact']) && ! isset($data['contacts'])) {
return $client;
}
-
+ */
+
$first = true;
$contacts = isset($data['contact']) ? [$data['contact']] : $data['contacts'];
$contactIds = [];
diff --git a/app/Ninja/Repositories/InvoiceRepository.php b/app/Ninja/Repositories/InvoiceRepository.php
index 2142588ec99a..31de427be56d 100644
--- a/app/Ninja/Repositories/InvoiceRepository.php
+++ b/app/Ninja/Repositories/InvoiceRepository.php
@@ -317,6 +317,7 @@ class InvoiceRepository extends BaseRepository
$total -= $invoice->discount;
} else {
$total *= (100 - $invoice->discount) / 100;
+ $total = round($total, 2);
}
}
diff --git a/app/Services/ImportService.php b/app/Services/ImportService.php
index 3fd21f07192b..ef01758e17d3 100644
--- a/app/Services/ImportService.php
+++ b/app/Services/ImportService.php
@@ -56,35 +56,39 @@ class ImportService
public function import($source, $files)
{
- $skipped = [];
+ $results = [];
$imported_files = null;
foreach ($files as $entityType => $file) {
- $result = $this->execute($source, $entityType, $file);
- $skipped = array_merge($skipped, $result);
+ $results[$entityType] = $this->execute($source, $entityType, $file);
}
- return $skipped;
+ return $results;
}
private function execute($source, $entityType, $file)
{
- $skipped = [];
+ $results = [
+ RESULT_SUCCESS => [],
+ RESULT_FAILURE => [],
+ ];
- Excel::load($file, function ($reader) use ($source, $entityType, &$skipped) {
+ Excel::load($file, function ($reader) use ($source, $entityType, &$results) {
$this->checkData($entityType, count($reader->all()));
$maps = $this->createMaps();
- $reader->each(function ($row) use ($source, $entityType, $maps, &$skipped) {
+ $reader->each(function ($row) use ($source, $entityType, $maps, &$results) {
$result = $this->saveData($source, $entityType, $row, $maps);
- if ( ! $result) {
- $skipped[] = $row;
+ if ($result) {
+ $results[RESULT_SUCCESS][] = $result;
+ } else {
+ $results[RESULT_FAILURE][] = $row;
}
});
});
- return $skipped;
+ return $results;
}
private function saveData($source, $entityType, $row, $maps)
@@ -346,19 +350,21 @@ class ImportService
public function importCSV($maps, $headers)
{
- $skipped = [];
+ $results = [];
foreach ($maps as $entityType => $map) {
- $result = $this->executeCSV($entityType, $map, $headers[$entityType]);
- $skipped = array_merge($skipped, $result);
+ $result[$entityType] = $this->executeCSV($entityType, $map, $headers[$entityType]);
}
- return $skipped;
+ return $results;
}
private function executeCSV($entityType, $map, $hasHeaders)
{
- $skipped = [];
+ $results = [
+ RESULT_SUCCESS => [],
+ RESULT_FAILURE => [],
+ ];
$source = IMPORT_CSV;
$data = Session::get("{$entityType}-data");
@@ -374,14 +380,16 @@ class ImportService
$row = $this->convertToObject($entityType, $row, $map);
$result = $this->saveData($source, $entityType, $row, $maps);
- if ( ! $result) {
- $skipped[] = $row;
+ if ($result) {
+ $results[RESULT_SUCCESS][] = $result;
+ } else {
+ $results[RESULT_FAILURE][] = $row;
}
}
Session::forget("{$entityType}-data");
- return $skipped;
+ return $results;
}
private function convertToObject($entityType, $data, $map)
diff --git a/app/Services/PaymentService.php b/app/Services/PaymentService.php
index 7f3d9c52d7a2..d09f30683c2b 100644
--- a/app/Services/PaymentService.php
+++ b/app/Services/PaymentService.php
@@ -224,6 +224,17 @@ class PaymentService extends BaseService
return $payment;
}
+ public function completePurchase($gateway, $accountGateway, $details, $token)
+ {
+ if ($accountGateway->isGateway(GATEWAY_MOLLIE)) {
+ $details['transactionReference'] = $token;
+ $response = $gateway->fetchTransaction($details)->send();
+ return $gateway->fetchTransaction($details)->send();
+ } else {
+ return $gateway->completePurchase($details)->send();
+ }
+ }
+
public function autoBillInvoice($invoice)
{
$client = $invoice->client;
diff --git a/public/favicon.ico b/public/favicon.ico
new file mode 100644
index 000000000000..464d8b596c2a
Binary files /dev/null and b/public/favicon.ico differ
diff --git a/resources/lang/en/texts.php b/resources/lang/en/texts.php
index 1fd8be863b3d..637258ceaa00 100644
--- a/resources/lang/en/texts.php
+++ b/resources/lang/en/texts.php
@@ -88,7 +88,7 @@ return array(
'company_details' => 'Company Details',
'online_payments' => 'Online Payments',
'notifications' => 'Email Notifications',
- 'import_export' => 'Import/Export',
+ 'import_export' => 'Import/Export/Cancel',
'done' => 'Done',
'save' => 'Save',
'create' => 'Create',
@@ -212,7 +212,7 @@ return array(
// application messages
'created_client' => 'Successfully created client',
- 'created_clients' => 'Successfully created :count clients',
+ 'created_clients' => 'Successfully created :count client(s)',
'updated_settings' => 'Successfully updated settings',
'removed_logo' => 'Successfully removed logo',
'sent_message' => 'Successfully sent message',
@@ -980,5 +980,7 @@ return array(
'button_confirmation_message' => 'Click to confirm your email address.',
'confirm' => 'Confirm',
'email_preferences' => 'Email Preferences',
-
+
+ 'created_invoices' => 'Successfully created :count invoice(s)',
+
);
diff --git a/resources/views/accounts/import_export.blade.php b/resources/views/accounts/import_export.blade.php
index edb9ee60234b..4dc452c7d46a 100644
--- a/resources/views/accounts/import_export.blade.php
+++ b/resources/views/accounts/import_export.blade.php
@@ -97,7 +97,7 @@
diff --git a/resources/views/accounts/templates_and_reminders.blade.php b/resources/views/accounts/templates_and_reminders.blade.php
index ae3602213e4d..d4b69eb0d73d 100644
--- a/resources/views/accounts/templates_and_reminders.blade.php
+++ b/resources/views/accounts/templates_and_reminders.blade.php
@@ -184,13 +184,14 @@
var keys = {!! json_encode(\App\Ninja\Mailers\ContactMailer::$variableFields) !!};
var vals = [
{!! json_encode($emailFooter) !!},
- "{{ Auth::user()->account->getDisplayName() }}",
+ "{{ $account->getDisplayName() }}",
"Client Name",
formatMoney(100),
"Contact Name",
"First Name",
"0001",
"0001",
+ "{{ $account->formatDate($account->getDateTime()) }}",
"{{ URL::to('/view/...') }}",
'{!! HTML::flatButton('view_invoice', '#0b4d78') !!}',
"{{ URL::to('/payment/...') }}",
diff --git a/resources/views/dashboard.blade.php b/resources/views/dashboard.blade.php
index dcf5782dc4c2..56f9690610ec 100644
--- a/resources/views/dashboard.blade.php
+++ b/resources/views/dashboard.blade.php
@@ -71,7 +71,7 @@
- {{ trans('texts.notifications') }}
+ {{ trans('texts.activity') }}
{{ trans_choice('texts.invoices_sent', $invoicesSent) }}
diff --git a/resources/views/emails/master.blade.php b/resources/views/emails/master.blade.php
index 7d4ea2329876..a45aa0add118 100644
--- a/resources/views/emails/master.blade.php
+++ b/resources/views/emails/master.blade.php
@@ -4,7 +4,7 @@
-
@yield('markup')
@@ -48,7 +48,7 @@
}
-
diff --git a/resources/views/master.blade.php b/resources/views/master.blade.php
index ad13a7759dc6..6d434ef08ceb 100644
--- a/resources/views/master.blade.php
+++ b/resources/views/master.blade.php
@@ -6,7 +6,7 @@
@else
{{ isset($title) ? ($title . ' | Invoice Ninja') : ('Invoice Ninja | ' . trans('texts.app_title')) }}
-
+
@endif
diff --git a/resources/views/partials/system_settings.blade.php b/resources/views/partials/system_settings.blade.php
index 81ca2ea40b16..c508ba0ee896 100644
--- a/resources/views/partials/system_settings.blade.php
+++ b/resources/views/partials/system_settings.blade.php
@@ -66,7 +66,7 @@
$('#dbTestResult').html('Working...').css('color', 'black');
// Send / Test Information
- $.post( "/setup", data, function( data ) {
+ $.post( "{{ URL::to('/setup') }}", data, function( data ) {
var color = 'red';
if(data == 'Success'){
color = 'green';
@@ -86,7 +86,7 @@
$('#mailTestResult').html('Working...').css('color', 'black');
// Send / Test Information
- $.post( "/setup", data, function( data ) {
+ $.post( "{{ URL::to('/setup') }}", data, function( data ) {
var color = 'red';
if(data == 'Sent'){
color = 'green';