mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-09 03:14:30 -04:00
commit
b1d43807c2
@ -57,7 +57,6 @@ DELETE_PDF_DAYS=60
|
||||
DELETE_BACKUP_DAYS=60
|
||||
|
||||
COMPOSER_AUTH='{"github-oauth": {"github.com": "${{ secrets.GITHUB_TOKEN }}"}}'
|
||||
SENTRY_LARAVEL_DSN=https://39389664f3f14969b4c43dadda00a40b@sentry2.invoicing.co/5
|
||||
|
||||
GOOGLE_PLAY_PACKAGE_NAME=
|
||||
APPSTORE_PASSWORD=
|
||||
|
@ -1 +1 @@
|
||||
5.5.33
|
||||
5.5.34
|
@ -1048,6 +1048,29 @@ class CheckData extends Command
|
||||
|
||||
$this->logMessage("Fixing - {$ninja_portal_url}");
|
||||
}
|
||||
else{
|
||||
|
||||
$c = Client::on('db-ninja-01')->where("company_id", config('ninja.ninja_default_company_id'))->where('custom_value2', $cu->account->key)->first();
|
||||
|
||||
if($c)
|
||||
{
|
||||
|
||||
$cc = $c->contacts()->first();
|
||||
|
||||
if($cc)
|
||||
{
|
||||
$ninja_portal_url = "https://invoiceninja.invoicing.co/client/ninja/{$cc->contact_key}/{$cu->account->key}";
|
||||
|
||||
$cu->ninja_portal_url = $ninja_portal_url;
|
||||
$cu->save();
|
||||
|
||||
$this->logMessage("Fixing - {$ninja_portal_url}");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
@ -56,10 +56,10 @@ class Kernel extends ConsoleKernel
|
||||
$schedule->job(new QueueSize)->everyFiveMinutes()->withoutOverlapping();
|
||||
|
||||
/* Checks for large companies and marked them as is_large */
|
||||
$schedule->job(new CompanySizeCheck)->daily()->withoutOverlapping();
|
||||
$schedule->job(new CompanySizeCheck)->dailyAt('23:20')->withoutOverlapping();
|
||||
|
||||
/* Pulls in the latest exchange rates */
|
||||
$schedule->job(new UpdateExchangeRates)->daily()->withoutOverlapping();
|
||||
$schedule->job(new UpdateExchangeRates)->dailyAt('23:30')->withoutOverlapping();
|
||||
|
||||
/* Runs cleanup code for subscriptions */
|
||||
$schedule->job(new SubscriptionCron)->daily()->withoutOverlapping();
|
||||
|
@ -136,6 +136,6 @@ class DesignFilters extends QueryFilters
|
||||
public function entityFilter()
|
||||
{
|
||||
//return $this->builder->whereCompanyId(auth()->user()->company()->id);
|
||||
return $this->builder->whereCompanyId(auth()->user()->company()->id)->orWhere('company_id', null);
|
||||
return $this->builder->where('company_id', auth()->user()->company()->id)->orWhere('company_id', null)->orderBy('id','asc');
|
||||
}
|
||||
}
|
||||
|
@ -141,7 +141,7 @@ class SwissQrGenerator
|
||||
// Optionally, add some human-readable information about what the bill is for.
|
||||
$qrBill->setAdditionalInformation(
|
||||
QrBill\DataGroup\Element\AdditionalInformation::create(
|
||||
$this->invoice->public_notes ?: ''
|
||||
$this->invoice->public_notes ?: ctrans('texts.invoice_number_placeholder', ['invoice' => $invoice_number])
|
||||
)
|
||||
);
|
||||
|
||||
@ -149,7 +149,7 @@ class SwissQrGenerator
|
||||
// Now get the QR code image and save it as a file.
|
||||
try {
|
||||
|
||||
$output = new QrBill\PaymentPart\Output\HtmlOutput\HtmlOutput($qrBill, 'en');
|
||||
$output = new QrBill\PaymentPart\Output\HtmlOutput\HtmlOutput($qrBill, $this->client->locale() ?: 'en');
|
||||
|
||||
$html = $output
|
||||
->setPrintable(false)
|
||||
|
@ -108,6 +108,8 @@ class ActivityController extends BaseController
|
||||
'credit' => $activity->credit ? $activity->credit : '',
|
||||
'task' => $activity->task ? $activity->task : '',
|
||||
'vendor' => $activity->vendor ? $activity->vendor : '',
|
||||
'vendor_contact' => $activity->vendor_contact ? $activity->vendor_contact : '',
|
||||
'purchase_order' => $activity->purchase_order ? $activity->purchase_order : '',
|
||||
];
|
||||
|
||||
return array_merge($arr, $activity->toArray());
|
||||
|
@ -592,7 +592,10 @@ class LoginController extends BaseController
|
||||
|
||||
$google = new Google();
|
||||
|
||||
$user = $google->getTokenResponse(request()->input('id_token'));
|
||||
if(request()->has('id_token'))
|
||||
$user = $google->getTokenResponse(request()->input('id_token'));
|
||||
else
|
||||
return response()->json(['message' => 'Illegal request'], 403);
|
||||
|
||||
if (is_array($user)) {
|
||||
$query = [
|
||||
|
@ -459,7 +459,8 @@ class BaseController extends Controller
|
||||
);
|
||||
|
||||
if ($query instanceof Builder) {
|
||||
$limit = request()->input('per_page', 20);
|
||||
//27-10-2022 - enforce unsigned integer
|
||||
$limit = $this->resolveQueryLimit();
|
||||
|
||||
$paginator = $query->paginate($limit);
|
||||
$query = $paginator->getCollection();
|
||||
@ -472,6 +473,14 @@ class BaseController extends Controller
|
||||
return $this->response($this->manager->createData($resource)->toArray());
|
||||
}
|
||||
|
||||
private function resolveQueryLimit()
|
||||
{
|
||||
if(request()->has('per_page'))
|
||||
return abs((int)request()->input('per_page', 20));
|
||||
|
||||
return 20;
|
||||
}
|
||||
|
||||
protected function miniLoadResponse($query)
|
||||
{
|
||||
$user = auth()->user();
|
||||
@ -524,7 +533,7 @@ class BaseController extends Controller
|
||||
);
|
||||
|
||||
if ($query instanceof Builder) {
|
||||
$limit = request()->input('per_page', 20);
|
||||
$limit = $this->resolveQueryLimit();
|
||||
|
||||
$paginator = $query->paginate($limit);
|
||||
$query = $paginator->getCollection();
|
||||
@ -782,7 +791,7 @@ class BaseController extends Controller
|
||||
);
|
||||
|
||||
if ($query instanceof Builder) {
|
||||
$limit = request()->input('per_page', 20);
|
||||
$limit = $this->resolveQueryLimit();
|
||||
|
||||
$paginator = $query->paginate($limit);
|
||||
$query = $paginator->getCollection();
|
||||
@ -831,7 +840,7 @@ class BaseController extends Controller
|
||||
}
|
||||
|
||||
if ($query instanceof Builder) {
|
||||
$limit = request()->input('per_page', 20);
|
||||
$limit = $this->resolveQueryLimit();
|
||||
$paginator = $query->paginate($limit);
|
||||
$query = $paginator->getCollection();
|
||||
$resource = new Collection($query, $transformer, $this->entity_type);
|
||||
|
@ -237,7 +237,7 @@ class InvoiceController extends BaseController
|
||||
'metadata' => [],
|
||||
];
|
||||
|
||||
TransactionLog::dispatch(TransactionEvent::INVOICE_UPDATED, $transaction, $invoice->company->db);
|
||||
// TransactionLog::dispatch(TransactionEvent::INVOICE_UPDATED, $transaction, $invoice->company->db);
|
||||
|
||||
return $this->itemResponse($invoice);
|
||||
}
|
||||
@ -433,7 +433,7 @@ class InvoiceController extends BaseController
|
||||
'metadata' => [],
|
||||
];
|
||||
|
||||
TransactionLog::dispatch(TransactionEvent::INVOICE_UPDATED, $transaction, $invoice->company->db);
|
||||
// TransactionLog::dispatch(TransactionEvent::INVOICE_UPDATED, $transaction, $invoice->company->db);
|
||||
|
||||
return $this->itemResponse($invoice);
|
||||
}
|
||||
|
@ -11,9 +11,12 @@
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Http\Requests\Twilio\Confirm2faRequest;
|
||||
use App\Http\Requests\Twilio\ConfirmSmsRequest;
|
||||
use App\Http\Requests\Twilio\Generate2faRequest;
|
||||
use App\Http\Requests\Twilio\GenerateSmsRequest;
|
||||
use App\Libraries\MultiDB;
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Bus\DispatchesJobs;
|
||||
use Illuminate\Http\Response;
|
||||
use Twilio\Rest\Client;
|
||||
@ -100,6 +103,87 @@ class TwilioController extends BaseController
|
||||
|
||||
return response()->json(['message' => 'SMS not verified'], 400);
|
||||
|
||||
}
|
||||
|
||||
public function generate2faResetCode(Generate2faRequest $request)
|
||||
{
|
||||
$user = User::where('email', $request->email)->first();
|
||||
|
||||
if(!$user)
|
||||
return response()->json(['message' => 'Unable to retrieve user.'], 400);
|
||||
|
||||
$sid = config('ninja.twilio_account_sid');
|
||||
$token = config('ninja.twilio_auth_token');
|
||||
|
||||
$twilio = new Client($sid, $token);
|
||||
|
||||
|
||||
try {
|
||||
$verification = $twilio->verify
|
||||
->v2
|
||||
->services(config('ninja.twilio_verify_sid'))
|
||||
->verifications
|
||||
->create($user->phone, "sms");
|
||||
}
|
||||
catch(\Exception $e) {
|
||||
|
||||
return response()->json(['message' => 'Invalid phone number on file, we are unable to reset. Please contact support.'], 400);
|
||||
|
||||
}
|
||||
|
||||
$user->sms_verification_code = $verification->sid;
|
||||
$user->save();
|
||||
|
||||
return response()->json(['message' => 'Code sent.'], 200);
|
||||
}
|
||||
|
||||
public function confirm2faResetCode(Confirm2faRequest $request)
|
||||
{
|
||||
$user = User::where('email', $request->email)->first();
|
||||
|
||||
if(!$user)
|
||||
return response()->json(['message' => 'Unable to retrieve user.'], 400);
|
||||
|
||||
$sid = config('ninja.twilio_account_sid');
|
||||
$token = config('ninja.twilio_auth_token');
|
||||
|
||||
$twilio = new Client($sid, $token);
|
||||
|
||||
$verification_check = $twilio->verify
|
||||
->v2
|
||||
->services(config('ninja.twilio_verify_sid'))
|
||||
->verificationChecks
|
||||
->create([
|
||||
"to" => $user->phone,
|
||||
"code" => $request->code
|
||||
]);
|
||||
|
||||
|
||||
if($verification_check->status == 'approved'){
|
||||
|
||||
$user->google_2fa_secret = '';
|
||||
$user->sms_verification_code = '';
|
||||
$user->save();
|
||||
|
||||
return response()->json(['message' => 'SMS verified, 2FA disabled.'], 200);
|
||||
}
|
||||
|
||||
return response()->json(['message' => 'SMS not verified.'], 400);
|
||||
|
||||
}
|
||||
|
||||
public function validatePhoneNumber()
|
||||
{
|
||||
|
||||
$sid = config('ninja.twilio_account_sid');
|
||||
$token = config('ninja.twilio_auth_token');
|
||||
|
||||
$twilio = new Client($sid, $token);
|
||||
|
||||
$phone_number = $twilio->lookups->v1->phoneNumbers("0417918829")
|
||||
->fetch(["countryCode" => "AU"]);
|
||||
|
||||
print($phone_number);
|
||||
|
||||
}
|
||||
|
||||
|
@ -389,15 +389,18 @@ class UserController extends BaseController
|
||||
$new_user = $user->fresh();
|
||||
|
||||
/* When changing email address we store the former email in case we need to rollback */
|
||||
/* 27-10-2022 we need to wipe the oauth data at this point*/
|
||||
if ($old_user_email != $new_email) {
|
||||
$user->last_confirmed_email_address = $old_user_email;
|
||||
$user->email_verified_at = null;
|
||||
$user->oauth_user_id = null;
|
||||
$user->oauth_provider_id = null;
|
||||
$user->oauth_user_refresh_token = null;
|
||||
$user->oauth_user_token = null;
|
||||
$user->save();
|
||||
UserEmailChanged::dispatch($new_user, json_decode($old_user), auth()->user()->company());
|
||||
}
|
||||
|
||||
// $user->company_users()->update(["permissions_updated_at" => now()]);
|
||||
|
||||
event(new UserWasUpdated($user, auth()->user(), auth()->user()->company, Ninja::eventVars(auth()->user() ? auth()->user()->id : null)));
|
||||
|
||||
return $this->itemResponse($user);
|
||||
|
@ -14,6 +14,7 @@ namespace App\Http\Controllers\VendorPortal;
|
||||
use App\Events\Credit\CreditWasViewed;
|
||||
use App\Events\Invoice\InvoiceWasViewed;
|
||||
use App\Events\Misc\InvitationWasViewed;
|
||||
use App\Events\PurchaseOrder\PurchaseOrderWasViewed;
|
||||
use App\Events\Quote\QuoteWasViewed;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Jobs\Entity\CreateRawPdf;
|
||||
@ -83,7 +84,8 @@ class InvitationController extends Controller
|
||||
|
||||
$invitation->markViewed();
|
||||
event(new InvitationWasViewed($invitation->purchase_order, $invitation, $invitation->company, Ninja::eventVars()));
|
||||
|
||||
event(new PurchaseOrderWasViewed($invitation, $invitation->company, Ninja::eventVars()));
|
||||
|
||||
}
|
||||
else{
|
||||
|
||||
|
50
app/Http/Requests/Twilio/Confirm2faRequest.php
Normal file
50
app/Http/Requests/Twilio/Confirm2faRequest.php
Normal file
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Http\Requests\Twilio;
|
||||
|
||||
use App\Http\Requests\Request;
|
||||
use App\Libraries\MultiDB;
|
||||
|
||||
|
||||
class Confirm2faRequest extends Request
|
||||
{
|
||||
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize() : bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function rules()
|
||||
{
|
||||
|
||||
return [
|
||||
'code' => 'required',
|
||||
'email' => 'required|exists:users,email',
|
||||
];
|
||||
}
|
||||
|
||||
public function prepareForValidation()
|
||||
{
|
||||
$input = $this->all();
|
||||
|
||||
if(array_key_exists('email', $input))
|
||||
MultiDB::userFindAndSetDb($input['email']);
|
||||
|
||||
$this->replace($input);
|
||||
}
|
||||
|
||||
}
|
51
app/Http/Requests/Twilio/Generate2faRequest.php
Normal file
51
app/Http/Requests/Twilio/Generate2faRequest.php
Normal file
@ -0,0 +1,51 @@
|
||||
<?php
|
||||
/**
|
||||
* Invoice Ninja (https://invoiceninja.com).
|
||||
*
|
||||
* @link https://github.com/invoiceninja/invoiceninja source repository
|
||||
*
|
||||
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
|
||||
*
|
||||
* @license https://www.elastic.co/licensing/elastic-license
|
||||
*/
|
||||
|
||||
namespace App\Http\Requests\Twilio;
|
||||
|
||||
use App\Http\Requests\Request;
|
||||
use App\Libraries\MultiDB;
|
||||
|
||||
|
||||
class Generate2faRequest extends Request
|
||||
{
|
||||
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize() : bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public function rules()
|
||||
{
|
||||
|
||||
return [
|
||||
'email' => 'required|exists:users,email',
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
public function prepareForValidation()
|
||||
{
|
||||
$input = $this->all();
|
||||
|
||||
if(array_key_exists('email', $input))
|
||||
MultiDB::userFindAndSetDb($input['email']);
|
||||
|
||||
$this->replace($input);
|
||||
}
|
||||
|
||||
}
|
@ -185,6 +185,8 @@ class MatchBankTransactions implements ShouldQueue
|
||||
$expense->transaction_reference = $this->bt->description;
|
||||
$expense->transaction_id = $this->bt->id;
|
||||
$expense->vendor_id = array_key_exists('vendor_id', $input) ? $input['vendor_id'] : null;
|
||||
$expense->invoice_documents = $this->company->invoice_expense_documents;
|
||||
$expense->should_be_invoiced = $this->company->mark_expenses_invoiceable;
|
||||
$expense->save();
|
||||
|
||||
$this->bt->expense_id = $expense->id;
|
||||
|
@ -25,7 +25,7 @@ class AutoBill implements ShouldQueue
|
||||
|
||||
public $tries = 1;
|
||||
|
||||
public Invoice $invoice;
|
||||
public int $invoice_id;
|
||||
|
||||
public string $db;
|
||||
|
||||
@ -34,9 +34,9 @@ class AutoBill implements ShouldQueue
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(Invoice $invoice, ?string $db)
|
||||
public function __construct(int $invoice_id, ?string $db)
|
||||
{
|
||||
$this->invoice = $invoice;
|
||||
$this->invoice_id = $invoice_id;
|
||||
$this->db = $db;
|
||||
}
|
||||
|
||||
@ -54,11 +54,13 @@ class AutoBill implements ShouldQueue
|
||||
}
|
||||
|
||||
try {
|
||||
nlog("autobill {$this->invoice->id}");
|
||||
nlog("autobill {$this->invoice_id}");
|
||||
|
||||
$invoice = Invoice::withTrashed()->find($this->invoice_id);
|
||||
|
||||
$this->invoice->service()->autoBill();
|
||||
$invoice->service()->autoBill();
|
||||
} catch (\Exception $e) {
|
||||
nlog("Failed to capture payment for {$this->invoice->company_id} - {$this->invoice->number} ->".$e->getMessage());
|
||||
nlog("Failed to capture payment for {$this->invoice_id} ->".$e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -58,13 +58,12 @@ class AutoBillCron
|
||||
->whereHas('company', function ($query) {
|
||||
$query->where('is_disabled', 0);
|
||||
})
|
||||
->orderBy('id', 'DESC')
|
||||
->with('company');
|
||||
->orderBy('id', 'DESC');
|
||||
|
||||
nlog($auto_bill_partial_invoices->count().' partial invoices to auto bill');
|
||||
|
||||
$auto_bill_partial_invoices->cursor()->each(function ($invoice) {
|
||||
AutoBill::dispatch($invoice, false);
|
||||
AutoBill::dispatch($invoice->id, false);
|
||||
});
|
||||
|
||||
$auto_bill_invoices = Invoice::whereDate('due_date', '<=', now())
|
||||
@ -76,13 +75,12 @@ class AutoBillCron
|
||||
->whereHas('company', function ($query) {
|
||||
$query->where('is_disabled', 0);
|
||||
})
|
||||
->orderBy('id', 'DESC')
|
||||
->with('company');
|
||||
->orderBy('id', 'DESC');
|
||||
|
||||
nlog($auto_bill_invoices->count().' full invoices to auto bill');
|
||||
|
||||
$auto_bill_invoices->cursor()->each(function ($invoice) {
|
||||
AutoBill::dispatch($invoice, false);
|
||||
AutoBill::dispatch($invoice->id, false);
|
||||
});
|
||||
} else {
|
||||
//multiDB environment, need to
|
||||
@ -98,13 +96,12 @@ class AutoBillCron
|
||||
->whereHas('company', function ($query) {
|
||||
$query->where('is_disabled', 0);
|
||||
})
|
||||
->orderBy('id', 'DESC')
|
||||
->with('company');
|
||||
->orderBy('id', 'DESC');
|
||||
|
||||
nlog($auto_bill_partial_invoices->count()." partial invoices to auto bill db = {$db}");
|
||||
|
||||
$auto_bill_partial_invoices->cursor()->each(function ($invoice) use ($db) {
|
||||
AutoBill::dispatch($invoice, $db);
|
||||
AutoBill::dispatch($invoice->id, $db);
|
||||
});
|
||||
|
||||
$auto_bill_invoices = Invoice::whereDate('due_date', '<=', now())
|
||||
@ -116,14 +113,13 @@ class AutoBillCron
|
||||
->whereHas('company', function ($query) {
|
||||
$query->where('is_disabled', 0);
|
||||
})
|
||||
->orderBy('id', 'DESC')
|
||||
->with('company');
|
||||
->orderBy('id', 'DESC');
|
||||
|
||||
nlog($auto_bill_invoices->count()." full invoices to auto bill db = {$db}");
|
||||
|
||||
$auto_bill_invoices->cursor()->each(function ($invoice) use ($db) {
|
||||
nlog($this->counter);
|
||||
AutoBill::dispatch($invoice, $db);
|
||||
AutoBill::dispatch($invoice->id, $db);
|
||||
$this->counter++;
|
||||
});
|
||||
}
|
||||
|
@ -122,12 +122,13 @@ class NinjaMailerJob implements ShouldQueue
|
||||
->to($this->nmo->to_user->email)
|
||||
->send($this->nmo->mailable);
|
||||
|
||||
LightLogs::create(new EmailSuccess($this->nmo->company->company_key))
|
||||
->batch();
|
||||
|
||||
/* Count the amount of emails sent across all the users accounts */
|
||||
Cache::increment($this->company->account->key);
|
||||
|
||||
LightLogs::create(new EmailSuccess($this->nmo->company->company_key))
|
||||
->send();
|
||||
|
||||
|
||||
} catch (\Exception | \RuntimeException | \Google\Service\Exception $e) {
|
||||
|
||||
nlog("error failed with {$e->getMessage()}");
|
||||
@ -394,7 +395,7 @@ class NinjaMailerJob implements ShouldQueue
|
||||
$job_failure->string_metric6 = substr($errors, 0, 150);
|
||||
|
||||
LightLogs::create($job_failure)
|
||||
->queue();
|
||||
->send();
|
||||
}
|
||||
|
||||
public function failed($exception = null)
|
||||
|
@ -63,8 +63,15 @@ class AdjustEmailQuota implements ShouldQueue
|
||||
|
||||
$email_count = Cache::get($account->key);
|
||||
|
||||
if($email_count > 0)
|
||||
LightLogs::create(new EmailCount($email_count, $account->key))->batch();
|
||||
if($email_count > 0){
|
||||
|
||||
try{
|
||||
LightLogs::create(new EmailCount($email_count, $account->key))->send();
|
||||
}
|
||||
catch(\Exception $e){
|
||||
nlog($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
Cache::forget($account->key);
|
||||
Cache::forget("throttle_notified:{$account->key}");
|
||||
|
@ -43,6 +43,6 @@ class QueueSize implements ShouldQueue
|
||||
public function handle()
|
||||
{
|
||||
LightLogs::create(new QueueSizeAnalytic(Queue::size()))
|
||||
->queue();
|
||||
->send();
|
||||
}
|
||||
}
|
||||
|
@ -142,7 +142,7 @@ class ProcessPostmarkWebhook implements ShouldQueue
|
||||
$this->invitation->opened_date = now();
|
||||
$this->invitation->save();
|
||||
|
||||
SystemLogger::dispatch($this->request,
|
||||
SystemLogger::dispatchSync($this->request,
|
||||
SystemLog::CATEGORY_MAIL,
|
||||
SystemLog::EVENT_MAIL_OPENED,
|
||||
SystemLog::TYPE_WEBHOOK_RESPONSE,
|
||||
@ -171,7 +171,7 @@ class ProcessPostmarkWebhook implements ShouldQueue
|
||||
$this->invitation->email_status = 'delivered';
|
||||
$this->invitation->save();
|
||||
|
||||
SystemLogger::dispatch($this->request,
|
||||
SystemLogger::dispatchSync($this->request,
|
||||
SystemLog::CATEGORY_MAIL,
|
||||
SystemLog::EVENT_MAIL_DELIVERY,
|
||||
SystemLog::TYPE_WEBHOOK_RESPONSE,
|
||||
@ -217,9 +217,9 @@ class ProcessPostmarkWebhook implements ShouldQueue
|
||||
$this->request['MessageID']
|
||||
);
|
||||
|
||||
LightLogs::create($bounce)->batch();
|
||||
LightLogs::create($bounce)->send();
|
||||
|
||||
SystemLogger::dispatch($this->request, SystemLog::CATEGORY_MAIL, SystemLog::EVENT_MAIL_BOUNCED, SystemLog::TYPE_WEBHOOK_RESPONSE, $this->invitation->contact->client, $this->invitation->company);
|
||||
SystemLogger::dispatchSync($this->request, SystemLog::CATEGORY_MAIL, SystemLog::EVENT_MAIL_BOUNCED, SystemLog::TYPE_WEBHOOK_RESPONSE, $this->invitation->contact->client, $this->invitation->company);
|
||||
|
||||
// if(config('ninja.notification.slack'))
|
||||
// $this->invitation->company->notification(new EmailBounceNotification($this->invitation->company->account))->ninja();
|
||||
@ -263,9 +263,9 @@ class ProcessPostmarkWebhook implements ShouldQueue
|
||||
$this->request['MessageID']
|
||||
);
|
||||
|
||||
LightLogs::create($spam)->batch();
|
||||
LightLogs::create($spam)->send();
|
||||
|
||||
SystemLogger::dispatch($this->request, SystemLog::CATEGORY_MAIL, SystemLog::EVENT_MAIL_SPAM_COMPLAINT, SystemLog::TYPE_WEBHOOK_RESPONSE, $this->invitation->contact->client, $this->invitation->company);
|
||||
SystemLogger::dispatchSync($this->request, SystemLog::CATEGORY_MAIL, SystemLog::EVENT_MAIL_SPAM_COMPLAINT, SystemLog::TYPE_WEBHOOK_RESPONSE, $this->invitation->contact->client, $this->invitation->company);
|
||||
|
||||
if(config('ninja.notification.slack'))
|
||||
$this->invitation->company->notification(new EmailSpamNotification($this->invitation->company->account))->ninja();
|
||||
|
@ -130,7 +130,7 @@ class SendRecurring implements ShouldQueue
|
||||
$invoice->invitations->each(function ($invitation) use ($invoice) {
|
||||
if ($invitation->contact && ! $invitation->contact->trashed() && strlen($invitation->contact->email) >= 1 && $invoice->client->getSetting('auto_email_invoice')) {
|
||||
try {
|
||||
EmailEntity::dispatch($invitation, $invoice->company)->delay(rand(10,20));
|
||||
EmailEntity::dispatch($invitation, $invoice->company)->delay(rand(1,2));
|
||||
} catch (\Exception $e) {
|
||||
nlog($e->getMessage());
|
||||
}
|
||||
@ -143,13 +143,13 @@ class SendRecurring implements ShouldQueue
|
||||
if ($invoice->client->getSetting('auto_bill_date') == 'on_send_date' && $invoice->auto_bill_enabled) {
|
||||
nlog("attempting to autobill {$invoice->number}");
|
||||
// $invoice->service()->autoBill();
|
||||
AutoBill::dispatch($invoice, $this->db)->delay(rand(30,40));
|
||||
AutoBill::dispatch($invoice->id, $this->db)->delay(rand(1,2));
|
||||
|
||||
} elseif ($invoice->client->getSetting('auto_bill_date') == 'on_due_date' && $invoice->auto_bill_enabled) {
|
||||
if ($invoice->due_date && Carbon::parse($invoice->due_date)->startOfDay()->lte(now()->startOfDay())) {
|
||||
nlog("attempting to autobill {$invoice->number}");
|
||||
// $invoice->service()->autoBill();
|
||||
AutoBill::dispatch($invoice, $this->db)->delay(rand(30,40));
|
||||
AutoBill::dispatch($invoice->id, $this->db)->delay(rand(1,2));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -181,7 +181,7 @@ class SendRecurring implements ShouldQueue
|
||||
$job_failure->string_metric6 = $exception->getMessage();
|
||||
|
||||
LightLogs::create($job_failure)
|
||||
->queue();
|
||||
->send();
|
||||
|
||||
nlog(print_r($exception->getMessage(), 1));
|
||||
}
|
||||
|
@ -99,7 +99,7 @@ class ReminderJob implements ShouldQueue
|
||||
(Ninja::isSelfHost() || $invoice->company->account->isPaidHostedClient())) {
|
||||
|
||||
$invoice->invitations->each(function ($invitation) use ($invoice, $reminder_template) {
|
||||
EmailEntity::dispatch($invitation, $invitation->company, $reminder_template);
|
||||
EmailEntity::dispatchSync($invitation, $invitation->company, $reminder_template);
|
||||
nlog("Firing reminder email for invoice {$invoice->number} - {$reminder_template}");
|
||||
});
|
||||
|
||||
@ -216,7 +216,7 @@ class ReminderJob implements ShouldQueue
|
||||
'metadata' => ['setLateFee'],
|
||||
];
|
||||
|
||||
TransactionLog::dispatch(TransactionEvent::CLIENT_STATUS, $transaction, $invoice->company->db);
|
||||
// TransactionLog::dispatch(TransactionEvent::CLIENT_STATUS, $transaction, $invoice->company->db);
|
||||
|
||||
return $invoice;
|
||||
}
|
||||
|
@ -38,19 +38,23 @@ class CreateInvoicePdf implements ShouldQueue
|
||||
|
||||
if (isset($event->invoice)) {
|
||||
$event->invoice->invitations->each(function ($invitation) {
|
||||
CreateEntityPdf::dispatch($invitation->load('invoice', 'contact.client.company'));
|
||||
// CreateEntityPdf::dispatch($invitation->load('invoice', 'contact.client.company'));
|
||||
(new CreateEntityPdf($invitation->load('invoice', 'contact.client.company')))->handle();
|
||||
});
|
||||
}
|
||||
|
||||
if (isset($event->quote)) {
|
||||
$event->quote->invitations->each(function ($invitation) {
|
||||
CreateEntityPdf::dispatch($invitation->load('quote', 'contact.client.company'));
|
||||
// CreateEntityPdf::dispatch($invitation->load('quote', 'contact.client.company'));
|
||||
(new CreateEntityPdf($invitation->load('quote', 'contact.client.company')))->handle();
|
||||
});
|
||||
}
|
||||
|
||||
if (isset($event->credit)) {
|
||||
$event->credit->invitations->each(function ($invitation) {
|
||||
CreateEntityPdf::dispatch($invitation->load('credit', 'contact.client.company'));
|
||||
// CreateEntityPdf::dispatch($invitation->load('credit', 'contact.client.company'));
|
||||
(new CreateEntityPdf($invitation->load('credit', 'contact.client.company')))->handle();
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -17,8 +17,10 @@ use App\Jobs\Mail\NinjaMailerObject;
|
||||
use App\Libraries\MultiDB;
|
||||
use App\Mail\Admin\EntityViewedObject;
|
||||
use App\Notifications\Admin\EntityViewedNotification;
|
||||
use App\Utils\Ninja;
|
||||
use App\Utils\Traits\Notifications\UserNotifies;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
|
||||
class InvitationViewedListener implements ShouldQueue
|
||||
@ -44,6 +46,11 @@ class InvitationViewedListener implements ShouldQueue
|
||||
{
|
||||
MultiDB::setDb($event->company->db);
|
||||
|
||||
App::forgetInstance('translator');
|
||||
$t = app('translator');
|
||||
$t->replace(Ninja::transformTranslations($event->company->settings));
|
||||
App::setLocale($event->company->getLocale());
|
||||
|
||||
$entity_name = lcfirst(class_basename($event->entity));
|
||||
$invitation = $event->invitation;
|
||||
|
||||
|
@ -329,4 +329,18 @@ class PaymentEmailEngine extends BaseEmailEngine
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function generateLabelsAndValues()
|
||||
{
|
||||
$data = [];
|
||||
|
||||
$values = $this->makePaymentVariables();
|
||||
|
||||
foreach ($values as $key => $value) {
|
||||
$data['values'][$key] = $value['value'];
|
||||
$data['labels'][$key.'_label'] = $value['label'];
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
@ -305,6 +305,16 @@ class Activity extends StaticModel
|
||||
return $this->belongsTo(Expense::class)->withTrashed();
|
||||
}
|
||||
|
||||
public function purchase_order()
|
||||
{
|
||||
return $this->belongsTo(PurchaseOrder::class)->withTrashed();
|
||||
}
|
||||
|
||||
public function vendor_contact()
|
||||
{
|
||||
return $this->belongsTo(VendorContact::class)->withTrashed();
|
||||
}
|
||||
|
||||
public function task()
|
||||
{
|
||||
return $this->belongsTo(Task::class)->withTrashed();
|
||||
|
@ -333,7 +333,7 @@ class BaseDriver extends AbstractPaymentDriver
|
||||
'metadata' => [],
|
||||
];
|
||||
|
||||
TransactionLog::dispatch(TransactionEvent::INVOICE_FEE_APPLIED, $transaction, $invoice->company->db);
|
||||
// TransactionLog::dispatch(TransactionEvent::INVOICE_FEE_APPLIED, $transaction, $invoice->company->db);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -209,7 +209,7 @@ class PaymentRepository extends BaseRepository {
|
||||
'metadata' => [],
|
||||
];
|
||||
|
||||
TransactionLog::dispatch(TransactionEvent::PAYMENT_MADE, $transaction, $payment->company->db);
|
||||
// TransactionLog::dispatch(TransactionEvent::PAYMENT_MADE, $transaction, $payment->company->db);
|
||||
|
||||
return $payment->refresh();
|
||||
}
|
||||
|
@ -113,7 +113,7 @@ class ApplyPayment extends AbstractService
|
||||
'metadata' => [],
|
||||
];
|
||||
|
||||
TransactionLog::dispatch(TransactionEvent::INVOICE_PAYMENT_APPLIED, $transaction, $this->invoice->company->db);
|
||||
// TransactionLog::dispatch(TransactionEvent::INVOICE_PAYMENT_APPLIED, $transaction, $this->invoice->company->db);
|
||||
|
||||
return $this->invoice;
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ class HandleCancellation extends AbstractService
|
||||
|
||||
//adjust client balance
|
||||
$this->invoice->client->service()->updateBalance($adjustment)->save();
|
||||
$this->invoice->fresh();
|
||||
// $this->invoice->fresh();
|
||||
|
||||
$this->invoice->service()->workFlow()->save();
|
||||
|
||||
@ -65,7 +65,7 @@ class HandleCancellation extends AbstractService
|
||||
'metadata' => [],
|
||||
];
|
||||
|
||||
TransactionLog::dispatch(TransactionEvent::INVOICE_CANCELLED, $transaction, $this->invoice->company->db);
|
||||
// TransactionLog::dispatch(TransactionEvent::INVOICE_CANCELLED, $transaction, $this->invoice->company->db);
|
||||
|
||||
return $this->invoice;
|
||||
}
|
||||
|
@ -12,6 +12,7 @@
|
||||
namespace App\Services\Invoice;
|
||||
|
||||
use App\Models\Invoice;
|
||||
use App\Models\Paymentable;
|
||||
use App\Services\AbstractService;
|
||||
use App\Utils\Ninja;
|
||||
use App\Utils\Traits\GeneratesCounter;
|
||||
@ -74,10 +75,14 @@ class HandleRestore extends AbstractService
|
||||
private function restorePaymentables()
|
||||
{
|
||||
$this->invoice->payments->each(function ($payment) {
|
||||
$payment->paymentables()
|
||||
->where('paymentable_type', '=', 'invoices')
|
||||
->where('paymentable_id', $this->invoice->id)
|
||||
->update(['deleted_at' => false]);
|
||||
|
||||
Paymentable::query()
|
||||
->withTrashed()
|
||||
->where('payment_id', $payment->id)
|
||||
->where('paymentable_type', '=', 'invoices')
|
||||
->where('paymentable_id', $this->invoice->id)
|
||||
->update(['deleted_at' => false]);
|
||||
|
||||
});
|
||||
|
||||
return $this;
|
||||
|
@ -147,7 +147,7 @@ class HandleReversal extends AbstractService
|
||||
'metadata' => [],
|
||||
];
|
||||
|
||||
TransactionLog::dispatch(TransactionEvent::INVOICE_REVERSED, $transaction, $this->invoice->company->db);
|
||||
// TransactionLog::dispatch(TransactionEvent::INVOICE_REVERSED, $transaction, $this->invoice->company->db);
|
||||
|
||||
return $this->invoice;
|
||||
//create a ledger row for this with the resulting Credit ( also include an explanation in the notes section )
|
||||
|
@ -56,7 +56,7 @@ class MarkInvoiceDeleted extends AbstractService
|
||||
'metadata' => ['total_payments' => $this->total_payments, 'balance_adjustment' => $this->balance_adjustment, 'adjustment_amount' => $this->adjustment_amount],
|
||||
];
|
||||
|
||||
TransactionLog::dispatch(TransactionEvent::INVOICE_DELETED, $transaction, $this->invoice->company->db);
|
||||
// TransactionLog::dispatch(TransactionEvent::INVOICE_DELETED, $transaction, $this->invoice->company->db);
|
||||
|
||||
return $this->invoice;
|
||||
}
|
||||
|
@ -141,7 +141,7 @@ class MarkPaid extends AbstractService
|
||||
'metadata' => [],
|
||||
];
|
||||
|
||||
TransactionLog::dispatch(TransactionEvent::INVOICE_MARK_PAID, $transaction, $this->invoice->company->db);
|
||||
// TransactionLog::dispatch(TransactionEvent::INVOICE_MARK_PAID, $transaction, $this->invoice->company->db);
|
||||
|
||||
return $this->invoice;
|
||||
}
|
||||
|
@ -132,7 +132,7 @@ class DeletePayment
|
||||
'metadata' => [],
|
||||
];
|
||||
|
||||
TransactionLog::dispatch(TransactionEvent::PAYMENT_DELETED, $transaction, $paymentable_invoice->company->db);
|
||||
// TransactionLog::dispatch(TransactionEvent::PAYMENT_DELETED, $transaction, $paymentable_invoice->company->db);
|
||||
});
|
||||
}
|
||||
|
||||
@ -151,7 +151,7 @@ class DeletePayment
|
||||
'metadata' => [],
|
||||
];
|
||||
|
||||
TransactionLog::dispatch(TransactionEvent::CLIENT_STATUS, $transaction, $this->payment->company->db);
|
||||
// TransactionLog::dispatch(TransactionEvent::CLIENT_STATUS, $transaction, $this->payment->company->db);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
@ -77,7 +77,7 @@ class RefundPayment
|
||||
'metadata' => [],
|
||||
];
|
||||
|
||||
TransactionLog::dispatch(TransactionEvent::PAYMENT_REFUND, $transaction, $this->payment->company->db);
|
||||
// TransactionLog::dispatch(TransactionEvent::PAYMENT_REFUND, $transaction, $this->payment->company->db);
|
||||
|
||||
$notes = ctrans('texts.refunded') . " : {$this->total_refund} - " . ctrans('texts.gateway_refund') . " : ";
|
||||
$notes .= $this->refund_data['gateway_refund'] !== false ? ctrans('texts.yes') : ctrans('texts.no');
|
||||
@ -296,7 +296,7 @@ class RefundPayment
|
||||
'metadata' => [],
|
||||
];
|
||||
|
||||
TransactionLog::dispatch(TransactionEvent::PAYMENT_REFUND, $transaction, $invoice->company->db);
|
||||
// TransactionLog::dispatch(TransactionEvent::PAYMENT_REFUND, $transaction, $invoice->company->db);
|
||||
|
||||
if ($invoice->is_deleted) {
|
||||
$invoice->delete();
|
||||
@ -319,7 +319,7 @@ class RefundPayment
|
||||
'metadata' => [],
|
||||
];
|
||||
|
||||
TransactionLog::dispatch(TransactionEvent::PAYMENT_REFUND, $transaction, $client->company->db);
|
||||
// TransactionLog::dispatch(TransactionEvent::PAYMENT_REFUND, $transaction, $client->company->db);
|
||||
} else {
|
||||
//if we are refunding and no payments have been tagged, then we need to decrement the client->paid_to_date by the total refund amount.
|
||||
|
||||
@ -339,7 +339,7 @@ class RefundPayment
|
||||
'metadata' => [],
|
||||
];
|
||||
|
||||
TransactionLog::dispatch(TransactionEvent::PAYMENT_REFUND, $transaction, $client->company->db);
|
||||
// TransactionLog::dispatch(TransactionEvent::PAYMENT_REFUND, $transaction, $client->company->db);
|
||||
}
|
||||
|
||||
return $this;
|
||||
|
@ -119,7 +119,7 @@ class UpdateInvoicePayment
|
||||
'metadata' => [],
|
||||
];
|
||||
|
||||
TransactionLog::dispatch(TransactionEvent::GATEWAY_PAYMENT_MADE, $transaction, $invoice->company->db);
|
||||
// TransactionLog::dispatch(TransactionEvent::GATEWAY_PAYMENT_MADE, $transaction, $invoice->company->db);
|
||||
|
||||
|
||||
});
|
||||
|
@ -15,8 +15,14 @@ use App\Models\Activity;
|
||||
use App\Models\Backup;
|
||||
use App\Models\ClientContact;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\PurchaseOrder;
|
||||
use App\Models\Task;
|
||||
use App\Models\User;
|
||||
use App\Models\Vendor;
|
||||
use App\Models\VendorContact;
|
||||
use App\Transformers\PurchaseOrderTransformer;
|
||||
use App\Transformers\VendorContactTransformer;
|
||||
use App\Transformers\VendorTransformer;
|
||||
use App\Utils\Traits\MakesHash;
|
||||
|
||||
class ActivityTransformer extends EntityTransformer
|
||||
@ -40,6 +46,9 @@ class ActivityTransformer extends EntityTransformer
|
||||
'payment',
|
||||
'expense',
|
||||
'task',
|
||||
'purchase_order',
|
||||
'vendor',
|
||||
'vendor_contact',
|
||||
];
|
||||
|
||||
/**
|
||||
@ -56,6 +65,7 @@ class ActivityTransformer extends EntityTransformer
|
||||
'recurring_invoice_id' => $activity->recurring_invoice_id ? (string) $this->encodePrimaryKey($activity->recurring_invoice_id) : '',
|
||||
'recurring_expense_id' => $activity->recurring_expense_id ? (string) $this->encodePrimaryKey($activity->recurring_expense_id) : '',
|
||||
'purchase_order_id' => $activity->purchase_order_id ? (string) $this->encodePrimaryKey($activity->purchase_order_id) : '',
|
||||
'vendor_id' => $activity->vendor_id ? (string) $this->encodePrimaryKey($activity->vendor_id) : '',
|
||||
'vendor_contact_id' => $activity->vendor_contact_id ? (string) $this->encodePrimaryKey($activity->vendor_contact_id) : '',
|
||||
'company_id' => $activity->company_id ? (string) $this->encodePrimaryKey($activity->company_id) : '',
|
||||
'user_id' => (string) $this->encodePrimaryKey($activity->user_id),
|
||||
@ -90,6 +100,13 @@ class ActivityTransformer extends EntityTransformer
|
||||
return $this->includeItem($activity->client, $transformer, Client::class);
|
||||
}
|
||||
|
||||
public function includeVendor(Activity $activity)
|
||||
{
|
||||
$transformer = new VendorTransformer($this->serializer);
|
||||
|
||||
return $this->includeItem($activity->vendor, $transformer, Vendor::class);
|
||||
}
|
||||
|
||||
public function includeContact(Activity $activity)
|
||||
{
|
||||
$transformer = new ClientContactTransformer($this->serializer);
|
||||
@ -97,6 +114,13 @@ class ActivityTransformer extends EntityTransformer
|
||||
return $this->includeItem($activity->contact, $transformer, ClientContact::class);
|
||||
}
|
||||
|
||||
public function includeVendorContact(Activity $activity)
|
||||
{
|
||||
$transformer = new VendorContactTransformer($this->serializer);
|
||||
|
||||
return $this->includeItem($activity->vendor_contact, $transformer, VendorContact::class);
|
||||
}
|
||||
|
||||
public function includeRecurringInvoice(Activity $activity)
|
||||
{
|
||||
$transformer = new RecurringInvoiceTransformer($this->serializer);
|
||||
@ -104,6 +128,14 @@ class ActivityTransformer extends EntityTransformer
|
||||
return $this->includeItem($activity->recurring_invoice, $transformer, RecurringInvoice::class);
|
||||
}
|
||||
|
||||
public function includePurchaseOrder(Activity $activity)
|
||||
{
|
||||
$transformer = new PurchaseOrderTransformer($this->serializer);
|
||||
|
||||
return $this->includeItem($activity->purchase_order(), $transformer, PurchaseOrder::class);
|
||||
}
|
||||
|
||||
|
||||
public function includeQuote(Activity $activity)
|
||||
{
|
||||
$transformer = new RecurringInvoiceTransformer($this->serializer);
|
||||
|
@ -13,6 +13,7 @@ namespace App\Utils;
|
||||
|
||||
use App\Libraries\MultiDB;
|
||||
use App\Mail\TestMailServer;
|
||||
use App\Models\Company;
|
||||
use Exception;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
@ -82,9 +83,34 @@ class SystemHealth
|
||||
'queue' => (string) config('queue.default'),
|
||||
'trailing_slash' => (bool) self::checkUrlState(),
|
||||
'file_permissions' => (string) self::checkFileSystem(),
|
||||
'exchange_rate_api_not_configured' => (bool)self::checkCurrencySanity(),
|
||||
];
|
||||
}
|
||||
|
||||
private static function checkCurrencySanity()
|
||||
{
|
||||
|
||||
if(strlen(config('ninja.currency_converter_api_key')) == 0){
|
||||
|
||||
$cs = DB::table('clients')
|
||||
->select('settings->currency_id as id')
|
||||
->get();
|
||||
|
||||
|
||||
$currency_count = $cs->unique('id')->filter(function ($value){
|
||||
return !is_null($value->id);
|
||||
})->count();
|
||||
|
||||
|
||||
if($currency_count > 1)
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
private static function checkQueueSize()
|
||||
{
|
||||
$count = 0;
|
||||
|
@ -13,10 +13,12 @@
|
||||
namespace App\Utils;
|
||||
|
||||
use App\DataMapper\EmailTemplateDefaults;
|
||||
use App\Mail\Engine\PaymentEmailEngine;
|
||||
use App\Models\Client;
|
||||
use App\Models\ClientContact;
|
||||
use App\Models\Invoice;
|
||||
use App\Models\InvoiceInvitation;
|
||||
use App\Models\Payment;
|
||||
use App\Models\PurchaseOrder;
|
||||
use App\Models\PurchaseOrderInvitation;
|
||||
use App\Models\Quote;
|
||||
@ -188,6 +190,8 @@ class TemplateEngine
|
||||
{
|
||||
if (in_array($this->entity, ['purchaseOrder', 'purchase_order']))
|
||||
$this->labels_and_values = (new VendorHtmlEngine($this->entity_obj->invitations->first()))->generateLabelsAndValues();
|
||||
elseif($this->entity == 'payment')
|
||||
$this->labels_and_values = (new PaymentEmailEngine($this->entity_obj, $this->entity_obj->client->contacts->first()))->generateLabelsAndValues();
|
||||
else
|
||||
$this->labels_and_values = (new HtmlEngine($this->entity_obj->invitations->first()))->generateLabelsAndValues();
|
||||
|
||||
@ -267,6 +271,8 @@ class TemplateEngine
|
||||
{
|
||||
if (!$this->entity && $this->template && str_contains($this->template, 'purchase_order'))
|
||||
$this->entity = 'purchaseOrder';
|
||||
elseif(str_contains($this->template, 'payment'))
|
||||
$this->entity = 'payment';
|
||||
|
||||
DB::connection(config('database.default'))->beginTransaction();
|
||||
|
||||
@ -285,6 +291,40 @@ class TemplateEngine
|
||||
'send_email' => true,
|
||||
]);
|
||||
|
||||
if ($this->entity == 'payment') {
|
||||
|
||||
|
||||
$this->entity_obj = Payment::factory()->create([
|
||||
'user_id' => auth()->user()->id,
|
||||
'company_id' => auth()->user()->company()->id,
|
||||
'client_id' => $client->id,
|
||||
'amount' => 10,
|
||||
'applied' => 10,
|
||||
'refunded' => 5,
|
||||
]);
|
||||
|
||||
$invoice = Invoice::factory()->create([
|
||||
'user_id' => auth()->user()->id,
|
||||
'company_id' => auth()->user()->company()->id,
|
||||
'client_id' => $client->id,
|
||||
'amount' => 10,
|
||||
'balance' => 10,
|
||||
'number' => rand(1,10000)
|
||||
]);
|
||||
|
||||
$invitation = InvoiceInvitation::factory()->create([
|
||||
'user_id' => auth()->user()->id,
|
||||
'company_id' => auth()->user()->company()->id,
|
||||
'invoice_id' => $invoice->id,
|
||||
'client_contact_id' => $contact->id,
|
||||
]);
|
||||
|
||||
$this->entity_obj->invoices()->attach($invoice->id, [
|
||||
'amount' => 10,
|
||||
]);
|
||||
|
||||
}
|
||||
|
||||
if (!$this->entity || $this->entity == 'invoice') {
|
||||
$this->entity_obj = Invoice::factory()->create([
|
||||
'user_id' => auth()->user()->id,
|
||||
@ -315,8 +355,6 @@ class TemplateEngine
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
if ($this->entity == 'purchaseOrder') {
|
||||
|
||||
$vendor = Vendor::factory()->create([
|
||||
|
@ -74,7 +74,7 @@
|
||||
"omnipay/paypal": "^3.0",
|
||||
"payfast/payfast-php-sdk": "^1.1",
|
||||
"pragmarx/google2fa": "^8.0",
|
||||
"predis/predis": "^1.1",
|
||||
"turbo124/predis": "^1.1",
|
||||
"razorpay/razorpay": "2.*",
|
||||
"sentry/sentry-laravel": "^2",
|
||||
"setasign/fpdf": "^1.8",
|
||||
|
1052
composer.lock
generated
1052
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@ -14,8 +14,8 @@ return [
|
||||
'require_https' => env('REQUIRE_HTTPS', true),
|
||||
'app_url' => rtrim(env('APP_URL', ''), '/'),
|
||||
'app_domain' => env('APP_DOMAIN', 'invoicing.co'),
|
||||
'app_version' => '5.5.33',
|
||||
'app_tag' => '5.5.33',
|
||||
'app_version' => '5.5.34',
|
||||
'app_tag' => '5.5.34',
|
||||
'minimum_client_version' => '5.0.16',
|
||||
'terms_version' => '1.0.1',
|
||||
'api_secret' => env('API_SECRET', ''),
|
||||
@ -38,7 +38,7 @@ return [
|
||||
'trusted_proxies' => env('TRUSTED_PROXIES', false),
|
||||
'is_docker' => env('IS_DOCKER', false),
|
||||
'local_download' => env('LOCAL_DOWNLOAD', false),
|
||||
'sentry_dsn' => env('SENTRY_LARAVEL_DSN', 'https://39389664f3f14969b4c43dadda00a40b@sentry2.invoicing.co/5'),
|
||||
'sentry_dsn' => env('SENTRY_LARAVEL_DSN', null),
|
||||
'environment' => env('NINJA_ENVIRONMENT', 'selfhost'), // 'hosted', 'development', 'selfhost', 'reseller'
|
||||
'preconfigured_install' => env('PRECONFIGURED_INSTALL', false),
|
||||
'update_secret' => env('UPDATE_SECRET', ''),
|
||||
|
@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
$table->string('sms_verification_code', 191)->nullable();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
//
|
||||
}
|
||||
};
|
@ -33,6 +33,13 @@
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
#qr-bill {
|
||||
width:100% !important;
|
||||
box-sizing: border-box;
|
||||
border-collapse: collapse;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.header-container {
|
||||
display: grid;
|
||||
|
@ -298,7 +298,6 @@ Route::group(['middleware' => ['throttle:300,1', 'api_db', 'token_auth', 'locale
|
||||
Route::post('settings/enable_two_factor', [TwoFactorController::class, 'enableTwoFactor']);
|
||||
Route::post('settings/disable_two_factor', [TwoFactorController::class, 'disableTwoFactor']);
|
||||
|
||||
|
||||
Route::post('verify', [TwilioController::class, 'generate'])->name('verify.generate')->middleware('throttle:100,1');
|
||||
Route::post('verify/confirm', [TwilioController::class, 'confirm'])->name('verify.confirm');
|
||||
|
||||
@ -344,6 +343,9 @@ Route::group(['middleware' => ['throttle:300,1', 'api_db', 'token_auth', 'locale
|
||||
|
||||
});
|
||||
|
||||
Route::post('api/v1/sms_reset', [TwilioController::class, 'generate2faResetCode'])->name('sms_reset.generate')->middleware('throttle:10,1');
|
||||
Route::post('api/v1/sms_reset/confirm', [TwilioController::class, 'confirm2faResetCode'])->name('sms_reset.confirm')->middleware('throttle:20,1');
|
||||
|
||||
Route::match(['get', 'post'], 'payment_webhook/{company_key}/{company_gateway_id}', PaymentWebhookController::class)
|
||||
->middleware('throttle:1000,1')
|
||||
->name('payment_webhook');
|
||||
|
@ -12,6 +12,8 @@
|
||||
|
||||
namespace Tests\Feature\Bank;
|
||||
|
||||
use App\Factory\BankIntegrationFactory;
|
||||
use App\Factory\BankTransactionFactory;
|
||||
use App\Models\BankTransaction;
|
||||
use App\Models\Invoice;
|
||||
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
||||
@ -54,10 +56,31 @@ class BankTransactionTest extends TestCase
|
||||
|
||||
public function testMatchBankTransactionValidationShouldPass()
|
||||
{
|
||||
|
||||
if (config('ninja.testvars.travis') !== false) {
|
||||
$this->markTestSkipped('Skip test for Github Actions');
|
||||
}
|
||||
|
||||
$data = [];
|
||||
|
||||
$bi = BankIntegrationFactory::create($this->company->id, $this->user->id, $this->account->id);
|
||||
$bi->save();
|
||||
|
||||
$bt = BankTransactionFactory::create($this->company->id, $this->user->id);
|
||||
$bt->bank_integration_id = $bi->id;
|
||||
$bt->description = 'Fuel';
|
||||
$bt->amount = 10;
|
||||
$bt->currency_code = $this->client->currency()->code;
|
||||
$bt->date = now()->format('Y-m-d');
|
||||
$bt->transaction_id = 1234567890;
|
||||
$bt->category_id = 10000003;
|
||||
$bt->base_type = 'DEBIT';
|
||||
$bt->save();
|
||||
|
||||
$data = [];
|
||||
|
||||
$data['transactions'][] = [
|
||||
'id' => $this->bank_transaction->hashed_id,
|
||||
'id' => $bt->hashed_id,
|
||||
];
|
||||
|
||||
$response = $this->withHeaders([
|
||||
|
@ -37,7 +37,7 @@ class YodleeApiTest extends TestCase
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
if(!config('ninja.yodlee.client_id'))
|
||||
// if(!config('ninja.yodlee.client_id'))
|
||||
$this->markTestSkipped('Skip test no Yodlee API credentials found');
|
||||
|
||||
$this->makeTestData();
|
||||
@ -160,55 +160,58 @@ class YodleeApiTest extends TestCase
|
||||
|
||||
}
|
||||
|
||||
public function testFunctionalMatching()
|
||||
{
|
||||
// public function testFunctionalMatching()
|
||||
// {
|
||||
|
||||
$yodlee = new Yodlee('sbMem62e1e69547bfb1');
|
||||
// $yodlee = new Yodlee('sbMem62e1e69547bfb1');
|
||||
|
||||
$accounts = $yodlee->getAccounts();
|
||||
// $accounts = $yodlee->getAccounts();
|
||||
|
||||
foreach($accounts as $account)
|
||||
{
|
||||
// foreach($accounts as $account)
|
||||
// {
|
||||
|
||||
if(!BankIntegration::where('bank_account_id', $account['id'])->where('company_id', $this->company->id)->exists())
|
||||
{
|
||||
$bank_integration = new BankIntegration();
|
||||
$bank_integration->company_id = $this->company->id;
|
||||
$bank_integration->account_id = $this->company->account_id;
|
||||
$bank_integration->user_id = $this->user->id;
|
||||
$bank_integration->bank_account_id = $account['id'];
|
||||
$bank_integration->bank_account_type = $account['account_type'];
|
||||
$bank_integration->bank_account_name = $account['account_name'];
|
||||
$bank_integration->bank_account_status = $account['account_status'];
|
||||
$bank_integration->bank_account_number = $account['account_number'];
|
||||
$bank_integration->provider_id = $account['provider_id'];
|
||||
$bank_integration->provider_name = $account['provider_name'];
|
||||
$bank_integration->nickname = $account['nickname'];
|
||||
$bank_integration->balance = $account['current_balance'];
|
||||
$bank_integration->currency = $account['account_currency'];
|
||||
// if(!BankIntegration::where('bank_account_id', $account['id'])->where('company_id', $this->company->id)->exists())
|
||||
// {
|
||||
// $bank_integration = new BankIntegration();
|
||||
// $bank_integration->company_id = $this->company->id;
|
||||
// $bank_integration->account_id = $this->company->account_id;
|
||||
// $bank_integration->user_id = $this->user->id;
|
||||
// $bank_integration->bank_account_id = $account['id'];
|
||||
// $bank_integration->bank_account_type = $account['account_type'];
|
||||
// $bank_integration->bank_account_name = $account['account_name'];
|
||||
// $bank_integration->bank_account_status = $account['account_status'];
|
||||
// $bank_integration->bank_account_number = $account['account_number'];
|
||||
// $bank_integration->provider_id = $account['provider_id'];
|
||||
// $bank_integration->provider_name = $account['provider_name'];
|
||||
// $bank_integration->nickname = $account['nickname'];
|
||||
// $bank_integration->balance = $account['current_balance'];
|
||||
// $bank_integration->currency = $account['account_currency'];
|
||||
|
||||
$bank_integration->save();
|
||||
// $bank_integration->save();
|
||||
|
||||
ProcessBankTransactions::dispatchSync('sbMem62e1e69547bfb1', $bank_integration);
|
||||
// ProcessBankTransactions::dispatchSync('sbMem62e1e69547bfb1', $bank_integration);
|
||||
|
||||
}
|
||||
}
|
||||
// }
|
||||
// }
|
||||
|
||||
$this->assertGreaterThan(0, BankIntegration::count());
|
||||
$this->assertGreaterThan(0, BankTransaction::count());
|
||||
// $this->assertGreaterThan(0, BankIntegration::count());
|
||||
// $this->assertGreaterThan(0, BankTransaction::count());
|
||||
|
||||
$this->invoice->number = "XXXXXX8501";
|
||||
$this->invoice->save();
|
||||
// $this->invoice->company_id = $this->company->id;
|
||||
// $this->invoice->number = "XXXXXX8501";
|
||||
// $this->invoice->save();
|
||||
|
||||
BankService::dispatchSync($this->company->id, $this->company->db);
|
||||
// BankService::dispatchSync($this->company->id, $this->company->db);
|
||||
|
||||
$bt = BankTransaction::where('invoice_ids', $this->invoice->hashed_id)->first();
|
||||
// $bt = BankTransaction::where('invoice_ids', $this->invoice->hashed_id)->first();
|
||||
|
||||
$this->assertNotNull($bt);
|
||||
// nlog(BankTransaction::where('company_id', $this->company->id)->pluck('invoice_ids'));
|
||||
|
||||
$this->assertEquals(BankTransaction::STATUS_MATCHED, $bt->status_id);
|
||||
// $this->assertNotNull($bt);
|
||||
|
||||
}
|
||||
// $this->assertEquals(BankTransaction::STATUS_MATCHED, $bt->status_id);
|
||||
|
||||
// }
|
||||
|
||||
|
||||
public function testDataMatching()
|
||||
|
Loading…
x
Reference in New Issue
Block a user