mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-08 17:04:30 -04:00
Added new acceptance tests
This commit is contained in:
parent
88c215d1df
commit
2c5667aacb
@ -44,8 +44,6 @@ class SendRecurringInvoices extends Command
|
|||||||
}
|
}
|
||||||
|
|
||||||
$recurInvoice->account->loadLocalizationSettings($recurInvoice->client);
|
$recurInvoice->account->loadLocalizationSettings($recurInvoice->client);
|
||||||
//date_default_timezone_set(session(SESSION_TIMEZONE));
|
|
||||||
|
|
||||||
$this->info('Processing Invoice '.$recurInvoice->id.' - Should send '.($recurInvoice->shouldSendToday() ? 'YES' : 'NO'));
|
$this->info('Processing Invoice '.$recurInvoice->id.' - Should send '.($recurInvoice->shouldSendToday() ? 'YES' : 'NO'));
|
||||||
$invoice = $this->invoiceRepo->createRecurringInvoice($recurInvoice);
|
$invoice = $this->invoiceRepo->createRecurringInvoice($recurInvoice);
|
||||||
|
|
||||||
|
@ -56,7 +56,7 @@ class AppController extends BaseController
|
|||||||
$test = Input::get('test');
|
$test = Input::get('test');
|
||||||
|
|
||||||
$app = Input::get('app');
|
$app = Input::get('app');
|
||||||
$app['key'] = str_random(RANDOM_KEY_LENGTH);
|
$app['key'] = env('APP_KEY') ?: str_random(RANDOM_KEY_LENGTH);
|
||||||
|
|
||||||
$database = Input::get('database');
|
$database = Input::get('database');
|
||||||
$dbType = $database['default'];
|
$dbType = $database['default'];
|
||||||
|
@ -131,13 +131,22 @@ class InvoiceController extends BaseController
|
|||||||
|
|
||||||
public function view($invitationKey)
|
public function view($invitationKey)
|
||||||
{
|
{
|
||||||
$invitation = $this->invoiceRepo->findInvoiceByInvitation($invitationKey);
|
if (!$invitation = $this->invoiceRepo->findInvoiceByInvitation($invitationKey)) {
|
||||||
|
return response()->view('error', [
|
||||||
|
'error' => trans('texts.invoice_not_found'),
|
||||||
|
'hideHeader' => true,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
$invoice = $invitation->invoice;
|
$invoice = $invitation->invoice;
|
||||||
$client = $invoice->client;
|
$client = $invoice->client;
|
||||||
$account = $invoice->account;
|
$account = $invoice->account;
|
||||||
|
|
||||||
if (!$account->checkSubdomain(Request::server('HTTP_HOST'))) {
|
if (!$account->checkSubdomain(Request::server('HTTP_HOST'))) {
|
||||||
app()->abort(404, trans('texts.invoice_not_found'));
|
return response()->view('error', [
|
||||||
|
'error' => trans('texts.invoice_not_found'),
|
||||||
|
'hideHeader' => true,
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Input::has('phantomjs') && !Session::has($invitationKey) && (!Auth::check() || Auth::user()->account_id != $invoice->account_id)) {
|
if (!Input::has('phantomjs') && !Session::has($invitationKey) && (!Auth::check() || Auth::user()->account_id != $invoice->account_id)) {
|
||||||
|
@ -22,7 +22,9 @@ class PublicClientController extends BaseController
|
|||||||
|
|
||||||
public function dashboard()
|
public function dashboard()
|
||||||
{
|
{
|
||||||
$invitation = $this->getInvitation();
|
if (!$invitation = $this->getInvitation()) {
|
||||||
|
return $this->returnError();
|
||||||
|
}
|
||||||
$account = $invitation->account;
|
$account = $invitation->account;
|
||||||
$invoice = $invitation->invoice;
|
$invoice = $invitation->invoice;
|
||||||
$client = $invoice->client;
|
$client = $invoice->client;
|
||||||
@ -40,7 +42,9 @@ class PublicClientController extends BaseController
|
|||||||
|
|
||||||
public function activityDatatable()
|
public function activityDatatable()
|
||||||
{
|
{
|
||||||
$invitation = $this->getInvitation();
|
if (!$invitation = $this->getInvitation()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
$invoice = $invitation->invoice;
|
$invoice = $invitation->invoice;
|
||||||
|
|
||||||
$query = DB::table('activities')
|
$query = DB::table('activities')
|
||||||
@ -59,7 +63,9 @@ class PublicClientController extends BaseController
|
|||||||
|
|
||||||
public function invoiceIndex()
|
public function invoiceIndex()
|
||||||
{
|
{
|
||||||
$invitation = $this->getInvitation();
|
if (!$invitation = $this->getInvitation()) {
|
||||||
|
return $this->returnError();
|
||||||
|
}
|
||||||
$account = $invitation->account;
|
$account = $invitation->account;
|
||||||
$color = $account->primary_color ? $account->primary_color : '#0b4d78';
|
$color = $account->primary_color ? $account->primary_color : '#0b4d78';
|
||||||
|
|
||||||
@ -76,7 +82,9 @@ class PublicClientController extends BaseController
|
|||||||
|
|
||||||
public function invoiceDatatable()
|
public function invoiceDatatable()
|
||||||
{
|
{
|
||||||
$invitation = $this->getInvitation();
|
if (!$invitation = $this->getInvitation()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return $this->invoiceRepo->getClientDatatable($invitation->contact_id, ENTITY_INVOICE, Input::get('sSearch'));
|
return $this->invoiceRepo->getClientDatatable($invitation->contact_id, ENTITY_INVOICE, Input::get('sSearch'));
|
||||||
}
|
}
|
||||||
@ -84,7 +92,9 @@ class PublicClientController extends BaseController
|
|||||||
|
|
||||||
public function paymentIndex()
|
public function paymentIndex()
|
||||||
{
|
{
|
||||||
$invitation = $this->getInvitation();
|
if (!$invitation = $this->getInvitation()) {
|
||||||
|
return $this->returnError();
|
||||||
|
}
|
||||||
$account = $invitation->account;
|
$account = $invitation->account;
|
||||||
$color = $account->primary_color ? $account->primary_color : '#0b4d78';
|
$color = $account->primary_color ? $account->primary_color : '#0b4d78';
|
||||||
|
|
||||||
@ -101,7 +111,9 @@ class PublicClientController extends BaseController
|
|||||||
|
|
||||||
public function paymentDatatable()
|
public function paymentDatatable()
|
||||||
{
|
{
|
||||||
$invitation = $this->getInvitation();
|
if (!$invitation = $this->getInvitation()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
$payments = $this->paymentRepo->findForContact($invitation->contact->id, Input::get('sSearch'));
|
$payments = $this->paymentRepo->findForContact($invitation->contact->id, Input::get('sSearch'));
|
||||||
|
|
||||||
return Datatable::query($payments)
|
return Datatable::query($payments)
|
||||||
@ -115,7 +127,9 @@ class PublicClientController extends BaseController
|
|||||||
|
|
||||||
public function quoteIndex()
|
public function quoteIndex()
|
||||||
{
|
{
|
||||||
$invitation = $this->getInvitation();
|
if (!$invitation = $this->getInvitation()) {
|
||||||
|
return $this->returnError();
|
||||||
|
}
|
||||||
$account = $invitation->account;
|
$account = $invitation->account;
|
||||||
$color = $account->primary_color ? $account->primary_color : '#0b4d78';
|
$color = $account->primary_color ? $account->primary_color : '#0b4d78';
|
||||||
|
|
||||||
@ -133,29 +147,39 @@ class PublicClientController extends BaseController
|
|||||||
|
|
||||||
public function quoteDatatable()
|
public function quoteDatatable()
|
||||||
{
|
{
|
||||||
$invitation = $this->getInvitation();
|
if (!$invitation = $this->getInvitation()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return $this->invoiceRepo->getClientDatatable($invitation->contact_id, ENTITY_QUOTE, Input::get('sSearch'));
|
return $this->invoiceRepo->getClientDatatable($invitation->contact_id, ENTITY_QUOTE, Input::get('sSearch'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function returnError()
|
||||||
|
{
|
||||||
|
return response()->view('error', [
|
||||||
|
'error' => trans('texts.invoice_not_found'),
|
||||||
|
'hideHeader' => true,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
private function getInvitation()
|
private function getInvitation()
|
||||||
{
|
{
|
||||||
$invitationKey = session('invitation_key');
|
$invitationKey = session('invitation_key');
|
||||||
|
|
||||||
if (!$invitationKey) {
|
if (!$invitationKey) {
|
||||||
app()->abort(404);
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$invitation = Invitation::where('invitation_key', '=', $invitationKey)->first();
|
$invitation = Invitation::where('invitation_key', '=', $invitationKey)->first();
|
||||||
|
|
||||||
if (!$invitation || $invitation->is_deleted) {
|
if (!$invitation || $invitation->is_deleted) {
|
||||||
app()->abort(404);
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$invoice = $invitation->invoice;
|
$invoice = $invitation->invoice;
|
||||||
|
|
||||||
if (!$invoice || $invoice->is_deleted) {
|
if (!$invoice || $invoice->is_deleted) {
|
||||||
app()->abort(404);
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $invitation;
|
return $invitation;
|
||||||
|
@ -9,6 +9,10 @@ class Mailer
|
|||||||
{
|
{
|
||||||
public function sendTo($toEmail, $fromEmail, $fromName, $subject, $view, $data = [])
|
public function sendTo($toEmail, $fromEmail, $fromName, $subject, $view, $data = [])
|
||||||
{
|
{
|
||||||
|
if (stristr($toEmail, '@example.com')) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (isset($_ENV['POSTMARK_API_TOKEN'])) {
|
if (isset($_ENV['POSTMARK_API_TOKEN'])) {
|
||||||
$views = 'emails.'.$view.'_html';
|
$views = 'emails.'.$view.'_html';
|
||||||
} else {
|
} else {
|
||||||
|
@ -579,20 +579,21 @@ class InvoiceRepository
|
|||||||
public function findInvoiceByInvitation($invitationKey)
|
public function findInvoiceByInvitation($invitationKey)
|
||||||
{
|
{
|
||||||
$invitation = Invitation::where('invitation_key', '=', $invitationKey)->first();
|
$invitation = Invitation::where('invitation_key', '=', $invitationKey)->first();
|
||||||
|
|
||||||
if (!$invitation) {
|
if (!$invitation) {
|
||||||
app()->abort(404, trans('texts.invoice_not_found'));
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$invoice = $invitation->invoice;
|
$invoice = $invitation->invoice;
|
||||||
if (!$invoice || $invoice->is_deleted) {
|
if (!$invoice || $invoice->is_deleted) {
|
||||||
app()->abort(404, trans('texts.invoice_not_found'));
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$invoice->load('user', 'invoice_items', 'invoice_design', 'account.country', 'client.contacts', 'client.country');
|
$invoice->load('user', 'invoice_items', 'invoice_design', 'account.country', 'client.contacts', 'client.country');
|
||||||
$client = $invoice->client;
|
$client = $invoice->client;
|
||||||
|
|
||||||
if (!$client || $client->is_deleted) {
|
if (!$client || $client->is_deleted) {
|
||||||
app()->abort(404, trans('texts.invoice_not_found'));
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $invitation;
|
return $invitation;
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
<div class="well">
|
<div class="well">
|
||||||
<div class="container" style="min-height:400px">
|
<div class="container" style="min-height:400px">
|
||||||
<h3>Something went wrong...</h3>
|
<h3>Something went wrong...</h3>
|
||||||
{{ $error }}
|
<h4>{{ $error }}</h4>
|
||||||
<h4>If you'd like help please email us at contact@invoiceninja.com.</h4>
|
<h4>If you'd like help please email us at contact@invoiceninja.com.</h4>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -439,7 +439,7 @@
|
|||||||
|
|
||||||
<ul class="nav navbar-nav navbar-right navbar-settings">
|
<ul class="nav navbar-nav navbar-right navbar-settings">
|
||||||
<li class="dropdown">
|
<li class="dropdown">
|
||||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
|
<a href="{{ URL::to('/settings') }}" class="dropdown-toggle">
|
||||||
<span class="glyphicon glyphicon-cog" title="{{ trans('texts.settings') }}"/>
|
<span class="glyphicon glyphicon-cog" title="{{ trans('texts.settings') }}"/>
|
||||||
</a>
|
</a>
|
||||||
<ul class="dropdown-menu">
|
<ul class="dropdown-menu">
|
||||||
@ -454,7 +454,7 @@
|
|||||||
|
|
||||||
<ul class="nav navbar-nav navbar-right navbar-history">
|
<ul class="nav navbar-nav navbar-right navbar-history">
|
||||||
<li class="dropdown">
|
<li class="dropdown">
|
||||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
|
<a href="{{ count(Session::get(RECENTLY_VIEWED)) ? Session::get(RECENTLY_VIEWED)[0]->url : '#' }}" class="dropdown-toggle">
|
||||||
<span class="glyphicon glyphicon-time" title="{{ trans('texts.history') }}"/>
|
<span class="glyphicon glyphicon-time" title="{{ trans('texts.history') }}"/>
|
||||||
</a>
|
</a>
|
||||||
<ul class="dropdown-menu">
|
<ul class="dropdown-menu">
|
||||||
|
@ -189,10 +189,10 @@
|
|||||||
<textarea data-bind="value: wrapped_notes, valueUpdate: 'afterkeydown'" rows="1" cols="60" style="resize: vertical" class="form-control word-wrap"></textarea>
|
<textarea data-bind="value: wrapped_notes, valueUpdate: 'afterkeydown'" rows="1" cols="60" style="resize: vertical" class="form-control word-wrap"></textarea>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<input onkeyup="onItemChange()" data-bind="value: prettyCost, valueUpdate: 'afterkeydown'" style="text-align: right" class="form-control"//>
|
<input onkeyup="onItemChange()" data-bind="value: prettyCost, valueUpdate: 'afterkeydown'" style="text-align: right" class="form-control"/>
|
||||||
</td>
|
</td>
|
||||||
<td style="{{ $account->hide_quantity ? 'display:none' : '' }}">
|
<td style="{{ $account->hide_quantity ? 'display:none' : '' }}">
|
||||||
<input onkeyup="onItemChange()" data-bind="value: prettyQty, valueUpdate: 'afterkeydown'" style="text-align: right" class="form-control"//>
|
<input onkeyup="onItemChange()" data-bind="value: prettyQty, valueUpdate: 'afterkeydown'" style="text-align: right" class="form-control" name="quantity"/>
|
||||||
</td>
|
</td>
|
||||||
<td style="display:none;" data-bind="visible: $root.invoice_item_taxes.show">
|
<td style="display:none;" data-bind="visible: $root.invoice_item_taxes.show">
|
||||||
<select class="form-control" style="width:100%" data-bind="value: tax, options: $root.tax_rates, optionsText: 'displayName'"></select>
|
<select class="form-control" style="width:100%" data-bind="value: tax, options: $root.tax_rates, optionsText: 'displayName'"></select>
|
||||||
|
@ -267,8 +267,14 @@
|
|||||||
if (!invoice || invoice.invoice_status_id == 5) {
|
if (!invoice || invoice.invoice_status_id == 5) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
var jsDate = convertToJsDate(invoice.created_at) || new Date().getTime();
|
var dayInSeconds = 1000*60*60*24;
|
||||||
return parseInt((new Date().getTime() - convertToJsDate(invoice.created_at)) / (1000*60*60*24));
|
@if (Auth::user()->account->isPro())
|
||||||
|
var date = convertToJsDate(invoice.created_at);
|
||||||
|
@else
|
||||||
|
var date = new Date().getTime() - (dayInSeconds * Math.random() * 100);
|
||||||
|
@endif
|
||||||
|
|
||||||
|
return parseInt((new Date().getTime() - date) / dayInSeconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
function convertToJsDate(isoDate) {
|
function convertToJsDate(isoDate) {
|
||||||
|
86
tests/acceptance/CheckBalanceCest.php
Normal file
86
tests/acceptance/CheckBalanceCest.php
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Codeception\Util\Fixtures;
|
||||||
|
use \AcceptanceTester;
|
||||||
|
use Faker\Factory;
|
||||||
|
|
||||||
|
class OnlinePaymentCest
|
||||||
|
{
|
||||||
|
private $faker;
|
||||||
|
|
||||||
|
public function _before(AcceptanceTester $I)
|
||||||
|
{
|
||||||
|
$I->checkIfLogin($I);
|
||||||
|
|
||||||
|
$this->faker = Factory::create();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function checkBalance(AcceptanceTester $I)
|
||||||
|
{
|
||||||
|
$I->wantTo('ensure the balance is correct');
|
||||||
|
|
||||||
|
$clientEmail = $this->faker->safeEmail;
|
||||||
|
$productKey = $this->faker->text(10);
|
||||||
|
$productPrice = $this->faker->numberBetween(1, 20);
|
||||||
|
|
||||||
|
// create client
|
||||||
|
$I->amOnPage('/clients/create');
|
||||||
|
$I->fillField(['name' => 'email'], $clientEmail);
|
||||||
|
$I->click('Save');
|
||||||
|
$I->wait(1);
|
||||||
|
$I->see($clientEmail);
|
||||||
|
|
||||||
|
$clientId = $I->grabFromCurrentUrl('~clients/(\d+)~');
|
||||||
|
|
||||||
|
// create product
|
||||||
|
$I->amOnPage('/products/create');
|
||||||
|
$I->fillField(['name' => 'product_key'], $productKey);
|
||||||
|
$I->fillField(['name' => 'notes'], $this->faker->text(80));
|
||||||
|
$I->fillField(['name' => 'cost'], $productPrice);
|
||||||
|
$I->click('Save');
|
||||||
|
$I->wait(1);
|
||||||
|
$I->see($productKey);
|
||||||
|
|
||||||
|
// create invoice
|
||||||
|
$I->amOnPage('/invoices/create');
|
||||||
|
$I->selectDropdown($I, $clientEmail, '.client_select .dropdown-toggle');
|
||||||
|
$I->fillField('table.invoice-table tbody tr:nth-child(1) #product_key', $productKey);
|
||||||
|
$I->click('Save');
|
||||||
|
$I->wait(1);
|
||||||
|
$I->see($clientEmail);
|
||||||
|
$invoiceId = $I->grabFromCurrentUrl('~invoices/(\d+)~');
|
||||||
|
$I->amOnPage("/clients/{$clientId}");
|
||||||
|
$I->see('Balance $' . $productPrice);
|
||||||
|
|
||||||
|
// update the invoice
|
||||||
|
$I->amOnPage('/invoices/' . $invoiceId);
|
||||||
|
$I->fillField(['name' => 'quantity'], 2);
|
||||||
|
$I->click('Save');
|
||||||
|
$I->wait(1);
|
||||||
|
$I->amOnPage("/clients/{$clientId}");
|
||||||
|
$I->see('Balance $' . ($productPrice * 2));
|
||||||
|
|
||||||
|
// enter payment
|
||||||
|
$I->amOnPage("/payments/create/{$clientId}/{$invoiceId}");
|
||||||
|
$I->click('Save');
|
||||||
|
$I->wait(1);
|
||||||
|
$I->see('Balance $0.00');
|
||||||
|
$I->see('Paid to Date $' . ($productPrice * 2));
|
||||||
|
|
||||||
|
// archive the invoice
|
||||||
|
$I->amOnPage('/invoices/' . $invoiceId);
|
||||||
|
$I->executeJS('submitAction("archive")');
|
||||||
|
$I->wait(1);
|
||||||
|
$I->amOnPage("/clients/{$clientId}");
|
||||||
|
$I->see('Balance $0.00');
|
||||||
|
$I->see('Paid to Date $' . ($productPrice * 2));
|
||||||
|
|
||||||
|
// delete the invoice
|
||||||
|
$I->amOnPage('/invoices/' . $invoiceId);
|
||||||
|
$I->executeJS('submitAction("delete")');
|
||||||
|
$I->wait(1);
|
||||||
|
$I->amOnPage("/clients/{$clientId}");
|
||||||
|
$I->see('Balance $0.00');
|
||||||
|
$I->see('Paid to Date $0.00');
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user