mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-09 03:14:30 -04:00
commit
fc8ea5392a
2
.github/workflows/phpunit.yml
vendored
2
.github/workflows/phpunit.yml
vendored
@ -12,7 +12,7 @@ jobs:
|
|||||||
runs-on: ${{ matrix.operating-system }}
|
runs-on: ${{ matrix.operating-system }}
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
operating-system: ['ubuntu-18.04', 'ubuntu-20.04', 'ubuntu-22.04']
|
operating-system: ['ubuntu-20.04', 'ubuntu-22.04']
|
||||||
php-versions: ['8.1']
|
php-versions: ['8.1']
|
||||||
phpunit-versions: ['latest']
|
phpunit-versions: ['latest']
|
||||||
|
|
||||||
|
@ -1 +1 @@
|
|||||||
5.5.17
|
5.5.18
|
@ -29,6 +29,7 @@ use App\Models\Payment;
|
|||||||
use App\Models\Paymentable;
|
use App\Models\Paymentable;
|
||||||
use App\Models\QuoteInvitation;
|
use App\Models\QuoteInvitation;
|
||||||
use App\Models\RecurringInvoiceInvitation;
|
use App\Models\RecurringInvoiceInvitation;
|
||||||
|
use App\Models\User;
|
||||||
use App\Models\Vendor;
|
use App\Models\Vendor;
|
||||||
use App\Utils\Ninja;
|
use App\Utils\Ninja;
|
||||||
use Exception;
|
use Exception;
|
||||||
@ -114,6 +115,8 @@ class CheckData extends Command
|
|||||||
$this->checkEntityInvitations();
|
$this->checkEntityInvitations();
|
||||||
$this->checkCompanyData();
|
$this->checkCompanyData();
|
||||||
$this->checkBalanceVsPaidStatus();
|
$this->checkBalanceVsPaidStatus();
|
||||||
|
$this->checkDuplicateRecurringInvoices();
|
||||||
|
$this->checkOauthSanity();
|
||||||
|
|
||||||
if(Ninja::isHosted())
|
if(Ninja::isHosted())
|
||||||
$this->checkAccountStatuses();
|
$this->checkAccountStatuses();
|
||||||
@ -145,6 +148,32 @@ class CheckData extends Command
|
|||||||
$this->log .= $str."\n";
|
$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()
|
||||||
|
{
|
||||||
|
|
||||||
|
if(Ninja::isHosted())
|
||||||
|
{
|
||||||
|
$c = Client::on('db-ninja-01')->where('company_id', config('ninja.ninja_default_company_id'))
|
||||||
|
->with('recurring_invoices')
|
||||||
|
->cursor()
|
||||||
|
->each(function ($client){
|
||||||
|
if($client->recurring_invoices()->where('is_deleted', 0)->where('deleted_at', null)->count() > 1)
|
||||||
|
$this->logMessage("Duplicate Recurring Invoice => {$client->custom_value1}");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private function checkOAuth()
|
private function checkOAuth()
|
||||||
{
|
{
|
||||||
// check for duplicate oauth ids
|
// check for duplicate oauth ids
|
||||||
@ -937,7 +966,7 @@ class CheckData extends Command
|
|||||||
{
|
{
|
||||||
$this->wrong_paid_status = 0;
|
$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++;
|
$this->wrong_paid_status++;
|
||||||
|
|
||||||
|
@ -168,6 +168,9 @@ class ClientFilters extends QueryFilters
|
|||||||
{
|
{
|
||||||
$sort_col = explode('|', $sort);
|
$sort_col = explode('|', $sort);
|
||||||
|
|
||||||
|
if($sort_col[0] == 'display_name')
|
||||||
|
$sort_col[0] = 'name';
|
||||||
|
|
||||||
return $this->builder->orderBy($sort_col[0], $sort_col[1]);
|
return $this->builder->orderBy($sort_col[0], $sort_col[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,6 +107,7 @@ class ActivityController extends BaseController
|
|||||||
'payment' => $activity->payment ? $activity->payment : '',
|
'payment' => $activity->payment ? $activity->payment : '',
|
||||||
'credit' => $activity->credit ? $activity->credit : '',
|
'credit' => $activity->credit ? $activity->credit : '',
|
||||||
'task' => $activity->task ? $activity->task : '',
|
'task' => $activity->task ? $activity->task : '',
|
||||||
|
'vendor' => $activity->vendor ? $activity->vendor : '',
|
||||||
];
|
];
|
||||||
|
|
||||||
return array_merge($arr, $activity->toArray());
|
return array_merge($arr, $activity->toArray());
|
||||||
|
@ -351,7 +351,7 @@ class LoginController extends BaseController
|
|||||||
private function handleSocialiteLogin($provider, $token)
|
private function handleSocialiteLogin($provider, $token)
|
||||||
{
|
{
|
||||||
$user = $this->getSocialiteUser($provider, $token);
|
$user = $this->getSocialiteUser($provider, $token);
|
||||||
nlog($user);
|
|
||||||
if ($user) {
|
if ($user) {
|
||||||
return $this->loginOrCreateFromSocialite($user, $provider);
|
return $this->loginOrCreateFromSocialite($user, $provider);
|
||||||
}
|
}
|
||||||
@ -368,6 +368,7 @@ class LoginController extends BaseController
|
|||||||
'oauth_user_id' => $user->id,
|
'oauth_user_id' => $user->id,
|
||||||
'oauth_provider_id' => $provider,
|
'oauth_provider_id' => $provider,
|
||||||
];
|
];
|
||||||
|
|
||||||
if ($existing_user = MultiDB::hasUser($query)) {
|
if ($existing_user = MultiDB::hasUser($query)) {
|
||||||
if (!$existing_user->account) {
|
if (!$existing_user->account) {
|
||||||
return response()->json(['message' => 'User exists, but not attached to any companies! Orphaned user!'], 400);
|
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')
|
public function handleMicrosoftProviderCallback($provider = 'microsoft')
|
||||||
{
|
{
|
||||||
$socialite_user = Socialite::driver($provider)->user();
|
$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'];
|
$oauth_user_token = $socialite_user->accessTokenResponseBody['access_token'];
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ class InvoiceController extends Controller
|
|||||||
|
|
||||||
$data = [
|
$data = [
|
||||||
'invoice' => $invoice,
|
'invoice' => $invoice,
|
||||||
'invitation' => $invitation,
|
'invitation' => $invitation ?: $invoice->invitations->first(),
|
||||||
'key' => $invitation ? $invitation->key : false,
|
'key' => $invitation ? $invitation->key : false,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -195,6 +195,7 @@ class NinjaPlanController extends Controller
|
|||||||
|
|
||||||
public function plan()
|
public function plan()
|
||||||
{
|
{
|
||||||
|
|
||||||
// return $this->trial();
|
// return $this->trial();
|
||||||
//harvest the current plan
|
//harvest the current plan
|
||||||
$data = [];
|
$data = [];
|
||||||
|
@ -101,7 +101,8 @@ class PaymentController extends Controller
|
|||||||
|
|
||||||
$data = [
|
$data = [
|
||||||
'invoice' => $invoice,
|
'invoice' => $invoice,
|
||||||
'key' => false
|
'key' => false,
|
||||||
|
'invitation' => $invoice->invitations->first()
|
||||||
];
|
];
|
||||||
|
|
||||||
if ($request->query('mode') === 'fullscreen') {
|
if ($request->query('mode') === 'fullscreen') {
|
||||||
|
@ -139,9 +139,14 @@ class Request extends FormRequest
|
|||||||
$input['invitations'][$key]['id'] = $this->decodePrimaryKey($input['invitations'][$key]['id']);
|
$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']);
|
$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']);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,6 +33,15 @@ class VendorMap
|
|||||||
14 => 'vendor.state',
|
14 => 'vendor.state',
|
||||||
15 => 'vendor.postal_code',
|
15 => 'vendor.postal_code',
|
||||||
16 => 'vendor.country_id',
|
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',
|
14 => 'texts.state',
|
||||||
15 => 'texts.postal_code',
|
15 => 'texts.postal_code',
|
||||||
16 => 'texts.country',
|
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',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,12 +16,14 @@ use App\Factory\ExpenseFactory;
|
|||||||
use App\Factory\InvoiceFactory;
|
use App\Factory\InvoiceFactory;
|
||||||
use App\Factory\PaymentFactory;
|
use App\Factory\PaymentFactory;
|
||||||
use App\Factory\ProductFactory;
|
use App\Factory\ProductFactory;
|
||||||
|
use App\Factory\QuoteFactory;
|
||||||
use App\Factory\VendorFactory;
|
use App\Factory\VendorFactory;
|
||||||
use App\Http\Requests\Client\StoreClientRequest;
|
use App\Http\Requests\Client\StoreClientRequest;
|
||||||
use App\Http\Requests\Expense\StoreExpenseRequest;
|
use App\Http\Requests\Expense\StoreExpenseRequest;
|
||||||
use App\Http\Requests\Invoice\StoreInvoiceRequest;
|
use App\Http\Requests\Invoice\StoreInvoiceRequest;
|
||||||
use App\Http\Requests\Payment\StorePaymentRequest;
|
use App\Http\Requests\Payment\StorePaymentRequest;
|
||||||
use App\Http\Requests\Product\StoreProductRequest;
|
use App\Http\Requests\Product\StoreProductRequest;
|
||||||
|
use App\Http\Requests\Quote\StoreQuoteRequest;
|
||||||
use App\Http\Requests\Vendor\StoreVendorRequest;
|
use App\Http\Requests\Vendor\StoreVendorRequest;
|
||||||
use App\Import\ImportException;
|
use App\Import\ImportException;
|
||||||
use App\Import\Providers\BaseImport;
|
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\InvoiceTransformer;
|
||||||
use App\Import\Transformer\Csv\PaymentTransformer;
|
use App\Import\Transformer\Csv\PaymentTransformer;
|
||||||
use App\Import\Transformer\Csv\ProductTransformer;
|
use App\Import\Transformer\Csv\ProductTransformer;
|
||||||
|
use App\Import\Transformer\Csv\QuoteTransformer;
|
||||||
use App\Import\Transformer\Csv\VendorTransformer;
|
use App\Import\Transformer\Csv\VendorTransformer;
|
||||||
use App\Repositories\ClientRepository;
|
use App\Repositories\ClientRepository;
|
||||||
use App\Repositories\ExpenseRepository;
|
use App\Repositories\ExpenseRepository;
|
||||||
use App\Repositories\InvoiceRepository;
|
use App\Repositories\InvoiceRepository;
|
||||||
use App\Repositories\PaymentRepository;
|
use App\Repositories\PaymentRepository;
|
||||||
use App\Repositories\ProductRepository;
|
use App\Repositories\ProductRepository;
|
||||||
|
use App\Repositories\QuoteRepository;
|
||||||
use App\Repositories\VendorRepository;
|
use App\Repositories\VendorRepository;
|
||||||
use Illuminate\Support\Facades\Validator;
|
use Illuminate\Support\Facades\Validator;
|
||||||
use Symfony\Component\HttpFoundation\ParameterBag;
|
use Symfony\Component\HttpFoundation\ParameterBag;
|
||||||
@ -55,6 +59,7 @@ class Csv extends BaseImport implements ImportInterface
|
|||||||
'payment',
|
'payment',
|
||||||
'vendor',
|
'vendor',
|
||||||
'expense',
|
'expense',
|
||||||
|
'quote',
|
||||||
])
|
])
|
||||||
) {
|
) {
|
||||||
$this->{$entity}();
|
$this->{$entity}();
|
||||||
@ -151,6 +156,35 @@ class Csv extends BaseImport implements ImportInterface
|
|||||||
$this->entity_count['invoices'] = $invoice_count;
|
$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()
|
public function payment()
|
||||||
{
|
{
|
||||||
$entity_type = 'payment';
|
$entity_type = 'payment';
|
||||||
@ -241,10 +275,6 @@ class Csv extends BaseImport implements ImportInterface
|
|||||||
$this->entity_count['expenses'] = $expense_count;
|
$this->entity_count['expenses'] = $expense_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function quote()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public function task()
|
public function task()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,14 @@ use App\Models\Country;
|
|||||||
use App\Models\ExpenseCategory;
|
use App\Models\ExpenseCategory;
|
||||||
use App\Models\PaymentType;
|
use App\Models\PaymentType;
|
||||||
use App\Models\User;
|
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 App\Utils\Number;
|
||||||
use Exception;
|
use Exception;
|
||||||
use Illuminate\Support\Carbon;
|
use Illuminate\Support\Carbon;
|
||||||
@ -67,8 +75,7 @@ class BaseTransformer
|
|||||||
{
|
{
|
||||||
|
|
||||||
if (! empty($client_name)) {
|
if (! empty($client_name)) {
|
||||||
$client_id_search = $this->company
|
$client_id_search = Client::where('company_id', $this->company->id)
|
||||||
->clients()
|
|
||||||
->where('is_deleted', false)
|
->where('is_deleted', false)
|
||||||
->where('id_number', $client_name);
|
->where('id_number', $client_name);
|
||||||
|
|
||||||
@ -76,8 +83,7 @@ class BaseTransformer
|
|||||||
return $client_id_search->first()->id;
|
return $client_id_search->first()->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
$client_name_search = $this->company
|
$client_name_search = Client::where('company_id', $this->company->id)
|
||||||
->clients()
|
|
||||||
->where('is_deleted', false)
|
->where('is_deleted', false)
|
||||||
->where('name', $client_name);
|
->where('name', $client_name);
|
||||||
|
|
||||||
@ -108,8 +114,7 @@ class BaseTransformer
|
|||||||
*/
|
*/
|
||||||
public function hasClient($name)
|
public function hasClient($name)
|
||||||
{
|
{
|
||||||
return $this->company
|
return Client::where('company_id', $this->company->id)
|
||||||
->clients()
|
|
||||||
->where('is_deleted', false)
|
->where('is_deleted', false)
|
||||||
->whereRaw("LOWER(REPLACE(`name`, ' ' ,'')) = ?", [
|
->whereRaw("LOWER(REPLACE(`name`, ' ' ,'')) = ?", [
|
||||||
strtolower(str_replace(' ', '', $name)),
|
strtolower(str_replace(' ', '', $name)),
|
||||||
@ -124,8 +129,7 @@ class BaseTransformer
|
|||||||
*/
|
*/
|
||||||
public function hasVendor($name)
|
public function hasVendor($name)
|
||||||
{
|
{
|
||||||
return $this->company
|
return Vendor::where('company_id', $this->company->id)
|
||||||
->vendors()
|
|
||||||
->where('is_deleted', false)
|
->where('is_deleted', false)
|
||||||
->whereRaw("LOWER(REPLACE(`name`, ' ' ,'')) = ?", [
|
->whereRaw("LOWER(REPLACE(`name`, ' ' ,'')) = ?", [
|
||||||
strtolower(str_replace(' ', '', $name)),
|
strtolower(str_replace(' ', '', $name)),
|
||||||
@ -140,8 +144,7 @@ class BaseTransformer
|
|||||||
*/
|
*/
|
||||||
public function hasProject($name)
|
public function hasProject($name)
|
||||||
{
|
{
|
||||||
return $this->company
|
return Project::where('company_id', $this->company->id)
|
||||||
->projects()
|
|
||||||
->where('is_deleted', false)
|
->where('is_deleted', false)
|
||||||
->whereRaw("LOWER(REPLACE(`name`, ' ' ,'')) = ?", [
|
->whereRaw("LOWER(REPLACE(`name`, ' ' ,'')) = ?", [
|
||||||
strtolower(str_replace(' ', '', $name)),
|
strtolower(str_replace(' ', '', $name)),
|
||||||
@ -156,8 +159,7 @@ class BaseTransformer
|
|||||||
*/
|
*/
|
||||||
public function hasProduct($key)
|
public function hasProduct($key)
|
||||||
{
|
{
|
||||||
return $this->company
|
return Product::where('company_id', $this->company->id)
|
||||||
->products()
|
|
||||||
->where('is_deleted', false)
|
->where('is_deleted', false)
|
||||||
->whereRaw("LOWER(REPLACE(`product_key`, ' ' ,'')) = ?", [
|
->whereRaw("LOWER(REPLACE(`product_key`, ' ' ,'')) = ?", [
|
||||||
strtolower(str_replace(' ', '', $key)),
|
strtolower(str_replace(' ', '', $key)),
|
||||||
@ -189,8 +191,7 @@ class BaseTransformer
|
|||||||
*/
|
*/
|
||||||
public function getClientId($name)
|
public function getClientId($name)
|
||||||
{
|
{
|
||||||
$client = $this->company
|
$client = Client::where('company_id', $this->company->id)
|
||||||
->clients()
|
|
||||||
->where('is_deleted', false)
|
->where('is_deleted', false)
|
||||||
->whereRaw("LOWER(REPLACE(`name`, ' ' ,'')) = ?", [
|
->whereRaw("LOWER(REPLACE(`name`, ' ' ,'')) = ?", [
|
||||||
strtolower(str_replace(' ', '', $name)),
|
strtolower(str_replace(' ', '', $name)),
|
||||||
@ -207,8 +208,7 @@ class BaseTransformer
|
|||||||
*/
|
*/
|
||||||
public function getProduct($key)
|
public function getProduct($key)
|
||||||
{
|
{
|
||||||
$product = $this->company
|
$product = Product::where('company_id', $this->company->id)
|
||||||
->products()
|
|
||||||
->where('is_deleted', false)
|
->where('is_deleted', false)
|
||||||
->whereRaw("LOWER(REPLACE(`product_key`, ' ' ,'')) = ?", [
|
->whereRaw("LOWER(REPLACE(`product_key`, ' ' ,'')) = ?", [
|
||||||
strtolower(str_replace(' ', '', $key)),
|
strtolower(str_replace(' ', '', $key)),
|
||||||
@ -225,8 +225,7 @@ class BaseTransformer
|
|||||||
*/
|
*/
|
||||||
public function getContact($email)
|
public function getContact($email)
|
||||||
{
|
{
|
||||||
$contact = $this->company
|
$contact = ClientContact::where('company_id', $this->company->id)
|
||||||
->client_contacts()
|
|
||||||
->whereRaw("LOWER(REPLACE(`email`, ' ' ,'')) = ?", [
|
->whereRaw("LOWER(REPLACE(`email`, ' ' ,'')) = ?", [
|
||||||
strtolower(str_replace(' ', '', $email)),
|
strtolower(str_replace(' ', '', $email)),
|
||||||
])
|
])
|
||||||
@ -278,8 +277,7 @@ class BaseTransformer
|
|||||||
{
|
{
|
||||||
$name = strtolower(trim($name));
|
$name = strtolower(trim($name));
|
||||||
|
|
||||||
$tax_rate = $this->company
|
$tax_rate = TaxRate::where('company_id', $this->company->id)
|
||||||
->tax_rates()
|
|
||||||
->where('is_deleted', false)
|
->where('is_deleted', false)
|
||||||
->whereRaw("LOWER(REPLACE(`name`, ' ' ,'')) = ?", [
|
->whereRaw("LOWER(REPLACE(`name`, ' ' ,'')) = ?", [
|
||||||
strtolower(str_replace(' ', '', $name)),
|
strtolower(str_replace(' ', '', $name)),
|
||||||
@ -298,8 +296,7 @@ class BaseTransformer
|
|||||||
{
|
{
|
||||||
$name = strtolower(trim($name));
|
$name = strtolower(trim($name));
|
||||||
|
|
||||||
$tax_rate = $this->company
|
$tax_rate = TaxRate::where('company_id', $this->company->id)
|
||||||
->tax_rates()
|
|
||||||
->where('is_deleted', false)
|
->where('is_deleted', false)
|
||||||
->whereRaw("LOWER(REPLACE(`name`, ' ' ,'')) = ?", [
|
->whereRaw("LOWER(REPLACE(`name`, ' ' ,'')) = ?", [
|
||||||
strtolower(str_replace(' ', '', $name)),
|
strtolower(str_replace(' ', '', $name)),
|
||||||
@ -348,8 +345,7 @@ class BaseTransformer
|
|||||||
*/
|
*/
|
||||||
public function getInvoiceId($invoice_number)
|
public function getInvoiceId($invoice_number)
|
||||||
{
|
{
|
||||||
$invoice = $this->company
|
$invoice = Invoice::where('company_id', $this->company->id)
|
||||||
->invoices()
|
|
||||||
->where('is_deleted', false)
|
->where('is_deleted', false)
|
||||||
->whereRaw("LOWER(REPLACE(`number`, ' ' ,'')) = ?", [
|
->whereRaw("LOWER(REPLACE(`number`, ' ' ,'')) = ?", [
|
||||||
strtolower(str_replace(' ', '', $invoice_number)),
|
strtolower(str_replace(' ', '', $invoice_number)),
|
||||||
@ -366,8 +362,7 @@ class BaseTransformer
|
|||||||
*/
|
*/
|
||||||
public function hasInvoice($invoice_number)
|
public function hasInvoice($invoice_number)
|
||||||
{
|
{
|
||||||
return $this->company
|
return Invoice::where('company_id', $this->company->id)
|
||||||
->invoices()
|
|
||||||
->where('is_deleted', false)
|
->where('is_deleted', false)
|
||||||
->whereRaw("LOWER(REPLACE(`number`, ' ' ,'')) = ?", [
|
->whereRaw("LOWER(REPLACE(`number`, ' ' ,'')) = ?", [
|
||||||
strtolower(str_replace(' ', '', $invoice_number)),
|
strtolower(str_replace(' ', '', $invoice_number)),
|
||||||
@ -380,8 +375,7 @@ class BaseTransformer
|
|||||||
*/
|
*/
|
||||||
public function hasExpense($expense_number)
|
public function hasExpense($expense_number)
|
||||||
{
|
{
|
||||||
return $this->company
|
return Expense::where('company_id', $this->company->id)
|
||||||
->expenses()
|
|
||||||
->where('is_deleted', false)
|
->where('is_deleted', false)
|
||||||
->whereRaw("LOWER(REPLACE(`number`, ' ' ,'')) = ?", [
|
->whereRaw("LOWER(REPLACE(`number`, ' ' ,'')) = ?", [
|
||||||
strtolower(str_replace(' ', '', $expense_number)),
|
strtolower(str_replace(' ', '', $expense_number)),
|
||||||
@ -396,8 +390,7 @@ class BaseTransformer
|
|||||||
*/
|
*/
|
||||||
public function hasQuote($quote_number)
|
public function hasQuote($quote_number)
|
||||||
{
|
{
|
||||||
return $this->company
|
return Quote::where('company_id', $this->company->id)
|
||||||
->quotes()
|
|
||||||
->where('is_deleted', false)
|
->where('is_deleted', false)
|
||||||
->whereRaw("LOWER(REPLACE(`number`, ' ' ,'')) = ?", [
|
->whereRaw("LOWER(REPLACE(`number`, ' ' ,'')) = ?", [
|
||||||
strtolower(str_replace(' ', '', $quote_number)),
|
strtolower(str_replace(' ', '', $quote_number)),
|
||||||
@ -412,8 +405,7 @@ class BaseTransformer
|
|||||||
*/
|
*/
|
||||||
public function getInvoiceClientId($invoice_number)
|
public function getInvoiceClientId($invoice_number)
|
||||||
{
|
{
|
||||||
$invoice = $this->company
|
$invoice = Invoice::where('company_id', $this->company->id)
|
||||||
->invoices()
|
|
||||||
->where('is_deleted', false)
|
->where('is_deleted', false)
|
||||||
->whereRaw("LOWER(REPLACE(`number`, ' ' ,'')) = ?", [
|
->whereRaw("LOWER(REPLACE(`number`, ' ' ,'')) = ?", [
|
||||||
strtolower(str_replace(' ', '', $invoice_number)),
|
strtolower(str_replace(' ', '', $invoice_number)),
|
||||||
@ -430,8 +422,7 @@ class BaseTransformer
|
|||||||
*/
|
*/
|
||||||
public function getVendorId($name)
|
public function getVendorId($name)
|
||||||
{
|
{
|
||||||
$vendor = $this->company
|
$vendor = Vendor::where('company_id', $this->company->id)
|
||||||
->vendors()
|
|
||||||
->where('is_deleted', false)
|
->where('is_deleted', false)
|
||||||
->whereRaw("LOWER(REPLACE(`name`, ' ' ,'')) = ?", [
|
->whereRaw("LOWER(REPLACE(`name`, ' ' ,'')) = ?", [
|
||||||
strtolower(str_replace(' ', '', $name)),
|
strtolower(str_replace(' ', '', $name)),
|
||||||
@ -467,8 +458,7 @@ class BaseTransformer
|
|||||||
*/
|
*/
|
||||||
public function getExpenseCategoryId($name)
|
public function getExpenseCategoryId($name)
|
||||||
{
|
{
|
||||||
$ec = $this->company
|
$ec = ExpenseCategory::where('company_id', $this->company->id)
|
||||||
->expense_categories()
|
|
||||||
->where('is_deleted', false)
|
->where('is_deleted', false)
|
||||||
->whereRaw("LOWER(REPLACE(`name`, ' ' ,'')) = ?", [
|
->whereRaw("LOWER(REPLACE(`name`, ' ' ,'')) = ?", [
|
||||||
strtolower(str_replace(' ', '', $name)),
|
strtolower(str_replace(' ', '', $name)),
|
||||||
@ -504,8 +494,7 @@ class BaseTransformer
|
|||||||
*/
|
*/
|
||||||
public function getProjectId($name, $clientId = null)
|
public function getProjectId($name, $clientId = null)
|
||||||
{
|
{
|
||||||
$project = $this->company
|
$project = Project::where('company_id', $this->company->id)
|
||||||
->projects()
|
|
||||||
->where('is_deleted', false)
|
->where('is_deleted', false)
|
||||||
->whereRaw("LOWER(REPLACE(`name`, ' ' ,'')) = ?", [
|
->whereRaw("LOWER(REPLACE(`name`, ' ' ,'')) = ?", [
|
||||||
strtolower(str_replace(' ', '', $name)),
|
strtolower(str_replace(' ', '', $name)),
|
||||||
|
@ -52,15 +52,42 @@ class VendorTransformer extends BaseTransformer
|
|||||||
'custom_value2' => $this->getString($data, 'vendor.custom_value2'),
|
'custom_value2' => $this->getString($data, 'vendor.custom_value2'),
|
||||||
'custom_value3' => $this->getString($data, 'vendor.custom_value3'),
|
'custom_value3' => $this->getString($data, 'vendor.custom_value3'),
|
||||||
'custom_value4' => $this->getString($data, 'vendor.custom_value4'),
|
'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(
|
'first_name' => $this->getString(
|
||||||
$data,
|
$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'])
|
'country_id' => isset($data['vendor.country_id'])
|
||||||
|
@ -44,12 +44,12 @@ class RecurringInvoicesCron
|
|||||||
nlog('Sending recurring invoices '.$start);
|
nlog('Sending recurring invoices '.$start);
|
||||||
|
|
||||||
if (! config('ninja.db.multi_db_enabled')) {
|
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')
|
->whereNotNull('next_send_date')
|
||||||
->whereNull('deleted_at')
|
->whereNull('deleted_at')
|
||||||
->where('is_deleted', false)
|
->where('next_send_date', '<=', now()->toDateTimeString())
|
||||||
->where('status_id', RecurringInvoice::STATUS_ACTIVE)
|
|
||||||
->where('remaining_cycles', '!=', '0')
|
|
||||||
->whereHas('client', function ($query) {
|
->whereHas('client', function ($query) {
|
||||||
$query->where('is_deleted', 0)
|
$query->where('is_deleted', 0)
|
||||||
->where('deleted_at', null);
|
->where('deleted_at', null);
|
||||||
@ -84,12 +84,12 @@ class RecurringInvoicesCron
|
|||||||
foreach (MultiDB::$dbs as $db) {
|
foreach (MultiDB::$dbs as $db) {
|
||||||
MultiDB::setDB($db);
|
MultiDB::setDB($db);
|
||||||
|
|
||||||
$recurring_invoices = RecurringInvoice::where('next_send_date', '<=', now()->toDateTimeString())
|
$recurring_invoices = RecurringInvoice::where('status_id', RecurringInvoice::STATUS_ACTIVE)
|
||||||
->whereNotNull('next_send_date')
|
|
||||||
->whereNull('deleted_at')
|
|
||||||
->where('is_deleted', false)
|
->where('is_deleted', false)
|
||||||
->where('status_id', RecurringInvoice::STATUS_ACTIVE)
|
|
||||||
->where('remaining_cycles', '!=', '0')
|
->where('remaining_cycles', '!=', '0')
|
||||||
|
->whereNull('deleted_at')
|
||||||
|
->whereNotNull('next_send_date')
|
||||||
|
->where('next_send_date', '<=', now()->toDateTimeString())
|
||||||
->whereHas('client', function ($query) {
|
->whereHas('client', function ($query) {
|
||||||
$query->where('is_deleted', 0)
|
$query->where('is_deleted', 0)
|
||||||
->where('deleted_at', null);
|
->where('deleted_at', null);
|
||||||
|
@ -74,7 +74,7 @@ class CSVIngest implements ShouldQueue
|
|||||||
|
|
||||||
$engine = $this->bootEngine();
|
$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);
|
$engine->import($entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -354,14 +354,19 @@ class NinjaMailerJob implements ShouldQueue
|
|||||||
if(!str_contains($this->nmo->to_user->email, "@"))
|
if(!str_contains($this->nmo->to_user->email, "@"))
|
||||||
return true;
|
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 */
|
/* 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))
|
if(class_exists(\Modules\Admin\Jobs\Account\EmailQuality::class))
|
||||||
return (new \Modules\Admin\Jobs\Account\EmailQuality($this->nmo, $this->company))->run();
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,11 +60,11 @@ class ReminderJob implements ShouldQueue
|
|||||||
{
|
{
|
||||||
nlog('Sending invoice reminders '.now()->format('Y-m-d h:i:s'));
|
nlog('Sending invoice reminders '.now()->format('Y-m-d h:i:s'));
|
||||||
|
|
||||||
Invoice::where('next_send_date', '<=', now()->toDateTimeString())
|
Invoice::where('is_deleted', 0)
|
||||||
->whereNull('deleted_at')
|
|
||||||
->where('is_deleted', 0)
|
|
||||||
->whereIn('status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL])
|
->whereIn('status_id', [Invoice::STATUS_SENT, Invoice::STATUS_PARTIAL])
|
||||||
|
->whereNull('deleted_at')
|
||||||
->where('balance', '>', 0)
|
->where('balance', '>', 0)
|
||||||
|
->where('next_send_date', '<=', now()->toDateTimeString())
|
||||||
->whereHas('client', function ($query) {
|
->whereHas('client', function ($query) {
|
||||||
$query->where('is_deleted', 0)
|
$query->where('is_deleted', 0)
|
||||||
->where('deleted_at', null);
|
->where('deleted_at', null);
|
||||||
|
@ -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_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['$view_button'] = &$data['$view_link'];
|
||||||
|
$data['$viewButton'] = &$data['$view_link'];
|
||||||
$data['$viewLink'] = &$data['$view_link'];
|
$data['$viewLink'] = &$data['$view_link'];
|
||||||
$data['$paymentLink'] = &$data['$view_link'];
|
$data['$paymentLink'] = &$data['$view_link'];
|
||||||
$data['$portalButton'] = ['value' => "<a href='{$this->payment->getPortalLink()}'>".ctrans('texts.login').'</a>', 'label' =>''];
|
$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['$invoice.po_number'] = ['value' => $this->formatPoNumber(), 'label' => ctrans('texts.po_number')];
|
||||||
$data['$poNumber'] = &$data['$invoice.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['$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));
|
$arrKeysLength = array_map('strlen', array_keys($data));
|
||||||
array_multisort($arrKeysLength, SORT_DESC, $data);
|
array_multisort($arrKeysLength, SORT_DESC, $data);
|
||||||
@ -244,6 +249,22 @@ class PaymentEmailEngine extends BaseEmailEngine
|
|||||||
return $data;
|
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()
|
private function formatInvoice()
|
||||||
{
|
{
|
||||||
$invoice = '';
|
$invoice = '';
|
||||||
@ -282,11 +303,15 @@ class PaymentEmailEngine extends BaseEmailEngine
|
|||||||
$invoice_list = '<br><br>';
|
$invoice_list = '<br><br>';
|
||||||
|
|
||||||
foreach ($this->payment->invoices as $invoice) {
|
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_number_short')." {$invoice->number} <br>";
|
||||||
$invoice_list .= ctrans('texts.invoice_amount').' '.Number::formatMoney($invoice->pivot->amount, $this->client).'<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 .= ctrans('texts.invoice_balance').' '.Number::formatMoney($invoice->fresh()->balance, $this->client).'<br>';
|
||||||
$invoice_list .= '-----<br>';
|
$invoice_list .= '-----<br>';
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $invoice_list;
|
return $invoice_list;
|
||||||
|
@ -266,6 +266,11 @@ class Activity extends StaticModel
|
|||||||
return $this->belongsTo(Invoice::class)->withTrashed();
|
return $this->belongsTo(Invoice::class)->withTrashed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function vendor()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Vendor::class)->withTrashed();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
|
@ -24,9 +24,6 @@ class UserObserver
|
|||||||
public function created(User $user)
|
public function created(User $user)
|
||||||
{
|
{
|
||||||
|
|
||||||
if(class_exists(\Modules\Admin\Jobs\Account\UserQuality::class))
|
|
||||||
\Modules\Admin\Jobs\Account\UserQuality::dispatch($user, $user->account->key);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -38,9 +35,6 @@ class UserObserver
|
|||||||
public function updated(User $user)
|
public function updated(User $user)
|
||||||
{
|
{
|
||||||
|
|
||||||
if(class_exists(\Modules\Admin\Jobs\Account\UserQuality::class))
|
|
||||||
\Modules\Admin\Jobs\Account\UserQuality::dispatch($user, $user->account->key);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -131,7 +131,8 @@ class PaymentRepository extends BaseRepository {
|
|||||||
|
|
||||||
/*Ensure payment number generated*/
|
/*Ensure payment number generated*/
|
||||||
if (! $payment->number || strlen($payment->number) == 0) {
|
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*/
|
/*Set local total variables*/
|
||||||
|
@ -62,7 +62,9 @@ class UserRepository extends BaseRepository
|
|||||||
// $account->num_users++;
|
// $account->num_users++;
|
||||||
// $account->save();
|
// $account->save();
|
||||||
// }
|
// }
|
||||||
|
if(array_key_exists('oauth_provider_id', $details))
|
||||||
|
unset($details['oauth_provider_id']);
|
||||||
|
|
||||||
$user->fill($details);
|
$user->fill($details);
|
||||||
|
|
||||||
//allow users to change only their passwords - not others!
|
//allow users to change only their passwords - not others!
|
||||||
|
@ -41,20 +41,37 @@ class MarkPaid extends AbstractService
|
|||||||
|
|
||||||
public function run()
|
public function run()
|
||||||
{
|
{
|
||||||
if ($this->invoice->status_id == Invoice::STATUS_DRAFT) {
|
|
||||||
$this->invoice->service()->markSent()->save();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*Don't double pay*/
|
/*Don't double pay*/
|
||||||
if ($this->invoice->status_id == Invoice::STATUS_PAID) {
|
if ($this->invoice->status_id == Invoice::STATUS_PAID) {
|
||||||
return $this->invoice;
|
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 */
|
/* Create Payment */
|
||||||
$payment = PaymentFactory::create($this->invoice->company_id, $this->invoice->user_id);
|
$payment = PaymentFactory::create($this->invoice->company_id, $this->invoice->user_id);
|
||||||
|
|
||||||
$payment->amount = $this->invoice->balance;
|
$payment->amount = $payable_balance;
|
||||||
$payment->applied = $this->invoice->balance;
|
$payment->applied = $payable_balance;
|
||||||
$payment->status_id = Payment::STATUS_COMPLETED;
|
$payment->status_id = Payment::STATUS_COMPLETED;
|
||||||
$payment->client_id = $this->invoice->client_id;
|
$payment->client_id = $this->invoice->client_id;
|
||||||
$payment->transaction_reference = ctrans('texts.manual_entry');
|
$payment->transaction_reference = ctrans('texts.manual_entry');
|
||||||
@ -79,20 +96,20 @@ class MarkPaid extends AbstractService
|
|||||||
|
|
||||||
/* Create a payment relationship to the invoice entity */
|
/* Create a payment relationship to the invoice entity */
|
||||||
$payment->invoices()->attach($this->invoice->id, [
|
$payment->invoices()->attach($this->invoice->id, [
|
||||||
'amount' => $payment->amount,
|
'amount' => $payable_balance,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
event('eloquent.created: App\Models\Payment', $payment);
|
event('eloquent.created: App\Models\Payment', $payment);
|
||||||
|
|
||||||
$this->invoice->next_send_date = null;
|
$this->invoice->next_send_date = null;
|
||||||
|
|
||||||
$this->invoice
|
// $this->invoice
|
||||||
->service()
|
// ->service()
|
||||||
->setExchangeRate()
|
// ->setExchangeRate()
|
||||||
->updateBalance($payment->amount * -1)
|
// ->updateBalance($payment->amount * -1)
|
||||||
->updatePaidToDate($payment->amount)
|
// ->updatePaidToDate($payment->amount)
|
||||||
->setStatus(Invoice::STATUS_PAID)
|
// ->setStatus(Invoice::STATUS_PAID)
|
||||||
->save();
|
// ->save();
|
||||||
|
|
||||||
$this->invoice
|
$this->invoice
|
||||||
->service()
|
->service()
|
||||||
@ -101,7 +118,7 @@ class MarkPaid extends AbstractService
|
|||||||
->save();
|
->save();
|
||||||
|
|
||||||
$payment->ledger()
|
$payment->ledger()
|
||||||
->updatePaymentBalance($payment->amount * -1);
|
->updatePaymentBalance($payable_balance * -1);
|
||||||
|
|
||||||
\DB::connection(config('database.default'))->transaction(function () use ($payment) {
|
\DB::connection(config('database.default'))->transaction(function () use ($payment) {
|
||||||
|
|
||||||
|
@ -42,9 +42,9 @@ class ZeroCostProduct extends AbstractService
|
|||||||
|
|
||||||
$invoice = $this->subscription->service()->createInvoice($this->data);
|
$invoice = $this->subscription->service()->createInvoice($this->data);
|
||||||
|
|
||||||
$invoice->service()
|
$invoice = $invoice->service()
|
||||||
->markPaid()
|
->markPaid()
|
||||||
->save();
|
->save();
|
||||||
|
|
||||||
$redirect_url = "/client/invoices/{$invoice->hashed_id}";
|
$redirect_url = "/client/invoices/{$invoice->hashed_id}";
|
||||||
|
|
||||||
|
@ -184,6 +184,9 @@ class SystemHealth
|
|||||||
|
|
||||||
private static function checkPhpCli()
|
private static function checkPhpCli()
|
||||||
{
|
{
|
||||||
|
if(!function_exists('exec'))
|
||||||
|
return "Unable to check CLI version";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
exec('php -v', $foo, $exitCode);
|
exec('php -v', $foo, $exitCode);
|
||||||
|
|
||||||
|
@ -408,6 +408,68 @@ class VendorHtmlEngine
|
|||||||
|
|
||||||
$data['$payments'] = ['value' => '', 'label' => ctrans('texts.payments')];
|
$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) ?: ' ', '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) ?: ' ', '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) ?: ' ', '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) ?: ' ', '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 ?: ' ', 'label' => ctrans('texts.number')];
|
||||||
|
|
||||||
|
$data['$client_name'] = ['value' => $this->entity->client->present()->name() ?: ' ', '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() ?: ' ', 'label' => ctrans('texts.address')];
|
||||||
|
$data['$client.address'] = &$data['$client_address'];
|
||||||
|
$data['$client.postal_code'] = ['value' => $this->entity->client->postal_code ?: ' ', 'label' => ctrans('texts.postal_code')];
|
||||||
|
$data['$client.public_notes'] = ['value' => $this->entity->client->public_notes ?: ' ', 'label' => ctrans('texts.notes')];
|
||||||
|
$data['$client.city'] = ['value' => $this->entity->client->city ?: ' ', 'label' => ctrans('texts.city')];
|
||||||
|
$data['$client.state'] = ['value' => $this->entity->client->state ?: ' ', '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) ?: ' ', '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) ?: ' ', '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() ?: ' ', 'label' => ctrans('texts.shipping_address')];
|
||||||
|
$data['$client.shipping_address1'] = ['value' => $this->entity->client->shipping_address1 ?: ' ', 'label' => ctrans('texts.shipping_address1')];
|
||||||
|
$data['$client.shipping_address2'] = ['value' => $this->entity->client->shipping_address2 ?: ' ', 'label' => ctrans('texts.shipping_address2')];
|
||||||
|
$data['$client.shipping_city'] = ['value' => $this->entity->client->shipping_city ?: ' ', 'label' => ctrans('texts.shipping_city')];
|
||||||
|
$data['$client.shipping_state'] = ['value' => $this->entity->client->shipping_state ?: ' ', 'label' => ctrans('texts.shipping_state')];
|
||||||
|
$data['$client.shipping_postal_code'] = ['value' => $this->entity->client->shipping_postal_code ?: ' ', '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));
|
$arrKeysLength = array_map('strlen', array_keys($data));
|
||||||
array_multisort($arrKeysLength, SORT_DESC, $data);
|
array_multisort($arrKeysLength, SORT_DESC, $data);
|
||||||
|
|
||||||
|
@ -14,8 +14,8 @@ return [
|
|||||||
'require_https' => env('REQUIRE_HTTPS', true),
|
'require_https' => env('REQUIRE_HTTPS', true),
|
||||||
'app_url' => rtrim(env('APP_URL', ''), '/'),
|
'app_url' => rtrim(env('APP_URL', ''), '/'),
|
||||||
'app_domain' => env('APP_DOMAIN', 'invoicing.co'),
|
'app_domain' => env('APP_DOMAIN', 'invoicing.co'),
|
||||||
'app_version' => '5.5.17',
|
'app_version' => '5.5.18',
|
||||||
'app_tag' => '5.5.17',
|
'app_tag' => '5.5.18',
|
||||||
'minimum_client_version' => '5.0.16',
|
'minimum_client_version' => '5.0.16',
|
||||||
'terms_version' => '1.0.1',
|
'terms_version' => '1.0.1',
|
||||||
'api_secret' => env('API_SECRET', ''),
|
'api_secret' => env('API_SECRET', ''),
|
||||||
|
@ -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()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
@ -800,7 +800,7 @@ $LANG = array(
|
|||||||
'activity_51' => ':user deleted user :user',
|
'activity_51' => ':user deleted user :user',
|
||||||
'activity_52' => ':user restored user :user',
|
'activity_52' => ':user restored user :user',
|
||||||
'activity_53' => ':user marked sent :invoice',
|
'activity_53' => ':user marked sent :invoice',
|
||||||
'activity_54' => ':user reopened ticket :ticket',
|
'activity_54' => ':user paid invoice :invoice',
|
||||||
'activity_55' => ':contact replied ticket :ticket',
|
'activity_55' => ':contact replied ticket :ticket',
|
||||||
'activity_56' => ':user viewed ticket :ticket',
|
'activity_56' => ':user viewed ticket :ticket',
|
||||||
|
|
||||||
|
4
public/flutter_service_worker.js
vendored
4
public/flutter_service_worker.js
vendored
@ -7,7 +7,7 @@ const RESOURCES = {
|
|||||||
"canvaskit/profiling/canvaskit.js": "ae2949af4efc61d28a4a80fffa1db900",
|
"canvaskit/profiling/canvaskit.js": "ae2949af4efc61d28a4a80fffa1db900",
|
||||||
"canvaskit/profiling/canvaskit.wasm": "95e736ab31147d1b2c7b25f11d4c32cd",
|
"canvaskit/profiling/canvaskit.wasm": "95e736ab31147d1b2c7b25f11d4c32cd",
|
||||||
"canvaskit/canvaskit.wasm": "4b83d89d9fecbea8ca46f2f760c5a9ba",
|
"canvaskit/canvaskit.wasm": "4b83d89d9fecbea8ca46f2f760c5a9ba",
|
||||||
"main.dart.js": "3234746bf3c8a3ccec3cf901969c352c",
|
"main.dart.js": "d55f18d67504e30a0afcd79c2681fc4b",
|
||||||
"favicon.ico": "51636d3a390451561744c42188ccd628",
|
"favicon.ico": "51636d3a390451561744c42188ccd628",
|
||||||
"assets/AssetManifest.json": "759f9ef9973f7e26c2a51450b55bb9fa",
|
"assets/AssetManifest.json": "759f9ef9973f7e26c2a51450b55bb9fa",
|
||||||
"assets/assets/google_fonts/Roboto-Regular.ttf": "8a36205bd9b83e03af0591a004bc97f4",
|
"assets/assets/google_fonts/Roboto-Regular.ttf": "8a36205bd9b83e03af0591a004bc97f4",
|
||||||
@ -295,7 +295,7 @@ const RESOURCES = {
|
|||||||
"assets/FontManifest.json": "087fb858dc3cbfbf6baf6a30004922f1",
|
"assets/FontManifest.json": "087fb858dc3cbfbf6baf6a30004922f1",
|
||||||
"assets/NOTICES": "254a5bf1eeb00601955e148b31cb925c",
|
"assets/NOTICES": "254a5bf1eeb00601955e148b31cb925c",
|
||||||
"flutter.js": "eb2682e33f25cd8f1fc59011497c35f8",
|
"flutter.js": "eb2682e33f25cd8f1fc59011497c35f8",
|
||||||
"/": "48872e415511ff066e9403545e4ba572",
|
"/": "acca806f9c3bee9e5e9560598f7376de",
|
||||||
"favicon.png": "dca91c54388f52eded692718d5a98b8b",
|
"favicon.png": "dca91c54388f52eded692718d5a98b8b",
|
||||||
"version.json": "9eca00898047311eda7456072e79d77d",
|
"version.json": "9eca00898047311eda7456072e79d77d",
|
||||||
"manifest.json": "ef43d90e57aa7682d7e2cfba2f484a40",
|
"manifest.json": "ef43d90e57aa7682d7e2cfba2f484a40",
|
||||||
|
3
public/images/Vector 1580.svg
Normal file
3
public/images/Vector 1580.svg
Normal 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 |
3
public/images/Vector 1581.svg
Normal file
3
public/images/Vector 1581.svg
Normal 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 |
9
public/images/hero-success.svg
Normal file
9
public/images/hero-success.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 127 KiB |
3
public/images/wave-bg.svg
Normal file
3
public/images/wave-bg.svg
Normal 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 |
186052
public/main.dart.js
vendored
186052
public/main.dart.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
186162
public/main.foss.dart.js
vendored
186162
public/main.foss.dart.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
9990
public/main.profile.dart.js
vendored
9990
public/main.profile.dart.js
vendored
File diff suppressed because one or more lines are too long
2
public/vendor/livewire/livewire.js
vendored
2
public/vendor/livewire/livewire.js
vendored
File diff suppressed because one or more lines are too long
2
public/vendor/livewire/livewire.js.map
vendored
2
public/vendor/livewire/livewire.js.map
vendored
File diff suppressed because one or more lines are too long
2
public/vendor/livewire/manifest.json
vendored
2
public/vendor/livewire/manifest.json
vendored
@ -1 +1 @@
|
|||||||
{"/livewire.js":"/livewire.js?id=c69d0f2801c01fcf8166"}
|
{"/livewire.js":"/livewire.js?id=de3fca26689cb5a39af4"}
|
@ -125,7 +125,7 @@
|
|||||||
<img src="{{ $logo ?? '' }}" alt="" width="155" border="0" align="middle" style="display:block;" />
|
<img src="{{ $logo ?? '' }}" alt="" width="155" border="0" align="middle" style="display:block;" />
|
||||||
<div style="mso-hide:all;">
|
<div style="mso-hide:all;">
|
||||||
<![endif]-->
|
<![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]>
|
<!--[if gte mso 9]>
|
||||||
</div>
|
</div>
|
||||||
<![endif]-->
|
<![endif]-->
|
||||||
|
@ -104,14 +104,13 @@
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td align="center" cellpadding="20">
|
<td align="center" cellpadding="20">
|
||||||
<div
|
<div style="border: 1px solid #c2c2c2; border-bottom: none; padding-bottom: 10px; border-top-left-radius: 3px; border-top-right-radius: 3px;">
|
||||||
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]>
|
<!--[if gte mso 9]>
|
||||||
<img src="{{ $logo ?? '' }}" alt="" width="400" border="0" align="middle" style="display:block;" />
|
<img src="{{ $logo ?? '' }}" alt="" width="400" border="0" align="middle" style="display:block;" />
|
||||||
<div style="mso-hide:all;">
|
<div style="mso-hide:all;">
|
||||||
<![endif]-->
|
<![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]>
|
<!--[if gte mso 9]>
|
||||||
</div>
|
</div>
|
||||||
<![endif]-->
|
<![endif]-->
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -72,7 +72,7 @@ class EntityPaidToDateTest extends TestCase
|
|||||||
|
|
||||||
$this->assertEquals($invoice->balance, 20);
|
$this->assertEquals($invoice->balance, 20);
|
||||||
|
|
||||||
$invoice->service()->markPaid()->save();
|
$invoice = $invoice->service()->markPaid()->save();
|
||||||
|
|
||||||
$this->assertEquals($invoice->paid_to_date, 20);
|
$this->assertEquals($invoice->paid_to_date, 20);
|
||||||
}
|
}
|
||||||
@ -81,7 +81,7 @@ class EntityPaidToDateTest extends TestCase
|
|||||||
{
|
{
|
||||||
$invoice = $this->bootNewInvoice();
|
$invoice = $this->bootNewInvoice();
|
||||||
|
|
||||||
$invoice->service()->markPaid()->save();
|
$invoice = $invoice->service()->markPaid()->save();
|
||||||
|
|
||||||
$this->assertEquals(20, $invoice->paid_to_date);
|
$this->assertEquals(20, $invoice->paid_to_date);
|
||||||
|
|
||||||
|
@ -1,24 +1,24 @@
|
|||||||
"Invoice Ninja v4.5.17 - December 19, 2020 11:28 pm","","","","","","","","","","","","","","","","","","","","","","","","",""
|
"Invoice Ninja v4.5.17 - December 19, 2020 11:28 pm",,,,,,,,,,,,,,,,,,,,,,,,,
|
||||||
"","","","","","","","","","","","","","","","","","","","","","","","","",""
|
,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||||
"Vendors","","","","","","","","","","","","","","","","","","","","","","","","",""
|
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"
|
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"
|
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","05144","","","","","","","","","","","","","","","Pink","Balistreri","gheidenreich@example.org","1-995-790-2394 x58884"
|
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","","","","","","","","","","","","","","","Shemar","Stehr","labadie.dominique@example.com","624-610-5940"
|
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","","","","","","","","","","","","","","","Fabiola","Mitchell","nico78@example.net","1-986-772-8058 x00345"
|
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. 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"
|
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"
|
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"
|
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"
|
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"
|
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"
|
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"
|
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"
|
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"
|
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"
|
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"
|
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"
|
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"
|
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"
|
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"
|
Ms. Alena Cassin,$262.45,$388.50,706 Delfina Burgs,Apt. 996,Bertaton,Ohio,22957,,,,,,,,,,,,,,,Eusebio,Reinger,golden.green@example.org,429-551-1362
|
||||||
|
|
@ -185,7 +185,7 @@ class InvoiceAmountPaymentTest extends TestCase
|
|||||||
$this->assertEquals(25, $invoice->balance);
|
$this->assertEquals(25, $invoice->balance);
|
||||||
$this->assertEquals(25, $invoice->amount);
|
$this->assertEquals(25, $invoice->amount);
|
||||||
|
|
||||||
$invoice->service()->markPaid()->save();
|
$invoice = $invoice->service()->markPaid()->save();
|
||||||
|
|
||||||
$invoice->fresh();
|
$invoice->fresh();
|
||||||
|
|
||||||
|
@ -1422,7 +1422,7 @@ class PaymentTest extends TestCase
|
|||||||
$this->assertEquals(10, $this->invoice->balance);
|
$this->assertEquals(10, $this->invoice->balance);
|
||||||
$this->assertEquals(10, $this->invoice->client->fresh()->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->balance);
|
||||||
$this->assertEquals(0, $this->invoice->client->balance);
|
$this->assertEquals(0, $this->invoice->client->balance);
|
||||||
|
@ -40,7 +40,7 @@ class GoogleAnalyticsTest extends TestCase
|
|||||||
$invoice = $this->invoice;
|
$invoice = $this->invoice;
|
||||||
$client = $this->client;
|
$client = $this->client;
|
||||||
|
|
||||||
$invoice->service()->markPaid()->save();
|
$invoice = $invoice->service()->markPaid()->save();
|
||||||
|
|
||||||
$payment = $invoice->payments->first();
|
$payment = $invoice->payments->first();
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ class InvoiceActionsTest extends TestCase
|
|||||||
{
|
{
|
||||||
$this->withoutEvents();
|
$this->withoutEvents();
|
||||||
|
|
||||||
$this->invoice->service()->markPaid()->save();
|
$this->invoice = $this->invoice->service()->markPaid()->save();
|
||||||
|
|
||||||
$this->assertFalse($this->invoiceDeletable($this->invoice));
|
$this->assertFalse($this->invoiceDeletable($this->invoice));
|
||||||
$this->assertTrue($this->invoiceReversable($this->invoice));
|
$this->assertTrue($this->invoiceReversable($this->invoice));
|
||||||
|
@ -82,7 +82,7 @@ class SubscriptionsCalcTest extends TestCase
|
|||||||
|
|
||||||
$this->assertFalse($sub_calculator->isPaidUp());
|
$this->assertFalse($sub_calculator->isPaidUp());
|
||||||
|
|
||||||
$invoice->service()->markPaid()->save();
|
$invoice = $invoice->service()->markPaid()->save();
|
||||||
|
|
||||||
$this->assertTrue($sub_calculator->isPaidUp());
|
$this->assertTrue($sub_calculator->isPaidUp());
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user