Merge pull request #7792 from turbo124/v5-develop

v5.5.18
This commit is contained in:
David Bomba 2022-09-01 20:28:26 +10:00 committed by GitHub
commit 68ff176725
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
45 changed files with 1508 additions and 147 deletions

View File

@ -12,7 +12,7 @@ jobs:
runs-on: ${{ matrix.operating-system }}
strategy:
matrix:
operating-system: ['ubuntu-18.04', 'ubuntu-20.04', 'ubuntu-22.04']
operating-system: ['ubuntu-20.04', 'ubuntu-22.04']
php-versions: ['8.1']
phpunit-versions: ['latest']

View File

@ -1 +1 @@
5.5.17
5.5.18

View File

@ -29,6 +29,7 @@ use App\Models\Payment;
use App\Models\Paymentable;
use App\Models\QuoteInvitation;
use App\Models\RecurringInvoiceInvitation;
use App\Models\User;
use App\Models\Vendor;
use App\Utils\Ninja;
use Exception;
@ -115,6 +116,7 @@ class CheckData extends Command
$this->checkCompanyData();
$this->checkBalanceVsPaidStatus();
$this->checkDuplicateRecurringInvoices();
$this->checkOauthSanity();
if(Ninja::isHosted())
$this->checkAccountStatuses();
@ -146,6 +148,15 @@ class CheckData extends Command
$this->log .= $str."\n";
}
private function checkOauthSanity()
{
User::where('oauth_provider_id', '1')->cursor()->each(function ($user){
$this->logMessage("Invalid provider ID for user id# {$user->id}");
});
}
private function checkDuplicateRecurringInvoices()
{
@ -955,7 +966,7 @@ class CheckData extends Command
{
$this->wrong_paid_status = 0;
foreach(Invoice::with(['payments'])->whereHas('payments')->where('status_id', 4)->where('balance', '>', 0)->where('is_deleted',0)->cursor() as $invoice)
foreach(Invoice::with(['payments'])->where('is_deleted',0)->where('balance', '>', 0)->whereHas('payments')->where('status_id', 4)->cursor() as $invoice)
{
$this->wrong_paid_status++;

View File

@ -168,6 +168,9 @@ class ClientFilters extends QueryFilters
{
$sort_col = explode('|', $sort);
if($sort_col[0] == 'display_name')
$sort_col[0] = 'name';
return $this->builder->orderBy($sort_col[0], $sort_col[1]);
}

View File

@ -107,6 +107,7 @@ class ActivityController extends BaseController
'payment' => $activity->payment ? $activity->payment : '',
'credit' => $activity->credit ? $activity->credit : '',
'task' => $activity->task ? $activity->task : '',
'vendor' => $activity->vendor ? $activity->vendor : '',
];
return array_merge($arr, $activity->toArray());

View File

@ -351,7 +351,7 @@ class LoginController extends BaseController
private function handleSocialiteLogin($provider, $token)
{
$user = $this->getSocialiteUser($provider, $token);
nlog($user);
if ($user) {
return $this->loginOrCreateFromSocialite($user, $provider);
}
@ -368,6 +368,7 @@ class LoginController extends BaseController
'oauth_user_id' => $user->id,
'oauth_provider_id' => $provider,
];
if ($existing_user = MultiDB::hasUser($query)) {
if (!$existing_user->account) {
return response()->json(['message' => 'User exists, but not attached to any companies! Orphaned user!'], 400);
@ -749,10 +750,6 @@ class LoginController extends BaseController
public function handleMicrosoftProviderCallback($provider = 'microsoft')
{
$socialite_user = Socialite::driver($provider)->user();
nlog($socialite_user);
nlog('refresh token ' . $socialite_user->accessTokenResponseBody['refresh_token']);
nlog('access token ' . $socialite_user->accessTokenResponseBody['access_token']);
$oauth_user_token = $socialite_user->accessTokenResponseBody['access_token'];

View File

@ -69,7 +69,7 @@ class InvoiceController extends Controller
$data = [
'invoice' => $invoice,
'invitation' => $invitation,
'invitation' => $invitation ?: $invoice->invitations->first(),
'key' => $invitation ? $invitation->key : false,
];

View File

@ -195,6 +195,7 @@ class NinjaPlanController extends Controller
public function plan()
{
// return $this->trial();
//harvest the current plan
$data = [];

View File

@ -101,7 +101,8 @@ class PaymentController extends Controller
$data = [
'invoice' => $invoice,
'key' => false
'key' => false,
'invitation' => $invoice->invitations->first()
];
if ($request->query('mode') === 'fullscreen') {

View File

@ -139,9 +139,14 @@ class Request extends FormRequest
$input['invitations'][$key]['id'] = $this->decodePrimaryKey($input['invitations'][$key]['id']);
}
if (is_string($input['invitations'][$key]['client_contact_id'])) {
if (array_key_exists('client_contact_id', $input['invitations'][$key]) && is_string($input['invitations'][$key]['client_contact_id'])) {
$input['invitations'][$key]['client_contact_id'] = $this->decodePrimaryKey($input['invitations'][$key]['client_contact_id']);
}
if (array_key_exists('vendor_contact_id', $input['invitations'][$key]) && is_string($input['invitations'][$key]['vendor_contact_id'])) {
$input['invitations'][$key]['vendor_contact_id'] = $this->decodePrimaryKey($input['invitations'][$key]['vendor_contact_id']);
}
}
}

View File

@ -33,6 +33,15 @@ class VendorMap
14 => 'vendor.state',
15 => 'vendor.postal_code',
16 => 'vendor.country_id',
17 => 'contact.first_name',
18 => 'contact.last_name',
19 => 'contact.email',
20 => 'contact.phone',
21 => 'contact.custom_value1',
22 => 'contact.custom_value2',
23 => 'contact.custom_value3',
24 => 'contact.custom_value4',
];
}
@ -56,6 +65,14 @@ class VendorMap
14 => 'texts.state',
15 => 'texts.postal_code',
16 => 'texts.country',
17 => 'texts.first_name',
18 => 'texts.last_name',
19 => 'texts.email',
20 => 'texts.phone',
21 => 'texts.custom_value',
22 => 'texts.custom_value',
23 => 'texts.custom_value',
24 => 'texts.custom_value',
];
}
}

View File

@ -16,12 +16,14 @@ use App\Factory\ExpenseFactory;
use App\Factory\InvoiceFactory;
use App\Factory\PaymentFactory;
use App\Factory\ProductFactory;
use App\Factory\QuoteFactory;
use App\Factory\VendorFactory;
use App\Http\Requests\Client\StoreClientRequest;
use App\Http\Requests\Expense\StoreExpenseRequest;
use App\Http\Requests\Invoice\StoreInvoiceRequest;
use App\Http\Requests\Payment\StorePaymentRequest;
use App\Http\Requests\Product\StoreProductRequest;
use App\Http\Requests\Quote\StoreQuoteRequest;
use App\Http\Requests\Vendor\StoreVendorRequest;
use App\Import\ImportException;
use App\Import\Providers\BaseImport;
@ -31,12 +33,14 @@ use App\Import\Transformer\Csv\ExpenseTransformer;
use App\Import\Transformer\Csv\InvoiceTransformer;
use App\Import\Transformer\Csv\PaymentTransformer;
use App\Import\Transformer\Csv\ProductTransformer;
use App\Import\Transformer\Csv\QuoteTransformer;
use App\Import\Transformer\Csv\VendorTransformer;
use App\Repositories\ClientRepository;
use App\Repositories\ExpenseRepository;
use App\Repositories\InvoiceRepository;
use App\Repositories\PaymentRepository;
use App\Repositories\ProductRepository;
use App\Repositories\QuoteRepository;
use App\Repositories\VendorRepository;
use Illuminate\Support\Facades\Validator;
use Symfony\Component\HttpFoundation\ParameterBag;
@ -55,6 +59,7 @@ class Csv extends BaseImport implements ImportInterface
'payment',
'vendor',
'expense',
'quote',
])
) {
$this->{$entity}();
@ -151,6 +156,35 @@ class Csv extends BaseImport implements ImportInterface
$this->entity_count['invoices'] = $invoice_count;
}
public function quote()
{
$entity_type = 'quote';
$data = $this->getCsvData($entity_type);
if (is_array($data)) {
$data = $this->preTransformCsv($data, $entity_type);
}
if (empty($data)) {
$this->entity_count['quotes'] = 0;
return;
}
$this->request_name = StoreQuoteRequest::class;
$this->repository_name = QuoteRepository::class;
$this->factory_name = QuoteFactory::class;
$this->repository = app()->make($this->repository_name);
$this->repository->import_mode = true;
$this->transformer = new QuoteTransformer($this->company);
$quote_count = $this->ingestQuotes($data, 'quote.number');
$this->entity_count['quotes'] = $quote_count;
}
public function payment()
{
$entity_type = 'payment';
@ -241,10 +275,6 @@ class Csv extends BaseImport implements ImportInterface
$this->entity_count['expenses'] = $expense_count;
}
public function quote()
{
}
public function task()
{
}

View File

@ -19,6 +19,14 @@ use App\Models\Country;
use App\Models\ExpenseCategory;
use App\Models\PaymentType;
use App\Models\User;
use App\Models\Expense;
use App\Models\Project;
use App\Models\Invoice;
use App\Models\Quote;
use App\Models\Client;
use App\Models\TaxRate;
use App\Models\Product;
use App\Models\Vendor;
use App\Utils\Number;
use Exception;
use Illuminate\Support\Carbon;
@ -67,8 +75,7 @@ class BaseTransformer
{
if (! empty($client_name)) {
$client_id_search = $this->company
->clients()
$client_id_search = Client::where('company_id', $this->company->id)
->where('is_deleted', false)
->where('id_number', $client_name);
@ -76,8 +83,7 @@ class BaseTransformer
return $client_id_search->first()->id;
}
$client_name_search = $this->company
->clients()
$client_name_search = Client::where('company_id', $this->company->id)
->where('is_deleted', false)
->where('name', $client_name);
@ -108,8 +114,7 @@ class BaseTransformer
*/
public function hasClient($name)
{
return $this->company
->clients()
return Client::where('company_id', $this->company->id)
->where('is_deleted', false)
->whereRaw("LOWER(REPLACE(`name`, ' ' ,'')) = ?", [
strtolower(str_replace(' ', '', $name)),
@ -124,8 +129,7 @@ class BaseTransformer
*/
public function hasVendor($name)
{
return $this->company
->vendors()
return Vendor::where('company_id', $this->company->id)
->where('is_deleted', false)
->whereRaw("LOWER(REPLACE(`name`, ' ' ,'')) = ?", [
strtolower(str_replace(' ', '', $name)),
@ -140,8 +144,7 @@ class BaseTransformer
*/
public function hasProject($name)
{
return $this->company
->projects()
return Project::where('company_id', $this->company->id)
->where('is_deleted', false)
->whereRaw("LOWER(REPLACE(`name`, ' ' ,'')) = ?", [
strtolower(str_replace(' ', '', $name)),
@ -156,8 +159,7 @@ class BaseTransformer
*/
public function hasProduct($key)
{
return $this->company
->products()
return Product::where('company_id', $this->company->id)
->where('is_deleted', false)
->whereRaw("LOWER(REPLACE(`product_key`, ' ' ,'')) = ?", [
strtolower(str_replace(' ', '', $key)),
@ -189,8 +191,7 @@ class BaseTransformer
*/
public function getClientId($name)
{
$client = $this->company
->clients()
$client = Client::where('company_id', $this->company->id)
->where('is_deleted', false)
->whereRaw("LOWER(REPLACE(`name`, ' ' ,'')) = ?", [
strtolower(str_replace(' ', '', $name)),
@ -207,8 +208,7 @@ class BaseTransformer
*/
public function getProduct($key)
{
$product = $this->company
->products()
$product = Product::where('company_id', $this->company->id)
->where('is_deleted', false)
->whereRaw("LOWER(REPLACE(`product_key`, ' ' ,'')) = ?", [
strtolower(str_replace(' ', '', $key)),
@ -225,8 +225,7 @@ class BaseTransformer
*/
public function getContact($email)
{
$contact = $this->company
->client_contacts()
$contact = ClientContact::where('company_id', $this->company->id)
->whereRaw("LOWER(REPLACE(`email`, ' ' ,'')) = ?", [
strtolower(str_replace(' ', '', $email)),
])
@ -278,8 +277,7 @@ class BaseTransformer
{
$name = strtolower(trim($name));
$tax_rate = $this->company
->tax_rates()
$tax_rate = TaxRate::where('company_id', $this->company->id)
->where('is_deleted', false)
->whereRaw("LOWER(REPLACE(`name`, ' ' ,'')) = ?", [
strtolower(str_replace(' ', '', $name)),
@ -298,8 +296,7 @@ class BaseTransformer
{
$name = strtolower(trim($name));
$tax_rate = $this->company
->tax_rates()
$tax_rate = TaxRate::where('company_id', $this->company->id)
->where('is_deleted', false)
->whereRaw("LOWER(REPLACE(`name`, ' ' ,'')) = ?", [
strtolower(str_replace(' ', '', $name)),
@ -348,8 +345,7 @@ class BaseTransformer
*/
public function getInvoiceId($invoice_number)
{
$invoice = $this->company
->invoices()
$invoice = Invoice::where('company_id', $this->company->id)
->where('is_deleted', false)
->whereRaw("LOWER(REPLACE(`number`, ' ' ,'')) = ?", [
strtolower(str_replace(' ', '', $invoice_number)),
@ -366,8 +362,7 @@ class BaseTransformer
*/
public function hasInvoice($invoice_number)
{
return $this->company
->invoices()
return Invoice::where('company_id', $this->company->id)
->where('is_deleted', false)
->whereRaw("LOWER(REPLACE(`number`, ' ' ,'')) = ?", [
strtolower(str_replace(' ', '', $invoice_number)),
@ -380,8 +375,7 @@ class BaseTransformer
*/
public function hasExpense($expense_number)
{
return $this->company
->expenses()
return Expense::where('company_id', $this->company->id)
->where('is_deleted', false)
->whereRaw("LOWER(REPLACE(`number`, ' ' ,'')) = ?", [
strtolower(str_replace(' ', '', $expense_number)),
@ -396,8 +390,7 @@ class BaseTransformer
*/
public function hasQuote($quote_number)
{
return $this->company
->quotes()
return Quote::where('company_id', $this->company->id)
->where('is_deleted', false)
->whereRaw("LOWER(REPLACE(`number`, ' ' ,'')) = ?", [
strtolower(str_replace(' ', '', $quote_number)),
@ -412,8 +405,7 @@ class BaseTransformer
*/
public function getInvoiceClientId($invoice_number)
{
$invoice = $this->company
->invoices()
$invoice = Invoice::where('company_id', $this->company->id)
->where('is_deleted', false)
->whereRaw("LOWER(REPLACE(`number`, ' ' ,'')) = ?", [
strtolower(str_replace(' ', '', $invoice_number)),
@ -430,8 +422,7 @@ class BaseTransformer
*/
public function getVendorId($name)
{
$vendor = $this->company
->vendors()
$vendor = Vendor::where('company_id', $this->company->id)
->where('is_deleted', false)
->whereRaw("LOWER(REPLACE(`name`, ' ' ,'')) = ?", [
strtolower(str_replace(' ', '', $name)),
@ -467,8 +458,7 @@ class BaseTransformer
*/
public function getExpenseCategoryId($name)
{
$ec = $this->company
->expense_categories()
$ec = ExpenseCategory::where('company_id', $this->company->id)
->where('is_deleted', false)
->whereRaw("LOWER(REPLACE(`name`, ' ' ,'')) = ?", [
strtolower(str_replace(' ', '', $name)),
@ -504,8 +494,7 @@ class BaseTransformer
*/
public function getProjectId($name, $clientId = null)
{
$project = $this->company
->projects()
$project = Project::where('company_id', $this->company->id)
->where('is_deleted', false)
->whereRaw("LOWER(REPLACE(`name`, ' ' ,'')) = ?", [
strtolower(str_replace(' ', '', $name)),

View File

@ -52,15 +52,42 @@ class VendorTransformer extends BaseTransformer
'custom_value2' => $this->getString($data, 'vendor.custom_value2'),
'custom_value3' => $this->getString($data, 'vendor.custom_value3'),
'custom_value4' => $this->getString($data, 'vendor.custom_value4'),
'vendor_contacts' => [
// 'vendor_contacts' => [
// [
// 'first_name' => $this->getString(
// $data,
// 'vendor.first_name'
// ),
// 'last_name' => $this->getString($data, 'vendor.last_name'),
// 'email' => $this->getString($data, 'vendor.email'),
// 'phone' => $this->getString($data, 'vendor.phone'),
// ],
// ],
'contacts' => [
[
'first_name' => $this->getString(
$data,
'vendor.first_name'
'contact.first_name'
),
'last_name' => $this->getString($data, 'contact.last_name'),
'email' => $this->getString($data, 'contact.email'),
'phone' => $this->getString($data, 'contact.phone'),
'custom_value1' => $this->getString(
$data,
'contact.custom_value1'
),
'custom_value2' => $this->getString(
$data,
'contact.custom_value2'
),
'custom_value3' => $this->getString(
$data,
'contact.custom_value3'
),
'custom_value4' => $this->getString(
$data,
'contact.custom_value4'
),
'last_name' => $this->getString($data, 'vendor.last_name'),
'email' => $this->getString($data, 'vendor.email'),
'phone' => $this->getString($data, 'vendor.phone'),
],
],
'country_id' => isset($data['vendor.country_id'])

View File

@ -44,12 +44,12 @@ class RecurringInvoicesCron
nlog('Sending recurring invoices '.$start);
if (! config('ninja.db.multi_db_enabled')) {
$recurring_invoices = RecurringInvoice::where('next_send_date', '<=', now()->toDateTimeString())
$recurring_invoices = RecurringInvoice::where('status_id', RecurringInvoice::STATUS_ACTIVE)
->where('is_deleted', false)
->where('remaining_cycles', '!=', '0')
->whereNotNull('next_send_date')
->whereNull('deleted_at')
->where('is_deleted', false)
->where('status_id', RecurringInvoice::STATUS_ACTIVE)
->where('remaining_cycles', '!=', '0')
->where('next_send_date', '<=', now()->toDateTimeString())
->whereHas('client', function ($query) {
$query->where('is_deleted', 0)
->where('deleted_at', null);
@ -84,12 +84,12 @@ class RecurringInvoicesCron
foreach (MultiDB::$dbs as $db) {
MultiDB::setDB($db);
$recurring_invoices = RecurringInvoice::where('next_send_date', '<=', now()->toDateTimeString())
->whereNotNull('next_send_date')
->whereNull('deleted_at')
$recurring_invoices = RecurringInvoice::where('status_id', RecurringInvoice::STATUS_ACTIVE)
->where('is_deleted', false)
->where('status_id', RecurringInvoice::STATUS_ACTIVE)
->where('remaining_cycles', '!=', '0')
->whereNull('deleted_at')
->whereNotNull('next_send_date')
->where('next_send_date', '<=', now()->toDateTimeString())
->whereHas('client', function ($query) {
$query->where('is_deleted', 0)
->where('deleted_at', null);

View File

@ -74,7 +74,7 @@ class CSVIngest implements ShouldQueue
$engine = $this->bootEngine();
foreach (['client', 'product', 'invoice', 'payment', 'vendor', 'expense'] as $entity) {
foreach (['client', 'product', 'invoice', 'payment', 'vendor', 'expense', 'quote'] as $entity) {
$engine->import($entity);
}

View File

@ -354,14 +354,19 @@ class NinjaMailerJob implements ShouldQueue
if(!str_contains($this->nmo->to_user->email, "@"))
return true;
/* On the hosted platform if the user has not verified their account we fail here - but still check what they are trying to send! */
if(Ninja::isHosted() && $this->company->account && !$this->company->account->account_sms_verified){
if(class_exists(\Modules\Admin\Jobs\Account\EmailQuality::class))
return (new \Modules\Admin\Jobs\Account\EmailQuality($this->nmo, $this->company))->run();
return true;
}
/* On the hosted platform we actively scan all outbound emails to ensure outbound email quality remains high */
if(class_exists(\Modules\Admin\Jobs\Account\EmailQuality::class))
return (new \Modules\Admin\Jobs\Account\EmailQuality($this->nmo, $this->company))->run();
/* On the hosted platform if the user has not verified their account we fail here */
if(Ninja::isHosted() && $this->company->account && !$this->company->account->account_sms_verified)
return true;
return false;
}

View File

@ -60,11 +60,11 @@ class ReminderJob implements ShouldQueue
{
nlog('Sending invoice reminders '.now()->format('Y-m-d h:i:s'));
Invoice::where('next_send_date', '<=', now()->toDateTimeString())
->whereNull('deleted_at')
->where('is_deleted', 0)
Invoice::where('is_deleted', 0)
->whereIn('status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL])
->whereNull('deleted_at')
->where('balance', '>', 0)
->where('next_send_date', '<=', now()->toDateTimeString())
->whereHas('client', function ($query) {
$query->where('is_deleted', 0)
->where('deleted_at', null);

View File

@ -222,6 +222,7 @@ class PaymentEmailEngine extends BaseEmailEngine
$data['$view_link'] = ['value' => '<a class="button" href="'.$this->payment->getLink().'">'.ctrans('texts.view_payment').'</a>', 'label' => ctrans('texts.view_payment')];
$data['$view_button'] = &$data['$view_link'];
$data['$viewButton'] = &$data['$view_link'];
$data['$viewLink'] = &$data['$view_link'];
$data['$paymentLink'] = &$data['$view_link'];
$data['$portalButton'] = ['value' => "<a href='{$this->payment->getPortalLink()}'>".ctrans('texts.login').'</a>', 'label' =>''];
@ -237,6 +238,10 @@ class PaymentEmailEngine extends BaseEmailEngine
$data['$invoice.po_number'] = ['value' => $this->formatPoNumber(), 'label' => ctrans('texts.po_number')];
$data['$poNumber'] = &$data['$invoice.po_number'];
$data['$payment.status'] = ['value' => $this->payment->stringStatus($this->payment->status_id), 'label' => ctrans('texts.payment_status')];
$data['$invoices.amount'] = ['value' => $this->formatInvoiceField('amount'), 'label' => ctrans('texts.invoices')];
$data['$invoices.balance'] = ['value' => $this->formatInvoiceField('balance'), 'label' => ctrans('texts.invoices')];
$data['$invoices.due_date'] = ['value' => $this->formatInvoiceField('due_date'), 'label' => ctrans('texts.invoices')];
$data['$invoices.po_number'] = ['value' => $this->formatInvoiceField('po_number'), 'label' => ctrans('texts.invoices')];
$arrKeysLength = array_map('strlen', array_keys($data));
array_multisort($arrKeysLength, SORT_DESC, $data);
@ -244,6 +249,22 @@ class PaymentEmailEngine extends BaseEmailEngine
return $data;
}
private function formatInvoiceField($field)
{
$invoice = '';
foreach ($this->payment->invoices as $invoice) {
$invoice_field = $invoice->{$field};
$invoice .= ctrans('texts.invoice_number_short') . "{$invoice->number} {$invoice_field}";
}
return $invoice;
}
private function formatInvoice()
{
$invoice = '';
@ -282,11 +303,15 @@ class PaymentEmailEngine extends BaseEmailEngine
$invoice_list = '<br><br>';
foreach ($this->payment->invoices as $invoice) {
$invoice_list .= ctrans('texts.po_number')." {$invoice->po_number} <br>";
if(strlen($invoice->po_number) > 1)
$invoice_list .= ctrans('texts.po_number')." {$invoice->po_number} <br>";
$invoice_list .= ctrans('texts.invoice_number_short')." {$invoice->number} <br>";
$invoice_list .= ctrans('texts.invoice_amount').' '.Number::formatMoney($invoice->pivot->amount, $this->client).'<br>';
$invoice_list .= ctrans('texts.invoice_balance').' '.Number::formatMoney($invoice->fresh()->balance, $this->client).'<br>';
$invoice_list .= '-----<br>';
}
return $invoice_list;

View File

@ -266,6 +266,11 @@ class Activity extends StaticModel
return $this->belongsTo(Invoice::class)->withTrashed();
}
public function vendor()
{
return $this->belongsTo(Vendor::class)->withTrashed();
}
/**
* @return mixed
*/

View File

@ -131,7 +131,8 @@ class PaymentRepository extends BaseRepository {
/*Ensure payment number generated*/
if (! $payment->number || strlen($payment->number) == 0) {
$payment->number = $payment->client->getNextPaymentNumber($payment->client, $payment);
// $payment->number = $payment->client->getNextPaymentNumber($payment->client, $payment);
$payment->service()->applyNumber();
}
/*Set local total variables*/

View File

@ -62,6 +62,8 @@ class UserRepository extends BaseRepository
// $account->num_users++;
// $account->save();
// }
if(array_key_exists('oauth_provider_id', $details))
unset($details['oauth_provider_id']);
$user->fill($details);

View File

@ -41,20 +41,37 @@ class MarkPaid extends AbstractService
public function run()
{
if ($this->invoice->status_id == Invoice::STATUS_DRAFT) {
$this->invoice->service()->markSent()->save();
}
/*Don't double pay*/
if ($this->invoice->status_id == Invoice::STATUS_PAID) {
return $this->invoice;
}
if ($this->invoice->status_id == Invoice::STATUS_DRAFT) {
$this->invoice->service()->markSent()->save();
}
$payable_balance = $this->invoice->balance;
\DB::connection(config('database.default'))->transaction(function () use($payable_balance) {
$this->invoice = Invoice::where('id', $this->invoice->id)->lockForUpdate()->first();
$this->invoice
->service()
->setExchangeRate()
->updateBalance($payable_balance * -1)
->updatePaidToDate($payable_balance)
->setStatus(Invoice::STATUS_PAID)
->save();
}, 1);
/* Create Payment */
$payment = PaymentFactory::create($this->invoice->company_id, $this->invoice->user_id);
$payment->amount = $this->invoice->balance;
$payment->applied = $this->invoice->balance;
$payment->amount = $payable_balance;
$payment->applied = $payable_balance;
$payment->status_id = Payment::STATUS_COMPLETED;
$payment->client_id = $this->invoice->client_id;
$payment->transaction_reference = ctrans('texts.manual_entry');
@ -79,20 +96,20 @@ class MarkPaid extends AbstractService
/* Create a payment relationship to the invoice entity */
$payment->invoices()->attach($this->invoice->id, [
'amount' => $payment->amount,
'amount' => $payable_balance,
]);
event('eloquent.created: App\Models\Payment', $payment);
$this->invoice->next_send_date = null;
$this->invoice
->service()
->setExchangeRate()
->updateBalance($payment->amount * -1)
->updatePaidToDate($payment->amount)
->setStatus(Invoice::STATUS_PAID)
->save();
// $this->invoice
// ->service()
// ->setExchangeRate()
// ->updateBalance($payment->amount * -1)
// ->updatePaidToDate($payment->amount)
// ->setStatus(Invoice::STATUS_PAID)
// ->save();
$this->invoice
->service()
@ -101,7 +118,7 @@ class MarkPaid extends AbstractService
->save();
$payment->ledger()
->updatePaymentBalance($payment->amount * -1);
->updatePaymentBalance($payable_balance * -1);
\DB::connection(config('database.default'))->transaction(function () use ($payment) {

View File

@ -42,9 +42,9 @@ class ZeroCostProduct extends AbstractService
$invoice = $this->subscription->service()->createInvoice($this->data);
$invoice->service()
->markPaid()
->save();
$invoice = $invoice->service()
->markPaid()
->save();
$redirect_url = "/client/invoices/{$invoice->hashed_id}";

View File

@ -184,6 +184,9 @@ class SystemHealth
private static function checkPhpCli()
{
if(!function_exists('exec'))
return "Unable to check CLI version";
try {
exec('php -v', $foo, $exitCode);

View File

@ -408,6 +408,68 @@ class VendorHtmlEngine
$data['$payments'] = ['value' => '', 'label' => ctrans('texts.payments')];
if($this->entity->client()->exists())
{
$data['$client1'] = ['value' => $this->helpers->formatCustomFieldValue($this->company->custom_fields, 'client1', $this->entity->client->custom_value1, $this->entity->client) ?: '&nbsp;', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'client1')];
$data['$client2'] = ['value' => $this->helpers->formatCustomFieldValue($this->company->custom_fields, 'client2', $this->entity->client->custom_value2, $this->entity->client) ?: '&nbsp;', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'client2')];
$data['$client3'] = ['value' => $this->helpers->formatCustomFieldValue($this->company->custom_fields, 'client3', $this->entity->client->custom_value3, $this->entity->client) ?: '&nbsp;', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'client3')];
$data['$client4'] = ['value' => $this->helpers->formatCustomFieldValue($this->company->custom_fields, 'client4', $this->entity->client->custom_value4, $this->entity->client) ?: '&nbsp;', 'label' => $this->helpers->makeCustomField($this->company->custom_fields, 'client4')];
$data['$client.custom1'] = &$data['$client1'];
$data['$client.custom2'] = &$data['$client2'];
$data['$client.custom3'] = &$data['$client3'];
$data['$client.custom4'] = &$data['$client4'];
$data['$client.number'] = ['value' => $this->entity->client->number ?: '&nbsp;', 'label' => ctrans('texts.number')];
$data['$client_name'] = ['value' => $this->entity->client->present()->name() ?: '&nbsp;', 'label' => ctrans('texts.client_name')];
$data['$client.name'] = &$data['$client_name'];
$data['$client'] = &$data['$client_name'];
$data['$client.address1'] = &$data['$address1'];
$data['$client.address2'] = &$data['$address2'];
$data['$client_address'] = ['value' => $this->entity->client->present()->address() ?: '&nbsp;', 'label' => ctrans('texts.address')];
$data['$client.address'] = &$data['$client_address'];
$data['$client.postal_code'] = ['value' => $this->entity->client->postal_code ?: '&nbsp;', 'label' => ctrans('texts.postal_code')];
$data['$client.public_notes'] = ['value' => $this->entity->client->public_notes ?: '&nbsp;', 'label' => ctrans('texts.notes')];
$data['$client.city'] = ['value' => $this->entity->client->city ?: '&nbsp;', 'label' => ctrans('texts.city')];
$data['$client.state'] = ['value' => $this->entity->client->state ?: '&nbsp;', 'label' => ctrans('texts.state')];
$data['$client.id_number'] = &$data['$id_number'];
$data['$client.vat_number'] = &$data['$vat_number'];
$data['$client.website'] = &$data['$website'];
$data['$client.phone'] = &$data['$phone'];
$data['$city_state_postal'] = ['value' => $this->entity->client->present()->cityStateZip($this->entity->client->city, $this->entity->client->state, $this->entity->client->postal_code, false) ?: '&nbsp;', 'label' => ctrans('texts.city_state_postal')];
$data['$client.city_state_postal'] = &$data['$city_state_postal'];
$data['$postal_city_state'] = ['value' => $this->entity->client->present()->cityStateZip($this->entity->client->city, $this->entity->client->state, $this->entity->client->postal_code, true) ?: '&nbsp;', 'label' => ctrans('texts.postal_city_state')];
$data['$client.postal_city_state'] = &$data['$postal_city_state'];
$data['$client.country'] = &$data['$country'];
$data['$client.email'] = &$data['$email'];
$data['$client.billing_address'] = &$data['$client_address'];
$data['$client.billing_address1'] = &$data['$client.address1'];
$data['$client.billing_address2'] = &$data['$client.address2'];
$data['$client.billing_city'] = &$data['$client.city'];
$data['$client.billing_state'] = &$data['$client.state'];
$data['$client.billing_postal_code'] = &$data['$client.postal_code'];
$data['$client.billing_country'] = &$data['$client.country'];
$data['$client.shipping_address'] = ['value' => $this->entity->client->present()->shipping_address() ?: '&nbsp;', 'label' => ctrans('texts.shipping_address')];
$data['$client.shipping_address1'] = ['value' => $this->entity->client->shipping_address1 ?: '&nbsp;', 'label' => ctrans('texts.shipping_address1')];
$data['$client.shipping_address2'] = ['value' => $this->entity->client->shipping_address2 ?: '&nbsp;', 'label' => ctrans('texts.shipping_address2')];
$data['$client.shipping_city'] = ['value' => $this->entity->client->shipping_city ?: '&nbsp;', 'label' => ctrans('texts.shipping_city')];
$data['$client.shipping_state'] = ['value' => $this->entity->client->shipping_state ?: '&nbsp;', 'label' => ctrans('texts.shipping_state')];
$data['$client.shipping_postal_code'] = ['value' => $this->entity->client->shipping_postal_code ?: '&nbsp;', 'label' => ctrans('texts.shipping_postal_code')];
$data['$client.shipping_country'] = ['value' => isset($this->entity->client->shipping_country->name) ? ctrans('texts.country_' . $this->entity->client->shipping_country->name) : '', 'label' => ctrans('texts.shipping_country')];
$data['$client.currency'] = ['value' => $this->entity->client->currency()->code, 'label' => ''];
$data['$client.lang_2'] = ['value' => optional($this->entity->client->language())->locale, 'label' => ''];
$data['$client.balance'] = ['value' => Number::formatMoney($this->entity->client->balance, $this->entity->client), 'label' => ctrans('texts.account_balance')];
$data['$client_balance'] = ['value' => Number::formatMoney($this->entity->client->balance, $this->entity->client), 'label' => ctrans('texts.account_balance')];
}
$arrKeysLength = array_map('strlen', array_keys($data));
array_multisort($arrKeysLength, SORT_DESC, $data);

View File

@ -14,8 +14,8 @@ return [
'require_https' => env('REQUIRE_HTTPS', true),
'app_url' => rtrim(env('APP_URL', ''), '/'),
'app_domain' => env('APP_DOMAIN', 'invoicing.co'),
'app_version' => '5.5.17',
'app_tag' => '5.5.17',
'app_version' => '5.5.18',
'app_tag' => '5.5.18',
'minimum_client_version' => '5.0.16',
'terms_version' => '1.0.1',
'api_secret' => env('API_SECRET', ''),

View File

@ -0,0 +1,43 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('payments', function (Blueprint $table) {
$table->index(['transaction_reference']);
});
Schema::table('paymentables', function (Blueprint $table) {
$table->index(['paymentable_id']);
});
Schema::table('invoices', function (Blueprint $table) {
$table->index(['recurring_id']);
$table->index(['status_id','balance']);
});
Schema::table('quotes', function (Blueprint $table) {
$table->index(['company_id','updated_at']);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
}
};

View File

@ -0,0 +1,3 @@
<svg width="598" height="450" viewBox="0 0 598 450" fill="none" xmlns="http://www.w3.org/2000/svg">
<path opacity="0.05" d="M474.826 149.58C537.96 127.127 603.054 7.0443 592.708 -44.907L-72.3135 -6.27372L-93.116 541.526C-51.621 532.17 19.6183 527.658 70.9927 465.58C155.706 363.219 239.064 427.938 284.962 383.031C330.859 338.124 315.01 295.858 330.529 241.045C346.048 186.232 395.909 177.647 474.826 149.58Z" fill="white" stroke="white" stroke-width="7"/>
</svg>

After

Width:  |  Height:  |  Size: 464 B

View File

@ -0,0 +1,3 @@
<svg width="595" height="450" viewBox="0 0 595 450" fill="none" xmlns="http://www.w3.org/2000/svg">
<path opacity="0.2" d="M474.942 153.487C538.076 131.034 603.17 10.9513 592.823 -41L-72.1976 -2.36674L-93 545.433C-51.505 536.077 19.7343 531.565 71.1087 469.487C155.822 367.126 239.18 431.845 285.078 386.938C330.975 342.031 315.126 299.765 330.645 244.952C346.164 190.139 396.025 181.554 474.942 153.487Z" stroke="white"/>
</svg>

After

Width:  |  Height:  |  Size: 430 B

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 127 KiB

View File

@ -0,0 +1,3 @@
<svg width="598" height="450" viewBox="0 0 598 450" fill="none" xmlns="http://www.w3.org/2000/svg">
<path opacity="0.05" d="M474.826 149.58C537.96 127.127 603.054 7.0443 592.708 -44.907L-72.3135 -6.27372L-93.116 541.526C-51.621 532.17 19.6183 527.658 70.9927 465.58C155.706 363.219 239.064 427.938 284.962 383.031C330.859 338.124 315.01 295.858 330.529 241.045C346.048 186.232 395.909 177.647 474.826 149.58Z" fill="white" stroke="white" stroke-width="7"/>
</svg>

After

Width:  |  Height:  |  Size: 464 B

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
{"/livewire.js":"/livewire.js?id=c69d0f2801c01fcf8166"}
{"/livewire.js":"/livewire.js?id=de3fca26689cb5a39af4"}

View File

@ -125,7 +125,7 @@
<img src="{{ $logo ?? '' }}" alt="" width="155" border="0" align="middle" style="display:block;" />
<div style="mso-hide:all;">
<![endif]-->
<img class="logo-light" src="{{ $logo ?? '' }}" alt="" width="400" style="margin-top: 10px; max-width: 570px; display: block; margin-left: auto; margin-right: auto;"/>
<img class="logo-light" src="{{ $logo ?? '' }}" alt="" width="400" style="margin-top: 10px; max-width: 200px; display: block; margin-left: auto; margin-right: auto;"/>
<!--[if gte mso 9]>
</div>
<![endif]-->

View File

@ -104,14 +104,13 @@
</tr>
<tr>
<td align="center" cellpadding="20">
<div
style="border: 1px solid #c2c2c2; border-bottom: none; padding-bottom: 10px; border-top-left-radius: 3px; border-top-right-radius: 3px;">
<div style="border: 1px solid #c2c2c2; border-bottom: none; padding-bottom: 10px; border-top-left-radius: 3px; border-top-right-radius: 3px;">
<!--[if gte mso 9]>
<img src="{{ $logo ?? '' }}" alt="" width="400" border="0" align="middle" style="display:block;" />
<div style="mso-hide:all;">
<![endif]-->
<img src="{{ $logo ?? '' }}" alt="" width="400" style="margin-top: 40px; max-width: 155px; display: block; margin-left: auto; margin-right: auto;"/>
<img src="{{ $logo ?? '' }}" alt="" width="400" style="margin-top: 40px; max-width: 200px; display: block; margin-left: auto; margin-right: auto;"/>
<!--[if gte mso 9]>
</div>
<![endif]-->

File diff suppressed because it is too large Load Diff

View File

@ -72,7 +72,7 @@ class EntityPaidToDateTest extends TestCase
$this->assertEquals($invoice->balance, 20);
$invoice->service()->markPaid()->save();
$invoice = $invoice->service()->markPaid()->save();
$this->assertEquals($invoice->paid_to_date, 20);
}
@ -81,7 +81,7 @@ class EntityPaidToDateTest extends TestCase
{
$invoice = $this->bootNewInvoice();
$invoice->service()->markPaid()->save();
$invoice = $invoice->service()->markPaid()->save();
$this->assertEquals(20, $invoice->paid_to_date);

View File

@ -1,24 +1,24 @@
"Invoice Ninja v4.5.17 - December 19, 2020 11:28 pm","","","","","","","","","","","","","","","","","","","","","","","","",""
"","","","","","","","","","","","","","","","","","","","","","","","","",""
"Vendors","","","","","","","","","","","","","","","","","","","","","","","","",""
"Name","Balance","Paid to Date","Billing Street","Billing Apt/Suite","Billing City","Billing State/Province","Billing Postal Code","Billing Country","Shipping Street","Shipping Apt/Suite","Shipping City","Shipping State/Province","Shipping Postal Code","Shipping Country","ID Number","VAT Number","Website","Phone","Currency","Public Notes","Private Notes","First Name","Last Name","Email","Phone"
"Ludwig Krajcik DVM","$-142.85","$205.15","371 O'Connell Summit","Suite 612","Lornamouth","New York","83425-0771","","","","","","","","","","","","","","","Terrill","Ondricka","brook59@example.org","1-537-759-0369"
"Bradly Jaskolski Sr.","$310.81","$313.71","21854 Prosacco Isle","Suite 619","Vicentastad","Colorado","05144","","","","","","","","","","","","","","","Pink","Balistreri","gheidenreich@example.org","1-995-790-2394 x58884"
"Mr. Dustin Stehr I","$285.70","$250.97","2941 Terence Station","Apt. 761","Bernierbury","Massachusetts","47675","","","","","","","","","","","","","","","Shemar","Stehr","labadie.dominique@example.com","624-610-5940"
"Dr. Baron Armstrong Sr.","$241.53","$280.42","9469 Ofelia Gateway","Suite 748","Evelynside","New Hampshire","66872","","","","","","","","","","","","","","","Fabiola","Mitchell","nico78@example.net","1-986-772-8058 x00345"
"Dr. Clemens Douglas MD","$317.94","$342.92","2919 Thompson Common Suite 410","Suite 381","Port Margie","Nevada","49890","","","","","","","","","","","","","","","Lolita","Tremblay","daphney.marquardt@example.com","1-461-699-9192 x9875"
"Dr. Claire Huel Sr.","$333.45","$359.51","363 Arlene Causeway Suite 763","Suite 409","Millerstad","Florida","25750","","","","","","","","","","","","","","","Brown","Lakin","vbeer@example.net","(776) 821-0650 x839"
"Francisca Padberg","$366.58","$203.16","5558 Ratke Flats","Suite 511","Krystelport","Alabama","15359-3783","","","","","","","","","","","","","","","Hallie","Dooley","kgottlieb@example.net","1-573-770-4753 x72129"
"Dr. Roy Kihn","$272.12","$251.41","20236 O'Hara Shores","Suite 368","Aliciaport","North Carolina","35415","","","","","","","","","","","","","","","Elwyn","Daugherty","wunsch.rozella@example.org","(745) 859-5855 x04216"
"Nasir Vandervort","$401.23","$173.17","24599 Hills Centers Suite 467","Apt. 038","North German","Ohio","85363-4720","","","","","","","","","","","","","","","Tre","Moore","wilfrid.kuhic@example.com","1-519-675-7395"
"Garry Rosenbaum","$271.82","$306.63","7127 Heidenreich Union Apt. 168","Suite 441","North Murray","North Carolina","29242","","","","","","","","","","","","","","","Ricardo","Johnston","ddubuque@example.com","(682) 216-1962"
"Hildegard Crona PhD","$398.96","$162.49","60142 Janice Islands","Apt. 627","South Stantown","Colorado","10298-5737","","","","","","","","","","","","","","","Miles","Tremblay","sabrina86@example.org","775-210-8656 x93138"
"Kristopher White I","$318.14","$423.20","7498 Brook Crest Apt. 175","Suite 682","Marianoland","Connecticut","86235-9979","","","","","","","","","","","","","","","Mateo","Welch","jedidiah64@example.com","847.353.7644"
"Ethan Grant","$380.71","$367.38","26755 June Extension Suite 589","Suite 706","North Krystelmouth","Delaware","12414","","","","","","","","","","","","","","","Colton","Muller","dorian.mayert@example.net","(267) 647-0537"
"Terry Shields","$230.25","$290.83","60946 Kayden Camp Apt. 046","Apt. 178","Douglashaven","Wyoming","68992","","","","","","","","","","","","","","","Dashawn","Homenick","hills.gina@example.net","(478) 814-9961"
"Agustina Lockman","$351.60","$264.81","152 Pattie Coves","Suite 971","North Mohamed","Hawaii","52966","","","","","","","","","","","","","","","Bert","Fritsch","greilly@example.org","15342929833"
"Alfonso Schimmel","$343.71","$200.99","358 Hills Coves","Apt. 032","Lake Aisha","District of Columbia","68945-0439","","","","","","","","","","","","","","","Antonio","Hayes","dkshlerin@example.com","1-350-691-4459 x775"
"Vergie Monahan","$210.27","$201.10","64004 Anderson Mall Suite 207","Suite 469","Oleshire","California","78369","","","","","","","","","","","","","","","Hilario","Morissette","zjacobs@example.net","552.914.6800 x81120"
"Carol Cremin","$301.53","$473.39","68731 Bartoletti Crescent","Suite 855","Aaronland","Wyoming","07924","","","","","","","","","","","","","","","Nathen","Wehner","jacobi.rosendo@example.com","1-223-910-2060 x09970"
"Randal Bosco MD","$318.71","$226.47","51884 Peter Falls","Suite 314","Angelicaville","Nebraska","78016-3254","","","","","","","","","","","","","","","Angelo","Ward","kozey.aurelio@example.org","1-329-488-8800"
"Ms. Alena Cassin","$262.45","$388.50","706 Delfina Burgs","Apt. 996","Bertaton","Ohio","22957","","","","","","","","","","","","","","","Eusebio","Reinger","golden.green@example.org","429-551-1362"
"Invoice Ninja v4.5.17 - December 19, 2020 11:28 pm",,,,,,,,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,,,,,,,
Vendors,,,,,,,,,,,,,,,,,,,,,,,,,
Name,Balance,Paid to Date,Billing Street,Billing Apt/Suite,Billing City,Billing State/Province,Billing Postal Code,Billing Country,Shipping Street,Shipping Apt/Suite,Shipping City,Shipping State/Province,Shipping Postal Code,Shipping Country,ID Number,VAT Number,Website,Phone,Currency,Public Notes,Private Notes,First Name,Last Name,Email,Phone
Ludwig Krajcik DVM,$-142.85,$205.15,371 O'Connell Summit,Suite 612,Lornamouth,New York,83425-0771,Australia,,,,,,,,,,,,,,Terrill,Ondricka,brook59@example.org,1-537-759-0369
Bradly Jaskolski Sr.,$310.81,$313.71,21854 Prosacco Isle,Suite 619,Vicentastad,Colorado,5144,Germany,,,,,,,,,,,,,,Pink,Balistreri,gheidenreich@example.org,1-995-790-2394 x58884
Mr. Dustin Stehr I,$285.70,$250.97,2941 Terence Station,Apt. 761,Bernierbury,Massachusetts,47675,USA,,,,,,,,,,,,,,Shemar,Stehr,labadie.dominique@example.com,624-610-5940
Dr. Baron Armstrong Sr.,$241.53,$280.42,9469 Ofelia Gateway,Suite 748,Evelynside,New Hampshire,66872,1,,,,,,,,,,,,,,Fabiola,Mitchell,nico78@example.net,1-986-772-8058 x00345
Dr. Clemens Douglas MD,$317.94,$342.92,2919 Thompson Common Suite 410,Suite 381,Port Margie,Nevada,49890,,,,,,,,,,,,,,,Lolita,Tremblay,daphney.marquardt@example.com,1-461-699-9192 x9875
Dr. Claire Huel Sr.,$333.45,$359.51,363 Arlene Causeway Suite 763,Suite 409,Millerstad,Florida,25750,,,,,,,,,,,,,,,Brown,Lakin,vbeer@example.net,(776) 821-0650 x839
Francisca Padberg,$366.58,$203.16,5558 Ratke Flats,Suite 511,Krystelport,Alabama,15359-3783,,,,,,,,,,,,,,,Hallie,Dooley,kgottlieb@example.net,1-573-770-4753 x72129
Dr. Roy Kihn,$272.12,$251.41,20236 O'Hara Shores,Suite 368,Aliciaport,North Carolina,35415,,,,,,,,,,,,,,,Elwyn,Daugherty,wunsch.rozella@example.org,(745) 859-5855 x04216
Nasir Vandervort,$401.23,$173.17,24599 Hills Centers Suite 467,Apt. 038,North German,Ohio,85363-4720,,,,,,,,,,,,,,,Tre,Moore,wilfrid.kuhic@example.com,1-519-675-7395
Garry Rosenbaum,$271.82,$306.63,7127 Heidenreich Union Apt. 168,Suite 441,North Murray,North Carolina,29242,,,,,,,,,,,,,,,Ricardo,Johnston,ddubuque@example.com,(682) 216-1962
Hildegard Crona PhD,$398.96,$162.49,60142 Janice Islands,Apt. 627,South Stantown,Colorado,10298-5737,,,,,,,,,,,,,,,Miles,Tremblay,sabrina86@example.org,775-210-8656 x93138
Kristopher White I,$318.14,$423.20,7498 Brook Crest Apt. 175,Suite 682,Marianoland,Connecticut,86235-9979,,,,,,,,,,,,,,,Mateo,Welch,jedidiah64@example.com,847.353.7644
Ethan Grant,$380.71,$367.38,26755 June Extension Suite 589,Suite 706,North Krystelmouth,Delaware,12414,,,,,,,,,,,,,,,Colton,Muller,dorian.mayert@example.net,(267) 647-0537
Terry Shields,$230.25,$290.83,60946 Kayden Camp Apt. 046,Apt. 178,Douglashaven,Wyoming,68992,,,,,,,,,,,,,,,Dashawn,Homenick,hills.gina@example.net,(478) 814-9961
Agustina Lockman,$351.60,$264.81,152 Pattie Coves,Suite 971,North Mohamed,Hawaii,52966,,,,,,,,,,,,,,,Bert,Fritsch,greilly@example.org,15342929833
Alfonso Schimmel,$343.71,$200.99,358 Hills Coves,Apt. 032,Lake Aisha,District of Columbia,68945-0439,,,,,,,,,,,,,,,Antonio,Hayes,dkshlerin@example.com,1-350-691-4459 x775
Vergie Monahan,$210.27,$201.10,64004 Anderson Mall Suite 207,Suite 469,Oleshire,California,78369,,,,,,,,,,,,,,,Hilario,Morissette,zjacobs@example.net,552.914.6800 x81120
Carol Cremin,$301.53,$473.39,68731 Bartoletti Crescent,Suite 855,Aaronland,Wyoming,7924,,,,,,,,,,,,,,,Nathen,Wehner,jacobi.rosendo@example.com,1-223-910-2060 x09970
Randal Bosco MD,$318.71,$226.47,51884 Peter Falls,Suite 314,Angelicaville,Nebraska,78016-3254,,,,,,,,,,,,,,,Angelo,Ward,kozey.aurelio@example.org,1-329-488-8800
Ms. Alena Cassin,$262.45,$388.50,706 Delfina Burgs,Apt. 996,Bertaton,Ohio,22957,,,,,,,,,,,,,,,Eusebio,Reinger,golden.green@example.org,429-551-1362

1 Invoice Ninja v4.5.17 - December 19, 2020 11:28 pm
2
3 Vendors
4 Name Balance Paid to Date Billing Street Billing Apt/Suite Billing City Billing State/Province Billing Postal Code Billing Country Shipping Street Shipping Apt/Suite Shipping City Shipping State/Province Shipping Postal Code Shipping Country ID Number VAT Number Website Phone Currency Public Notes Private Notes First Name Last Name Email Phone
5 Ludwig Krajcik DVM $-142.85 $205.15 371 O'Connell Summit Suite 612 Lornamouth New York 83425-0771 Australia Terrill Ondricka brook59@example.org 1-537-759-0369
6 Bradly Jaskolski Sr. $310.81 $313.71 21854 Prosacco Isle Suite 619 Vicentastad Colorado 05144 5144 Germany Pink Balistreri gheidenreich@example.org 1-995-790-2394 x58884
7 Mr. Dustin Stehr I $285.70 $250.97 2941 Terence Station Apt. 761 Bernierbury Massachusetts 47675 USA Shemar Stehr labadie.dominique@example.com 624-610-5940
8 Dr. Baron Armstrong Sr. $241.53 $280.42 9469 Ofelia Gateway Suite 748 Evelynside New Hampshire 66872 1 Fabiola Mitchell nico78@example.net 1-986-772-8058 x00345
9 Dr. Clemens Douglas MD $317.94 $342.92 2919 Thompson Common Suite 410 Suite 381 Port Margie Nevada 49890 Lolita Tremblay daphney.marquardt@example.com 1-461-699-9192 x9875
10 Dr. Claire Huel Sr. $333.45 $359.51 363 Arlene Causeway Suite 763 Suite 409 Millerstad Florida 25750 Brown Lakin vbeer@example.net (776) 821-0650 x839
11 Francisca Padberg $366.58 $203.16 5558 Ratke Flats Suite 511 Krystelport Alabama 15359-3783 Hallie Dooley kgottlieb@example.net 1-573-770-4753 x72129
12 Dr. Roy Kihn $272.12 $251.41 20236 O'Hara Shores Suite 368 Aliciaport North Carolina 35415 Elwyn Daugherty wunsch.rozella@example.org (745) 859-5855 x04216
13 Nasir Vandervort $401.23 $173.17 24599 Hills Centers Suite 467 Apt. 038 North German Ohio 85363-4720 Tre Moore wilfrid.kuhic@example.com 1-519-675-7395
14 Garry Rosenbaum $271.82 $306.63 7127 Heidenreich Union Apt. 168 Suite 441 North Murray North Carolina 29242 Ricardo Johnston ddubuque@example.com (682) 216-1962
15 Hildegard Crona PhD $398.96 $162.49 60142 Janice Islands Apt. 627 South Stantown Colorado 10298-5737 Miles Tremblay sabrina86@example.org 775-210-8656 x93138
16 Kristopher White I $318.14 $423.20 7498 Brook Crest Apt. 175 Suite 682 Marianoland Connecticut 86235-9979 Mateo Welch jedidiah64@example.com 847.353.7644
17 Ethan Grant $380.71 $367.38 26755 June Extension Suite 589 Suite 706 North Krystelmouth Delaware 12414 Colton Muller dorian.mayert@example.net (267) 647-0537
18 Terry Shields $230.25 $290.83 60946 Kayden Camp Apt. 046 Apt. 178 Douglashaven Wyoming 68992 Dashawn Homenick hills.gina@example.net (478) 814-9961
19 Agustina Lockman $351.60 $264.81 152 Pattie Coves Suite 971 North Mohamed Hawaii 52966 Bert Fritsch greilly@example.org 15342929833
20 Alfonso Schimmel $343.71 $200.99 358 Hills Coves Apt. 032 Lake Aisha District of Columbia 68945-0439 Antonio Hayes dkshlerin@example.com 1-350-691-4459 x775
21 Vergie Monahan $210.27 $201.10 64004 Anderson Mall Suite 207 Suite 469 Oleshire California 78369 Hilario Morissette zjacobs@example.net 552.914.6800 x81120
22 Carol Cremin $301.53 $473.39 68731 Bartoletti Crescent Suite 855 Aaronland Wyoming 07924 7924 Nathen Wehner jacobi.rosendo@example.com 1-223-910-2060 x09970
23 Randal Bosco MD $318.71 $226.47 51884 Peter Falls Suite 314 Angelicaville Nebraska 78016-3254 Angelo Ward kozey.aurelio@example.org 1-329-488-8800
24 Ms. Alena Cassin $262.45 $388.50 706 Delfina Burgs Apt. 996 Bertaton Ohio 22957 Eusebio Reinger golden.green@example.org 429-551-1362

View File

@ -185,7 +185,7 @@ class InvoiceAmountPaymentTest extends TestCase
$this->assertEquals(25, $invoice->balance);
$this->assertEquals(25, $invoice->amount);
$invoice->service()->markPaid()->save();
$invoice = $invoice->service()->markPaid()->save();
$invoice->fresh();

View File

@ -1422,7 +1422,7 @@ class PaymentTest extends TestCase
$this->assertEquals(10, $this->invoice->balance);
$this->assertEquals(10, $this->invoice->client->fresh()->balance);
$this->invoice->service()->markPaid()->save();
$this->invoice = $this->invoice->service()->markPaid()->save();
$this->assertEquals(0, $this->invoice->balance);
$this->assertEquals(0, $this->invoice->client->balance);

View File

@ -40,7 +40,7 @@ class GoogleAnalyticsTest extends TestCase
$invoice = $this->invoice;
$client = $this->client;
$invoice->service()->markPaid()->save();
$invoice = $invoice->service()->markPaid()->save();
$payment = $invoice->payments->first();

View File

@ -45,7 +45,7 @@ class InvoiceActionsTest extends TestCase
{
$this->withoutEvents();
$this->invoice->service()->markPaid()->save();
$this->invoice = $this->invoice->service()->markPaid()->save();
$this->assertFalse($this->invoiceDeletable($this->invoice));
$this->assertTrue($this->invoiceReversable($this->invoice));

View File

@ -82,7 +82,7 @@ class SubscriptionsCalcTest extends TestCase
$this->assertFalse($sub_calculator->isPaidUp());
$invoice->service()->markPaid()->save();
$invoice = $invoice->service()->markPaid()->save();
$this->assertTrue($sub_calculator->isPaidUp());