mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-06-23 20:00:33 -04:00
Merge branch 'v5-develop' of https://github.com/turbo124/invoiceninja into v5-develop
This commit is contained in:
commit
645c77ab04
@ -1 +1 @@
|
|||||||
5.3.29
|
5.3.31
|
@ -178,7 +178,8 @@ class EmailTemplateDefaults
|
|||||||
|
|
||||||
public static function emailReminder1Template()
|
public static function emailReminder1Template()
|
||||||
{
|
{
|
||||||
return '';
|
return self::emailInvoiceTemplate();
|
||||||
|
//return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function emailReminder2Subject()
|
public static function emailReminder2Subject()
|
||||||
@ -188,7 +189,8 @@ class EmailTemplateDefaults
|
|||||||
|
|
||||||
public static function emailReminder2Template()
|
public static function emailReminder2Template()
|
||||||
{
|
{
|
||||||
return '';
|
return self::emailInvoiceTemplate();
|
||||||
|
//return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function emailReminder3Subject()
|
public static function emailReminder3Subject()
|
||||||
@ -198,7 +200,8 @@ class EmailTemplateDefaults
|
|||||||
|
|
||||||
public static function emailReminder3Template()
|
public static function emailReminder3Template()
|
||||||
{
|
{
|
||||||
return '';
|
return self::emailInvoiceTemplate();
|
||||||
|
//return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function emailReminderEndlessSubject()
|
public static function emailReminderEndlessSubject()
|
||||||
@ -208,6 +211,7 @@ class EmailTemplateDefaults
|
|||||||
|
|
||||||
public static function emailReminderEndlessTemplate()
|
public static function emailReminderEndlessTemplate()
|
||||||
{
|
{
|
||||||
|
return self::emailInvoiceTemplate();
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
30
app/Helpers/Document/WithTypeHelpers.php
Normal file
30
app/Helpers/Document/WithTypeHelpers.php
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invoice Ninja (https://invoiceninja.com).
|
||||||
|
*
|
||||||
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2021. Invoice Ninja LLC (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @license https://www.elastic.co/licensing/elastic-license
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Helpers\Document;
|
||||||
|
|
||||||
|
trait WithTypeHelpers
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Returns boolean based on checks for image.
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isImage(): bool
|
||||||
|
{
|
||||||
|
if (in_array($this->type, ['png', 'svg', 'jpeg', 'jpg', 'tiff', 'gif'])) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
@ -70,7 +70,7 @@ class GmailTransport extends Transport
|
|||||||
if($child->getContentType() != 'text/plain')
|
if($child->getContentType() != 'text/plain')
|
||||||
{
|
{
|
||||||
|
|
||||||
$this->gmail->attach(TempFile::filePath($child->getBody(), $child->getHeaders()->get('Content-Type')->getParameter('name') ));
|
$this->gmail->attach(TempFile::filePath($child->getBody(), $child->getHeaders()->get('Content-Type')->getParameter('name') ));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,12 +36,9 @@ class ContactLoginController extends Controller
|
|||||||
|
|
||||||
public function showLoginForm(Request $request)
|
public function showLoginForm(Request $request)
|
||||||
{
|
{
|
||||||
//if we are on the root domain invoicing.co do not show any company logos
|
|
||||||
// if(Ninja::isHosted() && count(explode('.', request()->getHost())) == 2){
|
|
||||||
// $company = null;
|
|
||||||
// }else
|
|
||||||
|
|
||||||
$company = false;
|
$company = false;
|
||||||
|
$account = false;
|
||||||
|
|
||||||
if($request->has('company_key')){
|
if($request->has('company_key')){
|
||||||
MultiDB::findAndSetDbByCompanyKey($request->input('company_key'));
|
MultiDB::findAndSetDbByCompanyKey($request->input('company_key'));
|
||||||
@ -65,13 +62,16 @@ class ContactLoginController extends Controller
|
|||||||
|
|
||||||
}
|
}
|
||||||
elseif (Ninja::isSelfHost()) {
|
elseif (Ninja::isSelfHost()) {
|
||||||
$company = Account::first()->default_company;
|
$account = Account::first();
|
||||||
|
$company = $account->default_company;
|
||||||
} else {
|
} else {
|
||||||
$company = null;
|
$company = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$account_id = $request->get('account_id');
|
if(!$account){
|
||||||
$account = Account::find($account_id);
|
$account_id = $request->get('account_id');
|
||||||
|
$account = Account::find($account_id);
|
||||||
|
}
|
||||||
|
|
||||||
return $this->render('auth.login', ['account' => $account, 'company' => $company]);
|
return $this->render('auth.login', ['account' => $account, 'company' => $company]);
|
||||||
|
|
||||||
|
@ -334,7 +334,7 @@ class BaseController extends Controller
|
|||||||
|
|
||||||
},
|
},
|
||||||
'company.expense_categories'=> function ($query) use ($updated_at, $user) {
|
'company.expense_categories'=> function ($query) use ($updated_at, $user) {
|
||||||
$query->where('updated_at', '>=', $updated_at);
|
$query->whereNotNull('updated_at');
|
||||||
},
|
},
|
||||||
'company.task_statuses'=> function ($query) use ($updated_at, $user) {
|
'company.task_statuses'=> function ($query) use ($updated_at, $user) {
|
||||||
$query->whereNotNull('updated_at');
|
$query->whereNotNull('updated_at');
|
||||||
@ -568,7 +568,7 @@ class BaseController extends Controller
|
|||||||
|
|
||||||
},
|
},
|
||||||
'company.expense_categories'=> function ($query) use ($created_at, $user) {
|
'company.expense_categories'=> function ($query) use ($created_at, $user) {
|
||||||
$query->where('created_at', '>=', $created_at);
|
$query->whereNotNull('created_at');
|
||||||
|
|
||||||
},
|
},
|
||||||
'company.task_statuses'=> function ($query) use ($created_at, $user) {
|
'company.task_statuses'=> function ($query) use ($created_at, $user) {
|
||||||
|
@ -59,7 +59,6 @@ class InvoiceController extends Controller
|
|||||||
|
|
||||||
$invoice->service()->removeUnpaidGatewayFees()->save();
|
$invoice->service()->removeUnpaidGatewayFees()->save();
|
||||||
|
|
||||||
|
|
||||||
$invitation = $invoice->invitations()->where('client_contact_id', auth()->user()->id)->first();
|
$invitation = $invoice->invitations()->where('client_contact_id', auth()->user()->id)->first();
|
||||||
|
|
||||||
if ($invitation && auth()->guard('contact') && ! request()->has('silent') && ! $invitation->viewed_date) {
|
if ($invitation && auth()->guard('contact') && ! request()->has('silent') && ! $invitation->viewed_date) {
|
||||||
|
@ -200,6 +200,7 @@ class CreditController extends BaseController
|
|||||||
|
|
||||||
$credit = $credit->service()
|
$credit = $credit->service()
|
||||||
->fillDefaults()
|
->fillDefaults()
|
||||||
|
->triggeredActions($request)
|
||||||
->save();
|
->save();
|
||||||
|
|
||||||
event(new CreditWasCreated($credit, $credit->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
|
event(new CreditWasCreated($credit, $credit->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
|
||||||
@ -377,7 +378,9 @@ class CreditController extends BaseController
|
|||||||
|
|
||||||
$credit = $this->credit_repository->save($request->all(), $credit);
|
$credit = $this->credit_repository->save($request->all(), $credit);
|
||||||
|
|
||||||
$credit->service()->deletePdf();
|
$credit->service()
|
||||||
|
->triggeredActions($request)
|
||||||
|
->deletePdf();
|
||||||
|
|
||||||
event(new CreditWasUpdated($credit, $credit->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
|
event(new CreditWasUpdated($credit, $credit->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
|
||||||
|
|
||||||
|
@ -83,7 +83,7 @@ class ImportController extends Controller {
|
|||||||
$contents = file_get_contents( $file->getPathname() );
|
$contents = file_get_contents( $file->getPathname() );
|
||||||
|
|
||||||
// Store the csv in cache with an expiry of 10 minutes
|
// Store the csv in cache with an expiry of 10 minutes
|
||||||
Cache::put( $hash . '-' . $entityType, base64_encode( $contents ), 3600 );
|
Cache::put( $hash . '-' . $entityType, base64_encode( $contents ), 600 );
|
||||||
|
|
||||||
// Parse CSV
|
// Parse CSV
|
||||||
$csv_array = $this->getCsvData( $contents );
|
$csv_array = $this->getCsvData( $contents );
|
||||||
@ -111,7 +111,7 @@ class ImportController extends Controller {
|
|||||||
$contents = file_get_contents( $file->getPathname() );
|
$contents = file_get_contents( $file->getPathname() );
|
||||||
|
|
||||||
// Store the csv in cache with an expiry of 10 minutes
|
// Store the csv in cache with an expiry of 10 minutes
|
||||||
Cache::put( $hash . '-' . $entityType, base64_encode( $contents ), 3600 );
|
Cache::put( $hash . '-' . $entityType, base64_encode( $contents ), 600 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -532,9 +532,10 @@ class InvoiceController extends BaseController
|
|||||||
* Download Invoice/s
|
* Download Invoice/s
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if ($action == 'download' && $invoices->count() > 1) {
|
if ($action == 'bulk_download' && $invoices->count() > 1) {
|
||||||
$invoices->each(function ($invoice) {
|
$invoices->each(function ($invoice) {
|
||||||
if (auth()->user()->cannot('view', $invoice)) {
|
if (auth()->user()->cannot('view', $invoice)) {
|
||||||
|
nlog("access denied");
|
||||||
return response()->json(['message' => ctrans('text.access_denied')]);
|
return response()->json(['message' => ctrans('text.access_denied')]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -26,6 +26,8 @@ use Illuminate\Support\Facades\App;
|
|||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Illuminate\Support\Facades\Cache;
|
use Illuminate\Support\Facades\Cache;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
use App\DataMapper\ClientSettings;
|
||||||
use Livewire\Component;
|
use Livewire\Component;
|
||||||
|
|
||||||
class BillingPortalPurchase extends Component
|
class BillingPortalPurchase extends Component
|
||||||
@ -241,7 +243,8 @@ class BillingPortalPurchase extends Component
|
|||||||
'contacts' => [
|
'contacts' => [
|
||||||
['email' => $this->email],
|
['email' => $this->email],
|
||||||
],
|
],
|
||||||
'settings' => [],
|
'client_hash' => Str::random(40),
|
||||||
|
'settings' => ClientSettings::defaults(),
|
||||||
];
|
];
|
||||||
|
|
||||||
foreach ($this->request_data as $field => $value) {
|
foreach ($this->request_data as $field => $value) {
|
||||||
@ -290,7 +293,7 @@ class BillingPortalPurchase extends Component
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((int)$this->subscription->price == 0)
|
if ((int)$this->price == 0)
|
||||||
$this->steps['payment_required'] = false;
|
$this->steps['payment_required'] = false;
|
||||||
else
|
else
|
||||||
$this->steps['fetched_payment_methods'] = true;
|
$this->steps['fetched_payment_methods'] = true;
|
||||||
|
@ -36,6 +36,7 @@ class TasksTable extends Component
|
|||||||
{
|
{
|
||||||
$query = Task::query()
|
$query = Task::query()
|
||||||
->where('company_id', $this->company->id)
|
->where('company_id', $this->company->id)
|
||||||
|
->where('is_deleted', false)
|
||||||
->where('client_id', auth('contact')->user()->client->id);
|
->where('client_id', auth('contact')->user()->client->id);
|
||||||
|
|
||||||
if ($this->company->getSetting('show_all_tasks_client_portal') === 'invoiced') {
|
if ($this->company->getSetting('show_all_tasks_client_portal') === 'invoiced') {
|
||||||
|
@ -42,6 +42,16 @@ class TokenAuth
|
|||||||
return response()->json($error, 403);
|
return response()->json($error, 403);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(Ninja::isHosted() && $company_token->is_system == 0 && !$user->account->isPaid()){
|
||||||
|
|
||||||
|
$error = [
|
||||||
|
'message' => 'Feature not available with free / unpaid account.',
|
||||||
|
'errors' => new stdClass,
|
||||||
|
];
|
||||||
|
|
||||||
|
return response()->json($error, 403);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
|
||||||
| Necessary evil here: As we are authenticating on CompanyToken,
|
| Necessary evil here: As we are authenticating on CompanyToken,
|
||||||
|
@ -28,7 +28,8 @@ class ShowDocumentRequest extends FormRequest
|
|||||||
public function authorize()
|
public function authorize()
|
||||||
{
|
{
|
||||||
return auth()->user('contact')->client->id == $this->document->documentable_id
|
return auth()->user('contact')->client->id == $this->document->documentable_id
|
||||||
|| $this->document->documentable->client_id == auth()->user('contact')->client->id;
|
|| $this->document->documentable->client_id == auth()->user('contact')->client->id
|
||||||
|
|| $this->document->company_id == auth()->user('contact')->company->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -33,11 +33,13 @@ class CanAddUserRule implements Rule
|
|||||||
public function passes($attribute, $value)
|
public function passes($attribute, $value)
|
||||||
{
|
{
|
||||||
|
|
||||||
$count = CompanyUser::query()
|
$count = CompanyUser::query()
|
||||||
->where('account_id', auth()->user()->account_id)
|
->where('company_user.account_id', auth()->user()->account_id)
|
||||||
->whereNull('deleted_at')
|
->join('users', 'users.id', '=', 'company_user.user_id')
|
||||||
->distinct()
|
->whereNull('users.deleted_at')
|
||||||
->count('user_id');
|
->whereNull('company_user.deleted_at')
|
||||||
|
->distinct()
|
||||||
|
->count('company_user.user_id');
|
||||||
|
|
||||||
return $count < auth()->user()->company()->account->num_users;
|
return $count < auth()->user()->company()->account->num_users;
|
||||||
|
|
||||||
|
@ -33,12 +33,13 @@ class CanRestoreUserRule implements Rule
|
|||||||
public function passes($attribute, $value)
|
public function passes($attribute, $value)
|
||||||
{
|
{
|
||||||
|
|
||||||
$count = CompanyUser::query()
|
$count = CompanyUser::query()
|
||||||
->where('account_id', auth()->user()->account_id)
|
->where('company_user.account_id', auth()->user()->account_id)
|
||||||
->whereNull('deleted_at')
|
->join('users', 'users.id', '=', 'company_user.user_id')
|
||||||
->distinct()
|
->whereNull('users.deleted_at')
|
||||||
->count('user_id');
|
->whereNull('company_user.deleted_at')
|
||||||
|
->distinct()
|
||||||
|
->count('company_user.user_id');
|
||||||
|
|
||||||
return $count < auth()->user()->company()->account->num_users;
|
return $count < auth()->user()->company()->account->num_users;
|
||||||
|
|
||||||
|
@ -24,6 +24,8 @@ class ValidProjectForClient implements Rule
|
|||||||
|
|
||||||
public $input;
|
public $input;
|
||||||
|
|
||||||
|
public $message;
|
||||||
|
|
||||||
public function __construct($input)
|
public function __construct($input)
|
||||||
{
|
{
|
||||||
$this->input = $input;
|
$this->input = $input;
|
||||||
@ -35,15 +37,20 @@ class ValidProjectForClient implements Rule
|
|||||||
*/
|
*/
|
||||||
public function passes($attribute, $value)
|
public function passes($attribute, $value)
|
||||||
{
|
{
|
||||||
|
$this->message = ctrans('texts.project_client_do_not_match');
|
||||||
|
|
||||||
if (empty($this->input['project_id'])) {
|
if (empty($this->input['project_id'])) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_string($this->input['project_id'])) {
|
// if (is_string($this->input['project_id'])) {
|
||||||
$this->input['project_id'] = $this->decodePrimaryKey($this->input['project_id']);
|
// $this->input['project_id'] = $this->decodePrimaryKey($this->input['project_id']);
|
||||||
}
|
// }
|
||||||
|
|
||||||
$project = Project::findOrFail($this->input['project_id']);
|
$project = Project::find($this->input['project_id']);
|
||||||
|
|
||||||
|
if(!$project)
|
||||||
|
$this->message = "Project not found";
|
||||||
|
|
||||||
return $project->client_id == $this->input['client_id'];
|
return $project->client_id == $this->input['client_id'];
|
||||||
}
|
}
|
||||||
@ -53,6 +60,6 @@ class ValidProjectForClient implements Rule
|
|||||||
*/
|
*/
|
||||||
public function message()
|
public function message()
|
||||||
{
|
{
|
||||||
return ctrans('texts.project_client_do_not_match');
|
return $this->message;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -221,6 +221,9 @@ class BaseTransformer
|
|||||||
{
|
{
|
||||||
$name = strtolower(trim($name));
|
$name = strtolower(trim($name));
|
||||||
|
|
||||||
|
if(strlen($name) == 2)
|
||||||
|
return $this->getCountryIdBy2($name);
|
||||||
|
|
||||||
return isset($this->maps['countries'][$name]) ? $this->maps['countries'][$name] : null;
|
return isset($this->maps['countries'][$name]) ? $this->maps['countries'][$name] : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,6 +69,7 @@ class ApplyCreditPayment implements ShouldQueue
|
|||||||
|
|
||||||
$this->credit
|
$this->credit
|
||||||
->service()
|
->service()
|
||||||
|
->markSent()
|
||||||
->setStatus(Credit::STATUS_APPLIED)
|
->setStatus(Credit::STATUS_APPLIED)
|
||||||
->adjustBalance($this->amount * -1)
|
->adjustBalance($this->amount * -1)
|
||||||
->updatePaidToDate($this->amount)
|
->updatePaidToDate($this->amount)
|
||||||
@ -78,6 +79,7 @@ class ApplyCreditPayment implements ShouldQueue
|
|||||||
|
|
||||||
$this->credit
|
$this->credit
|
||||||
->service()
|
->service()
|
||||||
|
->markSent()
|
||||||
->setStatus(Credit::STATUS_PARTIAL)
|
->setStatus(Credit::STATUS_PARTIAL)
|
||||||
->adjustBalance($this->amount * -1)
|
->adjustBalance($this->amount * -1)
|
||||||
->updatePaidToDate($this->amount)
|
->updatePaidToDate($this->amount)
|
||||||
|
@ -134,10 +134,6 @@ class CSVImport implements ShouldQueue {
|
|||||||
'company' => $this->company,
|
'company' => $this->company,
|
||||||
];
|
];
|
||||||
|
|
||||||
App::forgetInstance('translator');
|
|
||||||
$t = app('translator');
|
|
||||||
$t->replace(Ninja::transformTranslations($this->company->settings));
|
|
||||||
|
|
||||||
$nmo = new NinjaMailerObject;
|
$nmo = new NinjaMailerObject;
|
||||||
$nmo->mailable = new ImportCompleted($this->company, $data);
|
$nmo->mailable = new ImportCompleted($this->company, $data);
|
||||||
$nmo->company = $this->company;
|
$nmo->company = $this->company;
|
||||||
@ -591,7 +587,7 @@ class CSVImport implements ShouldQueue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private function getCsvData( $entityType ) {
|
private function getCsvData( $entityType ) {
|
||||||
$base64_encoded_csv = Cache::get( $this->hash . '-' . $entityType );
|
$base64_encoded_csv = Cache::pull( $this->hash . '-' . $entityType );
|
||||||
if ( empty( $base64_encoded_csv ) ) {
|
if ( empty( $base64_encoded_csv ) ) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -120,6 +120,7 @@ class SendRecurring implements ShouldQueue
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
event('eloquent.created: App\Models\Invoice', $invoice);
|
||||||
|
|
||||||
//Admin notification for recurring invoice sent.
|
//Admin notification for recurring invoice sent.
|
||||||
if ($invoice->invitations->count() >= 1 ) {
|
if ($invoice->invitations->count() >= 1 ) {
|
||||||
|
@ -232,6 +232,7 @@ class Import implements ShouldQueue
|
|||||||
|
|
||||||
$account = $this->company->account;
|
$account = $this->company->account;
|
||||||
$account->default_company_id = $this->company->id;
|
$account->default_company_id = $this->company->id;
|
||||||
|
$account->is_migrated = true;
|
||||||
$account->save();
|
$account->save();
|
||||||
|
|
||||||
//company size check
|
//company size check
|
||||||
|
@ -49,15 +49,19 @@ class SystemLogger implements ShouldQueue
|
|||||||
|
|
||||||
public function handle() :void
|
public function handle() :void
|
||||||
{
|
{
|
||||||
if(!$this->company)
|
if(!$this->company){
|
||||||
|
nlog("SystemLogger:: No company");
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
MultiDB::setDb($this->company->db);
|
MultiDB::setDb($this->company->db);
|
||||||
|
|
||||||
$client_id = $this->client ? $this->client->id : null;
|
$client_id = $this->client ? $this->client->id : null;
|
||||||
|
|
||||||
if(!$this->client && !$this->company->owner())
|
if(!$this->client && !$this->company->owner()){
|
||||||
|
nlog("SystemLogger:: could not find client and/or company owner");
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
$user_id = $this->client ? $this->client->user_id : $this->company->owner()->id;
|
$user_id = $this->client ? $this->client->user_id : $this->company->owner()->id;
|
||||||
|
|
||||||
@ -71,9 +75,16 @@ class SystemLogger implements ShouldQueue
|
|||||||
'type_id' => $this->type_id,
|
'type_id' => $this->type_id,
|
||||||
];
|
];
|
||||||
|
|
||||||
if(!$this->log)
|
if(!$this->log){
|
||||||
|
nlog("SystemLogger:: no log to store");
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
SystemLog::create($sl);
|
SystemLog::create($sl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function failed($e)
|
||||||
|
{
|
||||||
|
nlog($e->getMessage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,6 +52,10 @@ class InvoiceCreatedNotification implements ShouldQueue
|
|||||||
|
|
||||||
/* The User */
|
/* The User */
|
||||||
$user = $company_user->user;
|
$user = $company_user->user;
|
||||||
|
|
||||||
|
if(!$user)
|
||||||
|
continue;
|
||||||
|
|
||||||
/* This is only here to handle the alternate message channels - ie Slack */
|
/* This is only here to handle the alternate message channels - ie Slack */
|
||||||
// $notification = new EntitySentNotification($event->invitation, 'invoice');
|
// $notification = new EntitySentNotification($event->invitation, 'invoice');
|
||||||
|
|
||||||
@ -71,11 +75,6 @@ class InvoiceCreatedNotification implements ShouldQueue
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Override the methods in the Notification Class */
|
|
||||||
// $notification->method = $methods;
|
|
||||||
|
|
||||||
// Notify on the alternate channels
|
|
||||||
// $user->notify($notification);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,6 +53,9 @@ class QuoteCreatedNotification implements ShouldQueue
|
|||||||
/* The User */
|
/* The User */
|
||||||
$user = $company_user->user;
|
$user = $company_user->user;
|
||||||
|
|
||||||
|
if(!$user)
|
||||||
|
continue;
|
||||||
|
|
||||||
/* This is only here to handle the alternate message channels - ie Slack */
|
/* This is only here to handle the alternate message channels - ie Slack */
|
||||||
// $notification = new EntitySentNotification($event->invitation, 'quote');
|
// $notification = new EntitySentNotification($event->invitation, 'quote');
|
||||||
|
|
||||||
|
@ -75,7 +75,7 @@ class ClientPaymentFailureObject
|
|||||||
$mail_obj->amount = $this->getAmount();
|
$mail_obj->amount = $this->getAmount();
|
||||||
$mail_obj->subject = $this->getSubject();
|
$mail_obj->subject = $this->getSubject();
|
||||||
$mail_obj->data = $this->getData();
|
$mail_obj->data = $this->getData();
|
||||||
$mail_obj->markdown = 'email.admin.generic';
|
$mail_obj->markdown = 'email.client.generic';
|
||||||
$mail_obj->tag = $this->company->company_key;
|
$mail_obj->tag = $this->company->company_key;
|
||||||
|
|
||||||
return $mail_obj;
|
return $mail_obj;
|
||||||
@ -113,14 +113,15 @@ class ClientPaymentFailureObject
|
|||||||
]
|
]
|
||||||
),
|
),
|
||||||
'greeting' => ctrans('texts.email_salutation', ['name' => $this->client->present()->name]),
|
'greeting' => ctrans('texts.email_salutation', ['name' => $this->client->present()->name]),
|
||||||
'message' => ctrans('texts.client_payment_failure_body', ['invoice' => implode(",", $this->invoices->pluck('number')->toArray()), 'amount' => $this->getAmount()]),
|
'content' => ctrans('texts.client_payment_failure_body', ['invoice' => implode(",", $this->invoices->pluck('number')->toArray()), 'amount' => $this->getAmount()]),
|
||||||
'signature' => $signature,
|
'signature' => $signature,
|
||||||
'logo' => $this->company->present()->logo(),
|
'logo' => $this->company->present()->logo(),
|
||||||
'settings' => $this->client->getMergedSettings(),
|
'settings' => $this->client->getMergedSettings(),
|
||||||
'whitelabel' => $this->company->account->isPaid() ? true : false,
|
'whitelabel' => $this->company->account->isPaid() ? true : false,
|
||||||
'url' => route('client.login'),
|
'url' => $this->invoices->first()->invitations->first()->getPaymentLink(),
|
||||||
'button' => ctrans('texts.login'),
|
'button' => 'texts.pay_now',
|
||||||
'additional_info' => false
|
'additional_info' => false,
|
||||||
|
'company' => $this->company,
|
||||||
];
|
];
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
|
@ -136,4 +136,4 @@ class InvoiceEmailEngine extends BaseEmailEngine
|
|||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -13,9 +13,11 @@
|
|||||||
namespace App\Mail\Import;
|
namespace App\Mail\Import;
|
||||||
|
|
||||||
use App\Models\Company;
|
use App\Models\Company;
|
||||||
|
use App\Utils\Ninja;
|
||||||
use Illuminate\Bus\Queueable;
|
use Illuminate\Bus\Queueable;
|
||||||
use Illuminate\Mail\Mailable;
|
use Illuminate\Mail\Mailable;
|
||||||
use Illuminate\Queue\SerializesModels;
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
use Illuminate\Support\Facades\App;
|
||||||
|
|
||||||
class ImportCompleted extends Mailable
|
class ImportCompleted extends Mailable
|
||||||
{
|
{
|
||||||
@ -45,6 +47,11 @@ class ImportCompleted extends Mailable
|
|||||||
*/
|
*/
|
||||||
public function build()
|
public function build()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
App::forgetInstance('translator');
|
||||||
|
$t = app('translator');
|
||||||
|
$t->replace(Ninja::transformTranslations($this->company->settings));
|
||||||
|
|
||||||
$data = array_merge($this->data, [
|
$data = array_merge($this->data, [
|
||||||
'logo' => $this->company->present()->logo(),
|
'logo' => $this->company->present()->logo(),
|
||||||
'settings' => $this->company->settings,
|
'settings' => $this->company->settings,
|
||||||
|
@ -3,9 +3,11 @@
|
|||||||
namespace App\Mail;
|
namespace App\Mail;
|
||||||
|
|
||||||
use App\Models\Company;
|
use App\Models\Company;
|
||||||
|
use App\Utils\Ninja;
|
||||||
use Illuminate\Bus\Queueable;
|
use Illuminate\Bus\Queueable;
|
||||||
use Illuminate\Mail\Mailable;
|
use Illuminate\Mail\Mailable;
|
||||||
use Illuminate\Queue\SerializesModels;
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
use Illuminate\Support\Facades\App;
|
||||||
|
|
||||||
class MigrationCompleted extends Mailable
|
class MigrationCompleted extends Mailable
|
||||||
{
|
{
|
||||||
@ -33,6 +35,11 @@ class MigrationCompleted extends Mailable
|
|||||||
*/
|
*/
|
||||||
public function build()
|
public function build()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
App::forgetInstance('translator');
|
||||||
|
$t = app('translator');
|
||||||
|
$t->replace(Ninja::transformTranslations($this->company->settings));
|
||||||
|
|
||||||
$data['settings'] = $this->company->settings;
|
$data['settings'] = $this->company->settings;
|
||||||
$data['company'] = $this->company->fresh();
|
$data['company'] = $this->company->fresh();
|
||||||
$data['whitelabel'] = $this->company->account->isPaid() ? true : false;
|
$data['whitelabel'] = $this->company->account->isPaid() ? true : false;
|
||||||
|
@ -18,6 +18,7 @@ use App\Models\ClientContact;
|
|||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use App\Services\PdfMaker\Designs\Utilities\DesignHelpers;
|
use App\Services\PdfMaker\Designs\Utilities\DesignHelpers;
|
||||||
use App\Utils\HtmlEngine;
|
use App\Utils\HtmlEngine;
|
||||||
|
use App\Utils\Ninja;
|
||||||
use App\Utils\TemplateEngine;
|
use App\Utils\TemplateEngine;
|
||||||
use Illuminate\Bus\Queueable;
|
use Illuminate\Bus\Queueable;
|
||||||
use Illuminate\Mail\Mailable;
|
use Illuminate\Mail\Mailable;
|
||||||
@ -114,6 +115,10 @@ class TemplateEmail extends Mailable
|
|||||||
$message->invitation = $this->invitation;
|
$message->invitation = $this->invitation;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/*In the hosted platform we need to slow things down a little for Storage to catch up.*/
|
||||||
|
if(Ninja::isHosted())
|
||||||
|
sleep(1);
|
||||||
|
|
||||||
foreach ($this->build_email->getAttachments() as $file) {
|
foreach ($this->build_email->getAttachments() as $file) {
|
||||||
|
|
||||||
if(is_string($file))
|
if(is_string($file))
|
||||||
|
@ -195,6 +195,8 @@ class BaseModel extends Model
|
|||||||
// Remove any runs of periods (thanks falstro!)
|
// Remove any runs of periods (thanks falstro!)
|
||||||
$formatted_number = mb_ereg_replace("([\.]{2,})", '', $formatted_number);
|
$formatted_number = mb_ereg_replace("([\.]{2,})", '', $formatted_number);
|
||||||
|
|
||||||
|
$formatted_number = str_replace(" ", "", $formatted_number);
|
||||||
|
|
||||||
return $formatted_number;
|
return $formatted_number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,6 +217,9 @@ class ClientContact extends Authenticatable implements HasLocalePreference
|
|||||||
{
|
{
|
||||||
$languages = Cache::get('languages');
|
$languages = Cache::get('languages');
|
||||||
|
|
||||||
|
if(!$languages)
|
||||||
|
$this->buildCache(true);
|
||||||
|
|
||||||
return $languages->filter(function ($item) {
|
return $languages->filter(function ($item) {
|
||||||
return $item->id == $this->client->getSetting('language_id');
|
return $item->id == $this->client->getSetting('language_id');
|
||||||
})->first()->locale;
|
})->first()->locale;
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use App\Helpers\Document\WithTypeHelpers;
|
||||||
use App\Models\Filterable;
|
use App\Models\Filterable;
|
||||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
@ -19,6 +20,7 @@ class Document extends BaseModel
|
|||||||
{
|
{
|
||||||
use SoftDeletes;
|
use SoftDeletes;
|
||||||
use Filterable;
|
use Filterable;
|
||||||
|
use WithTypeHelpers;
|
||||||
|
|
||||||
const DOCUMENT_PREVIEW_SIZE = 300; // pixels
|
const DOCUMENT_PREVIEW_SIZE = 300; // pixels
|
||||||
|
|
||||||
|
@ -404,7 +404,7 @@ class BaseDriver extends AbstractPaymentDriver
|
|||||||
throw new PaymentFailed($error, $e->getCode());
|
throw new PaymentFailed($error, $e->getCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function sendFailureMail(string $error)
|
public function sendFailureMail($error = '')
|
||||||
{
|
{
|
||||||
|
|
||||||
if (!is_null($this->payment_hash)) {
|
if (!is_null($this->payment_hash)) {
|
||||||
|
@ -63,8 +63,8 @@ class CreditCard
|
|||||||
$transaction = [
|
$transaction = [
|
||||||
'Reference' => $this->eway_driver->client->number,
|
'Reference' => $this->eway_driver->client->number,
|
||||||
'Title' => '',
|
'Title' => '',
|
||||||
'FirstName' => $this->eway_driver->client->contacts()->first()->present()->last_name(),
|
'FirstName' => $this->eway_driver->client->contacts()->first()->present()->first_name(),
|
||||||
'LastName' => $this->eway_driver->client->contacts()->first()->present()->first_name(),
|
'LastName' => $this->eway_driver->client->contacts()->first()->present()->last_name(),
|
||||||
'CompanyName' => $this->eway_driver->client->name,
|
'CompanyName' => $this->eway_driver->client->name,
|
||||||
'Street1' => $this->eway_driver->client->address1,
|
'Street1' => $this->eway_driver->client->address1,
|
||||||
'Street2' => $this->eway_driver->client->address2,
|
'Street2' => $this->eway_driver->client->address2,
|
||||||
|
@ -99,4 +99,9 @@ class RazorpayPaymentDriver extends BaseDriver
|
|||||||
{
|
{
|
||||||
return \number_format((float) $amount * 100, 0, '.', '');
|
return \number_format((float) $amount * 100, 0, '.', '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function processWebhookRequest(): void
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -524,10 +524,24 @@ class StripePaymentDriver extends BaseDriver
|
|||||||
if ($request->type === 'charge.succeeded' || $request->type === 'payment_intent.succeeded') {
|
if ($request->type === 'charge.succeeded' || $request->type === 'payment_intent.succeeded') {
|
||||||
|
|
||||||
foreach ($request->data as $transaction) {
|
foreach ($request->data as $transaction) {
|
||||||
$payment = Payment::query()
|
|
||||||
->where('transaction_reference', $transaction['id'])
|
if(array_key_exists('payment_intent', $transaction))
|
||||||
|
{
|
||||||
|
$payment = Payment::query()
|
||||||
->where('company_id', $request->getCompany()->id)
|
->where('company_id', $request->getCompany()->id)
|
||||||
|
->where(function ($query) use ($transaction) {
|
||||||
|
$query->where('transaction_reference', $transaction['payment_intent'])
|
||||||
|
->orWhere('transaction_reference', $transaction['id']);
|
||||||
|
})
|
||||||
->first();
|
->first();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$payment = Payment::query()
|
||||||
|
->where('company_id', $request->getCompany()->id)
|
||||||
|
->where('transaction_reference', $transaction['id'])
|
||||||
|
->first();
|
||||||
|
}
|
||||||
|
|
||||||
if ($payment) {
|
if ($payment) {
|
||||||
$payment->status_id = Payment::STATUS_COMPLETED;
|
$payment->status_id = Payment::STATUS_COMPLETED;
|
||||||
@ -546,10 +560,13 @@ class StripePaymentDriver extends BaseDriver
|
|||||||
|
|
||||||
if ($charge->captured) {
|
if ($charge->captured) {
|
||||||
$payment = Payment::query()
|
$payment = Payment::query()
|
||||||
->where('transaction_reference', $transaction['id'])
|
->where('transaction_reference', $transaction['payment_intent'])
|
||||||
->where('company_id', $request->getCompany()->id)
|
->where('company_id', $request->getCompany()->id)
|
||||||
|
->where(function ($query) use ($transaction) {
|
||||||
|
$query->where('transaction_reference', $transaction['payment_intent'])
|
||||||
|
->orWhere('transaction_reference', $transaction['id']);
|
||||||
|
})
|
||||||
->first();
|
->first();
|
||||||
|
|
||||||
if ($payment) {
|
if ($payment) {
|
||||||
$payment->status_id = Payment::STATUS_COMPLETED;
|
$payment->status_id = Payment::STATUS_COMPLETED;
|
||||||
$payment->save();
|
$payment->save();
|
||||||
|
@ -22,7 +22,9 @@ use Illuminate\Support\Str;
|
|||||||
*/
|
*/
|
||||||
class ClientContactRepository extends BaseRepository
|
class ClientContactRepository extends BaseRepository
|
||||||
{
|
{
|
||||||
public $is_primary;
|
private bool $is_primary = true;
|
||||||
|
|
||||||
|
private bool $set_send_email_on_contact = false;
|
||||||
|
|
||||||
public function save(array $data, Client $client) : void
|
public function save(array $data, Client $client) : void
|
||||||
{
|
{
|
||||||
@ -36,13 +38,20 @@ class ClientContactRepository extends BaseRepository
|
|||||||
ClientContact::destroy($contact);
|
ClientContact::destroy($contact);
|
||||||
});
|
});
|
||||||
|
|
||||||
$this->is_primary = true;
|
/* Ensure send_email always exists in at least one contact */
|
||||||
|
if(!$contacts->contains('send_email', true))
|
||||||
|
$this->set_send_email_on_contact = true;
|
||||||
|
|
||||||
/* Set first record to primary - always */
|
/* Set first record to primary - always */
|
||||||
$contacts = $contacts->sortByDesc('is_primary')->map(function ($contact) {
|
$contacts = $contacts->sortByDesc('is_primary')->map(function ($contact) {
|
||||||
$contact['is_primary'] = $this->is_primary;
|
$contact['is_primary'] = $this->is_primary;
|
||||||
$this->is_primary = false;
|
$this->is_primary = false;
|
||||||
|
|
||||||
|
if($this->set_send_email_on_contact){
|
||||||
|
$contact['send_email'] = true;
|
||||||
|
$this->set_send_email_on_contact = false;
|
||||||
|
}
|
||||||
|
|
||||||
return $contact;
|
return $contact;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -129,7 +129,7 @@ class PaymentRepository extends BaseRepository {
|
|||||||
|
|
||||||
//todo optimize this into a single query
|
//todo optimize this into a single query
|
||||||
foreach ($data['invoices'] as $paid_invoice) {
|
foreach ($data['invoices'] as $paid_invoice) {
|
||||||
$invoice = Invoice::whereId($paid_invoice['invoice_id'])->first();
|
$invoice = Invoice::withTrashed()->whereId($paid_invoice['invoice_id'])->first();
|
||||||
|
|
||||||
if ($invoice) {
|
if ($invoice) {
|
||||||
$invoice = $invoice->service()
|
$invoice = $invoice->service()
|
||||||
|
@ -23,7 +23,7 @@ class CreateInvitations extends AbstractService
|
|||||||
{
|
{
|
||||||
use MakesHash;
|
use MakesHash;
|
||||||
|
|
||||||
private $credit;
|
public $credit;
|
||||||
|
|
||||||
public function __construct(Credit $credit)
|
public function __construct(Credit $credit)
|
||||||
{
|
{
|
||||||
@ -45,6 +45,7 @@ class CreateInvitations extends AbstractService
|
|||||||
$invitation = CreditInvitation::whereCompanyId($this->credit->company_id)
|
$invitation = CreditInvitation::whereCompanyId($this->credit->company_id)
|
||||||
->whereClientContactId($contact->id)
|
->whereClientContactId($contact->id)
|
||||||
->whereCreditId($this->credit->id)
|
->whereCreditId($this->credit->id)
|
||||||
|
->withTrashed()
|
||||||
->first();
|
->first();
|
||||||
|
|
||||||
if (! $invitation) {
|
if (! $invitation) {
|
||||||
@ -58,6 +59,34 @@ class CreateInvitations extends AbstractService
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if($this->credit->invitations()->count() == 0) {
|
||||||
|
|
||||||
|
if($contacts->count() == 0){
|
||||||
|
$contact = $this->createBlankContact();
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
$contact = $contacts->first();
|
||||||
|
|
||||||
|
$invitation = CreditInvitation::where('company_id', $this->credit->company_id)
|
||||||
|
->where('client_contact_id', $contact->id)
|
||||||
|
->where('credit_id', $this->credit->id)
|
||||||
|
->withTrashed()
|
||||||
|
->first();
|
||||||
|
|
||||||
|
if($invitation){
|
||||||
|
$invitation->restore();
|
||||||
|
return $this->credit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$ii = CreditInvitationFactory::create($this->credit->company_id, $this->credit->user_id);
|
||||||
|
$ii->key = $this->createDbHash($this->credit->company->db);
|
||||||
|
$ii->credit_id = $this->credit->id;
|
||||||
|
$ii->client_contact_id = $contact->id;
|
||||||
|
$ii->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return $this->credit;
|
return $this->credit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,13 +13,15 @@ namespace App\Services\Credit;
|
|||||||
|
|
||||||
use App\Jobs\Util\UnlinkFile;
|
use App\Jobs\Util\UnlinkFile;
|
||||||
use App\Models\Credit;
|
use App\Models\Credit;
|
||||||
|
use App\Services\Credit\CreateInvitations;
|
||||||
|
use App\Services\Credit\TriggeredActions;
|
||||||
use App\Utils\Traits\MakesHash;
|
use App\Utils\Traits\MakesHash;
|
||||||
|
|
||||||
class CreditService
|
class CreditService
|
||||||
{
|
{
|
||||||
use MakesHash;
|
use MakesHash;
|
||||||
|
|
||||||
protected $credit;
|
public $credit;
|
||||||
|
|
||||||
public function __construct($credit)
|
public function __construct($credit)
|
||||||
{
|
{
|
||||||
@ -149,6 +151,13 @@ class CreditService
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function triggeredActions($request)
|
||||||
|
{
|
||||||
|
$this->invoice = (new TriggeredActions($this->credit, $request))->run();
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Saves the credit.
|
* Saves the credit.
|
||||||
* @return Credit object
|
* @return Credit object
|
||||||
|
76
app/Services/Credit/TriggeredActions.php
Normal file
76
app/Services/Credit/TriggeredActions.php
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Credit Ninja (https://invoiceninja.com).
|
||||||
|
*
|
||||||
|
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||||
|
*
|
||||||
|
* @copyright Copyright (c) 2021. Credit Ninja LLC (https://invoiceninja.com)
|
||||||
|
*
|
||||||
|
* @license https://www.elastic.co/licensing/elastic-license
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace App\Services\Credit;
|
||||||
|
|
||||||
|
use App\Events\Credit\CreditWasEmailed;
|
||||||
|
use App\Jobs\Entity\EmailEntity;
|
||||||
|
use App\Models\Credit;
|
||||||
|
use App\Services\AbstractService;
|
||||||
|
use App\Utils\Ninja;
|
||||||
|
use App\Utils\Traits\GeneratesCounter;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class TriggeredActions extends AbstractService
|
||||||
|
{
|
||||||
|
use GeneratesCounter;
|
||||||
|
|
||||||
|
private $request;
|
||||||
|
|
||||||
|
private $credit;
|
||||||
|
|
||||||
|
public function __construct(Credit $credit, Request $request)
|
||||||
|
{
|
||||||
|
$this->request = $request;
|
||||||
|
|
||||||
|
$this->credit = $credit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function run()
|
||||||
|
{
|
||||||
|
// if ($this->request->has('auto_bill') && $this->request->input('auto_bill') == 'true') {
|
||||||
|
// $this->credit = $this->credit->service()->autoBill()->save();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if ($this->request->has('paid') && $this->request->input('paid') == 'true') {
|
||||||
|
// $this->credit = $this->credit->service()->markPaid()->save();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if ($this->request->has('amount_paid') && is_numeric($this->request->input('amount_paid')) ) {
|
||||||
|
// $this->credit = $this->credit->service()->applyPaymentAmount($this->request->input('amount_paid'))->save();
|
||||||
|
// }
|
||||||
|
|
||||||
|
if ($this->request->has('send_email') && $this->request->input('send_email') == 'true') {
|
||||||
|
$this->sendEmail();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->request->has('mark_sent') && $this->request->input('mark_sent') == 'true') {
|
||||||
|
$this->credit = $this->credit->service()->markSent()->save();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return $this->credit;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function sendEmail()
|
||||||
|
{
|
||||||
|
|
||||||
|
$reminder_template = $this->credit->calculateTemplate('credit');
|
||||||
|
|
||||||
|
$this->credit->invitations->load('contact.client.country', 'credit.client.country', 'credit.company')->each(function ($invitation) use ($reminder_template) {
|
||||||
|
EmailEntity::dispatch($invitation, $this->credit->company, $reminder_template);
|
||||||
|
});
|
||||||
|
|
||||||
|
if ($this->credit->invitations->count() > 0) {
|
||||||
|
event(new CreditWasEmailed($this->credit->invitations->first(), $this->credit->company, Ninja::eventVars(), 'credit'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -47,7 +47,7 @@ class ApplyPayment extends AbstractService
|
|||||||
|
|
||||||
$amount_paid = $this->payment_amount * -1;
|
$amount_paid = $this->payment_amount * -1;
|
||||||
|
|
||||||
$this->invoice->service()->clearPartial()->setDueDate()->setStatus(Invoice::STATUS_PARTIAL)->updateBalance($amount_paid);
|
$this->invoice->service()->clearPartial()->setDueDate()->setStatus(Invoice::STATUS_PARTIAL)->updateBalance($amount_paid)->save();
|
||||||
|
|
||||||
}
|
}
|
||||||
elseif ($this->invoice->partial > 0 && $this->invoice->partial > $this->payment_amount)
|
elseif ($this->invoice->partial > 0 && $this->invoice->partial > $this->payment_amount)
|
||||||
@ -56,7 +56,7 @@ class ApplyPayment extends AbstractService
|
|||||||
|
|
||||||
$amount_paid = $this->payment_amount * -1;
|
$amount_paid = $this->payment_amount * -1;
|
||||||
|
|
||||||
$this->invoice->service()->updatePartial($amount_paid)->updateBalance($amount_paid);
|
$this->invoice->service()->updatePartial($amount_paid)->updateBalance($amount_paid)->save();
|
||||||
|
|
||||||
}
|
}
|
||||||
elseif ($this->invoice->partial > 0 && $this->invoice->partial < $this->payment_amount)
|
elseif ($this->invoice->partial > 0 && $this->invoice->partial < $this->payment_amount)
|
||||||
@ -65,7 +65,7 @@ class ApplyPayment extends AbstractService
|
|||||||
|
|
||||||
$amount_paid = $this->payment_amount * -1;
|
$amount_paid = $this->payment_amount * -1;
|
||||||
|
|
||||||
$this->invoice->service()->clearPartial()->setDueDate()->setStatus(Invoice::STATUS_PARTIAL)->updateBalance($amount_paid);
|
$this->invoice->service()->clearPartial()->setDueDate()->setStatus(Invoice::STATUS_PARTIAL)->updateBalance($amount_paid)->save();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,7 +76,7 @@ class ApplyPayment extends AbstractService
|
|||||||
{
|
{
|
||||||
$amount_paid = $this->payment_amount * -1;
|
$amount_paid = $this->payment_amount * -1;
|
||||||
|
|
||||||
$this->invoice->service()->clearPartial()->setStatus(Invoice::STATUS_PAID)->updateBalance($amount_paid);
|
$this->invoice->service()->clearPartial()->setStatus(Invoice::STATUS_PAID)->updateBalance($amount_paid)->save();
|
||||||
|
|
||||||
}
|
}
|
||||||
elseif ($this->payment_amount < $this->invoice->balance)
|
elseif ($this->payment_amount < $this->invoice->balance)
|
||||||
@ -85,7 +85,7 @@ class ApplyPayment extends AbstractService
|
|||||||
|
|
||||||
$amount_paid = $this->payment_amount * -1;
|
$amount_paid = $this->payment_amount * -1;
|
||||||
|
|
||||||
$this->invoice->service()->clearPartial()->setStatus(Invoice::STATUS_PARTIAL)->updateBalance($amount_paid);
|
$this->invoice->service()->clearPartial()->setStatus(Invoice::STATUS_PARTIAL)->updateBalance($amount_paid)->save();
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -95,7 +95,7 @@ class ApplyPayment extends AbstractService
|
|||||||
|
|
||||||
$amount_paid = $this->invoice->balance * -1;
|
$amount_paid = $this->invoice->balance * -1;
|
||||||
|
|
||||||
$this->invoice->service()->clearPartial()->setStatus(Invoice::STATUS_PAID)->updateBalance($amount_paid);
|
$this->invoice->service()->clearPartial()->setStatus(Invoice::STATUS_PAID)->updateBalance($amount_paid)->save();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,23 @@ class CreateInvitations extends AbstractService
|
|||||||
|
|
||||||
if($this->invoice->invitations()->count() == 0) {
|
if($this->invoice->invitations()->count() == 0) {
|
||||||
|
|
||||||
$contact = $this->createBlankContact();
|
if($contacts->count() == 0){
|
||||||
|
$contact = $this->createBlankContact();
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
$contact = $contacts->first();
|
||||||
|
|
||||||
|
$invitation = InvoiceInvitation::where('company_id', $this->invoice->company_id)
|
||||||
|
->where('client_contact_id', $contact->id)
|
||||||
|
->where('invoice_id', $this->invoice->id)
|
||||||
|
->withTrashed()
|
||||||
|
->first();
|
||||||
|
|
||||||
|
if($invitation){
|
||||||
|
$invitation->restore();
|
||||||
|
return $this->invoice;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$ii = InvoiceInvitationFactory::create($this->invoice->company_id, $this->invoice->user_id);
|
$ii = InvoiceInvitationFactory::create($this->invoice->company_id, $this->invoice->user_id);
|
||||||
$ii->key = $this->createDbHash($this->invoice->company->db);
|
$ii->key = $this->createDbHash($this->invoice->company->db);
|
||||||
|
@ -57,7 +57,7 @@ class HandleReversal extends AbstractService
|
|||||||
$paymentables->each(function ($paymentable) use ($total_paid) {
|
$paymentables->each(function ($paymentable) use ($total_paid) {
|
||||||
|
|
||||||
//new concept - when reversing, we unwind the payments
|
//new concept - when reversing, we unwind the payments
|
||||||
$payment = Payment::find($paymentable->payment_id);
|
$payment = Payment::withTrashed()->find($paymentable->payment_id);
|
||||||
|
|
||||||
$reversable_amount = $paymentable->amount - $paymentable->refunded;
|
$reversable_amount = $paymentable->amount - $paymentable->refunded;
|
||||||
$total_paid -= $reversable_amount;
|
$total_paid -= $reversable_amount;
|
||||||
|
@ -33,7 +33,7 @@ class InvoiceService
|
|||||||
{
|
{
|
||||||
use MakesHash;
|
use MakesHash;
|
||||||
|
|
||||||
private $invoice;
|
public $invoice;
|
||||||
|
|
||||||
public function __construct($invoice)
|
public function __construct($invoice)
|
||||||
{
|
{
|
||||||
|
@ -37,34 +37,37 @@ class MarkSent extends AbstractService
|
|||||||
return $this->invoice;
|
return $this->invoice;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$adjustment = $this->invoice->amount;
|
||||||
|
|
||||||
/*Set status*/
|
/*Set status*/
|
||||||
$this->invoice
|
$this->invoice
|
||||||
->service()
|
->service()
|
||||||
->setStatus(Invoice::STATUS_SENT)
|
->setStatus(Invoice::STATUS_SENT)
|
||||||
|
->updateBalance($adjustment, true)
|
||||||
->save();
|
->save();
|
||||||
|
|
||||||
$this->invoice
|
/*Adjust client balance*/
|
||||||
|
$this->client
|
||||||
|
->service()
|
||||||
|
->updateBalance($adjustment)
|
||||||
|
->save();
|
||||||
|
|
||||||
|
/*Update ledger*/
|
||||||
|
$this->invoice
|
||||||
|
->ledger()
|
||||||
|
->updateInvoiceBalance($adjustment, "Invoice {$this->invoice->number} marked as sent.");
|
||||||
|
|
||||||
|
/* Perform additional actions on invoice */
|
||||||
|
$this->invoice
|
||||||
->service()
|
->service()
|
||||||
->applyNumber()
|
->applyNumber()
|
||||||
->setDueDate()
|
->setDueDate()
|
||||||
->updateBalance($this->invoice->amount, true)
|
|
||||||
->deletePdf()
|
->deletePdf()
|
||||||
->setReminder()
|
->setReminder()
|
||||||
->save();
|
->save();
|
||||||
|
|
||||||
$this->invoice->markInvitationsSent();
|
$this->invoice->markInvitationsSent();
|
||||||
|
|
||||||
/*Adjust client balance*/
|
|
||||||
$this->client
|
|
||||||
->service()
|
|
||||||
->updateBalance($this->invoice->balance)
|
|
||||||
->save();
|
|
||||||
|
|
||||||
/*Update ledger*/
|
|
||||||
$this->invoice
|
|
||||||
->ledger()
|
|
||||||
->updateInvoiceBalance($this->invoice->balance, "Invoice {$this->invoice->number} marked as sent.");
|
|
||||||
|
|
||||||
event(new InvoiceWasUpdated($this->invoice, $this->invoice->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
|
event(new InvoiceWasUpdated($this->invoice, $this->invoice->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
|
||||||
|
|
||||||
return $this->invoice->fresh();
|
return $this->invoice->fresh();
|
||||||
|
@ -34,6 +34,9 @@ class UpdateBalance extends AbstractService
|
|||||||
if ($this->invoice->is_deleted) {
|
if ($this->invoice->is_deleted) {
|
||||||
return $this->invoice;
|
return $this->invoice;
|
||||||
}
|
}
|
||||||
|
nlog("invoice id = {$this->invoice->id}");
|
||||||
|
nlog("invoice balance = {$this->invoice->balance}");
|
||||||
|
nlog("invoice adjustment = {$this->balance_adjustment}");
|
||||||
|
|
||||||
$this->invoice->balance += floatval($this->balance_adjustment);
|
$this->invoice->balance += floatval($this->balance_adjustment);
|
||||||
|
|
||||||
@ -41,6 +44,8 @@ class UpdateBalance extends AbstractService
|
|||||||
$this->invoice->status_id = Invoice::STATUS_PAID;
|
$this->invoice->status_id = Invoice::STATUS_PAID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nlog("final balance = {$this->invoice->balance}");
|
||||||
|
|
||||||
return $this->invoice;
|
return $this->invoice;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,6 +59,33 @@ class CreateInvitations
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if($this->quote->invitations()->count() == 0) {
|
||||||
|
|
||||||
|
if($contacts->count() == 0){
|
||||||
|
$contact = $this->createBlankContact();
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
$contact = $contacts->first();
|
||||||
|
|
||||||
|
$invitation = QuoteInvitation::where('company_id', $this->quote->company_id)
|
||||||
|
->where('client_contact_id', $contact->id)
|
||||||
|
->where('quote_id', $this->quote->id)
|
||||||
|
->withTrashed()
|
||||||
|
->first();
|
||||||
|
|
||||||
|
if($invitation){
|
||||||
|
$invitation->restore();
|
||||||
|
return $this->quote;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$ii = QuoteInvitationFactory::create($this->quote->company_id, $this->quote->user_id);
|
||||||
|
$ii->key = $this->createDbHash($this->quote->company->db);
|
||||||
|
$ii->quote_id = $this->quote->id;
|
||||||
|
$ii->client_contact_id = $contact->id;
|
||||||
|
$ii->save();
|
||||||
|
}
|
||||||
|
|
||||||
return $this->quote->fresh();
|
return $this->quote->fresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,6 +82,7 @@ class AccountTransformer extends EntityTransformer
|
|||||||
'disable_auto_update' => (bool) config('ninja.disable_auto_update'),
|
'disable_auto_update' => (bool) config('ninja.disable_auto_update'),
|
||||||
'emails_sent' => (int) $account->emailsSent(),
|
'emails_sent' => (int) $account->emailsSent(),
|
||||||
'email_quota' => (int) $account->getDailyEmailLimit(),
|
'email_quota' => (int) $account->getDailyEmailLimit(),
|
||||||
|
'is_migrated' => (bool) $account->is_migrated,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,6 +151,7 @@ class HtmlEngine
|
|||||||
|
|
||||||
if($this->entity->project) {
|
if($this->entity->project) {
|
||||||
$data['$project.name'] = ['value' => $this->entity->project->name, 'label' => ctrans('texts.project_name')];
|
$data['$project.name'] = ['value' => $this->entity->project->name, 'label' => ctrans('texts.project_name')];
|
||||||
|
$data['$invoice.project'] = &$data['$project.name'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -480,6 +481,8 @@ class HtmlEngine
|
|||||||
$data['$statement_amount'] = ['value' => '', 'label' => ctrans('texts.amount')];
|
$data['$statement_amount'] = ['value' => '', 'label' => ctrans('texts.amount')];
|
||||||
$data['$statement'] = ['value' => '', 'label' => ctrans('texts.statement')];
|
$data['$statement'] = ['value' => '', 'label' => ctrans('texts.statement')];
|
||||||
|
|
||||||
|
$data['$entity_images'] = ['value' => $this->generateEntityImagesMarkup(), 'label' => ''];
|
||||||
|
|
||||||
$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);
|
||||||
|
|
||||||
@ -736,4 +739,38 @@ html {
|
|||||||
|
|
||||||
return $css;
|
return $css;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate markup for HTML images on entity.
|
||||||
|
*
|
||||||
|
* @return string|void
|
||||||
|
*/
|
||||||
|
protected function generateEntityImagesMarkup()
|
||||||
|
{
|
||||||
|
if ($this->client->getSetting('embed_documents') === false) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$dom = new \DOMDocument('1.0', 'UTF-8');
|
||||||
|
|
||||||
|
$container = $dom->createElement('div');
|
||||||
|
$container->setAttribute('style', 'display:grid; grid-auto-flow: row; grid-template-columns: repeat(4, 1fr); grid-template-rows: repeat(2, 1fr);');
|
||||||
|
|
||||||
|
foreach ($this->entity->documents as $document) {
|
||||||
|
if (!$document->isImage()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$image = $dom->createElement('img');
|
||||||
|
|
||||||
|
$image->setAttribute('src', $document->generateUrl());
|
||||||
|
$image->setAttribute('style', 'max-height: 100px; margin-top: 20px;');
|
||||||
|
|
||||||
|
$container->appendChild($image);
|
||||||
|
}
|
||||||
|
|
||||||
|
$dom->appendChild($container);
|
||||||
|
|
||||||
|
return $dom->saveHTML();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -113,8 +113,14 @@ class Ninja
|
|||||||
|
|
||||||
public static function eventVars($user_id = null)
|
public static function eventVars($user_id = null)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
if(request()->hasHeader('Cf-Connecting-Ip'))
|
||||||
|
$ip = request()->header('Cf-Connecting-Ip');
|
||||||
|
else
|
||||||
|
$ip = request()->getClientIp();
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'ip' => request()->getClientIp(),
|
'ip' => $ip,
|
||||||
'token' => request()->header('X-API-TOKEN'),
|
'token' => request()->header('X-API-TOKEN'),
|
||||||
'is_system' => app()->runningInConsole(),
|
'is_system' => app()->runningInConsole(),
|
||||||
'user_id' => $user_id,
|
'user_id' => $user_id,
|
||||||
|
@ -257,7 +257,7 @@ class TemplateEngine
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
||||||
if($this->entity == 'invoice')
|
if(!$this->entity || $this->entity == 'invoice')
|
||||||
{
|
{
|
||||||
$this->entity_obj = Invoice::factory()->create([
|
$this->entity_obj = Invoice::factory()->create([
|
||||||
'user_id' => auth()->user()->id,
|
'user_id' => auth()->user()->id,
|
||||||
|
@ -207,7 +207,7 @@ return [
|
|||||||
['options' => [
|
['options' => [
|
||||||
'replication' => 'sentinel',
|
'replication' => 'sentinel',
|
||||||
'service' => env('REDIS_SENTINEL_SERVICE', 'mymaster'),
|
'service' => env('REDIS_SENTINEL_SERVICE', 'mymaster'),
|
||||||
'sentinel_timeout' => 1.0,
|
'sentinel_timeout' => 2.0,
|
||||||
'parameters' => [
|
'parameters' => [
|
||||||
'password' => env('REDIS_PASSWORD', null),
|
'password' => env('REDIS_PASSWORD', null),
|
||||||
'database' => env('REDIS_DB', 0),
|
'database' => env('REDIS_DB', 0),
|
||||||
@ -226,7 +226,7 @@ return [
|
|||||||
['options' => [
|
['options' => [
|
||||||
'replication' => 'sentinel',
|
'replication' => 'sentinel',
|
||||||
'service' => env('REDIS_SENTINEL_SERVICE', 'mymaster'),
|
'service' => env('REDIS_SENTINEL_SERVICE', 'mymaster'),
|
||||||
'sentinel_timeout' => 1.0,
|
'sentinel_timeout' => 2.0,
|
||||||
'parameters' => [
|
'parameters' => [
|
||||||
'password' => env('REDIS_PASSWORD', null),
|
'password' => env('REDIS_PASSWORD', null),
|
||||||
'database' => env('REDIS_CACHE_DB', 1),
|
'database' => env('REDIS_CACHE_DB', 1),
|
||||||
|
@ -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.3.29',
|
'app_version' => '5.3.31',
|
||||||
'app_tag' => '5.3.29',
|
'app_tag' => '5.3.31',
|
||||||
'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', ''),
|
||||||
|
@ -1,21 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
use Illuminate\Database\Migrations\Migration;
|
|
||||||
use Illuminate\Database\Schema\Blueprint;
|
|
||||||
use Illuminate\Support\Facades\Schema;
|
|
||||||
|
|
||||||
class Onboarding extends Migration
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Run the migrations.
|
|
||||||
*
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function up()
|
|
||||||
{
|
|
||||||
Schema::table('accounts', function (Blueprint $table) {
|
|
||||||
$table->boolean('is_onboarding')->default(false);
|
|
||||||
$table->mediumText('onboarding')->nullable();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
37
database/migrations/2021_11_08_131308_onboarding.php
Normal file
37
database/migrations/2021_11_08_131308_onboarding.php
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
class Onboarding extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
|
||||||
|
if (!Schema::hasColumn('accounts', 'is_onboarding'))
|
||||||
|
{
|
||||||
|
|
||||||
|
Schema::table('accounts', function (Blueprint $table) {
|
||||||
|
$table->boolean('is_onboarding')->default(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (!Schema::hasColumn('accounts', 'onboarding'))
|
||||||
|
{
|
||||||
|
|
||||||
|
Schema::table('accounts', function (Blueprint $table) {
|
||||||
|
$table->mediumText('onboarding')->nullable();
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
class AddIsMigrateColumnToAccountsTable extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::table('accounts', function (Blueprint $table) {
|
||||||
|
$table->boolean('is_migrated')->default(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::table('accounts', function (Blueprint $table) {
|
||||||
|
//
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
663
package-lock.json
generated
663
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -7207,31 +7207,6 @@ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|||||||
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||||
USE OR OTHER DEALINGS IN THE SOFTWARE.
|
USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
|
||||||
flutter_share
|
|
||||||
|
|
||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2018 Lucas Britto
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
flutter_slidable
|
flutter_slidable
|
||||||
|
|
||||||
|
8
public/flutter_service_worker.js
vendored
8
public/flutter_service_worker.js
vendored
@ -6,12 +6,12 @@ const RESOURCES = {
|
|||||||
"icons/Icon-512.png": "0f9aff01367f0a0c69773d25ca16ef35",
|
"icons/Icon-512.png": "0f9aff01367f0a0c69773d25ca16ef35",
|
||||||
"icons/Icon-192.png": "bb1cf5f6982006952211c7c8404ffbed",
|
"icons/Icon-192.png": "bb1cf5f6982006952211c7c8404ffbed",
|
||||||
"favicon.png": "dca91c54388f52eded692718d5a98b8b",
|
"favicon.png": "dca91c54388f52eded692718d5a98b8b",
|
||||||
"/": "75a79956958abb5cc1e72568f6f5825f",
|
"/": "6310be19342ca9ed6920572bcc23151f",
|
||||||
"manifest.json": "ef43d90e57aa7682d7e2cfba2f484a40",
|
"manifest.json": "ef43d90e57aa7682d7e2cfba2f484a40",
|
||||||
"favicon.ico": "51636d3a390451561744c42188ccd628",
|
"favicon.ico": "51636d3a390451561744c42188ccd628",
|
||||||
"version.json": "3930722e1581f582eefe59c75ab50c99",
|
"version.json": "9c7b0edc83733da56c726678aacd9fd3",
|
||||||
"assets/fonts/MaterialIcons-Regular.otf": "4e6447691c9509f7acdbf8a931a85ca1",
|
"assets/fonts/MaterialIcons-Regular.otf": "4e6447691c9509f7acdbf8a931a85ca1",
|
||||||
"assets/NOTICES": "9eb7e2eb2888ea5bae5f536720db37cd",
|
"assets/NOTICES": "7610cf8f301427a1104669ea3f4074ac",
|
||||||
"assets/packages/material_design_icons_flutter/lib/fonts/materialdesignicons-webfont.ttf": "174c02fc4609e8fc4389f5d21f16a296",
|
"assets/packages/material_design_icons_flutter/lib/fonts/materialdesignicons-webfont.ttf": "174c02fc4609e8fc4389f5d21f16a296",
|
||||||
"assets/FontManifest.json": "cf3c681641169319e61b61bd0277378f",
|
"assets/FontManifest.json": "cf3c681641169319e61b61bd0277378f",
|
||||||
"assets/assets/images/payment_types/paypal.png": "8e06c094c1871376dfea1da8088c29d1",
|
"assets/assets/images/payment_types/paypal.png": "8e06c094c1871376dfea1da8088c29d1",
|
||||||
@ -34,7 +34,7 @@ const RESOURCES = {
|
|||||||
"assets/assets/images/google_logo.png": "0f118259ce403274f407f5e982e681c3",
|
"assets/assets/images/google_logo.png": "0f118259ce403274f407f5e982e681c3",
|
||||||
"assets/assets/images/logo_light.png": "e5f46d5a78e226e7a9553d4ca6f69219",
|
"assets/assets/images/logo_light.png": "e5f46d5a78e226e7a9553d4ca6f69219",
|
||||||
"assets/AssetManifest.json": "38d9aea341601f3a5c6fa7b5a1216ea5",
|
"assets/AssetManifest.json": "38d9aea341601f3a5c6fa7b5a1216ea5",
|
||||||
"main.dart.js": "6e207d13aff376878b13c6469e07163d"
|
"main.dart.js": "d57b5bf95106fcc642bac2ab5bc52fc3"
|
||||||
};
|
};
|
||||||
|
|
||||||
// The application shell files that are downloaded before a service worker can
|
// The application shell files that are downloaded before a service worker can
|
||||||
|
2
public/js/clients/invoices/payment.js
vendored
2
public/js/clients/invoices/payment.js
vendored
@ -1,2 +1,2 @@
|
|||||||
/*! For license information please see payment.js.LICENSE.txt */
|
/*! For license information please see payment.js.LICENSE.txt */
|
||||||
(()=>{function e(e,t){for(var n=0;n<t.length;n++){var a=t[n];a.enumerable=a.enumerable||!1,a.configurable=!0,"value"in a&&(a.writable=!0),Object.defineProperty(e,a.key,a)}}var t=function(){function t(e,n){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,t),this.shouldDisplayTerms=e,this.shouldDisplaySignature=n,this.termsAccepted=!1}var n,a,i;return n=t,(a=[{key:"handleMethodSelect",value:function(e){var t=this;document.getElementById("company_gateway_id").value=e.dataset.companyGatewayId,document.getElementById("payment_method_id").value=e.dataset.gatewayTypeId,this.shouldDisplaySignature&&!this.shouldDisplayTerms&&(this.displayTerms(),document.getElementById("accept-terms-button").addEventListener("click",(function(){t.termsAccepted=!0,t.submitForm()}))),!this.shouldDisplaySignature&&this.shouldDisplayTerms&&(this.displaySignature(),document.getElementById("signature-next-step").addEventListener("click",(function(){document.querySelector('input[name="signature"').value=t.signaturePad.toDataURL(),t.submitForm()}))),this.shouldDisplaySignature&&this.shouldDisplayTerms&&(this.displaySignature(),document.getElementById("signature-next-step").addEventListener("click",(function(){t.displayTerms(),document.getElementById("accept-terms-button").addEventListener("click",(function(){document.querySelector('input[name="signature"').value=t.signaturePad.toDataURL(),t.termsAccepted=!0,t.submitForm()}))}))),this.shouldDisplaySignature||this.shouldDisplayTerms||this.submitForm()}},{key:"submitForm",value:function(){document.getElementById("payment-form").submit()}},{key:"displayTerms",value:function(){document.getElementById("displayTermsModal").removeAttribute("style")}},{key:"displaySignature",value:function(){document.getElementById("displaySignatureModal").removeAttribute("style");var e=new SignaturePad(document.getElementById("signature-pad"),{penColor:"rgb(0, 0, 0)"});this.signaturePad=e}},{key:"handle",value:function(){var e=this;document.querySelectorAll(".dropdown-gateway-button").forEach((function(t){t.addEventListener("click",(function(){return e.handleMethodSelect(t)}))}))}}])&&e(n.prototype,a),i&&e(n,i),t}(),n=document.querySelector('meta[name="require-invoice-signature"]').content,a=document.querySelector('meta[name="show-invoice-terms"]').content;new t(Boolean(+n),Boolean(+a)).handle()})();
|
(()=>{function e(e,t){for(var n=0;n<t.length;n++){var a=t[n];a.enumerable=a.enumerable||!1,a.configurable=!0,"value"in a&&(a.writable=!0),Object.defineProperty(e,a.key,a)}}var t=function(){function t(e,n){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,t),this.shouldDisplayTerms=e,this.shouldDisplaySignature=n,this.termsAccepted=!1,this.submitting=!1}var n,a,i;return n=t,(a=[{key:"handleMethodSelect",value:function(e){var t=this;document.getElementById("company_gateway_id").value=e.dataset.companyGatewayId,document.getElementById("payment_method_id").value=e.dataset.gatewayTypeId,this.shouldDisplaySignature&&!this.shouldDisplayTerms&&(this.displayTerms(),document.getElementById("accept-terms-button").addEventListener("click",(function(){t.termsAccepted=!0,t.submitForm()}))),!this.shouldDisplaySignature&&this.shouldDisplayTerms&&(this.displaySignature(),document.getElementById("signature-next-step").addEventListener("click",(function(){document.querySelector('input[name="signature"').value=t.signaturePad.toDataURL(),t.submitForm()}))),this.shouldDisplaySignature&&this.shouldDisplayTerms&&(this.displaySignature(),document.getElementById("signature-next-step").addEventListener("click",(function(){t.displayTerms(),document.getElementById("accept-terms-button").addEventListener("click",(function(){document.querySelector('input[name="signature"').value=t.signaturePad.toDataURL(),t.termsAccepted=!0,t.submitForm()}))}))),this.shouldDisplaySignature||this.shouldDisplayTerms||this.submitForm()}},{key:"submitForm",value:function(){document.getElementById("payment-form").submit()}},{key:"displayTerms",value:function(){document.getElementById("displayTermsModal").removeAttribute("style")}},{key:"displaySignature",value:function(){document.getElementById("displaySignatureModal").removeAttribute("style");var e=new SignaturePad(document.getElementById("signature-pad"),{penColor:"rgb(0, 0, 0)"});this.signaturePad=e}},{key:"handle",value:function(){var e=this;document.querySelectorAll(".dropdown-gateway-button").forEach((function(t){t.addEventListener("click",(function(){e.submitting||(e.handleMethodSelect(t),e.submitting=!0)}))}))}}])&&e(n.prototype,a),i&&e(n,i),t}(),n=document.querySelector('meta[name="require-invoice-signature"]').content,a=document.querySelector('meta[name="show-invoice-terms"]').content;new t(Boolean(+n),Boolean(+a)).handle()})();
|
@ -1,2 +1,2 @@
|
|||||||
/*! For license information please see wepay-bank-account.js.LICENSE.txt */
|
/*! For license information please see wepay-bank-account.js.LICENSE.txt */
|
||||||
(()=>{function e(e,n){for(var t=0;t<n.length;t++){var o=n[t];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(e,o.key,o)}}var n=function(){function n(){!function(e,n){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}(this,n)}var t,o,r;return t=n,(o=[{key:"initializeWePay",value:function(){var e,n=null===(e=document.querySelector('meta[name="wepay-environment"]'))||void 0===e?void 0:e.content;return WePay.set_endpoint("staging"===n?"stage":"production"),this}},{key:"showBankPopup",value:function(){var e,n;WePay.bank_account.create({client_id:null===(e=document.querySelector("meta[name=wepay-client-id]"))||void 0===e?void 0:e.content,email:null===(n=document.querySelector("meta[name=contact-email]"))||void 0===n?void 0:n.content},(function(e){e.error?(errors.textContent="",errors.textContent=e.error_description,errors.hidden=!1):(document.querySelector('input[name="bank_account_id"]').value=e.bank_account_id,document.getElementById("server_response").submit())}),(function(e){e.error&&(errors.textContent="",errors.textContent=e.error_description,errors.hidden=!1)}))}},{key:"handle",value:function(){this.initializeWePay().showBankPopup()}}])&&e(t.prototype,o),r&&e(t,r),n}();document.addEventListener("DOMContentLoaded",(function(){(new n).handle()}))})();
|
(()=>{function e(e,n){for(var t=0;t<n.length;t++){var o=n[t];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(e,o.key,o)}}var n=function(){function n(){!function(e,n){if(!(e instanceof n))throw new TypeError("Cannot call a class as a function")}(this,n)}var t,o,r;return t=n,(o=[{key:"initializeWePay",value:function(){var e,n=null===(e=document.querySelector('meta[name="wepay-environment"]'))||void 0===e?void 0:e.content;return WePay.set_endpoint("staging"===n?"stage":"production"),this}},{key:"showBankPopup",value:function(){var e,n;WePay.bank_account.create({client_id:null===(e=document.querySelector("meta[name=wepay-client-id]"))||void 0===e?void 0:e.content,email:null===(n=document.querySelector("meta[name=contact-email]"))||void 0===n?void 0:n.content,options:{avoidMicrodeposits:!0}},(function(e){e.error?(errors.textContent="",errors.textContent=e.error_description,errors.hidden=!1):(document.querySelector('input[name="bank_account_id"]').value=e.bank_account_id,document.getElementById("server_response").submit())}),(function(e){e.error&&(errors.textContent="",errors.textContent=e.error_description,errors.hidden=!1)}))}},{key:"handle",value:function(){this.initializeWePay().showBankPopup()}}])&&e(t.prototype,o),r&&e(t,r),n}();document.addEventListener("DOMContentLoaded",(function(){(new n).handle()}))})();
|
2
public/js/clients/payments/razorpay-aio.js
vendored
2
public/js/clients/payments/razorpay-aio.js
vendored
@ -1,2 +1,2 @@
|
|||||||
/*! For license information please see razorpay-aio.js.LICENSE.txt */
|
/*! For license information please see razorpay-aio.js.LICENSE.txt */
|
||||||
(()=>{var e,n=JSON.parse(null===(e=document.querySelector("meta[name=razorpay-options]"))||void 0===e?void 0:e.content);n.handler=function(e){document.getElementById("razorpay_payment_id").value=e.razorpay_payment_id,document.getElementById("razorpay_signature").value=e.razorpay_signature,document.getElementById("server-response").submit()};var t=new Razorpay(n);document.getElementById("pay-now").onclick=function(e){e.target.parentElement.disabled=!0,t.open()}})();
|
(()=>{var e,n=JSON.parse(null===(e=document.querySelector("meta[name=razorpay-options]"))||void 0===e?void 0:e.content);n.handler=function(e){document.getElementById("razorpay_payment_id").value=e.razorpay_payment_id,document.getElementById("razorpay_signature").value=e.razorpay_signature,document.getElementById("server-response").submit()},n.modal={ondismiss:function(){o.disabled=!1}};var a=new Razorpay(n),o=document.getElementById("pay-now");o.onclick=function(e){o.disabled=!0,a.open()}})();
|
245394
public/main.dart.js
vendored
245394
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
250386
public/main.foss.dart.js
vendored
250386
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
243568
public/main.html.dart.js
vendored
243568
public/main.html.dart.js
vendored
File diff suppressed because one or more lines are too long
229747
public/main.next.dart.js
vendored
229747
public/main.next.dart.js
vendored
File diff suppressed because one or more lines are too long
13709
public/main.profile.dart.js
vendored
13709
public/main.profile.dart.js
vendored
File diff suppressed because one or more lines are too long
@ -4,7 +4,7 @@
|
|||||||
"/js/clients/payments/authorize-credit-card-payment.js": "/js/clients/payments/authorize-credit-card-payment.js?id=cfe5de1cf87a0b01568d",
|
"/js/clients/payments/authorize-credit-card-payment.js": "/js/clients/payments/authorize-credit-card-payment.js?id=cfe5de1cf87a0b01568d",
|
||||||
"/js/clients/payments/stripe-ach.js": "/js/clients/payments/stripe-ach.js?id=5e74bc0d346beeb57ee9",
|
"/js/clients/payments/stripe-ach.js": "/js/clients/payments/stripe-ach.js?id=5e74bc0d346beeb57ee9",
|
||||||
"/js/clients/invoices/action-selectors.js": "/js/clients/invoices/action-selectors.js?id=6b79265cbb8c963eef19",
|
"/js/clients/invoices/action-selectors.js": "/js/clients/invoices/action-selectors.js?id=6b79265cbb8c963eef19",
|
||||||
"/js/clients/invoices/payment.js": "/js/clients/invoices/payment.js?id=5b79f72432f92a85fefa",
|
"/js/clients/invoices/payment.js": "/js/clients/invoices/payment.js?id=d9132fae12153a6943a6",
|
||||||
"/js/clients/payments/stripe-sofort.js": "/js/clients/payments/stripe-sofort.js?id=926c7b9d1ee48bbf786b",
|
"/js/clients/payments/stripe-sofort.js": "/js/clients/payments/stripe-sofort.js?id=926c7b9d1ee48bbf786b",
|
||||||
"/js/clients/payments/stripe-alipay.js": "/js/clients/payments/stripe-alipay.js?id=1e159400d6a5ca4662c1",
|
"/js/clients/payments/stripe-alipay.js": "/js/clients/payments/stripe-alipay.js?id=1e159400d6a5ca4662c1",
|
||||||
"/js/clients/payments/checkout-credit-card.js": "/js/clients/payments/checkout-credit-card.js?id=0b47ce36fe20191adb33",
|
"/js/clients/payments/checkout-credit-card.js": "/js/clients/payments/checkout-credit-card.js?id=0b47ce36fe20191adb33",
|
||||||
@ -19,14 +19,14 @@
|
|||||||
"/js/clients/payments/braintree-credit-card.js": "/js/clients/payments/braintree-credit-card.js?id=a334dd9257dd510a1feb",
|
"/js/clients/payments/braintree-credit-card.js": "/js/clients/payments/braintree-credit-card.js?id=a334dd9257dd510a1feb",
|
||||||
"/js/clients/payments/braintree-paypal.js": "/js/clients/payments/braintree-paypal.js?id=37950e8a39281d2f596a",
|
"/js/clients/payments/braintree-paypal.js": "/js/clients/payments/braintree-paypal.js?id=37950e8a39281d2f596a",
|
||||||
"/js/clients/payments/wepay-credit-card.js": "/js/clients/payments/wepay-credit-card.js?id=ba4d5b7175117ababdb2",
|
"/js/clients/payments/wepay-credit-card.js": "/js/clients/payments/wepay-credit-card.js?id=ba4d5b7175117ababdb2",
|
||||||
"/js/clients/payment_methods/wepay-bank-account.js": "/js/clients/payment_methods/wepay-bank-account.js?id=b1704cb9bd7975605310",
|
"/js/clients/payment_methods/wepay-bank-account.js": "/js/clients/payment_methods/wepay-bank-account.js?id=8328c6c32a65cd3e8a3d",
|
||||||
"/js/clients/payments/paytrace-credit-card.js": "/js/clients/payments/paytrace-credit-card.js?id=59d9913b746fe5a540ff",
|
"/js/clients/payments/paytrace-credit-card.js": "/js/clients/payments/paytrace-credit-card.js?id=59d9913b746fe5a540ff",
|
||||||
"/js/clients/payments/mollie-credit-card.js": "/js/clients/payments/mollie-credit-card.js?id=c2cf632fb3cc91b4ff7c",
|
"/js/clients/payments/mollie-credit-card.js": "/js/clients/payments/mollie-credit-card.js?id=c2cf632fb3cc91b4ff7c",
|
||||||
"/js/clients/payments/eway-credit-card.js": "/js/clients/payments/eway-credit-card.js?id=ff17e039dd15d505448f",
|
"/js/clients/payments/eway-credit-card.js": "/js/clients/payments/eway-credit-card.js?id=ff17e039dd15d505448f",
|
||||||
"/js/clients/payment_methods/braintree-ach.js": "/js/clients/payment_methods/braintree-ach.js?id=656ad159838b726969f5",
|
"/js/clients/payment_methods/braintree-ach.js": "/js/clients/payment_methods/braintree-ach.js?id=656ad159838b726969f5",
|
||||||
"/js/clients/payments/square-credit-card.js": "/js/clients/payments/square-credit-card.js?id=8f05ce6bd2d6cae7e5f2",
|
"/js/clients/payments/square-credit-card.js": "/js/clients/payments/square-credit-card.js?id=8f05ce6bd2d6cae7e5f2",
|
||||||
"/js/clients/statements/view.js": "/js/clients/statements/view.js?id=ea3db0c04b4372f76735",
|
"/js/clients/statements/view.js": "/js/clients/statements/view.js?id=ea3db0c04b4372f76735",
|
||||||
"/js/clients/payments/razorpay-aio.js": "/js/clients/payments/razorpay-aio.js?id=1dae47a0b783814ce895",
|
"/js/clients/payments/razorpay-aio.js": "/js/clients/payments/razorpay-aio.js?id=c36ab5621413ef1de7c8",
|
||||||
"/js/clients/payments/stripe-sepa.js": "/js/clients/payments/stripe-sepa.js?id=cbd7bb4c483ca75333f4",
|
"/js/clients/payments/stripe-sepa.js": "/js/clients/payments/stripe-sepa.js?id=cbd7bb4c483ca75333f4",
|
||||||
"/js/clients/payment_methods/authorize-checkout-card.js": "/js/clients/payment_methods/authorize-checkout-card.js?id=61becda97682c7909f29",
|
"/js/clients/payment_methods/authorize-checkout-card.js": "/js/clients/payment_methods/authorize-checkout-card.js?id=61becda97682c7909f29",
|
||||||
"/js/clients/payments/stripe-giropay.js": "/js/clients/payments/stripe-giropay.js?id=cdf300d72a1564d19b72",
|
"/js/clients/payments/stripe-giropay.js": "/js/clients/payments/stripe-giropay.js?id=cdf300d72a1564d19b72",
|
||||||
|
@ -1 +1 @@
|
|||||||
{"app_name":"invoiceninja_flutter","version":"5.0.63","build_number":"63"}
|
{"app_name":"invoiceninja_flutter","version":"5.0.67","build_number":"67"}
|
11
resources/js/clients/invoices/payment.js
vendored
11
resources/js/clients/invoices/payment.js
vendored
@ -13,6 +13,7 @@ class Payment {
|
|||||||
this.shouldDisplayTerms = displayTerms;
|
this.shouldDisplayTerms = displayTerms;
|
||||||
this.shouldDisplaySignature = displaySignature;
|
this.shouldDisplaySignature = displaySignature;
|
||||||
this.termsAccepted = false;
|
this.termsAccepted = false;
|
||||||
|
this.submitting = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
handleMethodSelect(element) {
|
handleMethodSelect(element) {
|
||||||
@ -95,9 +96,13 @@ class Payment {
|
|||||||
document
|
document
|
||||||
.querySelectorAll(".dropdown-gateway-button")
|
.querySelectorAll(".dropdown-gateway-button")
|
||||||
.forEach(element => {
|
.forEach(element => {
|
||||||
element.addEventListener("click", () =>
|
element.addEventListener("click", () => {
|
||||||
this.handleMethodSelect(element)
|
if (!this.submitting) {
|
||||||
);
|
this.handleMethodSelect(element)
|
||||||
|
|
||||||
|
this.submitting = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,10 @@ class WePayBank {
|
|||||||
showBankPopup() {
|
showBankPopup() {
|
||||||
WePay.bank_account.create({
|
WePay.bank_account.create({
|
||||||
client_id: document.querySelector('meta[name=wepay-client-id]')?.content,
|
client_id: document.querySelector('meta[name=wepay-client-id]')?.content,
|
||||||
email: document.querySelector('meta[name=contact-email]')?.content
|
email: document.querySelector('meta[name=contact-email]')?.content,
|
||||||
|
options: {
|
||||||
|
avoidMicrodeposits:true
|
||||||
|
}
|
||||||
}, function (data) {
|
}, function (data) {
|
||||||
if (data.error) {
|
if (data.error) {
|
||||||
errors.textContent = '';
|
errors.textContent = '';
|
||||||
|
15
resources/js/clients/payments/razorpay-aio.js
vendored
15
resources/js/clients/payments/razorpay-aio.js
vendored
@ -12,7 +12,7 @@ let options = JSON.parse(
|
|||||||
document.querySelector('meta[name=razorpay-options]')?.content
|
document.querySelector('meta[name=razorpay-options]')?.content
|
||||||
);
|
);
|
||||||
|
|
||||||
options.handler = function(response) {
|
options.handler = function (response) {
|
||||||
document.getElementById('razorpay_payment_id').value =
|
document.getElementById('razorpay_payment_id').value =
|
||||||
response.razorpay_payment_id;
|
response.razorpay_payment_id;
|
||||||
document.getElementById('razorpay_signature').value =
|
document.getElementById('razorpay_signature').value =
|
||||||
@ -20,10 +20,17 @@ options.handler = function(response) {
|
|||||||
document.getElementById('server-response').submit();
|
document.getElementById('server-response').submit();
|
||||||
};
|
};
|
||||||
|
|
||||||
let razorpay = new Razorpay(options);
|
options.modal = {
|
||||||
|
ondismiss: function () {
|
||||||
|
payNowButton.disabled = false;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
document.getElementById('pay-now').onclick = function(event) {
|
let razorpay = new Razorpay(options);
|
||||||
event.target.parentElement.disabled = true;
|
let payNowButton = document.getElementById('pay-now');
|
||||||
|
|
||||||
|
payNowButton.onclick = function (event) {
|
||||||
|
payNowButton.disabled = true;
|
||||||
|
|
||||||
razorpay.open();
|
razorpay.open();
|
||||||
};
|
};
|
||||||
|
@ -367,6 +367,9 @@
|
|||||||
</tfoot>
|
</tfoot>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
$entity_images
|
||||||
|
|
||||||
<div id="footer">
|
<div id="footer">
|
||||||
<div>
|
<div>
|
||||||
<p data-ref="total_table-footer">$entity_footer</p>
|
<p data-ref="total_table-footer">$entity_footer</p>
|
||||||
|
@ -294,7 +294,7 @@
|
|||||||
/** To find out selectors on your own: https://invoiceninja.github.io/docs/custom-fields/#snippets **/
|
/** To find out selectors on your own: https://invoiceninja.github.io/docs/custom-fields/#snippets **/
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<table>
|
<table style="min-width: 100%">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
@ -347,6 +347,8 @@
|
|||||||
|
|
||||||
<div class="repeating-header" id="header"></div>
|
<div class="repeating-header" id="header"></div>
|
||||||
|
|
||||||
|
$entity_images
|
||||||
|
|
||||||
<div class="repeating-footer" id="footer">
|
<div class="repeating-footer" id="footer">
|
||||||
<p data-ref="total_table-footer">$entity_footer</p>
|
<p data-ref="total_table-footer">$entity_footer</p>
|
||||||
</div>
|
</div>
|
||||||
|
@ -258,7 +258,7 @@
|
|||||||
/** To find out selectors on your own: https://invoiceninja.github.io/docs/custom-fields/#snippets **/
|
/** To find out selectors on your own: https://invoiceninja.github.io/docs/custom-fields/#snippets **/
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<table>
|
<table style="min-width: 100%">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
@ -309,6 +309,8 @@
|
|||||||
|
|
||||||
<div class="repeating-header" id="header"></div>
|
<div class="repeating-header" id="header"></div>
|
||||||
|
|
||||||
|
$entity_images
|
||||||
|
|
||||||
<div class="repeating-footer" id="footer">
|
<div class="repeating-footer" id="footer">
|
||||||
<p data-ref="total_table-footer">$entity_footer</p>
|
<p data-ref="total_table-footer">$entity_footer</p>
|
||||||
</div>
|
</div>
|
||||||
|
@ -247,7 +247,7 @@
|
|||||||
/** To find out selectors on your own: https://invoiceninja.github.io/docs/custom-fields/#snippets **/
|
/** To find out selectors on your own: https://invoiceninja.github.io/docs/custom-fields/#snippets **/
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<table>
|
<table style="min-width: 100%">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
@ -307,6 +307,8 @@
|
|||||||
<p data-ref="total_table-footer">$entity_footer</p>
|
<p data-ref="total_table-footer">$entity_footer</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
$entity_images
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
// Clear up space a bit, if [product-table, tasks-table, delivery-note-table] isn't present.
|
// Clear up space a bit, if [product-table, tasks-table, delivery-note-table] isn't present.
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
@ -317,6 +317,8 @@
|
|||||||
<p data-ref="total_table-footer">$entity_footer</p>
|
<p data-ref="total_table-footer">$entity_footer</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
$entity_images
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
// Clear up space a bit, if [product-table, tasks-table, delivery-note-table] isn't present.
|
// Clear up space a bit, if [product-table, tasks-table, delivery-note-table] isn't present.
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
@ -272,7 +272,7 @@
|
|||||||
/** To find out selectors on your own: https://invoiceninja.github.io/docs/custom-fields/#snippets **/
|
/** To find out selectors on your own: https://invoiceninja.github.io/docs/custom-fields/#snippets **/
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<table>
|
<table style="min-width: 100%">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
@ -358,6 +358,8 @@
|
|||||||
<p data-ref="total_table-footer">$entity_footer</p>
|
<p data-ref="total_table-footer">$entity_footer</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
$entity_images
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
// Clear up space a bit, if [product-table, tasks-table, delivery-note-table] isn't present.
|
// Clear up space a bit, if [product-table, tasks-table, delivery-note-table] isn't present.
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
@ -344,6 +344,8 @@
|
|||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
$entity_images
|
||||||
|
|
||||||
<div id="footer">
|
<div id="footer">
|
||||||
<div class="footer-content">
|
<div class="footer-content">
|
||||||
<div>
|
<div>
|
||||||
|
@ -238,7 +238,7 @@
|
|||||||
/** To find out selectors on your own: https://invoiceninja.github.io/docs/custom-fields/#snippets **/
|
/** To find out selectors on your own: https://invoiceninja.github.io/docs/custom-fields/#snippets **/
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<table>
|
<table style="min-width: 100%">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
@ -292,6 +292,8 @@
|
|||||||
<p data-ref="total_table-footer">$entity_footer</p>
|
<p data-ref="total_table-footer">$entity_footer</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
$entity_images
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
// Clear up space a bit, if [product-table, tasks-table, delivery-note-table] isn't present.
|
// Clear up space a bit, if [product-table, tasks-table, delivery-note-table] isn't present.
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
@ -375,7 +375,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="repeating-footer" id="footer">
|
$entity_images
|
||||||
|
|
||||||
|
<div class="repeating-footer" id="footer">
|
||||||
<p data-ref="total_table-footer">$entity_footer</p>
|
<p data-ref="total_table-footer">$entity_footer</p>
|
||||||
|
|
||||||
<div id="footer-colors">
|
<div id="footer-colors">
|
||||||
|
@ -357,6 +357,8 @@
|
|||||||
<p data-ref="total_table-footer">$entity_footer</p>
|
<p data-ref="total_table-footer">$entity_footer</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
$entity_images
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
// Clear up space a bit, if [product-table, tasks-table, delivery-note-table] isn't present.
|
// Clear up space a bit, if [product-table, tasks-table, delivery-note-table] isn't present.
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
@ -1,23 +1,42 @@
|
|||||||
@if($entity->documents->count() > 0)
|
@if ($entity->documents->count() > 0 || $entity->company->documents->count() > 0)
|
||||||
<div class="bg-white shadow sm:rounded-lg my-4">
|
<div class="bg-white shadow sm:rounded-lg my-4">
|
||||||
<div class="px-4 py-5 sm:p-6">
|
<div class="px-4 py-5 sm:p-6">
|
||||||
<div class="sm:flex sm:items-start sm:justify-between">
|
<div class="sm:flex sm:items-start sm:justify-between">
|
||||||
<div>
|
<div>
|
||||||
<p class="text-lg leading-6 font-medium text-gray-900">{{ ctrans('texts.attachments') }}:</p>
|
<p class="text-lg leading-6 font-medium text-gray-900">{{ ctrans('texts.attachments') }}:</p>
|
||||||
@foreach($entity->documents as $document)
|
@foreach ($entity->documents as $document)
|
||||||
<div class="inline-flex items-center space-x-1">
|
<div class="inline-flex items-center space-x-1">
|
||||||
<a href="{{ route('client.documents.show', $document->hashed_id) }}" target="_blank"
|
<a href="{{ route('client.documents.show', $document->hashed_id) }}" target="_blank"
|
||||||
class="block text-sm button-link text-primary">{{ Illuminate\Support\Str::limit($document->name, 40) }}</a>
|
class="block text-sm button-link text-primary">{{ Illuminate\Support\Str::limit($document->name, 40) }}</a>
|
||||||
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
|
||||||
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
|
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
|
||||||
stroke-linejoin="round" class="text-primary h-6 w-4">
|
class="text-primary h-6 w-4">
|
||||||
<path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path>
|
<path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path>
|
||||||
<polyline points="15 3 21 3 21 9"></polyline>
|
<polyline points="15 3 21 3 21 9"></polyline>
|
||||||
<line x1="10" y1="14" x2="21" y2="3"></line>
|
<line x1="10" y1="14" x2="21" y2="3"></line>
|
||||||
</svg>
|
</svg>
|
||||||
|
|
||||||
@if(!$loop->last)
|
@if (!$loop->last)
|
||||||
|
<span>—</span>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
@endforeach
|
||||||
|
|
||||||
|
@foreach ($entity->company->documents as $document)
|
||||||
|
<div class="inline-flex items-center space-x-1">
|
||||||
|
<a href="{{ route('client.documents.show', $document->hashed_id) }}" target="_blank"
|
||||||
|
class="block text-sm button-link text-primary">{{ Illuminate\Support\Str::limit($document->name, 40) }}</a>
|
||||||
|
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
|
||||||
|
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
|
||||||
|
class="text-primary h-6 w-4">
|
||||||
|
<path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path>
|
||||||
|
<polyline points="15 3 21 3 21 9"></polyline>
|
||||||
|
<line x1="10" y1="14" x2="21" y2="3"></line>
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
@if (!$loop->last)
|
||||||
<span>—</span>
|
<span>—</span>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
@ -25,8 +25,8 @@
|
|||||||
@foreach($multiple_contacts as $contact)
|
@foreach($multiple_contacts as $contact)
|
||||||
<a data-turbolinks="false"
|
<a data-turbolinks="false"
|
||||||
href="{{ route('client.switch_company', $contact->hashed_id) }}"
|
href="{{ route('client.switch_company', $contact->hashed_id) }}"
|
||||||
class="block px-4 py-2 text-sm leading-5 text-gray-700 hover:bg-gray-100 hover:text-gray-900 focus:outline-none focus:bg-gray-100 focus:text-gray-900">{{ $contact->company->present()->name() }}
|
class="block px-4 py-2 text-sm leading-5 text-gray-700 hover:bg-gray-100 hover:text-gray-900 focus:outline-none focus:bg-gray-100 focus:text-gray-900">{{ $contact->client->present()->name()}} - {{ $contact->company->present()->name() }}
|
||||||
- {{ $contact->client->present()->name()}}</a>
|
</a>
|
||||||
@endforeach
|
@endforeach
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -64,7 +64,7 @@
|
|||||||
<option>15</option>
|
<option>15</option>
|
||||||
<option>20</option>
|
<option>20</option>
|
||||||
</select>
|
</select>
|
||||||
<button x-on:click="document.getElementById('multiple-downloads').submit()" class="button button-primary bg-primary py-2 ml-2">
|
<button onclick="document.getElementById('multiple-downloads').submit(); setTimeout(() => this.disabled = true, 0); setTimeout(() => this.disabled = false, 5000);" class="button button-primary bg-primary py-2 ml-2">
|
||||||
<span class="hidden md:block">
|
<span class="hidden md:block">
|
||||||
{{ ctrans('texts.download_selected') }}
|
{{ ctrans('texts.download_selected') }}
|
||||||
</span>
|
</span>
|
||||||
|
@ -99,7 +99,7 @@
|
|||||||
@csrf
|
@csrf
|
||||||
<input type="hidden" name="invoices[]" value="{{ $invoice->hashed_id }}">
|
<input type="hidden" name="invoices[]" value="{{ $invoice->hashed_id }}">
|
||||||
<input type="hidden" name="action" value="payment">
|
<input type="hidden" name="action" value="payment">
|
||||||
<button class="px-2 py-1 mr-3 text-xs uppercase button button-primary bg-primary" dusk="pay-now">
|
<button onclick="setTimeout(() => this.disabled = true, 0); return true;" class="px-2 py-1 mr-3 text-xs uppercase button button-primary bg-primary" dusk="pay-now">
|
||||||
{{ ctrans('texts.pay_now') }}
|
{{ ctrans('texts.pay_now') }}
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
|
@ -15,10 +15,10 @@
|
|||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<form action="{{ route('client.invoices.bulk') }}" method="post" id="bulkActions">
|
<form action="{{ route('client.invoices.bulk') }}" method="post" id="bulkActions">
|
||||||
@csrf
|
@csrf
|
||||||
<button type="submit" class="button button-primary bg-primary" name="action" value="download">{{ ctrans('texts.download') }}</button>
|
<button type="submit" onclick="setTimeout(() => this.disabled = true, 0); setTimeout(() => this.disabled = false, 5000); return true;" class="button button-primary bg-primary" name="action" value="download">{{ ctrans('texts.download') }}</button>
|
||||||
|
|
||||||
@if(!empty(auth()->user()->client->service()->getPaymentMethods(0)))
|
@if(!empty(auth()->user()->client->service()->getPaymentMethods(0)))
|
||||||
<button type="submit" class="button button-primary bg-primary" name="action" value="payment">{{ ctrans('texts.pay_now') }}</button>
|
<button onclick="setTimeout(() => this.disabled = true, 0); return true;" type="submit" class="button button-primary bg-primary" name="action" value="payment">{{ ctrans('texts.pay_now') }}</button>
|
||||||
@endif
|
@endif
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
@ -36,7 +36,7 @@
|
|||||||
<form action="{{ route('client.payment_methods.destroy', [$payment_method->hashed_id, 'method' => $payment_method->gateway_type->id]) }}" method="post">
|
<form action="{{ route('client.payment_methods.destroy', [$payment_method->hashed_id, 'method' => $payment_method->gateway_type->id]) }}" method="post">
|
||||||
@csrf
|
@csrf
|
||||||
@method('DELETE')
|
@method('DELETE')
|
||||||
<button type="submit" class="button button-danger button-block" dusk="confirm-payment-removal">
|
<button type="submit" onclick="setTimeout(() => this.disabled = true, 0); return true;" class="button button-danger button-block" dusk="confirm-payment-removal">
|
||||||
{{ ctrans('texts.remove') }}
|
{{ ctrans('texts.remove') }}
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
<div class="relative inline-block text-left">
|
<div class="relative inline-block text-left">
|
||||||
<div>
|
<div>
|
||||||
<div class="rounded-md shadow-sm">
|
<div class="rounded-md shadow-sm">
|
||||||
<button type="button" id="approve-button"
|
<button type="button" id="approve-button" onclick="setTimeout(() => this.disabled = true, 0); return true;"
|
||||||
class="inline-flex justify-center w-full rounded-md border border-gray-300 px-4 py-2 bg-white text-sm leading-5 font-medium text-gray-700 hover:text-gray-500 focus:outline-none focus:border-blue-300 focus:ring-blue active:bg-gray-50 active:text-gray-800 transition ease-in-out duration-150">
|
class="inline-flex justify-center w-full rounded-md border border-gray-300 px-4 py-2 bg-white text-sm leading-5 font-medium text-gray-700 hover:text-gray-500 focus:outline-none focus:border-blue-300 focus:ring-blue active:bg-gray-50 active:text-gray-800 transition ease-in-out duration-150">
|
||||||
{{ ctrans('texts.approve') }}
|
{{ ctrans('texts.approve') }}
|
||||||
</button>
|
</button>
|
||||||
|
@ -1,27 +1,30 @@
|
|||||||
<form action="{{ route('client.quotes.bulk') }}" method="post" id="approve-form" />
|
<form action="{{ route('client.quotes.bulk') }}" method="post" id="approve-form" />
|
||||||
@csrf
|
@csrf
|
||||||
<input type="hidden" name="action" value="approve">
|
|
||||||
<input type="hidden" name="process" value="true">
|
|
||||||
<input type="hidden" name="quotes[]" value="{{ $quote->hashed_id }}">
|
|
||||||
<input type="hidden" name="signature">
|
|
||||||
|
|
||||||
<div class="bg-white shadow sm:rounded-lg">
|
<input type="hidden" name="action" value="approve">
|
||||||
<div class="px-4 py-5 sm:p-6">
|
<input type="hidden" name="process" value="true">
|
||||||
<div class="sm:flex sm:items-start sm:justify-between">
|
<input type="hidden" name="quotes[]" value="{{ $quote->hashed_id }}">
|
||||||
<h3 class="text-lg leading-6 font-medium text-gray-900">
|
<input type="hidden" name="signature">
|
||||||
{{ ctrans('texts.approve') }}
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
<div class="mt-5 sm:mt-0 sm:ml-6 sm:flex-shrink-0 sm:flex sm:items-center">
|
<div class="bg-white shadow sm:rounded-lg">
|
||||||
@yield('quote-not-approved-right-side')
|
<div class="px-4 py-5 sm:p-6">
|
||||||
|
<div class="sm:flex sm:items-start sm:justify-between">
|
||||||
|
<h3 class="text-lg leading-6 font-medium text-gray-900">
|
||||||
|
{{ ctrans('texts.approve') }}
|
||||||
|
</h3>
|
||||||
|
|
||||||
<div class="inline-flex rounded-md shadow-sm">
|
<div class="mt-5 sm:mt-0 sm:ml-6 sm:flex-shrink-0 sm:flex sm:items-center">
|
||||||
<input type="hidden" name="action" value="payment">
|
@yield('quote-not-approved-right-side')
|
||||||
<button type="button" class="button button-primary bg-primary" id="approve-button">{{ ctrans('texts.approve') }}</button>
|
|
||||||
</div>
|
<div class="inline-flex rounded-md shadow-sm">
|
||||||
|
<input type="hidden" name="action" value="payment">
|
||||||
|
<button onclick="setTimeout(() => this.disabled = true, 0); return true;" type="button"
|
||||||
|
class="button button-primary bg-primary"
|
||||||
|
id="approve-button">{{ ctrans('texts.approve') }}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</div>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
@ -2,9 +2,9 @@
|
|||||||
@section('meta_title', ctrans('texts.quotes'))
|
@section('meta_title', ctrans('texts.quotes'))
|
||||||
|
|
||||||
@section('header')
|
@section('header')
|
||||||
@if($errors->any())
|
@if ($errors->any())
|
||||||
<div class="alert alert-failure mb-4">
|
<div class="alert alert-failure mb-4">
|
||||||
@foreach($errors->all() as $error)
|
@foreach ($errors->all() as $error)
|
||||||
<p>{{ $error }}</p>
|
<p>{{ $error }}</p>
|
||||||
@endforeach
|
@endforeach
|
||||||
</div>
|
</div>
|
||||||
@ -15,13 +15,17 @@
|
|||||||
<div class="flex justify-between items-center">
|
<div class="flex justify-between items-center">
|
||||||
<form action="{{ route('client.quotes.bulk') }}" method="post" id="bulkActions">
|
<form action="{{ route('client.quotes.bulk') }}" method="post" id="bulkActions">
|
||||||
@csrf
|
@csrf
|
||||||
<button type="submit" class="button button-primary bg-primary" name="action"
|
<button type="submit"
|
||||||
value="download">{{ ctrans('texts.download') }}</button>
|
onclick="setTimeout(() => this.disabled = true, 0); setTimeout(() => this.disabled = false, 5000); return true;"
|
||||||
<button type="submit" class="button button-primary bg-primary" name="action"
|
class="button button-primary bg-primary" name="action"
|
||||||
value="approve">{{ ctrans('texts.approve') }}</button>
|
value="download">{{ ctrans('texts.download') }}</button>
|
||||||
|
<button type="submit" onclick="setTimeout(() => this.disabled = true, 0); return true;"
|
||||||
|
class="button button-primary bg-primary" name="action"
|
||||||
|
value="approve">{{ ctrans('texts.approve') }}</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-col mt-4">
|
<div class="flex flex-col mt-4">
|
||||||
@livewire('quotes-table', ['company' => $company])
|
@livewire('quotes-table', ['company' => $company])
|
||||||
</div>
|
</div>
|
||||||
@endsection
|
@endsection
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
<span class="ml-2">{{ ctrans('texts.show_aging') }}</span>
|
<span class="ml-2">{{ ctrans('texts.show_aging') }}</span>
|
||||||
</label> <!-- End show aging checkbox -->
|
</label> <!-- End show aging checkbox -->
|
||||||
</div>
|
</div>
|
||||||
<button id="pdf-download" class="button button-primary bg-primary mt-4 md:mt-0">{{ ctrans('texts.download') }}</button>
|
<button onclick="setTimeout(() => this.disabled = true, 0); setTimeout(() => this.disabled = false, 5000); return true;" id="pdf-download" class="button button-primary bg-primary mt-4 md:mt-0">{{ ctrans('texts.download') }}</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@include('portal.ninja2020.components.pdf-viewer', ['url' => route('client.statement.raw')])
|
@include('portal.ninja2020.components.pdf-viewer', ['url' => route('client.statement.raw')])
|
||||||
|
@ -23,7 +23,7 @@ Route::get('tmp_pdf/{hash}', 'ClientPortal\TempRouteController@index')->name('tm
|
|||||||
|
|
||||||
Route::get('client/key_login/{contact_key}', 'ClientPortal\ContactHashLoginController@login')->name('client.contact_login')->middleware(['domain_db','contact_key_login']);
|
Route::get('client/key_login/{contact_key}', 'ClientPortal\ContactHashLoginController@login')->name('client.contact_login')->middleware(['domain_db','contact_key_login']);
|
||||||
Route::get('client/magic_link/{magic_link}', 'ClientPortal\ContactHashLoginController@magicLink')->name('client.contact_magic_link')->middleware(['domain_db','contact_key_login']);
|
Route::get('client/magic_link/{magic_link}', 'ClientPortal\ContactHashLoginController@magicLink')->name('client.contact_magic_link')->middleware(['domain_db','contact_key_login']);
|
||||||
Route::get('documents/{document_hash}', 'ClientPortal\DocumentController@publicDownload')->name('documents.public_download')->middleware(['document_db']);
|
Route::get('documents/{document_hash}', 'ClientPortal\DocumentController@publicDownload')->name('documents.public_download')->middleware(['domain_db']);
|
||||||
Route::get('error', 'ClientPortal\ContactHashLoginController@errorPage')->name('client.error');
|
Route::get('error', 'ClientPortal\ContactHashLoginController@errorPage')->name('client.error');
|
||||||
Route::get('client/payment/{contact_key}/{payment_id}', 'ClientPortal\InvitationController@paymentRouter')->middleware(['domain_db','contact_key_login']);
|
Route::get('client/payment/{contact_key}/{payment_id}', 'ClientPortal\InvitationController@paymentRouter')->middleware(['domain_db','contact_key_login']);
|
||||||
Route::get('client/ninja/{contact_key}/{company_key}', 'ClientPortal\NinjaPlanController@index')->name('client.ninja_contact_login')->middleware(['domain_db']);
|
Route::get('client/ninja/{contact_key}/{company_key}', 'ClientPortal\NinjaPlanController@index')->name('client.ninja_contact_login')->middleware(['domain_db']);
|
||||||
|
@ -297,6 +297,8 @@ class ClientTest extends TestCase
|
|||||||
$company_token->account_id = $account->id;
|
$company_token->account_id = $account->id;
|
||||||
$company_token->name = $user->first_name.' '.$user->last_name;
|
$company_token->name = $user->first_name.' '.$user->last_name;
|
||||||
$company_token->token = Str::random(64);
|
$company_token->token = Str::random(64);
|
||||||
|
$company_token->is_system = true;
|
||||||
|
|
||||||
$company_token->save();
|
$company_token->save();
|
||||||
|
|
||||||
$this->token = $company_token->token;
|
$this->token = $company_token->token;
|
||||||
@ -353,6 +355,7 @@ class ClientTest extends TestCase
|
|||||||
$company_token->account_id = $account->id;
|
$company_token->account_id = $account->id;
|
||||||
$company_token->name = $user->first_name.' '.$user->last_name;
|
$company_token->name = $user->first_name.' '.$user->last_name;
|
||||||
$company_token->token = Str::random(64);
|
$company_token->token = Str::random(64);
|
||||||
|
$company_token->is_system = true;
|
||||||
$company_token->save();
|
$company_token->save();
|
||||||
|
|
||||||
$this->token = $company_token->token;
|
$this->token = $company_token->token;
|
||||||
|
@ -160,6 +160,7 @@ class LoginTest extends TestCase
|
|||||||
$company_token->account_id = $account->id;
|
$company_token->account_id = $account->id;
|
||||||
$company_token->name = $user->first_name.' '.$user->last_name;
|
$company_token->name = $user->first_name.' '.$user->last_name;
|
||||||
$company_token->token = \Illuminate\Support\Str::random(64);
|
$company_token->token = \Illuminate\Support\Str::random(64);
|
||||||
|
$company_token->is_system = true;
|
||||||
$company_token->save();
|
$company_token->save();
|
||||||
|
|
||||||
$user->companies()->attach($company->id, [
|
$user->companies()->attach($company->id, [
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user